mirror of
git://erdgeist.org/opentracker
synced 2025-01-26 22:56:26 +00:00
Documentation improved, some reindenting (again), variable types checked, unnecessary defines removed
This commit is contained in:
parent
cb12e922d5
commit
805e46450c
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ CC?=gcc
|
||||
FEATURES=-DWANT_IP_FROM_QUERY_STRING #-DWANT_BLACKLIST -DWANT_CLOSED_TRACKER
|
||||
#DEBUG_OPTS=-g -ggdb -pg # -fprofile-arcs -ftest-coverage
|
||||
DEBUG_OPTS=-s -Os
|
||||
CFLAGS+=-I../libowfat -Wall -pipe
|
||||
CFLAGS+=-I../libowfat -Wall -pipe # -pedantic -ansi
|
||||
LDFLAGS+=-L../libowfat/ -lowfat -lm
|
||||
|
||||
HEADERS=trackerlogic.h scan_urlencoded_query.h
|
||||
|
394
opentracker.c
394
opentracker.c
@ -6,8 +6,8 @@
|
||||
#include "socket.h"
|
||||
#include "io.h"
|
||||
#include "buffer.h"
|
||||
#include "ip6.h"
|
||||
#include "array.h"
|
||||
#include "byte.h"
|
||||
#include "case.h"
|
||||
#include "fmt.h"
|
||||
#include "str.h"
|
||||
@ -25,14 +25,14 @@
|
||||
#include "trackerlogic.h"
|
||||
#include "scan_urlencoded_query.h"
|
||||
|
||||
unsigned long const OT_CLIENT_TIMEOUT = 15;
|
||||
unsigned long const OT_CLIENT_TIMEOUT_CHECKINTERVAL = 5;
|
||||
unsigned int const OT_CLIENT_TIMEOUT = 15;
|
||||
unsigned int const OT_CLIENT_TIMEOUT_CHECKINTERVAL = 5;
|
||||
|
||||
static unsigned int ot_overall_connections = 0;
|
||||
static time_t ot_start_time;
|
||||
static const unsigned int SUCCESS_HTTP_HEADER_LENGTH = 80;
|
||||
static const unsigned int SUCCESS_HTTP_SIZE_OFF = 17;
|
||||
// To always have space for error messages
|
||||
static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80;
|
||||
static const size_t SUCCESS_HTTP_SIZE_OFF = 17;
|
||||
/* To always have space for error messages ;) */
|
||||
static char static_reply[8192];
|
||||
|
||||
static void carp(const char* routine) {
|
||||
@ -49,13 +49,12 @@ static void panic(const char* routine) {
|
||||
|
||||
struct http_data {
|
||||
array r;
|
||||
unsigned long ip;
|
||||
unsigned char ip[4];
|
||||
};
|
||||
|
||||
int header_complete(struct http_data* r) {
|
||||
long l = array_bytes(&r->r);
|
||||
int l = array_bytes(&r->r), i;
|
||||
const char* c = array_start(&r->r);
|
||||
long i;
|
||||
|
||||
for (i=0; i+1<l; ++i) {
|
||||
if (c[i]=='\n' && c[i+1]=='\n') return i+2;
|
||||
@ -64,7 +63,7 @@ int header_complete(struct http_data* r) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// whoever sends data is not interested in its input-array
|
||||
/* whoever sends data is not interested in its input-array */
|
||||
void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
|
||||
size_t written_size;
|
||||
|
||||
@ -73,7 +72,7 @@ void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
|
||||
if( ( written_size < 0 ) || ( written_size == size ) ) {
|
||||
free(h); io_close( s );
|
||||
} else {
|
||||
// here we would take a copy of the buffer and remember it
|
||||
/* here we would take a copy of the buffer and remember it */
|
||||
fprintf( stderr, "Should have handled this.\n" );
|
||||
free(h); io_close( s );
|
||||
}
|
||||
@ -85,218 +84,225 @@ void httperror(int64 s,struct http_data* h,const char* title,const char* message
|
||||
senddata(s,h,static_reply,reply_size);
|
||||
}
|
||||
|
||||
// bestimmten http parameter auslesen und adresse zurueckgeben
|
||||
const char* http_header(struct http_data* r,const char* h) {
|
||||
long i;
|
||||
int i, l = array_bytes(&r->r);
|
||||
int sl = strlen(h);
|
||||
const char* c = array_start(&r->r);
|
||||
|
||||
long l = array_bytes(&r->r);
|
||||
long sl = strlen(h);
|
||||
const char* c = array_start(&r->r);
|
||||
|
||||
for (i=0; i+sl+2<l; ++i)
|
||||
{
|
||||
if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':')
|
||||
{
|
||||
c+=i+sl+1;
|
||||
if (*c==' ' || *c=='\t') ++c;
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
for (i=0; i+sl+2<l; ++i) {
|
||||
if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') {
|
||||
c+=i+sl+1;
|
||||
if (*c==' ' || *c=='\t') ++c;
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void httpresponse(int64 s,struct http_data* h)
|
||||
{
|
||||
char *c, *data; // must be enough
|
||||
ot_peer peer;
|
||||
ot_torrent *torrent;
|
||||
ot_hash *hash = NULL;
|
||||
int numwant, tmp, scanon;
|
||||
unsigned short port = htons(6881);
|
||||
size_t reply_size = 0;
|
||||
char *c, *data;
|
||||
ot_peer peer;
|
||||
ot_torrent *torrent;
|
||||
ot_hash *hash = NULL;
|
||||
int numwant, tmp, scanon;
|
||||
unsigned short port = htons(6881);
|
||||
size_t reply_size = 0;
|
||||
|
||||
array_cat0(&h->r);
|
||||
c = array_start(&h->r);
|
||||
array_cat0(&h->r);
|
||||
c = array_start(&h->r);
|
||||
|
||||
if (byte_diff(c,4,"GET ")) {
|
||||
if (byte_diff(c,4,"GET ")) {
|
||||
e400:
|
||||
return httperror(s,h,"400 Invalid Request","This server only understands GET.");
|
||||
}
|
||||
return httperror(s,h,"400 Invalid Request","This server only understands GET.");
|
||||
}
|
||||
|
||||
c+=4;
|
||||
for (data=c; *data!=' '&&*data!='\t'&&*data!='\n'&&*data!='\r'; ++data) ;
|
||||
c+=4;
|
||||
for (data=c; *data!=' '&&*data!='\t'&&*data!='\n'&&*data!='\r'; ++data) ;
|
||||
|
||||
if (*data!=' ') goto e400;
|
||||
*data=0;
|
||||
if (c[0]!='/') goto e404;
|
||||
while (*c=='/') ++c;
|
||||
if (*data!=' ') goto e400;
|
||||
*data=0;
|
||||
if (c[0]!='/') goto e404;
|
||||
while (*c=='/') ++c;
|
||||
|
||||
switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) )
|
||||
{
|
||||
case 6: /* scrape ? */
|
||||
if (byte_diff(data,6,"scrape"))
|
||||
switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) {
|
||||
case 6: /* scrape ? */
|
||||
if (byte_diff(data,6,"scrape"))
|
||||
goto e404;
|
||||
scanon = 1;
|
||||
|
||||
while( scanon ) {
|
||||
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
|
||||
case -2: /* terminator */
|
||||
scanon = 0;
|
||||
break;
|
||||
case -1: /* error */
|
||||
goto e404;
|
||||
scanon = 1;
|
||||
|
||||
while( scanon ) {
|
||||
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
|
||||
case -2: /* terminator */
|
||||
scanon = 0;
|
||||
break;
|
||||
case -1: /* error */
|
||||
goto e404;
|
||||
case 9:
|
||||
if(byte_diff(data,9,"info_hash")) {
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
continue;
|
||||
}
|
||||
/* ignore this, when we have less than 20 bytes */
|
||||
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) {
|
||||
case 9:
|
||||
if(byte_diff(data,9,"info_hash")) {
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
continue;
|
||||
}
|
||||
/* ignore this, when we have less than 20 bytes */
|
||||
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) {
|
||||
e400_param:
|
||||
return httperror(s,h,"400 Invalid Request","Invalid parameter");
|
||||
}
|
||||
hash = (ot_hash*)data; /* Fall through intended */
|
||||
break;
|
||||
default:
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
return httperror(s,h,"400 Invalid Request","Invalid parameter");
|
||||
}
|
||||
hash = (ot_hash*)data; /* Fall through intended */
|
||||
break;
|
||||
default:
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scanned whole query string, wo */
|
||||
if( !hash )
|
||||
return httperror(s,h,"400 Invalid Request","This server only serves specific scrapes.");
|
||||
/* Scanned whole query string, wo */
|
||||
if( !hash )
|
||||
return httperror(s,h,"400 Invalid Request","This server only serves specific scrapes.");
|
||||
|
||||
// Enough for http header + whole scrape string
|
||||
if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
|
||||
goto e500;
|
||||
break;
|
||||
case 8:
|
||||
if( byte_diff(data,8,"announce"))
|
||||
/* Enough for http header + whole scrape string */
|
||||
if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
|
||||
goto e500;
|
||||
break;
|
||||
case 8:
|
||||
if( byte_diff(data,8,"announce"))
|
||||
goto e404;
|
||||
|
||||
OT_SETIP( &peer, h->ip);
|
||||
OT_SETPORT( &peer, &port );
|
||||
OT_FLAG( &peer ) = 0;
|
||||
numwant = 50;
|
||||
scanon = 1;
|
||||
|
||||
while( scanon ) {
|
||||
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
|
||||
case -2: /* terminator */
|
||||
scanon = 0;
|
||||
break;
|
||||
case -1: /* error */
|
||||
goto e404;
|
||||
|
||||
OT_SETIP( &peer, &h->ip);
|
||||
OT_SETPORT( &peer, &port );
|
||||
OT_FLAG( &peer ) = 0;
|
||||
numwant = 50;
|
||||
scanon = 1;
|
||||
|
||||
while( scanon ) {
|
||||
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
|
||||
case -2: /* terminator */
|
||||
scanon = 0;
|
||||
break;
|
||||
case -1: /* error */
|
||||
goto e404;
|
||||
#ifdef WANT_IP_FROM_QUERY_STRING
|
||||
case 2:
|
||||
if(!byte_diff(data,2,"ip")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
unsigned char ip[4];
|
||||
if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param;
|
||||
OT_SETIP ( &peer, ip );
|
||||
} else
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
case 2:
|
||||
if(!byte_diff(data,2,"ip")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
unsigned char ip[4];
|
||||
if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param;
|
||||
OT_SETIP ( &peer, ip );
|
||||
} else
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
#endif
|
||||
case 4:
|
||||
if(!byte_diff(data,4,"port")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param;
|
||||
port = htons( tmp ); OT_SETPORT ( &peer, &port );
|
||||
} else if(!byte_diff(data,4,"left")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
|
||||
if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
|
||||
} else
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
case 5:
|
||||
if(byte_diff(data,5,"event"))
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
|
||||
case -1:
|
||||
goto e400_param;
|
||||
case 7:
|
||||
if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED;
|
||||
break;
|
||||
case 9:
|
||||
if(!byte_diff(data,9,"complete")) OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED;
|
||||
default: // Fall through intended
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(!byte_diff(data,4,"port")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param;
|
||||
port = htons( tmp ); OT_SETPORT ( &peer, &port );
|
||||
} else if(!byte_diff(data,4,"left")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
|
||||
if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
|
||||
} else
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
case 5:
|
||||
if(byte_diff(data,5,"event"))
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
|
||||
case -1:
|
||||
goto e400_param;
|
||||
case 7:
|
||||
if(!byte_diff(data,7,"numwant")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e400_param;
|
||||
if( numwant > 200 ) numwant = 200;
|
||||
} else if(!byte_diff(data,7,"compact")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
|
||||
if( !tmp )
|
||||
return httperror(s,h,"400 Invalid Request","This server only delivers compact results.");
|
||||
} else
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED;
|
||||
break;
|
||||
case 9:
|
||||
if(byte_diff(data,9,"info_hash")) {
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
continue;
|
||||
}
|
||||
/* ignore this, when we have less than 20 bytes */
|
||||
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 )
|
||||
goto e400;
|
||||
hash = (ot_hash*)data;
|
||||
if(!byte_diff(data,9,"complete")) OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED;
|
||||
default: /* Fall through intended */
|
||||
break;
|
||||
default:
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if(!byte_diff(data,7,"numwant")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e400_param;
|
||||
if( numwant > 200 ) numwant = 200;
|
||||
} else if(!byte_diff(data,7,"compact")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
|
||||
if( !tmp )
|
||||
return httperror(s,h,"400 Invalid Request","This server only delivers compact results.");
|
||||
} else
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
break;
|
||||
case 9:
|
||||
if(byte_diff(data,9,"info_hash")) {
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
continue;
|
||||
}
|
||||
/* ignore this, when we have less than 20 bytes */
|
||||
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 )
|
||||
goto e400;
|
||||
hash = (ot_hash*)data;
|
||||
break;
|
||||
default:
|
||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Scanned whole query string */
|
||||
if( !hash ) goto e400;
|
||||
|
||||
if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) {
|
||||
remove_peer_from_torrent( hash, &peer );
|
||||
MEMMOVE( static_reply + SUCCESS_HTTP_HEADER_LENGTH, "d15:warning message4:Okaye", reply_size = 26 );
|
||||
} else {
|
||||
torrent = add_peer_to_torrent( hash, &peer );
|
||||
if( !torrent ) {
|
||||
e500:
|
||||
return httperror(s,h,"500 Internal Server Error","A server error has occured. Please retry later.");
|
||||
}
|
||||
if( ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
|
||||
goto e500;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if( byte_diff(data,11,"mrtg_scrape"))
|
||||
goto e404;
|
||||
{
|
||||
unsigned long seconds_elapsed = time( NULL ) - ot_start_time;
|
||||
reply_size = sprintf( static_reply + SUCCESS_HTTP_HEADER_LENGTH,
|
||||
"%d\n%d\nUp: %ld seconds (%ld hours)\nPretuned by german engineers, currently handling %li connections per second.",
|
||||
ot_overall_connections, ot_overall_connections, seconds_elapsed,
|
||||
seconds_elapsed / 3600, ot_overall_connections / ( seconds_elapsed ? seconds_elapsed : 1 ) );
|
||||
}
|
||||
break;
|
||||
default: /* neither *scrape nor announce */
|
||||
e404:
|
||||
return httperror(s,h,"404 Not Found","No such file or directory.");
|
||||
}
|
||||
|
||||
if( reply_size ) {
|
||||
size_t reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_reply, 0, "%zd", reply_size );
|
||||
reply_size += 1 + sprintf( static_reply + reply_off, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", reply_size );
|
||||
static_reply[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
|
||||
senddata( s, h, static_reply + reply_off, reply_size );
|
||||
/* Scanned whole query string */
|
||||
if( !hash ) goto e400;
|
||||
|
||||
if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) {
|
||||
remove_peer_from_torrent( hash, &peer );
|
||||
memmove( static_reply + SUCCESS_HTTP_HEADER_LENGTH, "d15:warning message4:Okaye", reply_size = 26 );
|
||||
} else {
|
||||
if( h ) array_reset(&h->r);
|
||||
free( h ); io_close( s );
|
||||
torrent = add_peer_to_torrent( hash, &peer );
|
||||
if( !torrent ) {
|
||||
e500:
|
||||
return httperror(s,h,"500 Internal Server Error","A server error has occured. Please retry later.");
|
||||
}
|
||||
if( ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
|
||||
goto e500;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if( byte_diff(data,11,"mrtg_scrape"))
|
||||
goto e404;
|
||||
{
|
||||
time_t seconds_elapsed = time( NULL ) - ot_start_time;
|
||||
reply_size = sprintf( static_reply + SUCCESS_HTTP_HEADER_LENGTH,
|
||||
"%d\n%d\nUp: %ld seconds (%ld hours)\nPretuned by german engineers, currently handling %li connections per second.",
|
||||
ot_overall_connections, ot_overall_connections, seconds_elapsed,
|
||||
seconds_elapsed / 3600, ot_overall_connections / ( seconds_elapsed ? seconds_elapsed : 1 ) );
|
||||
}
|
||||
break;
|
||||
default: /* neither *scrape nor announce */
|
||||
e404:
|
||||
return httperror(s,h,"404 Not Found","No such file or directory.");
|
||||
}
|
||||
|
||||
if( reply_size ) {
|
||||
/* This one is rather ugly, so I take you step by step through it.
|
||||
|
||||
1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to
|
||||
write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our static buffer, which is enough for the static string
|
||||
plus dynamic space needed to expand our Content-Length value. We reserve SUCCESS_HTTP_SIZE_OFF for it expansion and calculate
|
||||
the space NOT needed to expand in reply_off
|
||||
*/
|
||||
size_t reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_reply, 0, "%zd", reply_size );
|
||||
|
||||
/* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete
|
||||
packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */
|
||||
reply_size += 1 + sprintf( static_reply + reply_off, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", reply_size );
|
||||
|
||||
/* 3. Finally we join both blocks neatly */
|
||||
static_reply[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
|
||||
|
||||
senddata( s, h, static_reply + reply_off, reply_size );
|
||||
} else {
|
||||
if( h ) array_reset(&h->r);
|
||||
free( h ); io_close( s );
|
||||
}
|
||||
}
|
||||
|
||||
void graceful( int s ) {
|
||||
@ -346,10 +352,10 @@ void help( char *name ) {
|
||||
int main( int argc, char **argv ) {
|
||||
int s=socket_tcp4();
|
||||
tai6464 t, next_timeout_check;
|
||||
unsigned long ip;
|
||||
char *serverip = NULL;
|
||||
char *serverdir = ".";
|
||||
uint16 port = 6969;
|
||||
unsigned char ip[4];
|
||||
|
||||
while( 1 ) {
|
||||
switch( getopt(argc,argv,":i:p:d:ocbBh") ) {
|
||||
@ -412,16 +418,16 @@ allparsed:
|
||||
}
|
||||
|
||||
while( ( i = io_canread() ) != -1 ) {
|
||||
if( i == s ) { // ist es der serversocket?
|
||||
if( i == s ) {
|
||||
int n;
|
||||
while( ( n = socket_accept4( s, (void*)&ip, &port) ) != -1 ) {
|
||||
while( ( n = socket_accept4( s, (char*)ip, &port) ) != -1 ) {
|
||||
if( io_fd( n ) ) {
|
||||
struct http_data* h=(struct http_data*)malloc(sizeof(struct http_data));
|
||||
io_wantread(n);
|
||||
|
||||
if (h) {
|
||||
byte_zero(h,sizeof(struct http_data));
|
||||
h->ip=ip;
|
||||
memmove(h->ip,ip,sizeof(ip));
|
||||
taia_now(&t);
|
||||
taia_addsec(&t,&t,OT_CLIENT_TIMEOUT);
|
||||
io_timeout(n,t);
|
||||
@ -437,7 +443,7 @@ allparsed:
|
||||
else
|
||||
carp("socket_accept4");
|
||||
} else {
|
||||
char buf[8192];
|
||||
/* unsigned (sic!) */ char buf[8192];
|
||||
struct http_data* h=io_getcookie(i);
|
||||
|
||||
int l=io_tryread(i,buf,sizeof buf);
|
||||
|
@ -4,15 +4,15 @@
|
||||
#include "scan.h"
|
||||
#include "scan_urlencoded_query.h"
|
||||
|
||||
// Idea is to do a in place replacement or guarantee at least
|
||||
// strlen( string ) bytes in deststring
|
||||
// watch http://www.ietf.org/rfc/rfc2396.txt
|
||||
// unreserved = alphanum | mark
|
||||
// mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
|
||||
// we add '%' to the matrix to not stop at encoded chars.
|
||||
|
||||
/* Idea is to do a in place replacement or guarantee at least
|
||||
strlen( string ) bytes in deststring
|
||||
watch http://www.ietf.org/rfc/rfc2396.txt
|
||||
unreserved = alphanum | mark
|
||||
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
|
||||
we add '%' to the matrix to not stop at encoded chars.
|
||||
*/
|
||||
static const unsigned char reserved_matrix[] = { 0xA2, 0x63, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x47};
|
||||
inline int is_unreserved( unsigned char c ) {
|
||||
static int is_unreserved( unsigned char c ) {
|
||||
if( ( c <= 32 ) || ( c >= 127 ) ) return 0; return 1&(reserved_matrix[(c-32)>>3]>>(c&7));
|
||||
}
|
||||
|
||||
|
@ -8,23 +8,26 @@
|
||||
#define SCAN_SEARCHPATH_PARAM 1
|
||||
#define SCAN_SEARCHPATH_VALUE 2
|
||||
|
||||
// string pointer to source, pointer to after terminator on return
|
||||
// deststring pointer to destination
|
||||
// flags determines, what to parse
|
||||
// returns number of valid converted characters in deststring
|
||||
// or -1 for parse error
|
||||
/* string pointer to source, pointer to after terminator on return
|
||||
deststring pointer to destination
|
||||
flags determines, what to parse
|
||||
returns number of valid converted characters in deststring
|
||||
or -1 for parse error
|
||||
*/
|
||||
size_t scan_urlencoded_query(char **string, char *deststring, int flags);
|
||||
|
||||
// data pointer to len chars of string
|
||||
// len length of chars in data to parse
|
||||
// number number to receive result
|
||||
// returns number of bytes not parsed, mostly !=0 means fail
|
||||
/* data pointer to len chars of string
|
||||
len length of chars in data to parse
|
||||
number number to receive result
|
||||
returns number of bytes not parsed, mostly !=0 means fail
|
||||
*/
|
||||
size_t scan_fixed_int( char *data, size_t len, int *number );
|
||||
|
||||
// data pointer to len chars of string
|
||||
// len length of chars in data to parse
|
||||
// ip buffer to receive result
|
||||
// returns number of bytes not parsed, mostly !=0 means fail
|
||||
/* data pointer to len chars of string
|
||||
len length of chars in data to parse
|
||||
ip buffer to receive result
|
||||
returns number of bytes not parsed, mostly !=0 means fail
|
||||
*/
|
||||
size_t scan_fixed_ip( char *data, size_t len, unsigned char ip[4] );
|
||||
|
||||
#endif
|
||||
|
125
trackerlogic.c
125
trackerlogic.c
@ -22,8 +22,7 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
// GLOBAL VARIABLES
|
||||
//
|
||||
/* GLOBAL VARIABLES */
|
||||
static ot_vector all_torrents[256];
|
||||
|
||||
#ifdef WANT_CLOSED_TRACKER
|
||||
@ -36,36 +35,37 @@ int g_check_blacklist = 1;
|
||||
static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2;
|
||||
#endif
|
||||
|
||||
// This function gives us a binary search that returns a pointer, even if
|
||||
// no exact match is found. In that case it sets exactmatch 0 and gives
|
||||
// calling functions the chance to insert data
|
||||
//
|
||||
static void *binary_search( const void *key, const void *base, unsigned long member_count, const unsigned long member_size,
|
||||
int compare_size, int *exactmatch ) {
|
||||
/* This function gives us a binary search that returns a pointer, even if
|
||||
no exact match is found. In that case it sets exactmatch 0 and gives
|
||||
calling functions the chance to insert data
|
||||
*/
|
||||
static void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size,
|
||||
size_t compare_size, int *exactmatch ) {
|
||||
size_t mc = member_count;
|
||||
ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
|
||||
*exactmatch = 1;
|
||||
|
||||
while( member_count ) {
|
||||
while( mc ) {
|
||||
int cmp = memcmp( lookat, key, compare_size);
|
||||
if (cmp == 0) return (void *)lookat;
|
||||
if (cmp < 0) {
|
||||
base = (void*)(lookat + member_size);
|
||||
--member_count;
|
||||
--mc;
|
||||
}
|
||||
member_count >>= 1;
|
||||
lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
|
||||
mc >>= 1;
|
||||
lookat = ((ot_byte*)base) + member_size * (mc >> 1);
|
||||
}
|
||||
*exactmatch = 0;
|
||||
return (void*)lookat;
|
||||
}
|
||||
|
||||
// Converter function from memory to human readable hex strings
|
||||
// * definitely not thread safe!!!
|
||||
//
|
||||
/* Converter function from memory to human readable hex strings
|
||||
- definitely not thread safe!!!
|
||||
*/
|
||||
char ths[2+2*20]="-";char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;}
|
||||
|
||||
static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int compare_size, int *exactmatch ) {
|
||||
ot_byte *match = BINARY_FIND( key, vector->data, vector->size, member_size, compare_size, exactmatch );
|
||||
ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch );
|
||||
|
||||
if( *exactmatch ) return match;
|
||||
|
||||
@ -74,13 +74,13 @@ static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_
|
||||
ot_byte *new_data = realloc( vector->data, new_space * member_size );
|
||||
if( !new_data ) return NULL;
|
||||
|
||||
// Adjust pointer if it moved by realloc
|
||||
/* Adjust pointer if it moved by realloc */
|
||||
match = new_data + (match - (ot_byte*)vector->data);
|
||||
|
||||
vector->data = new_data;
|
||||
vector->space = new_space;
|
||||
}
|
||||
MEMMOVE( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match );
|
||||
memmove( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match );
|
||||
vector->size++;
|
||||
return match;
|
||||
}
|
||||
@ -91,11 +91,11 @@ static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
|
||||
ot_peer *match;
|
||||
|
||||
if( !vector->size ) return 0;
|
||||
match = BINARY_FIND( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
|
||||
match = binary_search( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
|
||||
|
||||
if( !exactmatch ) return 0;
|
||||
exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1;
|
||||
MEMMOVE( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) );
|
||||
memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) );
|
||||
if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
|
||||
vector->space /= OT_VECTOR_SHRINK_RATIO;
|
||||
vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) );
|
||||
@ -117,15 +117,15 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
|
||||
ot_torrent *match;
|
||||
|
||||
if( !vector->size ) return 0;
|
||||
match = BINARY_FIND( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
match = binary_search( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
|
||||
if( !exactmatch ) return 0;
|
||||
|
||||
// If this is being called after a unsuccessful malloc() for peer_list
|
||||
// in add_peer_to_torrent, match->peer_list actually might be NULL
|
||||
/* If this is being called after a unsuccessful malloc() for peer_list
|
||||
in add_peer_to_torrent, match->peer_list actually might be NULL */
|
||||
if( match->peer_list) free_peerlist( match->peer_list );
|
||||
|
||||
MEMMOVE( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) );
|
||||
memmove( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) );
|
||||
if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
|
||||
vector->space /= OT_VECTOR_SHRINK_RATIO;
|
||||
vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) );
|
||||
@ -133,22 +133,21 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns 1, if torrent is gone, 0 otherwise
|
||||
/* Returns 1, if torrent is gone, 0 otherwise */
|
||||
static int clean_peerlist( ot_peerlist *peer_list ) {
|
||||
long timedout = NOW-peer_list->base;
|
||||
int i;
|
||||
int i, timedout = (int)( NOW - peer_list->base );
|
||||
|
||||
if( !timedout ) return 0;
|
||||
if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT;
|
||||
|
||||
for( i=OT_POOLS_COUNT-timedout; i<OT_POOLS_COUNT; ++i )
|
||||
for( i = OT_POOLS_COUNT - timedout; i < OT_POOLS_COUNT; ++i )
|
||||
free( peer_list->peers[i].data);
|
||||
|
||||
MEMMOVE( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * (OT_POOLS_COUNT-timedout) );
|
||||
memmove( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * (OT_POOLS_COUNT-timedout) );
|
||||
byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout );
|
||||
|
||||
MEMMOVE( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( unsigned long ) * (OT_POOLS_COUNT-timedout) );
|
||||
byte_zero( peer_list->seed_count, sizeof( unsigned long ) * timedout );
|
||||
memmove( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout) );
|
||||
byte_zero( peer_list->seed_count, sizeof( size_t ) * timedout );
|
||||
|
||||
peer_list->base = NOW;
|
||||
return timedout == OT_POOLS_COUNT;
|
||||
@ -178,8 +177,8 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||
if( !torrent ) return NULL;
|
||||
|
||||
if( !exactmatch ) {
|
||||
// Create a new torrent entry, then
|
||||
MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) );
|
||||
/* Create a new torrent entry, then */
|
||||
memmove( &torrent->hash, hash, sizeof( ot_hash ) );
|
||||
|
||||
torrent->peer_list = malloc( sizeof (ot_peerlist) );
|
||||
if( !torrent->peer_list ) {
|
||||
@ -195,11 +194,11 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||
peer_pool = &torrent->peer_list->peers[0];
|
||||
peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
|
||||
|
||||
// If we hadn't had a match in current pool, create peer there and
|
||||
// remove it from all older pools
|
||||
/* If we hadn't had a match in current pool, create peer there and
|
||||
remove it from all older pools */
|
||||
if( !exactmatch ) {
|
||||
int i;
|
||||
MEMMOVE( peer_dest, peer, sizeof( ot_peer ) );
|
||||
memmove( peer_dest, peer, sizeof( ot_peer ) );
|
||||
if( OT_FLAG(peer) & PEER_FLAG_SEEDING )
|
||||
torrent->peer_list->seed_count[0]++;
|
||||
for( i=1; i<OT_POOLS_COUNT; ++i ) {
|
||||
@ -221,27 +220,30 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||
return torrent;
|
||||
}
|
||||
|
||||
// Compiles a list of random peers for a torrent
|
||||
// * reply must have enough space to hold 24+6*amount bytes
|
||||
// * Selector function can be anything, maybe test for seeds, etc.
|
||||
// * RANDOM may return huge values
|
||||
// * does not yet check not to return self
|
||||
//
|
||||
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char *reply ) {
|
||||
char *r = reply;
|
||||
unsigned long peer_count, seed_count, index;
|
||||
signed long pool_offset = -1, pool_index = 0;
|
||||
signed long wert = -1;
|
||||
/* Compiles a list of random peers for a torrent
|
||||
* reply must have enough space to hold 24+6*amount bytes
|
||||
* Selector function can be anything, maybe test for seeds, etc.
|
||||
* RANDOM may return huge values
|
||||
* does not yet check not to return self
|
||||
*/
|
||||
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply ) {
|
||||
char *r = reply;
|
||||
unsigned int peer_count, seed_count, index;
|
||||
int pool_offset = -1, pool_index = 0, wert = -1;
|
||||
|
||||
#ifdef WANT_CLOSED_TRACKER
|
||||
if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) {
|
||||
return( FORMAT_FORMAT_STRING( reply, "d14:failure reason43:This torrent is not served by this tracker.e" ) );
|
||||
const char * const notvalid = "d14:failure reason43:This torrent is not served by this tracker.e";
|
||||
memmove( reply, notvalid, sizeof(notvalid));
|
||||
return sizeof(notvalid);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WANT_BLACKLIST
|
||||
if( torrent == OT_TORRENT_ON_BLACKLIST ) {
|
||||
return( FORMAT_FORMAT_STRING( reply, "d14:failure reason29:This torrent is black listed.e" ) );
|
||||
const char * const blacklisted = "d14:failure reason29:This torrent is black listed.e";
|
||||
memmove( reply, blacklisted, sizeof(blacklisted));
|
||||
return sizeof(blacklisted);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -251,23 +253,19 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char
|
||||
}
|
||||
if( peer_count < amount ) amount = peer_count;
|
||||
|
||||
r += FORMAT_FORMAT_STRING( r, "d8:completei%lie10:incompletei%lie8:intervali600e5:peers%li:", seed_count, peer_count-seed_count, 6*amount );
|
||||
r += sprintf( r, "d8:completei%ie10:incompletei%ie8:intervali600e5:peers%i:", seed_count, peer_count-seed_count, 6*amount );
|
||||
for( index = 0; index < amount; ++index ) {
|
||||
double step = 1.8*((double)( peer_count - wert - 1 ))/((double)( amount - index ));
|
||||
int off = random() % (int)floor( step );
|
||||
off = 1 + ( off % ( peer_count - wert - 1 ));
|
||||
wert += off; pool_offset += off;
|
||||
|
||||
// In some rare occasions random gets the last peer a round to early
|
||||
// correct that and return last peer twice
|
||||
// if( wert >= peer_count ) { wert--; pool_offset--; }
|
||||
|
||||
while( pool_offset >= torrent->peer_list->peers[pool_index].size ) {
|
||||
pool_offset -= torrent->peer_list->peers[pool_index].size;
|
||||
pool_index++;
|
||||
}
|
||||
|
||||
MEMMOVE( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 );
|
||||
memmove( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 );
|
||||
r += 6;
|
||||
}
|
||||
*r++ = 'e';
|
||||
@ -275,12 +273,12 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char
|
||||
return r - reply;
|
||||
}
|
||||
|
||||
// Fetches scrape info for a specific torrent
|
||||
/* Fetches scrape info for a specific torrent */
|
||||
size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
|
||||
char *r = reply;
|
||||
int exactmatch, peers = 0, seeds = 0, i;
|
||||
ot_vector *torrents_list = &all_torrents[*hash[0]];
|
||||
ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
|
||||
if( !exactmatch ) return 0;
|
||||
clean_peerlist( torrent->peer_list );
|
||||
@ -290,8 +288,8 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
|
||||
seeds += torrent->peer_list->seed_count[i];
|
||||
}
|
||||
|
||||
MEMMOVE( r, "d5:filesd20:", 12 ); MEMMOVE( r+12, hash, 20 );
|
||||
r += FORMAT_FORMAT_STRING( r+32, "d8:completei%de10:downloadedi%lde10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
|
||||
memmove( r, "d5:filesd20:", 12 ); memmove( r+12, hash, 20 );
|
||||
r += sprintf( r+32, "d8:completei%de10:downloadedi%de10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
|
||||
|
||||
return r - reply;
|
||||
}
|
||||
@ -299,11 +297,11 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
|
||||
void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||
int exactmatch, i;
|
||||
ot_vector *torrents_list = &all_torrents[*hash[0]];
|
||||
ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
|
||||
if( !exactmatch ) return;
|
||||
|
||||
// Maybe this does the job
|
||||
/* Maybe this does the job */
|
||||
if( clean_peerlist( torrent->peer_list ) ) {
|
||||
#ifdef WANT_CLOSED_TRACKER
|
||||
if( !g_closedtracker )
|
||||
@ -332,7 +330,7 @@ int init_logic( char *serverdir ) {
|
||||
|
||||
srandom( time(NULL));
|
||||
|
||||
// Initialize control structures
|
||||
/* Initialize control structures */
|
||||
byte_zero( all_torrents, sizeof (all_torrents));
|
||||
|
||||
return 0;
|
||||
@ -340,7 +338,8 @@ int init_logic( char *serverdir ) {
|
||||
|
||||
void deinit_logic( ) {
|
||||
int i, j;
|
||||
// Free all torrents...
|
||||
|
||||
/* Free all torrents... */
|
||||
for(i=0; i<256; ++i ) {
|
||||
if( all_torrents[i].size ) {
|
||||
ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data;
|
||||
|
@ -18,18 +18,12 @@ typedef ot_byte ot_hash[20];
|
||||
typedef ot_dword ot_ip;
|
||||
typedef time_t ot_time;
|
||||
|
||||
#define MEMMOVE memmove
|
||||
#define BZERO bzero
|
||||
#define FORMAT_FIXED_STRING sprintf
|
||||
#define FORMAT_FORMAT_STRING sprintf
|
||||
#define BINARY_FIND binary_search
|
||||
/* We maintain a list of 256 pointers to sorted list of ot_torrent structs
|
||||
Sort key is, of course, its hash */
|
||||
|
||||
// We maintain a list of 256 pointers to sorted list of ot_torrent structs
|
||||
// Sort key is, of course, its hash
|
||||
|
||||
// This list points to 9 pools of peers each grouped in five-minute-intervals
|
||||
// thus achieving a timeout of 2700s or 45 minutes
|
||||
// These pools are sorted by its binary content
|
||||
/* This list points to 9 pools of peers each grouped in five-minute-intervals
|
||||
thus achieving a timeout of 2700s or 45 minutes
|
||||
These pools are sorted by its binary content */
|
||||
|
||||
#define OT_POOLS_COUNT 9
|
||||
#define OT_POOLS_TIMEOUT 300
|
||||
@ -52,8 +46,8 @@ static const ot_byte PEER_FLAG_SEEDING = 0x80;
|
||||
static const ot_byte PEER_FLAG_COMPLETED = 0x40;
|
||||
static const ot_byte PEER_FLAG_STOPPED = 0x20;
|
||||
|
||||
#define OT_SETIP( peer, ip ) MEMMOVE((peer),(ip),4);
|
||||
#define OT_SETPORT( peer, port ) MEMMOVE(((ot_byte*)peer)+4,(port),2);
|
||||
#define OT_SETIP( peer, ip ) memmove((peer),(ip),4);
|
||||
#define OT_SETPORT( peer, port ) memmove(((ot_byte*)peer)+4,(port),2);
|
||||
#define OT_FLAG(peer) (((ot_byte*)(peer))[6])
|
||||
|
||||
#define OT_PEER_COMPARE_SIZE ((size_t)6)
|
||||
@ -61,8 +55,8 @@ static const ot_byte PEER_FLAG_STOPPED = 0x20;
|
||||
|
||||
typedef struct {
|
||||
ot_time base;
|
||||
unsigned long seed_count[ OT_POOLS_COUNT ];
|
||||
unsigned long downloaded;
|
||||
size_t seed_count[ OT_POOLS_COUNT ];
|
||||
unsigned int downloaded;
|
||||
ot_vector peers[ OT_POOLS_COUNT ];
|
||||
} ot_peerlist;
|
||||
|
||||
@ -71,9 +65,9 @@ typedef struct {
|
||||
ot_peerlist *peer_list;
|
||||
} ot_torrent;
|
||||
|
||||
//
|
||||
// Exported functions
|
||||
//
|
||||
/*
|
||||
Exported functions
|
||||
*/
|
||||
|
||||
int init_logic( char *serverdir );
|
||||
void deinit_logic( );
|
||||
@ -86,7 +80,7 @@ extern int g_check_blacklist;
|
||||
#endif
|
||||
|
||||
ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer );
|
||||
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char *reply );
|
||||
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply );
|
||||
size_t return_scrape_for_torrent( ot_hash *hash, char *reply );
|
||||
void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer );
|
||||
void cleanup_torrents( void );
|
||||
|
Loading…
x
Reference in New Issue
Block a user