dynamic-accesslists
erdgeist 16 years ago
parent 779d6c235f
commit 131211b4da

@ -19,6 +19,8 @@ LIBOWFAT_LIBRARY=$(PREFIX)/libowfat
BINDIR?=$(PREFIX)/bin BINDIR?=$(PREFIX)/bin
#FEATURES+=-DWANT_V6
#FEATURES+=-DWANT_ACCESSLIST_BLACK #FEATURES+=-DWANT_ACCESSLIST_BLACK
#FEATURES+=-DWANT_ACCESSLIST_WHITE #FEATURES+=-DWANT_ACCESSLIST_WHITE
@ -31,13 +33,12 @@ BINDIR?=$(PREFIX)/bin
FEATURES+=-DWANT_FULLSCRAPE FEATURES+=-DWANT_FULLSCRAPE
#FEATURES+=-D_DEBUG_HTTPERROR #FEATURES+=-D_DEBUG_HTTPERROR
#FEATURES+=-D_DEBUG_PEERID
OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage
OPTS_production=-Os OPTS_production=-Os
CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra #-ansi -pedantic CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra #-ansi -pedantic
LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lpthread -lz
BINARY =opentracker BINARY =opentracker
HEADERS=trackerlogic.h scan_urlencoded_query.h ot_mutex.h ot_stats.h ot_vector.h ot_clean.h ot_udp.h ot_iovec.h ot_fullscrape.h ot_accesslist.h ot_http.h ot_livesync.h HEADERS=trackerlogic.h scan_urlencoded_query.h ot_mutex.h ot_stats.h ot_vector.h ot_clean.h ot_udp.h ot_iovec.h ot_fullscrape.h ot_accesslist.h ot_http.h ot_livesync.h

@ -22,7 +22,7 @@
#include "iob.h" #include "iob.h"
#include "byte.h" #include "byte.h"
#include "scan.h" #include "scan.h"
#include "ip4.h" #include "ip6.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "trackerlogic.h"
@ -108,7 +108,7 @@ static ssize_t handle_read( const int64 clientsocket, struct ot_workstruct *ws )
struct http_data* h = io_getcookie( clientsocket ); struct http_data* h = io_getcookie( clientsocket );
ssize_t l; ssize_t l;
if( ( l = io_tryread( clientsocket, ws->inbuf, ws->inbuf_size ) ) <= 0 ) { if( ( l = io_tryread( clientsocket, ws->inbuf, G_INBUF_SIZE ) ) <= 0 ) {
handle_dead( clientsocket ); handle_dead( clientsocket );
return 0; return 0;
} }
@ -152,28 +152,28 @@ static void handle_write( const int64 clientsocket ) {
static void handle_accept( const int64 serversocket ) { static void handle_accept( const int64 serversocket ) {
struct http_data *h; struct http_data *h;
unsigned char ip[4]; ot_ip6 ip;
uint16 port; uint16 port;
tai6464 t; tai6464 t;
int64 i; int64 i;
while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) { while( ( i = socket_accept6( serversocket, ip, &port, NULL ) ) != -1 ) {
/* Put fd into a non-blocking mode */ /* Put fd into a non-blocking mode */
io_nonblock( i ); io_nonblock( i );
if( !io_fd( i ) || if( !io_fd( i ) ||
!( h = (struct http_data*)malloc( sizeof( struct http_data ) ) ) ) { !( h = (struct http_data*)malloc( sizeof(struct http_data) ) ) ) {
io_close( i ); io_close( i );
continue; continue;
} }
io_setcookie( i, h ); io_setcookie( i, h );
io_wantread( i ); io_wantread( i );
memset( h, 0, sizeof( struct http_data ) ); memset(h, 0, sizeof( struct http_data ) );
WRITE32(h->ip,0,READ32(ip,0)); memcpy(h->ip,ip,sizeof(ot_ip6));
stats_issue_event( EVENT_ACCEPT, FLAG_TCP, ntohl(*(uint32_t*)ip)); stats_issue_event( EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
/* That breaks taia encapsulation. But there is no way to take system /* 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 */ time this often in FreeBSD and libowfat does not allow to set unix time */
@ -193,20 +193,14 @@ static void server_mainloop( ) {
int iovec_entries; int iovec_entries;
/* Initialize our "thread local storage" */ /* Initialize our "thread local storage" */
ws.inbuf = malloc( THREAD_INBUF_SIZE ); ws.inbuf = malloc( G_INBUF_SIZE );
ws.outbuf = malloc( THREAD_OUTBUF_SIZE ); ws.outbuf = malloc( G_OUTBUF_SIZE );
#ifdef _DEBUG_HTTPERROR #ifdef _DEBUG_HTTPERROR
ws.debugbuf= malloc( THREAD_INBUF_SIZE ); ws.debugbuf= malloc( G_INBUF_SIZE );
#endif #endif
if( !ws.inbuf || !ws.outbuf ) if( !ws.inbuf || !ws.outbuf )
panic( "Initializing worker failed" ); panic( "Initializing worker failed" );
ws.inbuf_size = THREAD_INBUF_SIZE;
ws.outbuf_size = THREAD_OUTBUF_SIZE;
#ifdef _DEBUG_HTTPERROR
ws.debugbuf_size= THREAD_INBUF_SIZE;
#endif
for( ; ; ) { for( ; ; ) {
int64 i; int64 i;
@ -217,7 +211,7 @@ static void server_mainloop( ) {
if( (intptr_t)cookie == FLAG_TCP ) if( (intptr_t)cookie == FLAG_TCP )
handle_accept( i ); handle_accept( i );
else if( (intptr_t)cookie == FLAG_UDP ) else if( (intptr_t)cookie == FLAG_UDP )
handle_udp4( i, &ws ); handle_udp6( i, &ws );
else else
handle_read( i, &ws ); handle_read( i, &ws );
} }
@ -241,17 +235,20 @@ static void server_mainloop( ) {
} }
} }
static int64_t ot_try_bind( char ip[4], uint16_t port, PROTO_FLAG proto ) { static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
int64 s = proto == FLAG_TCP ? socket_tcp4( ) : socket_udp4( ); int64 s = proto == FLAG_TCP ? socket_tcp6( ) : socket_udp6( );
#ifdef _DEBUG #ifdef _DEBUG
char *protos[] = {"TCP","UDP","UDP mcast"}; char *protos[] = {"TCP","UDP","UDP mcast"};
uint8_t *_ip = (uint8_t *)ip; char _debug[512];
fprintf( stderr, "Binding socket type %s to address %d.%d.%d.%d:%d...", protos[proto],_ip[0],_ip[1],_ip[2],_ip[3],port); int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] );
off += fmt_ip6( _debug+off, ip);
off += snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port);
fputs( _debug, stderr );
#endif #endif
if( socket_bind4_reuse( s, ip, port ) == -1 ) if( socket_bind6_reuse( s, ip, port, 0 ) == -1 )
panic( "socket_bind4_reuse" ); panic( "socket_bind6_reuse" );
if( ( proto == FLAG_TCP ) && ( socket_listen( s, SOMAXCONN) == -1 ) ) if( ( proto == FLAG_TCP ) && ( socket_listen( s, SOMAXCONN) == -1 ) )
panic( "socket_listen" ); panic( "socket_listen" );
@ -279,16 +276,22 @@ char * set_config_option( char **option, char *value ) {
return *option = strdup( value ); return *option = strdup( value );
} }
static int scan_ip4_port( const char *src, char *ip, uint16 *port ) { static int scan_ip6_port( const char *src, ot_ip6 ip, uint16 *port ) {
const char *s = src; const char *s = src;
int off; int off, bracket = 0;
while( isspace(*s) ) ++s; while( isspace(*s) ) ++s;
if( !(off = scan_ip4( s, ip ) ) ) if( *s == '[' ) ++s, ++bracket; /* for v6 style notation */
if( !(off = scan_ip6( s, ip ) ) )
return 0; return 0;
s += off; s += off;
if( *s == 0 || isspace(*s)) return s-src; if( *s == 0 || isspace(*s)) return s-src;
if( *(s++) != ':' ) if( *s == ']' && bracket ) ++s;
return 0; if( !ip6_isv4mapped(ip)){
if( ( bracket && *(s) != ':' ) || ( *(s) != '.' ) ) return 0;
s++;
} else {
if( *(s++) != ':' ) return 0;
}
if( !(off = scan_ushort (s, port ) ) ) if( !(off = scan_ushort (s, port ) ) )
return 0; return 0;
return off+s-src; return off+s-src;
@ -296,7 +299,8 @@ static int scan_ip4_port( const char *src, char *ip, uint16 *port ) {
int parse_configfile( char * config_filename ) { int parse_configfile( char * config_filename ) {
FILE * accesslist_filehandle; FILE * accesslist_filehandle;
char inbuf[512], tmpip[4]; char inbuf[512];
ot_ip6 tmpip;
int bound = 0; int bound = 0;
accesslist_filehandle = fopen( config_filename, "r" ); accesslist_filehandle = fopen( config_filename, "r" );
@ -324,17 +328,17 @@ int parse_configfile( char * config_filename ) {
set_config_option( &g_serverdir, p+16 ); set_config_option( &g_serverdir, p+16 );
} else if(!byte_diff(p,14,"listen.tcp_udp" ) && isspace(p[14])) { } else if(!byte_diff(p,14,"listen.tcp_udp" ) && isspace(p[14])) {
uint16_t tmpport = 6969; uint16_t tmpport = 6969;
if( !scan_ip4_port( p+15, tmpip, &tmpport )) goto parse_error; if( !scan_ip6_port( p+15, tmpip, &tmpport )) goto parse_error;
ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound; ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound;
ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound; ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound;
} else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) { } else if(!byte_diff(p,10,"listen.tcp" ) && isspace(p[10])) {
uint16_t tmpport = 6969; uint16_t tmpport = 6969;
if( !scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error; if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error;
ot_try_bind( tmpip, tmpport, FLAG_TCP ); ot_try_bind( tmpip, tmpport, FLAG_TCP );
++bound; ++bound;
} else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) { } else if(!byte_diff(p, 10, "listen.udp" ) && isspace(p[10])) {
uint16_t tmpport = 6969; uint16_t tmpport = 6969;
if( !scan_ip4_port( p+11, tmpip, &tmpport )) goto parse_error; if( !scan_ip6_port( p+11, tmpip, &tmpport )) goto parse_error;
ot_try_bind( tmpip, tmpport, FLAG_UDP ); ot_try_bind( tmpip, tmpport, FLAG_UDP );
++bound; ++bound;
#ifdef WANT_ACCESSLIST_WHITE #ifdef WANT_ACCESSLIST_WHITE
@ -346,18 +350,18 @@ int parse_configfile( char * config_filename ) {
#endif #endif
#ifdef WANT_RESTRICT_STATS #ifdef WANT_RESTRICT_STATS
} else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) { } else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) {
if( !scan_ip4( p+13, tmpip )) goto parse_error; if( !scan_ip6( p+13, tmpip )) goto parse_error;
accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT ); accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT );
#endif #endif
} else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) { } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) {
set_config_option( &g_redirecturl, p+21 ); set_config_option( &g_redirecturl, p+21 );
#ifdef WANT_SYNC_LIVE #ifdef WANT_SYNC_LIVE
} else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) { } else if(!byte_diff(p, 24, "livesync.cluster.node_ip" ) && isspace(p[24])) {
if( !scan_ip4( p+25, tmpip )) goto parse_error; if( !scan_ip6( p+25, tmpip )) goto parse_error;
accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC ); accesslist_blessip( tmpip, OT_PERMISSION_MAY_LIVESYNC );
} else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) { } else if(!byte_diff(p, 23, "livesync.cluster.listen" ) && isspace(p[23])) {
uint16_t tmpport = LIVESYNC_PORT; uint16_t tmpport = LIVESYNC_PORT;
if( !scan_ip4_port( p+24, tmpip, &tmpport )) goto parse_error; if( !scan_ip6_port( p+24, tmpip, &tmpport )) goto parse_error;
livesync_bind_mcast( tmpip, tmpport ); livesync_bind_mcast( tmpip, tmpport );
#endif #endif
} else } else
@ -411,10 +415,12 @@ int drop_privileges (const char * const serverdir) {
} }
int main( int argc, char **argv ) { int main( int argc, char **argv ) {
char serverip[4] = {0,0,0,0}, tmpip[4]; ot_ip6 serverip, tmpip;
int bound = 0, scanon = 1; int bound = 0, scanon = 1;
uint16_t tmpport; uint16_t tmpport;
memset( serverip, 0, sizeof(ot_ip6) );
while( scanon ) { while( scanon ) {
switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v" switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v"
#ifdef WANT_ACCESSLIST_BLACK #ifdef WANT_ACCESSLIST_BLACK
@ -425,7 +431,7 @@ while( scanon ) {
"h" ) ) { "h" ) ) {
case -1 : scanon = 0; break; case -1 : scanon = 0; break;
case 'i': case 'i':
if( !scan_ip4( optarg, serverip )) { usage( argv[0] ); exit( 1 ); } if( !scan_ip6( optarg, serverip )) { usage( argv[0] ); exit( 1 ); }
break; break;
#ifdef WANT_ACCESSLIST_BLACK #ifdef WANT_ACCESSLIST_BLACK
case 'b': set_config_option( &g_accesslist_filename, optarg); break; case 'b': set_config_option( &g_accesslist_filename, optarg); break;
@ -446,7 +452,7 @@ while( scanon ) {
case 'd': set_config_option( &g_serverdir, optarg ); break; case 'd': set_config_option( &g_serverdir, optarg ); break;
case 'r': set_config_option( &g_redirecturl, optarg ); break; case 'r': set_config_option( &g_redirecturl, optarg ); break;
case 'A': case 'A':
if( !scan_ip4( optarg, tmpip )) { usage( argv[0] ); exit( 1 ); } if( !scan_ip6( optarg, tmpip )) { usage( argv[0] ); exit( 1 ); }
accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */ accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */
break; break;
case 'f': bound += parse_configfile( optarg ); break; case 'f': bound += parse_configfile( optarg ); break;

@ -8,10 +8,12 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include <unistd.h>
/* Libowfat */ /* Libowfat */
#include "byte.h" #include "byte.h"
#include "scan.h" #include "scan.h"
#include "ip6.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "trackerlogic.h"
@ -32,14 +34,14 @@ void accesslist_deinit( void ) {
accesslist_reset( ); accesslist_reset( );
} }
static int accesslist_addentry( ot_hash *infohash ) { static int accesslist_addentry( ot_hash infohash ) {
int eger; int eger;
void *insert = vector_find_or_insert( &accesslist, infohash, OT_HASH_COMPARE_SIZE, OT_HASH_COMPARE_SIZE, &eger ); void *insert = vector_find_or_insert( &accesslist, infohash, OT_HASH_COMPARE_SIZE, OT_HASH_COMPARE_SIZE, &eger );
if( !insert ) if( !insert )
return -1; return -1;
memmove( insert, infohash, OT_HASH_COMPARE_SIZE ); memcpy( insert, infohash, OT_HASH_COMPARE_SIZE );
return 0; return 0;
} }
@ -64,7 +66,7 @@ static void accesslist_readfile( int foo ) {
/* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */ /* We do ignore anything that is not of the form "^[:xdigit:]{40}[^:xdigit:].*" */
while( fgets( inbuf, sizeof(inbuf), accesslist_filehandle ) ) { while( fgets( inbuf, sizeof(inbuf), accesslist_filehandle ) ) {
int i; int i;
for( i=0; i<20; ++i ) { for( i=0; i<(int)sizeof(ot_hash); ++i ) {
int eger = 16 * scan_fromhex( inbuf[ 2*i ] ) + scan_fromhex( inbuf[ 1 + 2*i ] ); int eger = 16 * scan_fromhex( inbuf[ 2*i ] ) + scan_fromhex( inbuf[ 1 + 2*i ] );
if( eger < 0 ) if( eger < 0 )
continue; continue;
@ -74,13 +76,13 @@ static void accesslist_readfile( int foo ) {
continue; continue;
/* Append accesslist to accesslist vector */ /* Append accesslist to accesslist vector */
accesslist_addentry( &infohash ); accesslist_addentry( infohash );
} }
fclose( accesslist_filehandle ); fclose( accesslist_filehandle );
} }
int accesslist_hashisvalid( ot_hash *hash ) { int accesslist_hashisvalid( ot_hash hash ) {
int exactmatch; int exactmatch;
binary_search( hash, accesslist.data, accesslist.size, OT_HASH_COMPARE_SIZE, OT_HASH_COMPARE_SIZE, &exactmatch ); binary_search( hash, accesslist.data, accesslist.size, OT_HASH_COMPARE_SIZE, OT_HASH_COMPARE_SIZE, &exactmatch );
@ -102,30 +104,39 @@ void accesslist_init( ) {
} }
#endif #endif
static uint32_t g_adminip_addresses[OT_ADMINIP_MAX]; static ot_ip6 g_adminip_addresses[OT_ADMINIP_MAX];
static ot_permissions g_adminip_permissions[OT_ADMINIP_MAX]; static ot_permissions g_adminip_permissions[OT_ADMINIP_MAX];
static unsigned int g_adminip_count = 0; static unsigned int g_adminip_count = 0;
int accesslist_blessip( char *ip, ot_permissions permissions ) { int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ) {
if( g_adminip_count >= OT_ADMINIP_MAX ) if( g_adminip_count >= OT_ADMINIP_MAX )
return -1; return -1;
WRITE32(g_adminip_addresses + g_adminip_count,0,READ32(ip,0));
memcpy(g_adminip_addresses + g_adminip_count,ip,sizeof(ot_ip6));
g_adminip_permissions[ g_adminip_count++ ] = permissions; g_adminip_permissions[ g_adminip_count++ ] = permissions;
#ifdef _DEBUG #ifdef _DEBUG
uint8_t *_ip = (uint8_t*)ip; {
fprintf( stderr, "Blessing ip address %d.%d.%d.%d with:", _ip[0], _ip[1], _ip[2], _ip[3]); char _debug[512];
if( permissions & OT_PERMISSION_MAY_STAT ) fputs( " may_fetch_stats", stderr ); int off = snprintf( _debug, sizeof(_debug), "Blessing ip address " );
if( permissions & OT_PERMISSION_MAY_LIVESYNC ) fputs( " may_sync_live", stderr ); off += fmt_ip6(_debug+off, ip );
if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) fputs( " may_fetch_fullscrapes", stderr );
if( !permissions ) fputs(" nothing.\n", stderr); else fputs(".\n", stderr ); if( permissions & OT_PERMISSION_MAY_STAT ) off += snprintf( _debug+off, 512-off, " may_fetch_stats" );
if( permissions & OT_PERMISSION_MAY_LIVESYNC ) off += snprintf( _debug+off, 512-off, " may_sync_live" );
if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) off += snprintf( _debug+off, 512-off, " may_fetch_fullscrapes" );
if( !permissions ) off += snprintf( _debug+off, sizeof(_debug)-off, " nothing\n" );
_debug[off++] = '.';
write( 2, _debug, off );
}
#endif #endif
return 0; return 0;
} }
int accesslist_isblessed( char *ip, ot_permissions permissions ) { int accesslist_isblessed( ot_ip6 ip, ot_permissions permissions ) {
unsigned int i; unsigned int i;
for( i=0; i<g_adminip_count; ++i ) for( i=0; i<g_adminip_count; ++i )
if( !memcmp( g_adminip_addresses + i, ip, 4) && ( g_adminip_permissions[ i ] & permissions ) ) if( !memcmp( g_adminip_addresses + i, ip, sizeof(ot_ip6)) && ( g_adminip_permissions[ i ] & permissions ) )
return 1; return 1;
return 0; return 0;
} }

@ -14,7 +14,7 @@
#define WANT_ACCESSLIST #define WANT_ACCESSLIST
void accesslist_init( ); void accesslist_init( );
void accesslist_deinit( ); void accesslist_deinit( );
int accesslist_hashisvalid( ot_hash *hash ); int accesslist_hashisvalid( ot_hash hash );
extern char *g_accesslist_filename; extern char *g_accesslist_filename;
@ -30,7 +30,7 @@ typedef enum {
OT_PERMISSION_MAY_LIVESYNC = 0x4 OT_PERMISSION_MAY_LIVESYNC = 0x4
} ot_permissions; } ot_permissions;
int accesslist_blessip( char * ip, ot_permissions permissions ); int accesslist_blessip( ot_ip6 ip, ot_permissions permissions );
int accesslist_isblessed( char * ip, ot_permissions permissions ); int accesslist_isblessed( ot_ip6 ip, ot_permissions permissions );
#endif #endif

@ -115,7 +115,7 @@ static int fullscrape_increase( int *iovec_entries, struct iovec **iovector,
} }
static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) { static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) {
int bucket,i; int bucket;
char *r, *re; char *r, *re;
#ifdef WANT_COMPRESSION_GZIP #ifdef WANT_COMPRESSION_GZIP
char compress_buffer[OT_SCRAPE_MAXENTRYLEN]; char compress_buffer[OT_SCRAPE_MAXENTRYLEN];
@ -165,17 +165,17 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
/* push hash as bencoded string */ /* push hash as bencoded string */
*r++='2'; *r++='0'; *r++=':'; *r++='2'; *r++='0'; *r++=':';
for(i=0;i<20;i+=4) WRITE32(r,i,READ32(hash,i)); r+=20; memcpy( r, hash, sizeof(ot_hash) ); r += sizeof(ot_hash);
/* push rest of the scrape string */ /* push rest of the scrape string */
r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count ); r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count );
break; break;
case TASK_FULLSCRAPE_TPB_ASCII: case TASK_FULLSCRAPE_TPB_ASCII:
to_hex( r, *hash ); r+=40; to_hex( r, *hash ); r+= 2 * sizeof(ot_hash);
r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count ); r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count );
break; break;
case TASK_FULLSCRAPE_TPB_BINARY: case TASK_FULLSCRAPE_TPB_BINARY:
for(i=0;i<20;i+=4) WRITE32(r,i,READ32(hash,i)); r+=20; memcpy( r, *hash, sizeof(ot_hash) ); r += sizeof(ot_hash);
*(uint32_t*)(r+0) = htonl( (uint32_t) peer_list->seed_count ); *(uint32_t*)(r+0) = htonl( (uint32_t) peer_list->seed_count );
*(uint32_t*)(r+4) = htonl( (uint32_t)( peer_list->peer_count-peer_list->seed_count) ); *(uint32_t*)(r+4) = htonl( (uint32_t)( peer_list->peer_count-peer_list->seed_count) );
r+=8; r+=8;

@ -15,6 +15,7 @@
#include "byte.h" #include "byte.h"
#include "array.h" #include "array.h"
#include "iob.h" #include "iob.h"
#include "ip6.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "trackerlogic.h"
@ -34,11 +35,6 @@ enum {
SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32, SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32,
SUCCESS_HTTP_SIZE_OFF = 17 }; SUCCESS_HTTP_SIZE_OFF = 17 };
#ifdef _DEBUG_PEERID
size_t g_this_peerid_len = 0;
char *g_this_peerid_data = NULL;
#endif
static void http_senddata( const int64 client_socket, struct ot_workstruct *ws ) { static void http_senddata( const int64 client_socket, struct ot_workstruct *ws ) {
struct http_data *h = io_getcookie( client_socket ); struct http_data *h = io_getcookie( client_socket );
ssize_t written_size; ssize_t written_size;
@ -63,7 +59,7 @@ static void http_senddata( const int64 client_socket, struct ot_workstruct *ws )
} }
iob_reset( &h->data.batch ); iob_reset( &h->data.batch );
memmove( outbuf, ws->reply + written_size, ws->reply_size - written_size ); memcpy( outbuf, ws->reply + written_size, ws->reply_size - written_size );
iob_addbuf_free( &h->data.batch, outbuf, ws->reply_size - written_size ); iob_addbuf_free( &h->data.batch, outbuf, ws->reply_size - written_size );
h->flag |= STRUCT_HTTP_FLAG_IOB_USED; h->flag |= STRUCT_HTTP_FLAG_IOB_USED;
@ -89,9 +85,9 @@ ssize_t http_issue_error( const int64 client_socket, struct ot_workstruct *ws, i
ws->reply = ws->outbuf; ws->reply = ws->outbuf;
if( code == CODE_HTTPERROR_302 ) if( code == CODE_HTTPERROR_302 )
ws->reply_size = snprintf( ws->reply, ws->outbuf_size, "HTTP/1.0 302 Found\r\nContent-Length: 0\r\nLocation: %s\r\n\r\n", g_redirecturl ); ws->reply_size = snprintf( ws->reply, G_OUTBUF_SIZE, "HTTP/1.0 302 Found\r\nContent-Length: 0\r\nLocation: %s\r\n\r\n", g_redirecturl );
else else
ws->reply_size = snprintf( ws->reply, ws->outbuf_size, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n", title, strlen(title)+16-4,title+4); ws->reply_size = snprintf( ws->reply, G_OUTBUF_SIZE, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n", title, strlen(title)+16-4,title+4);
#ifdef _DEBUG_HTTPERROR #ifdef _DEBUG_HTTPERROR
fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf ); fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf );
@ -245,13 +241,13 @@ static ssize_t http_handle_fullscrape( const int64 client_socket, struct ot_work
if( strstr( ws->request, "gzip" ) ) { if( strstr( ws->request, "gzip" ) ) {
h->flag |= STRUCT_HTTP_FLAG_GZIP; h->flag |= STRUCT_HTTP_FLAG_GZIP;
format = TASK_FLAG_GZIP; format = TASK_FLAG_GZIP;
stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, *(int*)h->ip, 0 ); stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, 0, (uintptr_t)h->ip );
} else } else
#endif #endif
stats_issue_event( EVENT_FULLSCRAPE_REQUEST, *(int*)h->ip, 0 ); stats_issue_event( EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)h->ip );
#ifdef _DEBUG_HTTPERROR #ifdef _DEBUG_HTTPERROR
write( 2, ws->debugbuf, ws->debugbuf_size ); write( 2, ws->debugbuf, G_DEBUGBUF_SIZE );
#endif #endif
/* Pass this task to the worker thread */ /* Pass this task to the worker thread */
@ -263,6 +259,7 @@ write( 2, ws->debugbuf, ws->debugbuf_size );
return ws->reply_size = -2; return ws->reply_size = -2;
} }
#endif #endif
static ssize_t http_handle_scrape( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { static ssize_t http_handle_scrape( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) {
static const ot_keywords keywords_scrape[] = { { "info_hash", 1 }, { NULL, -3 } }; static const ot_keywords keywords_scrape[] = { { "info_hash", 1 }, { NULL, -3 } };
@ -306,9 +303,6 @@ static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "even
#ifdef WANT_IP_FROM_QUERY_STRING #ifdef WANT_IP_FROM_QUERY_STRING
{ "ip", 7 }, { "ip", 7 },
#endif #endif
#ifdef _DEBUG_PEERID
{ "peer_id", 8 },
#endif
{ NULL, -3 } }; { NULL, -3 } };
static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } }; static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } };
static ssize_t http_handle_announce( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { static ssize_t http_handle_announce( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) {
@ -332,10 +326,6 @@ static ssize_t http_handle_announce( const int64 client_socket, struct ot_workst
numwant = 50; numwant = 50;
scanon = 1; scanon = 1;
#ifdef _DEBUG_PEERID
ws->peer_id = NULL;
#endif
while( scanon ) { while( scanon ) {
switch( scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) { switch( scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) {
case -2: scanon = 0; break; /* TERMINATOR */ case -2: scanon = 0; break; /* TERMINATOR */
@ -383,16 +373,14 @@ static ssize_t http_handle_announce( const int64 client_socket, struct ot_workst
break; break;
#ifdef WANT_IP_FROM_QUERY_STRING #ifdef WANT_IP_FROM_QUERY_STRING
case 7: /* matched "ip" */ case 7: /* matched "ip" */
len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ); {
if( ( len <= 0 ) || scan_fixed_ip( write_ptr, len, (unsigned char*)/*tmp*/ws->reply ) ) HTTPERROR_400_PARAM; char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply+16;
OT_SETIP( &peer, /*tmp*/ws->reply ); len = scan_urlencoded_query( &read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE );
tmp_buf2[len] = 0;
if( ( len <= 0 ) || scan_ip6( tmp_buf2, tmp_buf1 ) ) HTTPERROR_400_PARAM;
OT_SETIP( &peer, tmp_buf1 );
}
break; break;
#endif
#ifdef _DEBUG_PEERID
case 8: /* matched "peer_id" */
ws->peer_id_size = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
ws->peer_id = ws->peer_id_size > 0 ? write_ptr : 0;
break;
#endif #endif
} }
} }
@ -402,9 +390,9 @@ static ssize_t http_handle_announce( const int64 client_socket, struct ot_workst
return ws->reply_size = sprintf( ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" ); return ws->reply_size = sprintf( ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" );
if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED )
ws->reply_size = remove_peer_from_torrent( hash, &peer, ws->reply, FLAG_TCP ); ws->reply_size = remove_peer_from_torrent( *hash, &peer, ws->reply, FLAG_TCP );
else else
ws->reply_size = add_peer_to_torrent_and_return_peers(hash, &peer, FLAG_TCP, numwant, ws->reply ); ws->reply_size = add_peer_to_torrent_and_return_peers( *hash, &peer, FLAG_TCP, numwant, ws->reply );
if( !ws->reply_size ) HTTPERROR_500; if( !ws->reply_size ) HTTPERROR_500;
@ -418,9 +406,9 @@ ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws
#ifdef _DEBUG_HTTPERROR #ifdef _DEBUG_HTTPERROR
reply_off = ws->request_size; reply_off = ws->request_size;
if( ws->request_size >= (ssize_t)ws->debugbuf_size ) if( ws->request_size >= G_DEBUGBUF_SIZE )
reply_off = ws->debugbuf_size - 1; reply_off = G_DEBUGBUF_SIZE - 1;
memmove( ws->debugbuf, ws->request, reply_off ); memcpy( ws->debugbuf, ws->request, reply_off );
ws->debugbuf[ reply_off ] = 0; ws->debugbuf[ reply_off ] = 0;
#endif #endif

@ -19,7 +19,7 @@ struct http_data {
array request; array request;
io_batch batch; io_batch batch;
} data; } data;
char ip[4]; ot_ip6 ip;
STRUCT_HTTP_FLAG flag; STRUCT_HTTP_FLAG flag;
}; };

@ -15,6 +15,7 @@
#include "socket.h" #include "socket.h"
#include "ndelay.h" #include "ndelay.h"
#include "byte.h" #include "byte.h"
#include "ip6.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "trackerlogic.h"
@ -88,14 +89,14 @@ void livesync_init( ) {
/* Prepare outgoing peers buffer */ /* Prepare outgoing peers buffer */
g_peerbuffer_pos = g_peerbuffer_start; g_peerbuffer_pos = g_peerbuffer_start;
memmove( g_peerbuffer_pos, &g_tracker_id, sizeof( g_tracker_id ) ); memcpy( g_peerbuffer_pos, &g_tracker_id, sizeof( g_tracker_id ) );
uint32_pack_big( (char*)g_peerbuffer_pos + sizeof( g_tracker_id ), OT_SYNC_PEER); uint32_pack_big( (char*)g_peerbuffer_pos + sizeof( g_tracker_id ), OT_SYNC_PEER);
g_peerbuffer_pos += sizeof( g_tracker_id ) + sizeof( uint32_t); g_peerbuffer_pos += sizeof( g_tracker_id ) + sizeof( uint32_t);
#ifdef WANT_SYNC_SCRAPE #ifdef WANT_SYNC_SCRAPE
/* Prepare outgoing scrape buffer */ /* Prepare outgoing scrape buffer */
g_scrapebuffer_pos = g_scrapebuffer_start; g_scrapebuffer_pos = g_scrapebuffer_start;
memmove( g_scrapebuffer_pos, &g_tracker_id, sizeof( g_tracker_id ) ); memcpy( g_scrapebuffer_pos, &g_tracker_id, sizeof( g_tracker_id ) );
uint32_pack_big( (char*)g_scrapebuffer_pos + sizeof( g_tracker_id ), OT_SYNC_SCRAPE_TELL); uint32_pack_big( (char*)g_scrapebuffer_pos + sizeof( g_tracker_id ), OT_SYNC_SCRAPE_TELL);
g_scrapebuffer_pos += sizeof( g_tracker_id ) + sizeof( uint32_t); g_scrapebuffer_pos += sizeof( g_tracker_id ) + sizeof( uint32_t);
@ -116,8 +117,13 @@ void livesync_deinit() {
pthread_cancel( thread_id ); pthread_cancel( thread_id );
} }
void livesync_bind_mcast( char *ip, uint16_t port) { void livesync_bind_mcast( ot_ip6 ip, uint16_t port) {
char tmpip[4] = {0,0,0,0}; char tmpip[4] = {0,0,0,0};
char *v4ip;
if( !ip6_isv4mapped(ip))
exerr("v6 mcast support not yet available.");
v4ip = ip+12;
if( g_socket_in != -1 ) if( g_socket_in != -1 )
exerr("Error: Livesync listen ip specified twice."); exerr("Error: Livesync listen ip specified twice.");
@ -129,12 +135,12 @@ void livesync_bind_mcast( char *ip, uint16_t port) {
if( socket_bind4_reuse( g_socket_in, tmpip, port ) == -1 ) if( socket_bind4_reuse( g_socket_in, tmpip, port ) == -1 )
exerr("Error: Cant bind live sync incoming socket." ); exerr("Error: Cant bind live sync incoming socket." );
if( socket_mcjoin4( g_socket_in, groupip_1, ip ) ) if( socket_mcjoin4( g_socket_in, groupip_1, v4ip ) )
exerr("Error: Cant make live sync incoming socket join mcast group."); exerr("Error: Cant make live sync incoming socket join mcast group.");
if( ( g_socket_out = socket_udp4()) < 0) if( ( g_socket_out = socket_udp4()) < 0)
exerr("Error: Cant create live sync outgoing socket." ); exerr("Error: Cant create live sync outgoing socket." );
if( socket_bind4_reuse( g_socket_out, ip, port ) == -1 ) if( socket_bind4_reuse( g_socket_out, v4ip, port ) == -1 )
exerr("Error: Cant bind live sync outgoing socket." ); exerr("Error: Cant bind live sync outgoing socket." );
socket_mcttl4(g_socket_out, 1); socket_mcttl4(g_socket_out, 1);
@ -160,9 +166,9 @@ static void livesync_handle_peersync( ssize_t datalen ) {
if( !g_opentracker_running ) return; if( !g_opentracker_running ) return;
if( OT_PEERFLAG(peer) & PEER_FLAG_STOPPED ) if( OT_PEERFLAG(peer) & PEER_FLAG_STOPPED )
remove_peer_from_torrent(hash, peer, NULL, FLAG_MCA ); remove_peer_from_torrent( *hash, peer, NULL, FLAG_MCA );
else else
add_peer_to_torrent( hash, peer, FLAG_MCA ); add_peer_to_torrent( *hash, peer, FLAG_MCA );
off += sizeof( ot_hash ) + sizeof( ot_peer ); off += sizeof( ot_hash ) + sizeof( ot_peer );
} }
@ -175,7 +181,7 @@ void livesync_issue_beacon( ) {
size_t torrent_count = mutex_get_torrent_count(); size_t torrent_count = mutex_get_torrent_count();
uint8_t beacon[ sizeof(g_tracker_id) + sizeof(uint32_t) + sizeof( uint64_t ) ]; uint8_t beacon[ sizeof(g_tracker_id) + sizeof(uint32_t) + sizeof( uint64_t ) ];
memmove( beacon, &g_tracker_id, sizeof( g_tracker_id ) ); memcpy( beacon, &g_tracker_id, sizeof( g_tracker_id ) );
uint32_pack_big( (char*)beacon + sizeof( g_tracker_id ), OT_SYNC_SCRAPE_BEACON); uint32_pack_big( (char*)beacon + sizeof( g_tracker_id ), OT_SYNC_SCRAPE_BEACON);
uint32_pack_big( (char*)beacon + sizeof( g_tracker_id ) + sizeof(uint32_t), (uint32_t)((uint64_t)(torrent_count)>>32) ); uint32_pack_big( (char*)beacon + sizeof( g_tracker_id ) + sizeof(uint32_t), (uint32_t)((uint64_t)(torrent_count)>>32) );
uint32_pack_big( (char*)beacon + sizeof( g_tracker_id ) + 2 * sizeof(uint32_t), (uint32_t)torrent_count ); uint32_pack_big( (char*)beacon + sizeof( g_tracker_id ) + 2 * sizeof(uint32_t), (uint32_t)torrent_count );
@ -202,7 +208,7 @@ void livesync_handle_beacon( ssize_t datalen ) {
if( torrent_count_remote > g_inquire_remote_count ) { if( torrent_count_remote > g_inquire_remote_count ) {
g_inquire_remote_count = torrent_count_remote; g_inquire_remote_count = torrent_count_remote;
memmove( &g_inquire_remote_host, g_inbuffer, sizeof( g_tracker_id ) ); memcpy( &g_inquire_remote_host, g_inbuffer, sizeof( g_tracker_id ) );
} }
} }
} }
@ -210,9 +216,9 @@ void livesync_handle_beacon( ssize_t datalen ) {
void livesync_issue_inquire( ) { void livesync_issue_inquire( ) {
uint8_t inquire[ sizeof(g_tracker_id) + sizeof(uint32_t) + sizeof(g_tracker_id)]; uint8_t inquire[ sizeof(g_tracker_id) + sizeof(uint32_t) + sizeof(g_tracker_id)];
memmove( inquire, &g_tracker_id, sizeof( g_tracker_id ) ); memcpy( inquire, &g_tracker_id, sizeof( g_tracker_id ) );
uint32_pack_big( (char*)inquire + sizeof( g_tracker_id ), OT_SYNC_SCRAPE_INQUIRE); uint32_pack_big( (char*)inquire + sizeof( g_tracker_id ), OT_SYNC_SCRAPE_INQUIRE);
memmove( inquire + sizeof(g_tracker_id) + sizeof(uint32_t), &g_inquire_remote_host, sizeof( g_tracker_id ) ); memcpy( inquire + sizeof(g_tracker_id) + sizeof(uint32_t), &g_inquire_remote_host, sizeof( g_tracker_id ) );
socket_send4(g_socket_out, (char*)inquire, sizeof(inquire), groupip_1, LIVESYNC_PORT); socket_send4(g_socket_out, (char*)inquire, sizeof(inquire), groupip_1, LIVESYNC_PORT);
} }
@ -239,7 +245,7 @@ void livesync_issue_tell( ) {
unsigned int j; unsigned int j;
for( j=0; j<torrents_list->size; ++j ) { for( j=0; j<torrents_list->size; ++j ) {
ot_torrent *torrent = (ot_torrent*)(torrents_list->data) + j; ot_torrent *torrent = (ot_torrent*)(torrents_list->data) + j;
memmove(g_scrapebuffer_pos, torrent->hash, sizeof(ot_hash)); memcpy(g_scrapebuffer_pos, torrent->hash, sizeof(ot_hash));
g_scrapebuffer_pos += sizeof(ot_hash); g_scrapebuffer_pos += sizeof(ot_hash);
uint32_pack_big( (char*)g_scrapebuffer_pos , (uint32_t)(g_now_minutes - torrent->peer_list->base )); uint32_pack_big( (char*)g_scrapebuffer_pos , (uint32_t)(g_now_minutes - torrent->peer_list->base ));
uint32_pack_big( (char*)g_scrapebuffer_pos + 4, (uint32_t)((uint64_t)(torrent->peer_list->down_count)>>32) ); uint32_pack_big( (char*)g_scrapebuffer_pos + 4, (uint32_t)((uint64_t)(torrent->peer_list->down_count)>>32) );
@ -268,29 +274,29 @@ void livesync_handle_tell( ssize_t datalen ) {
/* Some instance is in progress of telling. Our inquiry was successful. /* Some instance is in progress of telling. Our inquiry was successful.
Don't ask again until we see next beacon. */ Don't ask again until we see next beacon. */
g_next_inquire_time = 0; g_next_inquire_time = 0;
/* Don't cause any new inquiries during another tracker's tell */ /* Don't cause any new inquiries during another tracker's tell */
if( g_next_beacon_time - g_now_seconds < LIVESYNC_BEACON_INTERVAL ) if( g_next_beacon_time - g_now_seconds < LIVESYNC_BEACON_INTERVAL )
g_next_beacon_time = g_now_seconds + LIVESYNC_BEACON_INTERVAL; g_next_beacon_time = g_now_seconds + LIVESYNC_BEACON_INTERVAL;
while( off + sizeof(ot_hash) + 12 <= (size_t)datalen ) { while( off + sizeof(ot_hash) + 12 <= (size_t)datalen ) {
ot_hash *hash = (ot_hash*)(g_inbuffer+off); ot_hash *hash = (ot_hash*)(g_inbuffer+off);
ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); ot_vector *torrents_list = mutex_bucket_lock_by_hash(*hash);
size_t down_count_remote; size_t down_count_remote;
int exactmatch; int exactmatch;
ot_torrent * torrent = vector_find_or_insert(torrents_list, hash, sizeof(ot_hash), OT_HASH_COMPARE_SIZE, &exactmatch); ot_torrent * torrent = vector_find_or_insert(torrents_list, hash, sizeof(ot_hash), OT_HASH_COMPARE_SIZE, &exactmatch);
if( !torrent ) { if( !torrent ) {
mutex_bucket_unlock_by_hash( hash, 0 ); mutex_bucket_unlock_by_hash( *hash, 0 );
continue; continue;
} }
if( !exactmatch ) { if( !exactmatch ) {
/* Create a new torrent entry, then */ /* Create a new torrent entry, then */
int i; for(i=0;i<20;i+=4) WRITE32(&torrent->hash,i,READ32(hash,i)); memcpy( &torrent->hash, hash, sizeof(ot_hash));
if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) {
vector_remove_torrent( torrents_list, torrent ); vector_remove_torrent( torrents_list, torrent );
mutex_bucket_unlock_by_hash( hash, 0 ); mutex_bucket_unlock_by_hash( *hash, 0 );
continue; continue;
} }
@ -298,8 +304,8 @@ void livesync_handle_tell( ssize_t datalen ) {
torrent->peer_list->base = g_now_minutes - uint32_read_big((char*)g_inbuffer+off+sizeof(ot_hash)); torrent->peer_list->base = g_now_minutes - uint32_read_big((char*)g_inbuffer+off+sizeof(ot_hash));
} }
down_count_remote = (size_t)(((uint64_t)uint32_read_big((char*)g_inbuffer+off+sizeof( ot_hash ) + sizeof(uint32_t))) << 32); down_count_remote = (size_t)(((uint64_t)uint32_read_big((char*)g_inbuffer+off+sizeof(ot_hash ) + sizeof(uint32_t))) << 32);
down_count_remote |= (size_t) uint32_read_big((char*)g_inbuffer+off+sizeof( ot_hash ) + 2 * sizeof(uint32_t)); down_count_remote |= (size_t) uint32_read_big((char*)g_inbuffer+off+sizeof(ot_hash ) + 2 * sizeof(uint32_t));
if( down_count_remote > torrent->peer_list->down_count ) if( down_count_remote > torrent->peer_list->down_count )
torrent->peer_list->down_count = down_count_remote; torrent->peer_list->down_count = down_count_remote;
@ -319,7 +325,7 @@ void livesync_handle_tell( ssize_t datalen ) {
stuck when there's not enough traffic to fill udp packets fast stuck when there's not enough traffic to fill udp packets fast
enough */ enough */
void livesync_ticker( ) { void livesync_ticker( ) {
/* livesync_issue_peersync sets g_next_packet_time */ /* livesync_issue_peersync sets g_next_packet_time */
if( g_now_seconds > g_next_packet_time && if( g_now_seconds > g_next_packet_time &&
g_peerbuffer_pos > g_peerbuffer_start + sizeof( g_tracker_id ) ) g_peerbuffer_pos > g_peerbuffer_start + sizeof( g_tracker_id ) )
@ -350,21 +356,19 @@ void livesync_ticker( ) {
} }
/* Inform live sync about whats going on. */ /* Inform live sync about whats going on. */
void livesync_tell( ot_hash * const info_hash, const ot_peer * const peer ) { void livesync_tell( ot_hash const info_hash, const ot_peer * const peer ) {
unsigned int i;
for(i=0;i<sizeof(ot_hash)/4;i+=4) WRITE32(g_peerbuffer_pos,i,READ32(info_hash,i));
WRITE32(g_peerbuffer_pos,sizeof(ot_hash) ,READ32(peer,0)); memcpy( g_peerbuffer_pos, info_hash, sizeof(ot_hash) );
WRITE32(g_peerbuffer_pos,sizeof(ot_hash)+4,READ32(peer,4)); memcpy( g_peerbuffer_pos+sizeof(ot_hash), peer, sizeof(ot_peer) );
g_peerbuffer_pos += sizeof(ot_hash)+8; g_peerbuffer_pos += sizeof(ot_hash)+sizeof(ot_peer);
if( g_peerbuffer_pos >= g_peerbuffer_highwater ) if( g_peerbuffer_pos >= g_peerbuffer_highwater )
livesync_issue_peersync(); livesync_issue_peersync();
} }
static void * livesync_worker( void * args ) { static void * livesync_worker( void * args ) {
uint8_t in_ip[4]; uint16_t in_port; ot_ip6 in_ip; uint16_t in_port;
ssize_t datalen; ssize_t datalen;
(void)args; (void)args;
@ -375,7 +379,7 @@ static void * livesync_worker( void * args ) {
/* Expect at least tracker id and packet type */ /* Expect at least tracker id and packet type */
if( datalen <= (ssize_t)(sizeof( g_tracker_id ) + sizeof( uint32_t )) ) if( datalen <= (ssize_t)(sizeof( g_tracker_id ) + sizeof( uint32_t )) )
continue; continue;
if( !accesslist_isblessed((char*)in_ip, OT_PERMISSION_MAY_LIVESYNC)) if( !accesslist_isblessed(in_ip, OT_PERMISSION_MAY_LIVESYNC))
continue; continue;
if( !memcmp( g_inbuffer, &g_tracker_id, sizeof( g_tracker_id ) ) ) { if( !memcmp( g_inbuffer, &g_tracker_id, sizeof( g_tracker_id ) ) ) {
/* TODO: log packet coming from ourselves */ /* TODO: log packet coming from ourselves */

@ -86,7 +86,7 @@ void livesync_deinit();
void livesync_bind_mcast( char *ip, uint16_t port ); void livesync_bind_mcast( char *ip, uint16_t port );
/* Inform live sync about whats going on. */ /* Inform live sync about whats going on. */
void livesync_tell( ot_hash * const info_hash, const ot_peer * const peer ); void livesync_tell( ot_hash const info_hash, const ot_peer * const peer );
/* Tickle the live sync module from time to time, so no events get /* Tickle the live sync module from time to time, so no events get
stuck when there's not enough traffic to fill udp packets fast stuck when there's not enough traffic to fill udp packets fast

@ -80,8 +80,8 @@ ot_vector *mutex_bucket_lock( int bucket ) {
return all_torrents + bucket; return all_torrents + bucket;
} }
ot_vector *mutex_bucket_lock_by_hash( ot_hash *hash ) { ot_vector *mutex_bucket_lock_by_hash( ot_hash hash ) {
int bucket = uint32_read_big( (char*)*hash ) >> OT_BUCKET_COUNT_SHIFT; int bucket = uint32_read_big( (char*)hash ) >> OT_BUCKET_COUNT_SHIFT;
/* Can block */ /* Can block */
mutex_bucket_lock( bucket ); mutex_bucket_lock( bucket );
@ -96,8 +96,8 @@ void mutex_bucket_unlock( int bucket, int delta_torrentcount ) {
pthread_mutex_unlock( &bucket_mutex ); pthread_mutex_unlock( &bucket_mutex );
} }
void mutex_bucket_unlock_by_hash( ot_hash *hash, int delta_torrentcount ) { void mutex_bucket_unlock_by_hash( ot_hash hash, int delta_torrentcount ) {
mutex_bucket_unlock( uint32_read_big( (char*)*hash ) >> OT_BUCKET_COUNT_SHIFT, delta_torrentcount ); mutex_bucket_unlock( uint32_read_big( (char*)hash ) >> OT_BUCKET_COUNT_SHIFT, delta_torrentcount );
} }
size_t mutex_get_torrent_count( ) { size_t mutex_get_torrent_count( ) {

@ -12,10 +12,10 @@ void mutex_init( );
void mutex_deinit( ); void mutex_deinit( );
ot_vector *mutex_bucket_lock( int bucket ); ot_vector *mutex_bucket_lock( int bucket );
ot_vector *mutex_bucket_lock_by_hash( ot_hash *hash ); ot_vector *mutex_bucket_lock_by_hash( ot_hash hash );
void mutex_bucket_unlock( int bucket, int delta_torrentcount ); void mutex_bucket_unlock( int bucket, int delta_torrentcount );
void mutex_bucket_unlock_by_hash( ot_hash *hash, int delta_torrentcount ); void mutex_bucket_unlock_by_hash( ot_hash hash, int delta_torrentcount );
size_t mutex_get_torrent_count(); size_t mutex_get_torrent_count();

@ -12,10 +12,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h>
/* Libowfat */ /* Libowfat */
#include "byte.h" #include "byte.h"
#include "io.h" #include "io.h"
#include "ip6.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "trackerlogic.h"
@ -132,8 +134,8 @@ static void stats_get_highscore_networks( stats_network_node *node, int depth, u
while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j; while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j;
--j; --j;
memmove( scores, scores + 1, j * sizeof( *scores ) ); memcpy( scores, scores + 1, j * sizeof( *scores ) );
memmove( networks, networks + 1, j * sizeof( *networks ) ); memcpy( networks, networks + 1, j * sizeof( *networks ) );
scores[ j ] = node->counters[ i ]; scores[ j ] = node->counters[ i ];
networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ); networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) );
} }
@ -176,13 +178,13 @@ size_t stats_top10_txt( char * reply ) {
ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list;
int idx = 9; while( (idx >= 0) && ( peer_list->peer_count > top10c[idx].val ) ) --idx; int idx = 9; while( (idx >= 0) && ( peer_list->peer_count > top10c[idx].val ) ) --idx;
if ( idx++ != 9 ) { if ( idx++ != 9 ) {
memmove( top10c + idx + 1, top10c + idx, ( 9 - idx ) * sizeof( ot_record ) ); memcpy( top10c + idx + 1, top10c + idx, ( 9 - idx ) * sizeof( ot_record ) );
top10c[idx].val = peer_list->peer_count; top10c[idx].val = peer_list->peer_count;
top10c[idx].torrent = (ot_torrent*)(torrents_list->data) + j; top10c[idx].torrent = (ot_torrent*)(torrents_list->data) + j;
} }
idx = 9; while( (idx >= 0) && ( peer_list->seed_count > top10s[idx].val ) ) --idx; idx = 9; while( (idx >= 0) && ( peer_list->seed_count > top10s[idx].val ) ) --idx;
if ( idx++ != 9 ) { if ( idx++ != 9 ) {
memmove( top10s + idx + 1, top10s + idx, ( 9 - idx ) * sizeof( ot_record ) ); memcpy( top10s + idx + 1, top10s + idx, ( 9 - idx ) * sizeof( ot_record ) );
top10s[idx].val = peer_list->seed_count; top10s[idx].val = peer_list->seed_count;
top10s[idx].torrent = (ot_torrent*)(torrents_list->data) + j; top10s[idx].torrent = (ot_torrent*)(torrents_list->data) + j;
} }
@ -269,7 +271,7 @@ static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh )
while( ( insert_pos >= 0 ) && ( count[j] > slash24s[ 2 * insert_pos ] ) ) while( ( insert_pos >= 0 ) && ( count[j] > slash24s[ 2 * insert_pos ] ) )
--insert_pos; --insert_pos;
++insert_pos; ++insert_pos;
memmove( slash24s + 2 * ( insert_pos + 1 ), slash24s + 2 * ( insert_pos ), 2 * sizeof( uint32_t ) * ( amount - insert_pos - 1 ) ); memcpy( slash24s + 2 * ( insert_pos + 1 ), slash24s + 2 * ( insert_pos ), 2 * sizeof( uint32_t ) * ( amount - insert_pos - 1 ) );
slash24s[ 2 * insert_pos ] = count[j]; slash24s[ 2 * insert_pos ] = count[j];
slash24s[ 2 * insert_pos + 1 ] = ( i << NUM_TOPBITS ) + j; slash24s[ 2 * insert_pos + 1 ] = ( i << NUM_TOPBITS ) + j;
if( slash24s[ 2 * amount - 2 ] > thresh ) if( slash24s[ 2 * amount - 2 ] > thresh )
@ -537,7 +539,7 @@ static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype
iovec_fixlast( iovec_entries, iovector, r ); iovec_fixlast( iovec_entries, iovector, r );
} }
void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uint32_t event_data ) { void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event_data ) {
switch( event ) { switch( event ) {
case EVENT_ACCEPT: case EVENT_ACCEPT:
if( proto == FLAG_TCP ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; if( proto == FLAG_TCP ) ot_overall_tcp_connections++; else ot_overall_udp_connections++;
@ -559,16 +561,24 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uint32_t event_
break; break;
case EVENT_FULLSCRAPE_REQUEST: case EVENT_FULLSCRAPE_REQUEST:
{ {
uint8_t ip[4]; *(uint32_t*)ip = (uint32_t)proto; /* ugly hack to transfer ip to stats */ ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */
LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE\n", (unsigned int)(g_now_seconds - ot_start_time)/60, ip[0], ip[1], ip[2], ip[3] ); char _debug[512];
ot_full_scrape_request_count++; int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 );
off += fmt_ip6( _debug+off, *ip );
off += snprintf( _debug, sizeof(_debug)-off, " - FULL SCRAPE\n" );
write( 2, _debug, off );
ot_full_scrape_request_count++;
} }
break; break;
case EVENT_FULLSCRAPE_REQUEST_GZIP: case EVENT_FULLSCRAPE_REQUEST_GZIP:
{ {
uint8_t ip[4]; *(uint32_t*)ip = (uint32_t)proto; /* ugly hack to transfer ip to stats */ ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */
LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE GZIP\n", (unsigned int)(g_now_seconds - ot_start_time)/60, ip[0], ip[1], ip[2], ip[3] ); char _debug[512];
ot_full_scrape_request_count++; int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 );
off += fmt_ip6(_debug+off, *ip );
off += snprintf( _debug, sizeof(_debug)-off, " - FULL SCRAPE\n" );
write( 2, _debug, off );
ot_full_scrape_request_count++;
} }
break; break;
case EVENT_FAILED: case EVENT_FAILED:

@ -32,7 +32,7 @@ enum {
CODE_HTTPERROR_COUNT CODE_HTTPERROR_COUNT
}; };
void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uint32_t event_data ); void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event_data );
void stats_deliver( int64 socket, int tasktype ); void stats_deliver( int64 socket, int tasktype );
size_t return_stats_for_tracker( char *reply, int mode, int format ); size_t return_stats_for_tracker( char *reply, int mode, int format );
size_t stats_return_tracker_version( char *reply ); size_t stats_return_tracker_version( char *reply );

@ -19,15 +19,15 @@
static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff }; static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff };
static void udp_make_connectionid( uint32_t * connid, const char * remoteip ) { static void udp_make_connectionid( uint32_t * connid, const ot_ip6 remoteip ) {
/* Touch unused variable */ /* Touch unused variable */
(void)remoteip; (void)remoteip;
/* Use a static secret for now */ /* Use a static secret for now */
memmove( connid, g_static_connid, 8 ); memcpy( connid, g_static_connid, 8 );
} }
static int udp_test_connectionid( const uint32_t * const connid, const char * remoteip ) { static int udp_test_connectionid( const uint32_t * const connid, const ot_ip6 remoteip ) {
/* Touch unused variable */ /* Touch unused variable */
(void)remoteip; (void)remoteip;
@ -36,19 +36,19 @@ static int udp_test_connectionid( const uint32_t * const connid, const char * re
} }
/* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */ /* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */
void handle_udp4( int64 serversocket, struct ot_workstruct *ws ) { void handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
ot_peer peer; ot_peer peer;
ot_hash *hash = NULL; ot_hash *hash = NULL;
char remoteip[4]; ot_ip6 remoteip;
uint32_t *inpacket = (uint32_t*)ws->inbuf; uint32_t *inpacket = (uint32_t*)ws->inbuf;
uint32_t *outpacket = (uint32_t*)ws->outbuf; uint32_t *outpacket = (uint32_t*)ws->outbuf;
uint32_t numwant, left, event; uint32_t numwant, left, event, scopeid;
uint16_t port, remoteport; uint16_t port, remoteport;
size_t r, r_out; size_t r, r_out;
r = socket_recv4( serversocket, ws->inbuf, ws->inbuf_size, remoteip, &remoteport); r = socket_recv6( serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid );
stats_issue_event( EVENT_ACCEPT, FLAG_UDP, ntohl(*(uint32_t*)remoteip) ); stats_issue_event( EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip );
stats_issue_event( EVENT_READ, FLAG_UDP, r ); stats_issue_event( EVENT_READ, FLAG_UDP, r );
/* Minimum udp tracker packet size, also catches error */ /* Minimum udp tracker packet size, also catches error */
@ -65,7 +65,7 @@ void handle_udp4( int64 serversocket, struct ot_workstruct *ws ) {
outpacket[1] = inpacket[3]; outpacket[1] = inpacket[3];
udp_make_connectionid( outpacket + 2, remoteip ); udp_make_connectionid( outpacket + 2, remoteip );
socket_send4( serversocket, ws->outbuf, 16, remoteip, remoteport ); socket_send6( serversocket, ws->outbuf, 16, remoteip, remoteport, 0 );
stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 ); stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 );
break; break;
case 1: /* This is an announce action */ case 1: /* This is an announce action */
@ -103,11 +103,11 @@ void handle_udp4( int64 serversocket, struct ot_workstruct *ws ) {
outpacket[1] = inpacket[12/4]; outpacket[1] = inpacket[12/4];
if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */ if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */
r = remove_peer_from_torrent( hash, &peer, ws->outbuf, FLAG_UDP ); r = remove_peer_from_torrent( *hash, &peer, ws->outbuf, FLAG_UDP );
else else
r = 8 + add_peer_to_torrent_and_return_peers( hash, &peer, FLAG_UDP, numwant, ((char*)outpacket) + 8 ); r = 8 + add_peer_to_torrent_and_return_peers( *hash, &peer, FLAG_UDP, numwant, ((char*)outpacket) + 8 );
socket_send4( serversocket, ws->outbuf, r, remoteip, remoteport ); socket_send6( serversocket, ws->outbuf, r, remoteip, remoteport, 0 );
stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r ); stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r );
break; break;
@ -119,9 +119,9 @@ void handle_udp4( int64 serversocket, struct ot_workstruct *ws ) {
outpacket[1] = inpacket[12/4]; outpacket[1] = inpacket[12/4];
for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ ) for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ )
return_udp_scrape_for_torrent( (ot_hash*)( ((char*)inpacket) + 16 + 20 * r_out ), ((char*)outpacket) + 8 + 12 * r_out ); return_udp_scrape_for_torrent( *(ot_hash*)( ((char*)inpacket) + 16 + 20 * r_out ), ((char*)outpacket) + 8 + 12 * r_out );
socket_send4( serversocket, ws->outbuf, 8 + 12 * r_out, remoteip, remoteport ); socket_send6( serversocket, ws->outbuf, 8 + 12 * r_out, remoteip, remoteport, 0 );
stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r ); stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r );
break; break;
} }

@ -6,6 +6,6 @@
#ifndef __OT_UDP_H__ #ifndef __OT_UDP_H__
#define __OT_UDP_H__ #define __OT_UDP_H__
void handle_udp4( int64 serversocket, struct ot_workstruct *ws ); void handle_udp6( int64 serversocket, struct ot_workstruct *ws );
#endif #endif

@ -17,9 +17,7 @@
#include "uint16.h" #include "uint16.h"
static int vector_compare_peer(const void *peer1, const void *peer2 ) { static int vector_compare_peer(const void *peer1, const void *peer2 ) {
int32_t cmp = READ32(peer2,0) - READ32(peer1,0); return memcmp( peer1, peer2, OT_PEER_COMPARE_SIZE );
if (cmp == 0) cmp = READ16(peer2,4) - READ16(peer1,4);
return cmp;
} }
/* This function gives us a binary search that returns a pointer, even if /* This function gives us a binary search that returns a pointer, even if
@ -30,19 +28,14 @@ static int vector_compare_peer(const void *peer1, const void *peer2 ) {
*/ */
void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size, 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 compare_size, int *exactmatch ) {
size_t offs, mc = member_count; size_t mc = member_count;
int8_t *lookat = ((int8_t*)base) + member_size * (mc >> 1); int8_t *lookat = ((int8_t*)base) + member_size * (mc >> 1);
int32_t key_cache = READ32(key,0);
*exactmatch = 1; *exactmatch = 1;
while( mc ) { while( mc ) {
int32_t cmp = READ32(lookat,0) - key_cache; int32_t cmp = memcmp( lookat, key, compare_size );
if (cmp == 0) { if( cmp == 0 )
for( offs = 4; cmp == 0 && offs < compare_size; offs += 4 ) return (void *)lookat;
cmp = READ32(lookat,offs) - READ32(key,offs);
if( cmp == 0 )
return (void *)lookat;
}
if (cmp < 0) { if (cmp < 0) {
base = (void*)(lookat + member_size); base = (void*)(lookat + member_size);
@ -60,13 +53,10 @@ void *binary_search( const void * const key, const void * base, const size_t mem
ot_peer *binary_search_peer( const ot_peer * const peer, const ot_peer * base, const size_t member_count, int *exactmatch ) { ot_peer *binary_search_peer( const ot_peer * const peer, const ot_peer * base, const size_t member_count, int *exactmatch ) {
size_t mc = member_count; size_t mc = member_count;
const ot_peer *lookat = base + (mc >> 1); const ot_peer *lookat = base + (mc >> 1);
int32_t low = READ32(peer,0);
int16_t high = READ16(peer,4);
*exactmatch = 1; *exactmatch = 1;
while( mc ) { while( mc ) {
int32_t cmp = READ32(lookat,0) - low; int32_t cmp = memcmp(lookat,peer,OT_PEER_COMPARE_SIZE );
if(cmp == 0) cmp = READ16(lookat,4) - high;
if(cmp == 0) return (ot_peer*)lookat; if(cmp == 0) return (ot_peer*)lookat;
if (cmp < 0) { if (cmp < 0) {
@ -84,7 +74,7 @@ ot_peer *binary_search_peer( const ot_peer * const peer, const ot_peer * base, c
static uint8_t vector_hash_peer( ot_peer *peer, int bucket_count ) { static uint8_t vector_hash_peer( ot_peer *peer, int bucket_count ) {
unsigned int hash = 5381, i = 6; unsigned int hash = 5381, i = OT_PEER_COMPARE_SIZE;
uint8_t *p = (uint8_t*)peer; uint8_t *p = (uint8_t*)peer;
while( i-- ) hash += (hash<<5) + *(p++); while( i-- ) hash += (hash<<5) + *(p++);
return hash % bucket_count; return hash % bucket_count;

@ -140,21 +140,4 @@ ssize_t scan_fixed_int( char *data, size_t len, int *tmp ) {
return len; return len;
} }
ssize_t scan_fixed_ip( char *data, size_t len, unsigned char ip[4] ) {
int u, i;
for( i=0; i<4; ++i ) {
ssize_t j = scan_fixed_int( data, len, &u );
if( j == (ssize_t)len ) return len;
ip[i] = u;
data += len - j;
len = j;
if ( i<3 ) {
if( !len || *data != '.') return -1;
--len; ++data;
}
}
return len;
}
const char *g_version_scan_urlencoded_query_c = "$Source$: $Revision$\n"; const char *g_version_scan_urlencoded_query_c = "$Source$: $Revision$\n";

@ -46,17 +46,10 @@ int scan_find_keywords( const ot_keywords * keywords, char **string, SCAN_SEARCH
void scan_urlencoded_skipvalue( char **string ); void scan_urlencoded_skipvalue( char **string );
/* data pointer to len chars of string /* data pointer to len chars of string
len length of chars in data to parse len length of chars in data to parse
number number to receive result number number to receive result
returns number of bytes not parsed, mostly !=0 means fail returns number of bytes not parsed, mostly !=0 means fail
*/ */
ssize_t scan_fixed_int( char *data, size_t len, int *number ); ssize_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
*/
ssize_t scan_fixed_ip( char *data, size_t len, unsigned char ip[4] );
#endif #endif

@ -41,12 +41,7 @@ void free_peerlist( ot_peerlist *peer_list ) {
free( peer_list ); free( peer_list );
} }
#ifdef _DEBUG_PEERID size_t add_peer_to_torrent_and_return_peers( ot_hash hash, ot_peer *peer, PROTO_FLAG proto, size_t amount, char * reply ) {
extern size_t g_this_peerid_len;
extern char *g_this_peerid_data;
#endif
size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO_FLAG proto, size_t amount, char * reply ) {
int exactmatch, delta_torrentcount = 0; int exactmatch, delta_torrentcount = 0;
size_t reply_size; size_t reply_size;
ot_torrent *torrent; ot_torrent *torrent;
@ -66,7 +61,7 @@ size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO
if( !exactmatch ) { if( !exactmatch ) {
/* Create a new torrent entry, then */ /* Create a new torrent entry, then */
int i; for(i=0;i<20;i+=4) WRITE32(&torrent->hash,i,READ32(hash,i)); memcpy( torrent->hash, hash, sizeof(ot_hash) );
if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) {
vector_remove_torrent( torrents_list, torrent ); vector_remove_torrent( torrents_list, torrent );
@ -114,16 +109,6 @@ size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO
} else { } else {
stats_issue_event( EVENT_RENEW, 0, OT_PEERTIME( peer_dest ) ); stats_issue_event( EVENT_RENEW, 0, OT_PEERTIME( peer_dest ) );
#ifdef _DEBUG_PEERID
if( OT_PEERTIME( peer_dest ) < 2 ) {
uint8_t *_ip = (uint8_t*)peer_dest;
int i;
for( i=0;i<20;++i)printf("%02X",(*hash)[i]);
if( g_this_peerid_data ) g_this_peerid_data[g_this_peerid_len] = 0;
printf( " %d.%d.%d.%d:%d\t%d %02X %s\n", _ip[0], _ip[1], _ip[2], _ip[3], OT_PEERTIME( peer_dest ), *(uint16_t*)( ((char*)peer_dest)+4 ), OT_PEERFLAG(peer_dest), g_this_peerid_data ? g_this_peerid_data : "-" );
}
#endif
#ifdef WANT_SYNC_LIVE #ifdef WANT_SYNC_LIVE
/* Won't live sync peers that come back too fast. Only exception: /* Won't live sync peers that come back too fast. Only exception:
fresh "completed" reports */ fresh "completed" reports */
@ -144,7 +129,7 @@ size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO
OT_PEERFLAG( peer ) |= PEER_FLAG_COMPLETED; OT_PEERFLAG( peer ) |= PEER_FLAG_COMPLETED;
} }
*(uint64_t*)(peer_dest) = *(uint64_t*)(peer); *peer_dest = *peer;
#ifdef WANT_SYNC #ifdef WANT_SYNC
if( proto == FLAG_MCA ) { if( proto == FLAG_MCA ) {
mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); mutex_bucket_unlock_by_hash( hash, delta_torrentcount );
@ -153,7 +138,7 @@ size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO
#endif #endif
reply_size = return_peers_for_torrent( torrent, amount, reply, proto ); reply_size = return_peers_for_torrent( torrent, amount, reply, proto );
mutex_bucket_unlock_by_hash( &torrent->hash, delta_torrentcount ); mutex_bucket_unlock_by_hash( torrent->hash, delta_torrentcount );
return reply_size; return reply_size;
} }
@ -171,9 +156,9 @@ static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) {
ot_peer * peers = (ot_peer*)bucket_list[bucket].data; ot_peer * peers = (ot_peer*)bucket_list[bucket].data;
size_t peer_count = bucket_list[bucket].size; size_t peer_count = bucket_list[bucket].size;
while( peer_count-- ) { while( peer_count-- ) {
WRITE32(r,0,READ32(peers,0)); memcpy(r,peers,OT_PEER_COMPARE_SIZE);
WRITE16(r,4,READ16(peers++,4)); peers+=sizeof(ot_peer);
r+=6; r+=OT_PEER_COMPARE_SIZE;
} }
} }
@ -216,9 +201,8 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha
bucket_index = ( bucket_index + 1 ) % num_buckets; bucket_index = ( bucket_index + 1 ) % num_buckets;
} }
peer = ((ot_peer*)bucket_list[bucket_index].data) + bucket_offset; peer = ((ot_peer*)bucket_list[bucket_index].data) + bucket_offset;
WRITE32(r,0,READ32(peer,0)); memcpy(r,peer,OT_PEER_COMPARE_SIZE);
WRITE16(r,4,READ16(peer,4)); r+=OT_PEER_COMPARE_SIZE;
r+=6;
} }
return r - reply; return r - reply;
} }
@ -236,7 +220,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply
if( proto == FLAG_TCP ) { if( proto == FLAG_TCP ) {
int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM;
r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie5:peers%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, 6*amount ); r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie5:peers" PEERS6 "%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, OT_PEER_COMPARE_SIZE*amount );
} else { } else {
*(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM );
*(uint32_t*)(r+4) = htonl( peer_list->peer_count ); *(uint32_t*)(r+4) = htonl( peer_list->peer_count );
@ -258,7 +242,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply
} }
/* Fetches scrape info for a specific torrent */ /* Fetches scrape info for a specific torrent */
size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { size_t return_udp_scrape_for_torrent( ot_hash hash, char *reply ) {
int exactmatch, delta_torrentcount = 0; int exactmatch, delta_torrentcount = 0;
ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); 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_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
@ -292,7 +276,7 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl
for( i=0; i<amount; ++i ) { for( i=0; i<amount; ++i ) {
ot_hash *hash = hash_list + i; ot_hash *hash = hash_list + i;
ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); 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_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
if( exactmatch ) { if( exactmatch ) {
@ -300,14 +284,13 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl
vector_remove_torrent( torrents_list, torrent ); vector_remove_torrent( torrents_list, torrent );
delta_torrentcount = -1; delta_torrentcount = -1;
} else { } else {
int j;
*r++='2';*r++='0';*r++=':'; *r++='2';*r++='0';*r++=':';
for(j=0;j<20;j+=4) WRITE32(r,j,READ32(hash,j)); r += 20; memcpy( r, hash, sizeof(ot_hash) ); r+=sizeof(ot_hash);
r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee",
torrent->peer_list->seed_count, torrent->peer_list->down_count, torrent->peer_list->peer_count-torrent->peer_list->seed_count ); torrent->peer_list->seed_count, torrent->peer_list->down_count, torrent->peer_list->peer_count-torrent->peer_list->seed_count );
} }
} }
mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); mutex_bucket_unlock_by_hash( *hash, delta_torrentcount );
} }
*r++ = 'e'; *r++ = 'e'; *r++ = 'e'; *r++ = 'e';
@ -315,7 +298,7 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl
} }
static ot_peerlist dummy_list; static ot_peerlist dummy_list;
size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, PROTO_FLAG proto ) { size_t remove_peer_from_torrent( ot_hash hash, ot_peer *peer, char *reply, PROTO_FLAG proto ) {
int exactmatch; int exactmatch;
size_t reply_size = 0; size_t reply_size = 0;
ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash );

@ -11,17 +11,16 @@
#include <time.h> #include <time.h>
#include <stdint.h> #include <stdint.h>
/* Libowfat */
#include <uint16.h>
#include <uint32.h>
#define READ16(addr,offs) ((int16_t)uint16_read((offs)+(uint8_t*)(addr)))
#define READ32(addr,offs) ((int32_t)uint32_read((offs)+(uint8_t*)(addr)))
#define WRITE16(addr,offs,val) uint16_pack((offs)+(uint8_t*)(addr),(val))
#define WRITE32(addr,offs,val) uint32_pack((offs)+(uint8_t*)(addr),(val))
typedef uint8_t ot_hash[20]; typedef uint8_t ot_hash[20];
typedef time_t ot_time; typedef time_t ot_time;
typedef char ot_ip6[16];
#ifdef WANT_V6
#define OT_IP_SIZE 16
#define PEERS6 "6"
#else
#define OT_IP_SIZE 4
#define PEERS6 ""
#endif
/* Some tracker behaviour tunable */ /* Some tracker behaviour tunable */
#define OT_CLIENT_TIMEOUT 30 #define OT_CLIENT_TIMEOUT 30
@ -60,7 +59,7 @@ extern uint32_t g_tracker_id;
typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA } PROTO_FLAG; typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA } PROTO_FLAG;
typedef struct { typedef struct {
uint8_t data[8]; uint8_t data[OT_IP_SIZE+2+2];
} ot_peer; } ot_peer;
static const uint8_t PEER_FLAG_SEEDING = 0x80; static const uint8_t PEER_FLAG_SEEDING = 0x80;
static const uint8_t PEER_FLAG_COMPLETED = 0x40; static const uint8_t PEER_FLAG_COMPLETED = 0x40;
@ -68,12 +67,17 @@ static const uint8_t PEER_FLAG_STOPPED = 0x20;
static const uint8_t PEER_FLAG_FROM_SYNC = 0x10; static const uint8_t PEER_FLAG_FROM_SYNC = 0x10;
static const uint8_t PEER_FLAG_LEECHING = 0x00; static const uint8_t PEER_FLAG_LEECHING = 0x00;
#define OT_SETIP(peer,ip) WRITE32((peer),0,READ32((ip),0)) #ifdef WANT_V6
#define OT_SETPORT(peer,port) WRITE16((peer),4,READ16((port),0)) #define OT_SETIP(peer,ip) memcpy((peer),(ip),(OT_IP_SIZE))
#define OT_PEERFLAG(peer) (((uint8_t*)(peer))[6]) #else
#define OT_PEERTIME(peer) (((uint8_t*)(peer))[7]) #define OT_SETIP(peer,ip) memcpy((peer),(((uint8_t*)ip)+12),(OT_IP_SIZE))
#endif
#define OT_SETPORT(peer,port) memcpy(((uint8_t*)(peer))+(OT_IP_SIZE),(port),2)
#define OT_PEERFLAG(peer) (((uint8_t*)(peer))[(OT_IP_SIZE)+2])
#define OT_PEERTIME(peer) (((uint8_t*)(peer))[(OT_IP_SIZE)+3])
#define OT_HASH_COMPARE_SIZE (sizeof(ot_hash)) #define OT_HASH_COMPARE_SIZE (sizeof(ot_hash))
#define OT_PEER_COMPARE_SIZE ((OT_IP_SIZE)+2)
struct ot_peerlist; struct ot_peerlist;
typedef struct ot_peerlist ot_peerlist; typedef struct ot_peerlist ot_peerlist;
@ -98,16 +102,13 @@ struct ot_peerlist {
struct ot_workstruct { struct ot_workstruct {
/* Thread specific, static */ /* Thread specific, static */
#define THREAD_INBUF_SIZE 8192
char *inbuf; char *inbuf;
size_t inbuf_size; #define G_INBUF_SIZE 8192
#define THREAD_OUTBUF_SIZE 8192
char *outbuf; char *outbuf;
size_t outbuf_size; #define G_OUTBUF_SIZE 8192
#ifdef _DEBUG_HTTPERROR #ifdef _DEBUG_HTTPERROR
#define THREAD_DEBUGBUF_SIZE 8192
char *debugbuf; char *debugbuf;
size_t debugbuf_size; #define G_DEBUGBUF_SIZE 8192
#endif #endif
/* HTTP specific, non static */ /* HTTP specific, non static */
@ -115,10 +116,6 @@ struct ot_workstruct {
ssize_t request_size; ssize_t request_size;
char *reply; char *reply;
ssize_t reply_size; ssize_t reply_size;
#ifdef _DEBUG_PEERID
char *peer_id;
ssize_t peer_id_size;
#endif
}; };
/* /*
@ -135,6 +132,10 @@ struct ot_workstruct {
#define WANT_SYNC_PARAM( param ) #define WANT_SYNC_PARAM( param )
#endif #endif
#if defined WANT_V6 && defined WANT_LOG_NETWORKS
#undef WANT_LOG_NETWORKS
#endif
void trackerlogic_init( ); void trackerlogic_init( );
void trackerlogic_deinit( void ); void trackerlogic_deinit( void );
void exerr( char * message ); void exerr( char * message );
@ -142,10 +143,10 @@ void exerr( char * message );
/* add_peer_to_torrent does only release the torrent bucket if from_sync is set, /* add_peer_to_torrent does only release the torrent bucket if from_sync is set,
otherwise it is released in return_peers_for_torrent */ otherwise it is released in return_peers_for_torrent */
#define add_peer_to_torrent(hash,peer,proto) add_peer_to_torrent_and_return_peers(hash,peer,proto,0,NULL) #define add_peer_to_torrent(hash,peer,proto) add_peer_to_torrent_and_return_peers(hash,peer,proto,0,NULL)
size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO_FLAG proto, size_t amount, char * reply ); size_t add_peer_to_torrent_and_return_peers( ot_hash hash, ot_peer *peer, PROTO_FLAG proto, size_t amount, char * reply );
size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, PROTO_FLAG proto ); size_t remove_peer_from_torrent( ot_hash hash, ot_peer *peer, char *reply, PROTO_FLAG proto );
size_t return_tcp_scrape_for_torrent( ot_hash *hash, int amount, char *reply ); 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 ); size_t return_udp_scrape_for_torrent( ot_hash hash, char *reply );
/* Helper, before it moves to its own object */ /* Helper, before it moves to its own object */
void free_peerlist( ot_peerlist *peer_list ); void free_peerlist( ot_peerlist *peer_list );

Loading…
Cancel
Save