From e534db03c6877f8ac0559f63840e9a00e9bd43bf Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Sat, 4 Oct 2008 05:40:51 +0000 Subject: added live sync code added a config file parser added tracker id changed WANT_CLOSED_TRACKER and WANT_BLACKLIST into WANT_ACCESS_WHITE and WANT_ACCESS_BLACK changed WANT_TRACKER_SYNC to WANT_SYNC_BATCH and added WANT_SYNC_LIVE added an option to switch off fullscrapes cleaned up many internal hardcoded values, like PROTO_FLAG, --- opentracker.c | 179 ++++++++++++++++++++++++++-------- opentracker.xcodeproj/project.pbxproj | 6 ++ ot_accesslist.c | 18 ++-- ot_accesslist.h | 16 +-- ot_clean.c | 4 +- ot_fullscrape.c | 3 + ot_fullscrape.h | 9 ++ ot_http.c | 35 +++---- ot_stats.c | 20 ++-- ot_stats.h | 2 +- ot_sync.c | 4 +- ot_sync.h | 7 +- ot_udp.c | 14 +-- scan_urlencoded_query.c | 4 +- tests/testsuite2.sh | 14 +++ trackerlogic.c | 70 ++++++++----- trackerlogic.h | 25 +++-- 17 files changed, 304 insertions(+), 126 deletions(-) create mode 100644 tests/testsuite2.sh diff --git a/opentracker.c b/opentracker.c index fda914a..b7431d4 100644 --- a/opentracker.c +++ b/opentracker.c @@ -8,12 +8,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include /* Libowfat */ @@ -21,6 +23,7 @@ #include "io.h" #include "iob.h" #include "array.h" +#include "byte.h" #include "fmt.h" #include "scan.h" #include "ip4.h" @@ -34,17 +37,18 @@ #include "ot_clean.h" #include "ot_accesslist.h" #include "ot_stats.h" +#include "ot_livesync.h" /* Globals */ -time_t g_now; -char * g_redirecturl = NULL; +time_t g_now; +char * g_redirecturl = NULL; +uint32_t g_tracker_id; + +static char * g_serverdir = NULL; /* To always have space for error messages ;) */ static char static_inbuf[8192]; -static char *FLAG_TCP = "T"; -static char *FLAG_UDP = "U"; - static void panic( const char *routine ) { fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); exit( 111 ); @@ -63,10 +67,10 @@ static void signal_handler( int s ) { } static void usage( char *name ) { - fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip]" -#ifdef WANT_BLACKLISTING + fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip] [-f config] [-s livesyncport]" +#ifdef WANT_ACCESSLIST_BLACK " [-b blacklistfile]" -#elif defined ( WANT_CLOSED_TRACKER ) +#elif defined ( WANT_ACCESSLIST_WHITE ) " [-w whitelistfile]" #endif "\n", name ); @@ -82,9 +86,9 @@ static void help( char *name ) { HELPLINE("-r redirecturl","specify url where / should be redirected to (default none)"); HELPLINE("-d dir","specify directory to try to chroot to (default: \".\")"); HELPLINE("-A ip","bless an ip address as admin address (e.g. to allow syncs from this address)"); -#ifdef WANT_BLACKLISTING +#ifdef WANT_ACCESSLIST_BLACK HELPLINE("-b file","specify blacklist file."); -#elif defined( WANT_CLOSED_TRACKER ) +#elif defined( WANT_ACCESSLIST_WHITE ) HELPLINE("-w file","specify whitelist file."); #endif @@ -168,7 +172,7 @@ static void handle_accept( const int64 serversocket ) { memset( h, 0, sizeof( struct http_data ) ); memmove( h->ip, ip, sizeof( ip ) ); - stats_issue_event( EVENT_ACCEPT, 1, ntohl(*(uint32_t*)ip)); + stats_issue_event( EVENT_ACCEPT, FLAG_TCP, ntohl(*(uint32_t*)ip)); /* That breaks taia encapsulation. But there is no way to take system time this often in FreeBSD and libowfat does not allow to set unix time */ @@ -194,10 +198,12 @@ static void server_mainloop( ) { while( ( i = io_canread( ) ) != -1 ) { const void *cookie = io_getcookie( i ); - if( cookie == FLAG_TCP ) + if( (int)cookie == FLAG_TCP ) handle_accept( i ); - else if( cookie == FLAG_UDP ) + else if( (int)cookie == FLAG_UDP ) handle_udp4( i ); + else if( (int)cookie == FLAG_MCA ) + handle_livesync(i); else handle_read( i ); } @@ -214,6 +220,8 @@ static void server_mainloop( ) { next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; } + livesync_ticker(); + /* See if we need to move our pools */ if( NOW != ot_last_clean_time ) { ot_last_clean_time = NOW; @@ -225,55 +233,148 @@ static void server_mainloop( ) { } } -static void ot_try_bind( char ip[4], uint16 port, int is_tcp ) { - int64 s = is_tcp ? socket_tcp4( ) : socket_udp4(); - +int64_t ot_try_bind( char ip[4], uint16_t port, PROTO_FLAG proto ) { + int64 s = proto == FLAG_TCP ? socket_tcp4( ) : socket_udp4(); + if( socket_bind4_reuse( s, ip, port ) == -1 ) panic( "socket_bind4_reuse" ); - if( is_tcp && ( socket_listen( s, SOMAXCONN) == -1 ) ) + if( ( proto == FLAG_TCP ) && ( socket_listen( s, SOMAXCONN) == -1 ) ) panic( "socket_listen" ); if( !io_fd( s ) ) panic( "io_fd" ); - io_setcookie( s, is_tcp ? FLAG_TCP : FLAG_UDP ); + io_setcookie( s, (void*)proto ); io_wantread( s ); + + return s; +} + +char * set_config_option( char **option, char *value ) { + while( isspace(*value) ) ++value; + if( *option ) free( *option ); + return *option = strdup( value ); +} + +/* WARNING! Does not behave like scan_ip4 regarding return values */ +static int scan_ip4_port( const char *src, char *ip, uint16 *port ) { + int off; + while( isspace(*src) ) ++src; + if( !(off = scan_ip4( src, ip ) ) ) + return -1; + src += off; + if( *src == 0 ) return 0; + if( *src != ':' ) + return -1; + *port = atol(src+1); + return 0; +} + +int parse_configfile( char * config_filename ) { + FILE * accesslist_filehandle; + char inbuf[512], tmpip[4]; + int bound = 0; + + accesslist_filehandle = fopen( config_filename, "r" ); + + if( accesslist_filehandle == NULL ) { + fprintf( stderr, "Warning: Can't open config file: %s.", config_filename ); + return 0; + } + + while( fgets( inbuf, sizeof(inbuf), accesslist_filehandle ) ) { + char *newl; + char *p = inbuf; + + /* Skip white spaces */ + while(isspace(*p)) ++p; + + /* Ignore comments and empty lines */ + if((*p=='#')||(*p=='\n')||(*p==0)) continue; + + /* chomp */ + if(( newl = strchr(p, '\n' ))) *newl = 0; + + /* Scan for commands */ + if(!byte_diff(p,15,"tracker.rootdir" ) && isspace(p[15])) { + set_config_option( &g_serverdir, p+16 ); + } else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) { + uint16_t tmpport = 6969; + if( scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error; + ot_try_bind( tmpip, tmpport, FLAG_TCP ); + ++bound; + } else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) { + uint16_t tmpport = 6969; + if( scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error; + ot_try_bind( tmpip, tmpport, FLAG_UDP ); + ++bound; +#ifdef WANT_ACCESSLIST_BLACK + } else if(!byte_diff(p, 16, "access.whitelist" ) && isspace(p[16])) { + set_config_option( &g_accesslist_filename, p+17 ); +#elif defined( WANT_ACCESSLIST_WHITE ) + } else if(!byte_diff(p, 16, "access.blacklist" ) && isspace(p[16])) { + set_config_option( &g_accesslist_filename, p+17 ); +#endif + } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) { + set_config_option( &g_redirecturl, p+21 ); +#ifdef WANT_SYNC_BATCH + } else if(!byte_diff(p, 26, "batchsync.cluster.admin_ip" ) && isspace(p[26])) { + if(!scan_ip4( p+27, tmpip )) goto parse_error; + accesslist_blessip( tmpip, OT_PERMISSION_MAY_SYNC ); +#endif +#ifdef WANT_SYNC_LIVE + } else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) { + if( !scan_ip4( p+25, tmpip )) goto parse_error; + accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC ); + } else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) { + uint16_t tmpport = LIVESYNC_PORT; + if( scan_ip4_port( p+24, tmpip, &tmpport )) goto parse_error; + livesync_bind_mcast( tmpip, tmpport ); +#endif + } else + fprintf( stderr, "Unhandled line in config file: %s\n", inbuf ); + continue; + parse_error: + fprintf( stderr, "Parse error in config file: %s\n", inbuf); + } + fclose( accesslist_filehandle ); + return bound; } int main( int argc, char **argv ) { struct passwd *pws = NULL; char serverip[4] = {0,0,0,0}, tmpip[4]; - char *serverdir = "."; int bound = 0, scanon = 1; -#ifdef WANT_ACCESS_CONTROL - char *accesslist_filename = NULL; -#endif - - while( scanon ) { - switch( getopt( argc, argv, ":i:p:A:P:d:r:v" -#ifdef WANT_BLACKLISTING + +while( scanon ) { + switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v" +#ifdef WANT_ACCESSLIST_BLACK "b:" -#elif defined( WANT_CLOSED_TRACKER ) +#elif defined( WANT_ACCESSLIST_WHITE ) "w:" #endif "h" ) ) { case -1 : scanon = 0; break; case 'i': scan_ip4( optarg, serverip ); break; -#ifdef WANT_BLACKLISTING - case 'b': accesslist_filename = optarg; break; -#elif defined( WANT_CLOSED_TRACKER ) - case 'w': accesslist_filename = optarg; break; +#ifdef WANT_ACCESSLIST_BLACK + case 'b': set_config_option( &g_accesslist_filename, optarg); break; +#elif defined( WANT_ACCESSLIST_WHITE ) + case 'w': set_config_option( &g_accesslist_filename, optarg); break; #endif - case 'p': ot_try_bind( serverip, (uint16)atol( optarg ), 1 ); bound++; break; - case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); bound++; break; - case 'd': serverdir = optarg; break; - case 'r': g_redirecturl = optarg; break; + case 'p': ot_try_bind( serverip, (uint16)atol( optarg ), FLAG_TCP ); bound++; break; + case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), FLAG_UDP ); bound++; break; +#ifdef WANT_SYNC_LIVE + case 's': livesync_bind_mcast( serverip, (uint16)atol( optarg )); break; +#endif + case 'd': set_config_option( &g_serverdir, optarg ); break; + case 'r': set_config_option( &g_redirecturl, optarg ); break; case 'A': scan_ip4( optarg, tmpip ); accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */ break; + case 'f': bound += parse_configfile( optarg ); break; case 'h': help( argv[0] ); exit( 0 ); case 'v': write( 2, static_inbuf, stats_return_tracker_version( static_inbuf )); exit( 0 ); default: @@ -283,8 +384,8 @@ int main( int argc, char **argv ) { /* Bind to our default tcp/udp ports */ if( !bound) { - ot_try_bind( serverip, 6969, 1 ); - ot_try_bind( serverip, 6969, 0 ); + ot_try_bind( serverip, 6969, FLAG_TCP ); + ot_try_bind( serverip, 6969, FLAG_UDP ); } /* Drop permissions */ @@ -298,15 +399,13 @@ int main( int argc, char **argv ) { } endpwent(); - accesslist_init( accesslist_filename ); - signal( SIGPIPE, SIG_IGN ); signal( SIGINT, signal_handler ); signal( SIGALRM, signal_handler ); g_now = time( NULL ); - if( trackerlogic_init( serverdir ) == -1 ) + if( trackerlogic_init( g_serverdir ? g_serverdir : "." ) == -1 ) panic( "Logic not started" ); alarm(5); diff --git a/opentracker.xcodeproj/project.pbxproj b/opentracker.xcodeproj/project.pbxproj index 7068fa5..895f63f 100644 --- a/opentracker.xcodeproj/project.pbxproj +++ b/opentracker.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 65542EE80CE0CA6B00469330 /* ot_udp.c in Sources */ = {isa = PBXBuildFile; fileRef = 65542EE70CE0CA6B00469330 /* ot_udp.c */; }; 65542F920CE17CA900469330 /* ot_fullscrape.c in Sources */ = {isa = PBXBuildFile; fileRef = 65542F910CE17CA900469330 /* ot_fullscrape.c */; }; 65B8DF3C0D0310D20017149E /* ot_http.c in Sources */ = {isa = PBXBuildFile; fileRef = 65B8DF3B0D0310D20017149E /* ot_http.c */; }; + 65FA33990E7EF09200F7D5A5 /* ot_livesync.c in Sources */ = {isa = PBXBuildFile; fileRef = 65FA33980E7EF09200F7D5A5 /* ot_livesync.c */; }; 8DD76FB00486AB0100D96B5E /* opentracker.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* opentracker.1 */; }; /* End PBXBuildFile section */ @@ -66,6 +67,8 @@ 65542F910CE17CA900469330 /* ot_fullscrape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ot_fullscrape.c; sourceTree = ""; }; 65B8DF3A0D0310D20017149E /* ot_http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ot_http.h; sourceTree = ""; }; 65B8DF3B0D0310D20017149E /* ot_http.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ot_http.c; sourceTree = ""; }; + 65FA33970E7EF09200F7D5A5 /* ot_livesync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ot_livesync.h; sourceTree = ""; }; + 65FA33980E7EF09200F7D5A5 /* ot_livesync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ot_livesync.c; sourceTree = ""; }; C6A0FF2C0290799A04C91782 /* opentracker.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = opentracker.1; sourceTree = ""; }; /* End PBXFileReference section */ @@ -107,6 +110,7 @@ 65542E740CE08B9100469330 /* ot_clean.c */, 65542F910CE17CA900469330 /* ot_fullscrape.c */, 65B8DF3B0D0310D20017149E /* ot_http.c */, + 65FA33980E7EF09200F7D5A5 /* ot_livesync.c */, 653A56B40CE28EC5000CF140 /* ot_iovec.c */, 65542D8F0CE07CED00469330 /* ot_mutex.c */, 65542D910CE07CED00469330 /* ot_stats.c */, @@ -132,6 +136,7 @@ 65542D810CE0786F00469330 /* Headers */ = { isa = PBXGroup; children = ( + 65FA33970E7EF09200F7D5A5 /* ot_livesync.h */, 653A320A0CE7F475007F0D03 /* ot_accesslist.h */, 65542E730CE08B9100469330 /* ot_clean.h */, 65542F900CE17CA900469330 /* ot_fullscrape.h */, @@ -248,6 +253,7 @@ 653A56B50CE28EC5000CF140 /* ot_iovec.c in Sources */, 653A320C0CE7F475007F0D03 /* ot_accesslist.c in Sources */, 65B8DF3C0D0310D20017149E /* ot_http.c in Sources */, + 65FA33990E7EF09200F7D5A5 /* ot_livesync.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ot_accesslist.c b/ot_accesslist.c index df3d64c..cebb064 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c @@ -18,8 +18,8 @@ #include "ot_accesslist.h" /* GLOBAL VARIABLES */ -#ifdef WANT_ACCESS_CONTROL -static char *accesslist_filename = NULL; +#ifdef WANT_ACCESSLIST +char *g_accesslist_filename = NULL; static ot_vector accesslist; static void accesslist_reset( void ) { @@ -46,13 +46,13 @@ static void accesslist_readfile( int foo ) { char inbuf[512]; foo = foo; - accesslist_filehandle = fopen( accesslist_filename, "r" ); + accesslist_filehandle = fopen( g_accesslist_filename, "r" ); /* Free accesslist vector in trackerlogic.c*/ accesslist_reset(); if( accesslist_filehandle == NULL ) { - fprintf( stderr, "Warning: Can't open accesslist file: %s (but will try to create it later, if necessary and possible).", accesslist_filename ); + fprintf( stderr, "Warning: Can't open accesslist file: %s (but will try to create it later, if necessary and possible).", g_accesslist_filename ); return; } @@ -79,21 +79,20 @@ int accesslist_hashisvalid( ot_hash *hash ) { int exactmatch; binary_search( hash, accesslist.data, accesslist.size, OT_HASH_COMPARE_SIZE, OT_HASH_COMPARE_SIZE, &exactmatch ); -#ifdef WANT_BLACKLISTING +#ifdef WANT_ACCESSLIST_BLACK exactmatch = !exactmatch; #endif return exactmatch; } -void accesslist_init( char *accesslist_filename_in ) { +void accesslist_init( ) { byte_zero( &accesslist, sizeof( accesslist ) ); /* Passing "0" since read_blacklist_file also is SIGHUP handler */ - if( accesslist_filename_in ) { - accesslist_filename = accesslist_filename_in; + if( g_accesslist_filename ) { accesslist_readfile( 0 ); - signal( SIGHUP, accesslist_readfile ); + signal( SIGHUP, accesslist_readfile ); } } @@ -108,6 +107,7 @@ int accesslist_blessip( char *ip, ot_permissions permissions ) { return -1; memmove( g_adminip_addresses + g_adminip_count, ip, 4 ); g_adminip_permissions[ g_adminip_count++ ] = permissions; +// fprintf( stderr, "Blessing ip address %d.%d.%d.%d with %02x\n", (uint8_t)ip[0], (uint8_t)ip[1], (uint8_t)ip[2], (uint8_t)ip[3], permissions ); return 0; } diff --git a/ot_accesslist.h b/ot_accesslist.h index 6adefd9..2783b3c 100644 --- a/ot_accesslist.h +++ b/ot_accesslist.h @@ -6,14 +6,17 @@ #ifndef __OT_ACCESSLIST_H__ #define __OT_ACCESSLIST_H__ -#if defined ( WANT_BLACKLISTING ) && defined (WANT_CLOSED_TRACKER ) - #error WANT_BLACKLISTING and WANT_CLOSED_TRACKER are exclusive. +#if defined ( WANT_ACCESSLIST_BLACK ) && defined (WANT_ACCESSLIST_WHITE ) + #error WANT_ACCESSLIST_BLACK and WANT_ACCESSLIST_WHITE are exclusive. #endif -#if defined ( WANT_BLACKLISTING ) || defined (WANT_CLOSED_TRACKER ) -#define WANT_ACCESS_CONTROL -void accesslist_init( char *accesslist_filename ); +#if defined ( WANT_ACCESSLIST_BLACK ) || defined (WANT_ACCESSLIST_WHITE ) +#define WANT_ACCESSLIST +void accesslist_init( ); int accesslist_hashisvalid( ot_hash *hash ); + +extern char *g_accesslist_filename; + #else #define accesslist_init( accesslist_filename ) #define accesslist_hashisvalid( hash ) 1 @@ -22,7 +25,8 @@ int accesslist_hashisvalid( ot_hash *hash ); typedef enum { OT_PERMISSION_MAY_FULLSCRAPE, OT_PERMISSION_MAY_SYNC, - OT_PERMISSION_MAY_STAT + OT_PERMISSION_MAY_STAT, + OT_PERMISSION_MAY_LIVESYNC } ot_permissions; int accesslist_blessip( char * ip, ot_permissions permissions ); diff --git a/ot_clean.c b/ot_clean.c index a45a3dc..f8bb637 100644 --- a/ot_clean.c +++ b/ot_clean.c @@ -25,7 +25,7 @@ int clean_single_torrent( ot_torrent *torrent ) { size_t peers_count = 0, seeds_count; time_t timedout = (int)( NOW - peer_list->base ); int i; -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH char *new_peers; #endif @@ -55,7 +55,7 @@ int clean_single_torrent( ot_torrent *torrent ) { memmove( peer_list->seed_counts + timedout, peer_list->seed_counts, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout ) ); byte_zero( peer_list->seed_counts, sizeof( size_t ) * timedout ); -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH /* Save the block modified within last OT_POOLS_TIMEOUT */ if( peer_list->peers[1].size && ( new_peers = realloc( peer_list->changeset.data, sizeof( ot_peer ) * peer_list->peers[1].size ) ) ) diff --git a/ot_fullscrape.c b/ot_fullscrape.c index 0aa7fb9..8175722 100644 --- a/ot_fullscrape.c +++ b/ot_fullscrape.c @@ -3,6 +3,8 @@ $id$ */ +#ifdef WANT_FULLSCRAPE + /* System */ #include #include @@ -226,5 +228,6 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas /* Release unused memory in current output buffer */ iovec_fixlast( iovec_entries, iovector, r ); } +#endif const char *g_version_fullscrape_c = "$Source$: $Revision$\n"; diff --git a/ot_fullscrape.h b/ot_fullscrape.h index ccd39f4..4025be1 100644 --- a/ot_fullscrape.h +++ b/ot_fullscrape.h @@ -6,8 +6,17 @@ #ifndef __OT_FULLSCRAPE_H__ #define __OT_FULLSCRAPE_H__ +#ifdef WANT_FULLSCRAPE + void fullscrape_init( ); void fullscrape_deinit( ); void fullscrape_deliver( int64 socket, ot_tasktype tasktype ); +#else + +#define fullscrape_init() +#define fullscrape_deinit() + +#endif + #endif diff --git a/ot_http.c b/ot_http.c index 682195b..462b8dd 100644 --- a/ot_http.c +++ b/ot_http.c @@ -28,10 +28,6 @@ #include "ot_accesslist.h" #include "ot_sync.h" -#ifndef WANT_TRACKER_SYNC -#define add_peer_to_torrent(A,B,C) add_peer_to_torrent(A,B) -#endif - #define OT_MAXMULTISCRAPE_COUNT 64 static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT]; extern char *g_redirecturl; @@ -103,7 +99,7 @@ ssize_t http_issue_error( const int64 client_socket, int code ) { #ifdef _DEBUG_HTTPERROR fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request ); #endif - stats_issue_event( EVENT_FAILED, 1, code ); + stats_issue_event( EVENT_FAILED, FLAG_TCP, code ); http_senddata( client_socket, static_outbuf, reply_size); return -2; } @@ -169,7 +165,7 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct return 0; } -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH static ssize_t http_handle_sync( const int64 client_socket, char *data ) { struct http_data* h = io_getcookie( client_socket ); size_t len; @@ -193,7 +189,7 @@ static ssize_t http_handle_sync( const int64 client_socket, char *data ) { if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) < 10 ) HTTPERROR_400_PARAM; if( add_changeset_to_tracker( (uint8_t*)data, len ) ) HTTPERROR_400_PARAM; if( mode == SYNC_OUT ) { - stats_issue_event( EVENT_SYNC_IN, 1, 0 ); + stats_issue_event( EVENT_SYNC_IN, FLAG_TCP, 0 ); mode = SYNC_IN; } break; @@ -203,7 +199,7 @@ static ssize_t http_handle_sync( const int64 client_socket, char *data ) { if( mode == SYNC_OUT ) { /* Pass this task to the worker thread */ h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; - stats_issue_event( EVENT_SYNC_OUT_REQUEST, 1, 0 ); + stats_issue_event( EVENT_SYNC_OUT_REQUEST, FLAG_TCP, 0 ); sync_deliver( client_socket ); io_dontwantread( client_socket ); return -2; @@ -216,7 +212,6 @@ static ssize_t http_handle_sync( const int64 client_socket, char *data ) { #endif static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d, size_t l ) { - struct http_data* h = io_getcookie( client_socket ); char *c = data; int mode = TASK_STATS_PEERS, scanon = 1, format = 0; @@ -284,7 +279,11 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d } } + /* Touch variable */ + d=d; +#ifdef WANT_FULLSCRAPE if( mode == TASK_STATS_TPB ) { + struct http_data* h = io_getcookie( client_socket ); tai6464 t; #ifdef WANT_COMPRESSION_GZIP d[l-1] = 0; @@ -292,9 +291,6 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d h->flag |= STRUCT_HTTP_FLAG_GZIP; format |= TASK_FLAG_GZIP; } -#else - /* Touch variable */ - d=d; #endif /* Pass this task to the worker thread */ h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; @@ -305,12 +301,14 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d io_dontwantread( client_socket ); return -2; } +#endif /* default format for now */ if( !( l = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500; return l; } +#ifdef WANT_FULLSCRAPE static ssize_t http_handle_fullscrape( const int64 client_socket, char *d, size_t l ) { struct http_data* h = io_getcookie( client_socket ); int format = 0; @@ -341,6 +339,7 @@ write( 2, debug_request, l ); io_dontwantread( client_socket ); return -2; } +#endif static ssize_t http_handle_scrape( const int64 client_socket, char *data ) { int scanon = 1, numwant = 0; @@ -387,7 +386,7 @@ UTORRENT1600_WORKAROUND: /* Enough for http header + whole scrape string */ if( !( l = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500; - stats_issue_event( EVENT_SCRAPE, 1, l ); + stats_issue_event( EVENT_SCRAPE, FLAG_TCP, l ); return l; } @@ -486,12 +485,12 @@ static ssize_t http_handle_announce( const int64 client_socket, char *data ) { return sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d14:failure reason81:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" ); if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) - len = remove_peer_from_torrent( hash, &peer, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ); + len = remove_peer_from_torrent( hash, &peer, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, FLAG_TCP ); else { - torrent = add_peer_to_torrent( hash, &peer, 0 ); + torrent = add_peer_to_torrent( hash, &peer WANT_SYNC_PARAM( 0 ) ); if( !torrent || !( len = return_peers_for_torrent( hash, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500; } - stats_issue_event( EVENT_ANNOUNCE, 1, len); + stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, len); return len; } @@ -529,14 +528,16 @@ ssize_t http_handle_request( const int64 client_socket, char *data, size_t recv_ /* This is the hardcore match for announce*/ if( ( *data == 'a' ) || ( *data == '?' ) ) reply_size = http_handle_announce( client_socket, c ); +#ifdef WANT_FULLSCRAPE else if( !byte_diff( data, 12, "scrape HTTP/" ) ) reply_size = http_handle_fullscrape( client_socket, recv_header, recv_length ); +#endif /* This is the hardcore match for scrape */ else if( !byte_diff( data, 2, "sc" ) ) reply_size = http_handle_scrape( client_socket, c ); /* All the rest is matched the standard way */ else switch( len ) { -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH case 4: /* sync ? */ if( byte_diff( data, 4, "sync") ) HTTPERROR_404; reply_size = http_handle_sync( client_socket, c ); diff --git a/ot_stats.c b/ot_stats.c index 1177616..cc7dc30 100644 --- a/ot_stats.c +++ b/ot_stats.c @@ -443,13 +443,13 @@ static size_t stats_httperrors_txt ( char * reply ) { extern const char *g_version_opentracker_c, *g_version_accesslist_c, *g_version_clean_c, *g_version_fullscrape_c, *g_version_http_c, *g_version_iovec_c, *g_version_mutex_c, *g_version_stats_c, *g_version_sync_c, *g_version_udp_c, *g_version_vector_c, -*g_version_scan_urlencoded_query_c, *g_version_trackerlogic_c; +*g_version_scan_urlencoded_query_c, *g_version_trackerlogic_c, *g_version_livesync_c; size_t stats_return_tracker_version( char *reply ) { - return sprintf( reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s", + return sprintf( reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, g_version_http_c, g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_sync_c, g_version_udp_c, g_version_vector_c, - g_version_scan_urlencoded_query_c, g_version_trackerlogic_c ); + g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c ); } size_t return_stats_for_tracker( char *reply, int mode, int format ) { @@ -490,36 +490,36 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) { } } -void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data ) { +void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uint32_t event_data ) { switch( event ) { case EVENT_ACCEPT: - if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; + if( proto == FLAG_TCP ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; #ifdef WANT_LOG_NETWORKS stat_increase_network_count( &stats_network_counters_root, 0, event_data ); #endif break; case EVENT_ANNOUNCE: - if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; + if( proto == FLAG_TCP ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; break; case EVENT_CONNECT: - if( is_tcp ) ot_overall_tcp_connects++; else ot_overall_udp_connects++; + if( proto == FLAG_TCP ) ot_overall_tcp_connects++; else ot_overall_udp_connects++; break; case EVENT_SCRAPE: - if( is_tcp ) ot_overall_tcp_successfulscrapes++; else ot_overall_udp_successfulscrapes++; + if( proto == FLAG_TCP ) ot_overall_tcp_successfulscrapes++; else ot_overall_udp_successfulscrapes++; case EVENT_FULLSCRAPE: ot_full_scrape_count++; ot_full_scrape_size += event_data; break; case EVENT_FULLSCRAPE_REQUEST: { - unsigned char ip[4]; *(int*)ip = is_tcp; /* ugly hack to transfer ip to stats */ + unsigned char ip[4]; *(int*)ip = (int)proto; /* ugly hack to transfer ip to stats */ LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE\n", (unsigned int)(g_now - ot_start_time), ip[0], ip[1], ip[2], ip[3] ); ot_full_scrape_request_count++; } break; case EVENT_FULLSCRAPE_REQUEST_GZIP: { - unsigned char ip[4]; *(int*)ip = is_tcp; /* ugly hack to transfer ip to stats */ + unsigned char ip[4]; *(int*)ip = (int)proto; /* ugly hack to transfer ip to stats */ LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE GZIP\n", (unsigned int)(g_now - ot_start_time), ip[0], ip[1], ip[2], ip[3] ); ot_full_scrape_request_count++; } diff --git a/ot_stats.h b/ot_stats.h index 8cc7a5b..72c5b93 100644 --- a/ot_stats.h +++ b/ot_stats.h @@ -34,7 +34,7 @@ enum { CODE_HTTPERROR_COUNT }; -void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data ); +void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uint32_t event_data ); size_t return_stats_for_tracker( char *reply, int mode, int format ); size_t stats_return_tracker_version( char *reply ); void stats_init( ); diff --git a/ot_sync.c b/ot_sync.c index 5f772fb..4beb60d 100644 --- a/ot_sync.c +++ b/ot_sync.c @@ -23,7 +23,7 @@ #include "ot_stats.h" #include "ot_iovec.h" -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH #define OT_SYNC_CHUNK_SIZE (512*1024) @@ -141,7 +141,7 @@ static void * sync_worker( void * args) { ot_tasktype tasktype = TASK_SYNC_OUT; ot_taskid taskid = mutex_workqueue_poptask( &tasktype ); sync_make( &iovec_entries, &iovector ); - stats_issue_event( EVENT_SYNC_OUT, 1, iovec_length( &iovec_entries, &iovector) ); + stats_issue_event( EVENT_SYNC_OUT, FLAG_TCP, iovec_length( &iovec_entries, &iovector) ); if( mutex_workqueue_pushresult( taskid, iovec_entries, iovector ) ) iovec_free( &iovec_entries, &iovector ); } diff --git a/ot_sync.h b/ot_sync.h index 210d9d7..ae54e67 100644 --- a/ot_sync.h +++ b/ot_sync.h @@ -6,7 +6,7 @@ #ifndef __OT_SYNC_H__ #define __OT_SYNC_H__ -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH enum { SYNC_IN, SYNC_OUT }; void sync_init( ); @@ -14,6 +14,11 @@ void sync_deinit( ); void sync_deliver( int64 socket ); int add_changeset_to_tracker( uint8_t *data, size_t len ); +#else + +#define sync_init() +#define sync_deinit() + #endif #endif diff --git a/ot_udp.c b/ot_udp.c index 0a6458e..64f9c50 100644 --- a/ot_udp.c +++ b/ot_udp.c @@ -52,8 +52,8 @@ void handle_udp4( int64 serversocket ) { r = socket_recv4( serversocket, static_inbuf, sizeof( static_inbuf ), remoteip, &remoteport); - stats_issue_event( EVENT_ACCEPT, 0, ntohl(*(uint32_t*)remoteip) ); - stats_issue_event( EVENT_READ, 0, r ); + stats_issue_event( EVENT_ACCEPT, FLAG_UDP, ntohl(*(uint32_t*)remoteip) ); + stats_issue_event( EVENT_READ, FLAG_UDP, r ); /* Minimum udp tracker packet size, also catches error */ if( r < 16 ) @@ -72,7 +72,7 @@ void handle_udp4( int64 serversocket ) { udp_make_connectionid( outpacket + 2, remoteip ); socket_send4( serversocket, static_outbuf, 16, remoteip, remoteport ); - stats_issue_event( EVENT_CONNECT, 0, 16 ); + stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 ); break; case 1: /* This is an announce action */ /* Minimum udp announce packet size */ @@ -109,9 +109,9 @@ void handle_udp4( int64 serversocket ) { outpacket[1] = inpacket[12/4]; if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */ - r = remove_peer_from_torrent( hash, &peer, static_outbuf, 0 ); + r = remove_peer_from_torrent( hash, &peer, static_outbuf, FLAG_UDP ); else { - torrent = add_peer_to_torrent( hash, &peer WANT_TRACKER_SYNC_PARAM( 0 ) ); + torrent = add_peer_to_torrent( hash, &peer WANT_SYNC_PARAM( 0 ) ); if( !torrent ) return; /* XXX maybe send error */ @@ -119,7 +119,7 @@ void handle_udp4( int64 serversocket ) { } socket_send4( serversocket, static_outbuf, r, remoteip, remoteport ); - stats_issue_event( EVENT_ANNOUNCE, 0, r ); + stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r ); break; case 2: /* This is a scrape action */ @@ -133,7 +133,7 @@ void handle_udp4( int64 serversocket ) { return_udp_scrape_for_torrent( (ot_hash*)( static_inbuf + 16 + 20 * r_out ), static_outbuf + 8 + 12 * r_out ); socket_send4( serversocket, static_outbuf, 8 + 12 * r_out, remoteip, remoteport ); - stats_issue_event( EVENT_SCRAPE, 0, r ); + stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r ); break; } } diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c index 85f0d82..e84fbfd 100644 --- a/scan_urlencoded_query.c +++ b/scan_urlencoded_query.c @@ -64,13 +64,13 @@ void scan_urlencoded_skipvalue( char **string ) { ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) { const unsigned char* s=*(const unsigned char**) string; unsigned char *d = (unsigned char*)deststring; - unsigned char b, c, f; + unsigned char b, c; /* This is the main decoding loop. 'flag' determines, which characters are non-terminating in current context (ie. stop at '=' and '&' if scanning for a 'param'; stop at '?' if scanning for the path ) */ - while( ( f = is_unreserved[ c = *s++ ] ) & flags ) { + while( is_unreserved[ c = *s++ ] & flags ) { /* When encountering an url escaped character, try to decode */ if( c=='%') { diff --git a/tests/testsuite2.sh b/tests/testsuite2.sh new file mode 100644 index 0000000..5189187 --- /dev/null +++ b/tests/testsuite2.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +while true; do + request_string="GET /announce?info_hash=012345678901234567\ +%$(printf %02X $(( $RANDOM & 0xff )) )\ +%$(printf %02X $(( $RANDOM & 0xff )) )\ +&ip=$(( $RANDOM & 0xff )).17.13.15&port=$(( $RANDOM & 0xff )) HTTP/1.0\n" + + echo $request_string + echo + echo $request_string | nc 10.0.1.3 6969 >/dev/null + echo + +done diff --git a/trackerlogic.c b/trackerlogic.c index 37bb878..bff3a3c 100644 --- a/trackerlogic.c +++ b/trackerlogic.c @@ -14,6 +14,7 @@ #include #include #include +#include /* Libowfat */ #include "scan.h" @@ -28,19 +29,20 @@ #include "ot_accesslist.h" #include "ot_fullscrape.h" #include "ot_sync.h" +#include "ot_livesync.h" void free_peerlist( ot_peerlist *peer_list ) { size_t i; for( i=0; ipeers[i].data ) free( peer_list->peers[i].data ); -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH free( peer_list->changeset.data ); #endif free( peer_list ); } -ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_TRACKER_SYNC_PARAM( int from_changeset ) ) { +ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( int from_changeset ) ) { int exactmatch; ot_torrent *torrent; ot_peer *peer_dest; @@ -58,6 +60,11 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_TRACKER_SYNC return NULL; } +#ifdef WANT_SYNC_LIVE + if( !from_changeset ) + livesync_tell( hash, peer, PEER_FLAG_LEECHING ); +#endif + if( !exactmatch ) { /* Create a new torrent entry, then */ memmove( &torrent->hash, hash, sizeof( ot_hash ) ); @@ -79,7 +86,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_TRACKER_SYNC if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED; -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC if( from_changeset ) { /* Check, whether peer already is in current pool, do nothing if so */ peer_pool = &torrent->peer_list->peers[0]; @@ -148,7 +155,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_TRACKER_SYNC * RANDOM may return huge values * does not yet check not to return self */ -size_t return_peers_for_torrent( ot_hash *hash, size_t amount, char *reply, int is_tcp ) { +size_t return_peers_for_torrent( ot_hash *hash, size_t amount, char *reply, PROTO_FLAG proto ) { char *r = reply; int exactmatch; ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); @@ -164,7 +171,7 @@ size_t return_peers_for_torrent( ot_hash *hash, size_t amount, char *reply, int if( peer_list->peer_count < amount ) amount = peer_list->peer_count; - if( is_tcp ) + if( proto == FLAG_TCP ) r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie5:peers%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount ); else { *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); @@ -204,7 +211,7 @@ size_t return_peers_for_torrent( ot_hash *hash, size_t amount, char *reply, int r += 6; } } - if( is_tcp ) + if( proto == FLAG_TCP ) *r++ = 'e'; mutex_bucket_unlock_by_hash( hash ); @@ -263,23 +270,33 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl return r - reply; } -size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int is_tcp ) { +size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, PROTO_FLAG proto ) { int exactmatch; size_t index; ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); ot_peerlist *peer_list; +#ifdef WANT_SYNC_LIVE + if( proto != FLAG_MCA ) + livesync_tell( hash, peer, PEER_FLAG_STOPPED ); +#endif + if( !exactmatch ) { mutex_bucket_unlock_by_hash( hash ); - if( is_tcp ) + if( proto == FLAG_TCP ) return sprintf( reply, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM ); /* Create fake packet to satisfy parser on the other end */ - ((uint32_t*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); - ((uint32_t*)reply)[3] = ((uint32_t*)reply)[4] = 0; - return (size_t)20; + if( proto == FLAG_UDP ) { + ((uint32_t*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); + ((uint32_t*)reply)[3] = ((uint32_t*)reply)[4] = 0; + return (size_t)20; + } + + if( proto == FLAG_MCA ) + return 0; } peer_list = torrent->peer_list; @@ -296,37 +313,46 @@ size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int exit_loop: - if( is_tcp ) { + if( proto == FLAG_TCP ) { size_t reply_size = sprintf( reply, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers0:e", peer_list->seed_count, peer_list->peer_count - peer_list->seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM ); mutex_bucket_unlock_by_hash( hash ); return reply_size; } - /* else { Handle UDP reply */ - ((uint32_t*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); - ((uint32_t*)reply)[3] = htonl( peer_list->peer_count - peer_list->seed_count ); - ((uint32_t*)reply)[4] = htonl( peer_list->seed_count); + /* Handle UDP reply */ + if( proto == FLAG_TCP ) { + ((uint32_t*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); + ((uint32_t*)reply)[3] = htonl( peer_list->peer_count - peer_list->seed_count ); + ((uint32_t*)reply)[4] = htonl( peer_list->seed_count); + } mutex_bucket_unlock_by_hash( hash ); return (size_t)20; } +void exerr( char * message ) { + fprintf( stderr, "%s\n", message ); + exit( 111 ); +} + int trackerlogic_init( const char * const serverdir ) { if( serverdir && chdir( serverdir ) ) { - fprintf( stderr, "Could not chdir() to %s\n", serverdir ); + fprintf( stderr, "Could not chdir() to %s, because %s\n", serverdir, strerror(errno) ); return -1; } srandom( time(NULL) ); - + g_tracker_id = random(); + /* Initialise background worker threads */ mutex_init( ); clean_init( ); fullscrape_init( ); -#ifdef WANT_TRACKER_SYNC + accesslist_init( ); + livesync_init( ); sync_init( ); -#endif stats_init( ); + return 0; } @@ -349,9 +375,9 @@ void trackerlogic_deinit( void ) { /* Deinitialise background worker threads */ stats_deinit( ); -#ifdef WANT_TRACKER_SYNC sync_deinit( ); -#endif + livesync_init( ); + accesslist_init( ); fullscrape_deinit( ); clean_deinit( ); mutex_deinit( ); diff --git a/trackerlogic.h b/trackerlogic.h index 3525421..986c17a 100644 --- a/trackerlogic.h +++ b/trackerlogic.h @@ -43,6 +43,11 @@ typedef time_t ot_time; /* From opentracker.c */ extern time_t g_now; #define NOW (g_now/OT_POOLS_TIMEOUT) +extern uint32_t g_tracker_id; +typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA } PROTO_FLAG; + +/* Try to bind to ip:port pair. May call exit() on failure */ +int64_t ot_try_bind( char ip[4], uint16_t port, PROTO_FLAG proto ); typedef struct { uint8_t data[8]; @@ -50,6 +55,7 @@ typedef struct { static const uint8_t PEER_FLAG_SEEDING = 0x80; static const uint8_t PEER_FLAG_COMPLETED = 0x40; static const uint8_t PEER_FLAG_STOPPED = 0x20; +static const uint8_t PEER_FLAG_LEECHING = 0x00; #define OT_SETIP( peer, ip ) memmove((peer),(ip),4); #define OT_SETPORT( peer, port ) memmove(((uint8_t*)peer)+4,(port),2); @@ -74,7 +80,7 @@ struct ot_peerlist { size_t down_count; size_t seed_counts[ OT_POOLS_COUNT ]; ot_vector peers[ OT_POOLS_COUNT ]; -#ifdef WANT_TRACKER_SYNC +#ifdef WANT_SYNC_BATCH ot_vector changeset; #endif }; @@ -83,18 +89,23 @@ struct ot_peerlist { Exported functions */ -#ifdef WANT_TRACKER_SYNC -#define WANT_TRACKER_SYNC_PARAM( param ) , param +#if defined( WANT_SYNC_BATCH ) || defined( WANT_SYNC_LIVE ) +#define WANT_SYNC +#endif + +#ifdef WANT_SYNC +#define WANT_SYNC_PARAM( param ) , param #else -#define WANT_TRACKER_SYNC_PARAM( param ) +#define WANT_SYNC_PARAM( param ) #endif int trackerlogic_init( const char * const serverdir ); void trackerlogic_deinit( void ); +void exerr( char * message ); -ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_TRACKER_SYNC_PARAM( int from_changeset ) ); -size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int is_tcp ); -size_t return_peers_for_torrent( ot_hash *hash, size_t amount, char *reply, int is_tcp ); +ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( int from_changeset ) ); +size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, PROTO_FLAG proto ); +size_t return_peers_for_torrent( ot_hash *hash, size_t amount, char *reply, PROTO_FLAG proto ); size_t return_tcp_scrape_for_torrent( ot_hash *hash, int amount, char *reply ); size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ); -- cgit v1.2.3