mirror of
git://erdgeist.org/opentracker
synced 2025-01-11 15:30:07 +00:00
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,
This commit is contained in:
parent
8cbfc8602c
commit
e534db03c6
169
opentracker.c
169
opentracker.c
@ -8,12 +8,14 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <ctype.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* 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;
|
||||
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
|
||||
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);
|
||||
|
@ -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 = "<group>"; };
|
||||
65B8DF3A0D0310D20017149E /* ot_http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ot_http.h; sourceTree = "<group>"; };
|
||||
65B8DF3B0D0310D20017149E /* ot_http.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ot_http.c; sourceTree = "<group>"; };
|
||||
65FA33970E7EF09200F7D5A5 /* ot_livesync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ot_livesync.h; sourceTree = "<group>"; };
|
||||
65FA33980E7EF09200F7D5A5 /* ot_livesync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ot_livesync.c; sourceTree = "<group>"; };
|
||||
C6A0FF2C0290799A04C91782 /* opentracker.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = opentracker.1; sourceTree = "<group>"; };
|
||||
/* 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;
|
||||
};
|
||||
|
@ -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,19 +79,18 @@ 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 );
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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 ) ) )
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
$id$ */
|
||||
|
||||
#ifdef WANT_FULLSCRAPE
|
||||
|
||||
/* System */
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
@ -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";
|
||||
|
@ -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
|
||||
|
35
ot_http.c
35
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 );
|
||||
|
20
ot_stats.c
20
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++;
|
||||
}
|
||||
|
@ -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( );
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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
|
||||
|
14
ot_udp.c
14
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;
|
||||
}
|
||||
}
|
||||
|
@ -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=='%') {
|
||||
|
14
tests/testsuite2.sh
Normal file
14
tests/testsuite2.sh
Normal file
@ -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
|
@ -14,6 +14,7 @@
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* 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; i<OT_POOLS_COUNT; ++i )
|
||||
if( peer_list->peers[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,25 +270,35 @@ 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 */
|
||||
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;
|
||||
for( index = 0; index<OT_POOLS_COUNT; ++index ) {
|
||||
switch( vector_remove_peer( &peer_list->peers[index], peer, index == 0 ) ) {
|
||||
@ -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 */
|
||||
/* 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( );
|
||||
|
@ -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 );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user