Browse Source

clang-format

master
Dirk Engling 7 months ago
parent
commit
7c633c259e
  1. 199
      opentracker.c
  2. 44
      ot_accesslist.c
  3. 3
      ot_accesslist.h
  4. 24
      ot_clean.c
  5. 43
      ot_fullscrape.c
  6. 2
      ot_fullscrape.h
  7. 250
      ot_http.c
  8. 5
      ot_iovec.c
  9. 32
      ot_livesync.c
  10. 11
      ot_mutex.c
  11. 1
      ot_mutex.h
  12. 283
      ot_stats.c
  13. 2
      ot_stats.h
  14. 37
      ot_udp.c
  15. 54
      ot_vector.c
  16. 3
      ot_vector.h
  17. 59
      scan_urlencoded_query.c
  18. 74
      trackerlogic.c
  19. 15
      trackerlogic.h

199
opentracker.c

@ -5,37 +5,37 @@
$Id$ */ $Id$ */
/* System */ /* System */
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <ctype.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <pthread.h>
#include <pwd.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <pwd.h> #include <stdlib.h>
#include <ctype.h> #include <string.h>
#include <pthread.h> #include <sys/socket.h>
#include <unistd.h>
#ifdef WANT_SYSLOGS #ifdef WANT_SYSLOGS
#include <syslog.h> #include <syslog.h>
#endif #endif
/* Libowfat */ /* Libowfat */
#include "socket.h" #include "byte.h"
#include "io.h" #include "io.h"
#include "iob.h" #include "iob.h"
#include "byte.h"
#include "scan.h"
#include "ip6.h" #include "ip6.h"
#include "scan.h"
#include "socket.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_mutex.h"
#include "ot_http.h"
#include "ot_udp.h"
#include "ot_accesslist.h" #include "ot_accesslist.h"
#include "ot_stats.h" #include "ot_http.h"
#include "ot_livesync.h" #include "ot_livesync.h"
#include "ot_mutex.h"
#include "ot_stats.h"
#include "ot_udp.h"
#include "trackerlogic.h"
/* Globals */ /* Globals */
time_t g_now_seconds; time_t g_now_seconds;
@ -99,13 +99,15 @@ static void install_signal_handlers( void ) {
} }
static void usage(char *name) { static void usage(char *name) {
fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip[/bits]] [-f config] [-s livesyncport]" fprintf(stderr,
"Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip[/bits]] [-f config] [-s livesyncport]"
#ifdef WANT_ACCESSLIST_BLACK #ifdef WANT_ACCESSLIST_BLACK
" [-b blacklistfile]" " [-b blacklistfile]"
#elif defined(WANT_ACCESSLIST_WHITE) #elif defined(WANT_ACCESSLIST_WHITE)
" [-w whitelistfile]" " [-w whitelistfile]"
#endif #endif
"\n", name ); "\n",
name);
} }
#define HELPLINE(opt, desc) fprintf(stderr, "\t%-10s%s\n", opt, desc) #define HELPLINE(opt, desc) fprintf(stderr, "\t%-10s%s\n", opt, desc)
@ -145,7 +147,8 @@ static ssize_t header_complete( char * request, ssize_t byte_count ) {
state = (state >> 2) | ((c << 6) & 0xc0); state = (state >> 2) | ((c << 6) & 0xc0);
else else
break; break;
if( state >= 0xa0 || state == 0x99 ) return i + 1; if (state >= 0xa0 || state == 0x99)
return i + 1;
} }
} }
return 0; return 0;
@ -253,8 +256,7 @@ static void handle_accept( const int64 serversocket ) {
/* Put fd into a non-blocking mode */ /* Put fd into a non-blocking mode */
io_nonblock(sock); io_nonblock(sock);
if( !io_fd( sock ) || if (!io_fd(sock) || !(cookie = (struct http_data *)malloc(sizeof(struct http_data)))) {
!( cookie = (struct http_data*)malloc( sizeof(struct http_data) ) ) ) {
io_close(sock); io_close(sock);
continue; continue;
} }
@ -377,7 +379,8 @@ char * set_config_option( char **option, char *value ) {
#ifdef _DEBUG #ifdef _DEBUG
fprintf(stderr, "Setting config option: %s\n", value); fprintf(stderr, "Setting config option: %s\n", value);
#endif #endif
while( isspace(*value) ) ++value; while (isspace(*value))
++value;
free(*option); free(*option);
return *option = strdup(value); return *option = strdup(value);
} }
@ -385,19 +388,26 @@ char * set_config_option( char **option, char *value ) {
static int scan_ip6_port(const char *src, ot_ip6 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, bracket = 0; int off, bracket = 0;
while( isspace(*s) ) ++s; while (isspace(*s))
if( *s == '[' ) ++s, ++bracket; /* for v6 style notation */ ++s;
if (*s == '[')
++s, ++bracket; /* for v6 style notation */
if (!(off = scan_ip6(s, ip))) if (!(off = scan_ip6(s, ip)))
return 0; return 0;
s += off; s += off;
if( bracket && *s == ']' ) ++s; if (bracket && *s == ']')
if( *s == 0 || isspace(*s)) return s-src; ++s;
if (*s == 0 || isspace(*s))
return s - src;
if (!ip6_isv4mapped(ip)) { if (!ip6_isv4mapped(ip)) {
if( *s != ':' && *s != '.' ) return 0; if (*s != ':' && *s != '.')
if( !bracket && *(s) == ':' ) return 0; return 0;
if (!bracket && *(s) == ':')
return 0;
s++; s++;
} else { } else {
if( *(s++) != ':' ) return 0; if (*(s++) != ':')
return 0;
} }
if (!(off = scan_ushort(s, port))) if (!(off = scan_ushort(s, port)))
return 0; return 0;
@ -407,7 +417,8 @@ static int scan_ip6_port( const char *src, ot_ip6 ip, uint16 *port ) {
static int scan_ip6_net(const char *src, ot_net *net) { static int scan_ip6_net(const char *src, ot_net *net) {
const char *s = src; const char *s = src;
int off; int off;
while( isspace(*s) ) ++s; while (isspace(*s))
++s;
if (!(off = scan_ip6(s, net->address))) if (!(off = scan_ip6(s, net->address)))
return 0; return 0;
s += off; s += off;
@ -447,10 +458,12 @@ int parse_configfile( char * config_filename ) {
size_t strl; size_t strl;
/* Skip white spaces */ /* Skip white spaces */
while(isspace(*p)) ++p; while (isspace(*p))
++p;
/* Ignore comments and empty lines */ /* Ignore comments and empty lines */
if((*p=='#')||(*p=='\n')||(*p==0)) continue; if ((*p == '#') || (*p == '\n') || (*p == 0))
continue;
/* consume trailing new lines and spaces */ /* consume trailing new lines and spaces */
strl = strlen(p); strl = strlen(p);
@ -464,22 +477,28 @@ int parse_configfile( char * config_filename ) {
set_config_option(&g_serveruser, p + 13); set_config_option(&g_serveruser, p + 13);
} 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_ip6_port( p+15, tmpip, &tmpport )) goto parse_error; if (!scan_ip6_port(p + 15, tmpip, &tmpport))
ot_try_bind( tmpip, tmpport, FLAG_TCP ); ++bound; goto parse_error;
ot_try_bind( tmpip, tmpport, FLAG_UDP ); ++bound; ot_try_bind(tmpip, tmpport, FLAG_TCP);
++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_ip6_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_ip6_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;
} else if (!byte_diff(p, 18, "listen.udp.workers") && isspace(p[18])) { } else if (!byte_diff(p, 18, "listen.udp.workers") && isspace(p[18])) {
char *value = p + 18; char *value = p + 18;
while( isspace(*value) ) ++value; while (isspace(*value))
++value;
scan_uint(value, &g_udp_workers); scan_uint(value, &g_udp_workers);
#ifdef WANT_ACCESSLIST_WHITE #ifdef WANT_ACCESSLIST_WHITE
} else if (!byte_diff(p, 16, "access.whitelist") && isspace(p[16])) { } else if (!byte_diff(p, 16, "access.whitelist") && isspace(p[16])) {
@ -496,25 +515,29 @@ 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_ip6_net( p+13, &tmpnet )) goto parse_error; if (!scan_ip6_net(p + 13, &tmpnet))
goto parse_error;
accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT); accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT);
#endif #endif
} else if (!byte_diff(p, 17, "access.stats_path") && isspace(p[17])) { } else if (!byte_diff(p, 17, "access.stats_path") && isspace(p[17])) {
set_config_option(&g_stats_path, p + 18); set_config_option(&g_stats_path, p + 18);
#ifdef WANT_IP_FROM_PROXY #ifdef WANT_IP_FROM_PROXY
} else if (!byte_diff(p, 12, "access.proxy") && isspace(p[12])) { } else if (!byte_diff(p, 12, "access.proxy") && isspace(p[12])) {
if( !scan_ip6_net( p+13, &tmpnet )) goto parse_error; if (!scan_ip6_net(p + 13, &tmpnet))
goto parse_error;
accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY); accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY);
#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_ip6_net( p+25, &tmpnet )) goto parse_error; if (!scan_ip6_net(p + 25, &tmpnet))
goto parse_error;
accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC); accesslist_bless_net(&tmpnet, 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_ip6_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
@ -551,12 +574,15 @@ void load_state(const char * const state_filename ) {
infohash[i] = eger; infohash[i] = eger;
} }
if( i != (int)sizeof(ot_hash) ) continue; if (i != (int)sizeof(ot_hash))
continue;
i *= 2; i *= 2;
if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &base ) ) ) continue; if (inbuf[i++] != ':' || !(consumed = scan_ulonglong(inbuf + i, &base)))
continue;
i += consumed; i += consumed;
if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &downcount ) ) ) continue; if (inbuf[i++] != ':' || !(consumed = scan_ulonglong(inbuf + i, &downcount)))
continue;
add_torrent_from_saved_state(infohash, base, downcount); add_torrent_from_saved_state(infohash, base, downcount);
} }
@ -592,16 +618,14 @@ int drop_privileges ( const char * const serveruser, const char * const serverdi
fprintf(stderr, "Warning: Could not get password entry for %s. Reverting to uid -2.\n", serveruser); fprintf(stderr, "Warning: Could not get password entry for %s. Reverting to uid -2.\n", serveruser);
if (setegid((gid_t)-2) || setgid((gid_t)-2) || setuid((uid_t)-2) || seteuid((uid_t)-2)) if (setegid((gid_t)-2) || setgid((gid_t)-2) || setuid((uid_t)-2) || seteuid((uid_t)-2))
panic("Could not set uid to value -2"); panic("Could not set uid to value -2");
} } else {
else {
if (setegid(pws->pw_gid) || setgid(pws->pw_gid) || setuid(pws->pw_uid) || seteuid(pws->pw_uid)) if (setegid(pws->pw_gid) || setgid(pws->pw_gid) || setuid(pws->pw_uid) || seteuid(pws->pw_uid))
panic("Could not set uid to specified value"); panic("Could not set uid to specified value");
} }
if (geteuid() == 0 || getegid() == 0) if (geteuid() == 0 || getegid() == 0)
panic("Still running with root privileges?!"); panic("Still running with root privileges?!");
} } else {
else {
/* Normal user, just chdir() */ /* Normal user, just chdir() */
if (serverdir && chdir(serverdir)) { if (serverdir && chdir(serverdir)) {
fprintf(stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno)); fprintf(stderr, "Could not chroot to %s, because: %s\n", serverdir, strerror(errno));
@ -641,43 +665,82 @@ int main( int argc, char **argv ) {
#endif #endif
while (scanon) { while (scanon) {
switch( getopt( argc, argv, ":i:p:A:P:d:u:r:s:f:l:v" switch (getopt(argc, argv,
":i:p:A:P:d:u:r:s:f:l:v"
#ifdef WANT_ACCESSLIST_BLACK #ifdef WANT_ACCESSLIST_BLACK
"b:" "b:"
#elif defined(WANT_ACCESSLIST_WHITE) #elif defined(WANT_ACCESSLIST_WHITE)
"w:" "w:"
#endif #endif
"h")) { "h")) {
case -1 : scanon = 0; break; case -1:
scanon = 0;
break;
case 'i': case 'i':
if( !scan_ip6( 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;
#elif defined(WANT_ACCESSLIST_WHITE) #elif defined(WANT_ACCESSLIST_WHITE)
case 'w': set_config_option( &g_accesslist_filename, optarg); break; case 'w':
set_config_option(&g_accesslist_filename, optarg);
break;
#endif #endif
case 'p': case 'p':
if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); } if (!scan_ushort(optarg, &tmpport)) {
ot_try_bind( serverip, tmpport, FLAG_TCP ); bound++; break; usage(argv[0]);
exit(1);
}
ot_try_bind(serverip, tmpport, FLAG_TCP);
bound++;
break;
case 'P': case 'P':
if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); } if (!scan_ushort(optarg, &tmpport)) {
ot_try_bind( serverip, tmpport, FLAG_UDP ); bound++; break; usage(argv[0]);
exit(1);
}
ot_try_bind(serverip, tmpport, FLAG_UDP);
bound++;
break;
#ifdef WANT_SYNC_LIVE #ifdef WANT_SYNC_LIVE
case 's': case 's':
if( !scan_ushort( optarg, &tmpport)) { usage( argv[0] ); exit( 1 ); } if (!scan_ushort(optarg, &tmpport)) {
livesync_bind_mcast( serverip, tmpport); break; usage(argv[0]);
exit(1);
}
livesync_bind_mcast(serverip, tmpport);
break;
#endif #endif
case 'd': set_config_option( &g_serverdir, optarg ); break; case 'd':
case 'u': set_config_option( &g_serveruser, optarg ); break; set_config_option(&g_serverdir, optarg);
case 'r': set_config_option( &g_redirecturl, optarg ); break; break;
case 'l': statefile = optarg; break; case 'u':
set_config_option(&g_serveruser, optarg);
break;
case 'r':
set_config_option(&g_redirecturl, optarg);
break;
case 'l':
statefile = optarg;
break;
case 'A': case 'A':
if( !scan_ip6_net( optarg, &tmpnet )) { usage( argv[0] ); exit( 1 ); } if (!scan_ip6_net(optarg, &tmpnet)) {
usage(argv[0]);
exit(1);
}
accesslist_bless_net(&tmpnet, 0xffff); /* Allow everything for now */ accesslist_bless_net(&tmpnet, 0xffff); /* Allow everything for now */
break; break;
case 'f': bound += parse_configfile( optarg ); break; case 'f':
case 'h': help( argv[0] ); exit( 0 ); bound += parse_configfile(optarg);
break;
case 'h':
help(argv[0]);
exit(0);
case 'v': { case 'v': {
char buffer[8192]; char buffer[8192];
stats_return_tracker_version(buffer); stats_return_tracker_version(buffer);
@ -685,7 +748,9 @@ int main( int argc, char **argv ) {
exit(0); exit(0);
} }
default: default:
case '?': usage( argv[0] ); exit( 1 ); case '?':
usage(argv[0]);
exit(1);
} }
} }

44
ot_accesslist.c

@ -5,28 +5,28 @@
/* System */ /* System */
#include <pthread.h> #include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h> #include <unistd.h>
#ifdef WANT_DYNAMIC_ACCESSLIST #ifdef WANT_DYNAMIC_ACCESSLIST
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif #endif
/* Libowfat */ /* Libowfat */
#include "byte.h" #include "byte.h"
#include "scan.h" #include "fmt.h"
#include "ip6.h" #include "ip6.h"
#include "mmap.h" #include "mmap.h"
#include "fmt.h" #include "scan.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_accesslist.h" #include "ot_accesslist.h"
#include "ot_vector.h" #include "ot_vector.h"
#include "trackerlogic.h"
/* GLOBAL VARIABLES */ /* GLOBAL VARIABLES */
#ifdef WANT_ACCESSLIST #ifdef WANT_ACCESSLIST
@ -62,9 +62,7 @@ static ot_accesslist * _Atomic g_accesslist_delete = NULL;
#endif #endif
/* Helpers to work on access lists */ /* Helpers to work on access lists */
static int vector_compare_hash(const void *hash1, const void *hash2 ) { static int vector_compare_hash(const void *hash1, const void *hash2) { return memcmp(hash1, hash2, OT_HASH_COMPARE_SIZE); }
return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE );
}
static ot_accesslist *accesslist_free(ot_accesslist *accesslist) { static ot_accesslist *accesslist_free(ot_accesslist *accesslist) {
while (accesslist) { while (accesslist) {
@ -149,7 +147,8 @@ static void accesslist_readfile( void ) {
} }
/* Find start of next line */ /* Find start of next line */
while( read_offs <= map_end && *(read_offs++) != '\n' ); while (read_offs <= map_end && *(read_offs++) != '\n')
;
} }
#ifdef _DEBUG #ifdef _DEBUG
fprintf(stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new->list)); fprintf(stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new->list));
@ -226,7 +225,8 @@ static void * accesslist_worker( void * args ) {
accesslist_readfile(); accesslist_readfile();
/* Wait for signals */ /* Wait for signals */
while( sigwait (&signal_mask, &sig) != 0 && sig != SIGHUP ); while (sigwait(&signal_mask, &sig) != 0 && sig != SIGHUP)
;
} }
return NULL; return NULL;
} }
@ -403,8 +403,7 @@ void *set_value_for_net( const ot_net *net, ot_vector *vector, const void *value
/* Check each net in vector for overlap */ /* Check each net in vector for overlap */
uint8_t *member = ((uint8_t *)vector->data); uint8_t *member = ((uint8_t *)vector->data);
for (i = 0; i < vector->size; ++i) { for (i = 0; i < vector->size; ++i) {
if( address_in_net( *(ot_ip6*)member, net ) || if (address_in_net(*(ot_ip6 *)member, net) || address_in_net(net->address, (ot_net *)member))
address_in_net( net->address, (ot_net*)member ) )
return 0; return 0;
member += member_size; member += member_size;
} }
@ -437,8 +436,8 @@ void *get_value_for_net( const ot_ip6 address, const ot_vector *vector, const si
#ifdef WANT_FULLLOG_NETWORKS #ifdef WANT_FULLLOG_NETWORKS
static ot_vector g_lognets_list; static ot_vector g_lognets_list;
ot_log *g_logchain_first, *g_logchain_last; ot_log *g_logchain_first, *g_logchain_last;
static pthread_mutex_t g_lognets_list_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_lognets_list_mutex = PTHREAD_MUTEX_INITIALIZER;
void loglist_add_network(const ot_net *net) { void loglist_add_network(const ot_net *net) {
pthread_mutex_lock(&g_lognets_list_mutex); pthread_mutex_lock(&g_lognets_list_mutex);
set_value_for_net(net, &g_lognets_list, NULL, sizeof(ot_net)); set_value_for_net(net, &g_lognets_list, NULL, sizeof(ot_net));
@ -534,11 +533,16 @@ int accesslist_bless_net( ot_net *net, ot_permissions permissions ) {
off += fmt_long(_debug + off, net->bits); off += fmt_long(_debug + off, net->bits);
} }
if( permissions & OT_PERMISSION_MAY_STAT ) off += snprintf( _debug+off, 512-off, " may_fetch_stats" ); if (permissions & OT_PERMISSION_MAY_STAT)
if( permissions & OT_PERMISSION_MAY_LIVESYNC ) off += snprintf( _debug+off, 512-off, " may_sync_live" ); off += snprintf(_debug + off, 512 - off, " may_fetch_stats");
if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) off += snprintf( _debug+off, 512-off, " may_fetch_fullscrapes" ); if (permissions & OT_PERMISSION_MAY_LIVESYNC)
if( permissions & OT_PERMISSION_MAY_PROXY ) off += snprintf( _debug+off, 512-off, " may_proxy" ); off += snprintf(_debug + off, 512 - off, " may_sync_live");
if( !permissions ) off += snprintf( _debug+off, sizeof(_debug)-off, " nothing" ); if (permissions & OT_PERMISSION_MAY_FULLSCRAPE)
off += snprintf(_debug + off, 512 - off, " may_fetch_fullscrapes");
if (permissions & OT_PERMISSION_MAY_PROXY)
off += snprintf(_debug + off, 512 - off, " may_proxy");
if (!permissions)
off += snprintf(_debug + off, sizeof(_debug) - off, " nothing");
_debug[off++] = '.'; _debug[off++] = '.';
_debug[off++] = '\n'; _debug[off++] = '\n';
(void)write(2, _debug, off); (void)write(2, _debug, off);

3
ot_accesslist.h

@ -6,6 +6,8 @@
#ifndef OT_ACCESSLIST_H__ #ifndef OT_ACCESSLIST_H__
#define OT_ACCESSLIST_H__ #define OT_ACCESSLIST_H__
#include "trackerlogic.h"
#if defined(WANT_ACCESSLIST_BLACK) && defined(WANT_ACCESSLIST_WHITE) #if defined(WANT_ACCESSLIST_BLACK) && defined(WANT_ACCESSLIST_WHITE)
#error WANT_ACCESSLIST_BLACK and WANT_ACCESSLIST_WHITE are exclusive. #error WANT_ACCESSLIST_BLACK and WANT_ACCESSLIST_WHITE are exclusive.
#endif #endif
@ -53,7 +55,6 @@ void *set_value_for_net( const ot_net *net, ot_vector *vector, const void *value
*/ */
void *get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size); void *get_value_for_net(const ot_ip6 address, const ot_vector *vector, const size_t member_size);
#ifdef WANT_IP_FROM_PROXY #ifdef WANT_IP_FROM_PROXY
int proxylist_add_network(const ot_net *proxy, const ot_net *net); int proxylist_add_network(const ot_net *proxy, const ot_net *net);
int proxylist_check_network(const ot_ip6 *proxy, const ot_ip6 address /* can be NULL to only check proxy */); int proxylist_check_network(const ot_ip6 *proxy, const ot_ip6 address /* can be NULL to only check proxy */);

24
ot_clean.c

@ -5,19 +5,19 @@
/* System */ /* System */
#include <pthread.h> #include <pthread.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <unistd.h>
/* Libowfat */ /* Libowfat */
#include "io.h" #include "io.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "ot_accesslist.h"
#include "ot_mutex.h"
#include "ot_vector.h"
#include "ot_clean.h" #include "ot_clean.h"
#include "ot_mutex.h"
#include "ot_stats.h" #include "ot_stats.h"
#include "ot_accesslist.h" #include "ot_vector.h"
#include "trackerlogic.h"
/* Returns amount of removed peers */ /* Returns amount of removed peers */
static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t peer_size, time_t timedout, int *removed_seeders) { static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t peer_size, time_t timedout, int *removed_seeders) {
@ -40,8 +40,7 @@ static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, size_t pe
OT_PEERTIME(peers, peer_size) = timediff; OT_PEERTIME(peers, peer_size) = timediff;
memcpy(insert_point, peers, peer_size); memcpy(insert_point, peers, peer_size);
insert_point += peer_size; insert_point += peer_size;
} else } else if (OT_PEERFLAG_D(peers, peer_size) & PEER_FLAG_SEEDING)
if( OT_PEERFLAG_D( peers, peer_size ) & PEER_FLAG_SEEDING )
(*removed_seeders)++; (*removed_seeders)++;
} }
@ -104,8 +103,7 @@ int clean_single_peer_list( ot_peerlist *peer_list, size_t peer_size ) {
return 1 if torrent timed out return 1 if torrent timed out
*/ */
int clean_single_torrent(ot_torrent *torrent) { int clean_single_torrent(ot_torrent *torrent) {
return clean_single_peer_list( torrent->peer_list6, OT_PEER_SIZE6) * return clean_single_peer_list(torrent->peer_list6, OT_PEER_SIZE6) * clean_single_peer_list(torrent->peer_list4, OT_PEER_SIZE4);
clean_single_peer_list( torrent->peer_list4, OT_PEER_SIZE4);
} }
/* Clean up all peers in current bucket, remove timedout pools and /* Clean up all peers in current bucket, remove timedout pools and
@ -141,12 +139,8 @@ static void * clean_worker( void * args ) {
} }
static pthread_t thread_id; static pthread_t thread_id;
void clean_init( void ) { void clean_init(void) { pthread_create(&thread_id, NULL, clean_worker, NULL); }
pthread_create( &thread_id, NULL, clean_worker, NULL );
}
void clean_deinit( void ) { void clean_deinit(void) { pthread_cancel(thread_id); }
pthread_cancel( thread_id );
}
const char *g_version_clean_c = "$Source$: $Revision$\n"; const char *g_version_clean_c = "$Source$: $Revision$\n";

43
ot_fullscrape.c

@ -6,11 +6,11 @@
#ifdef WANT_FULLSCRAPE #ifdef WANT_FULLSCRAPE
/* System */ /* System */
#include <sys/param.h> #include <arpa/inet.h>
#include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <pthread.h> #include <sys/param.h>
#include <arpa/inet.h>
#ifdef WANT_COMPRESSION_GZIP #ifdef WANT_COMPRESSION_GZIP
#include <zlib.h> #include <zlib.h>
#endif #endif
@ -21,10 +21,10 @@
#include "textcode.h" #include "textcode.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_mutex.h"
#include "ot_iovec.h"
#include "ot_fullscrape.h" #include "ot_fullscrape.h"
#include "ot_iovec.h"
#include "ot_mutex.h"
#include "trackerlogic.h"
/* Fetch full scrape info for all torrents /* Fetch full scrape info for all torrents
Full scrapes usually are huge and one does not want to Full scrapes usually are huge and one does not want to
@ -43,7 +43,17 @@ static void fullscrape_make_gzip( int taskid, ot_tasktype mode);
/* Converter function from memory to human readable hex strings /* Converter function from memory to human readable hex strings
XXX - Duplicated from ot_stats. Needs fix. */ XXX - Duplicated from ot_stats. Needs fix. */
static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} static char *to_hex(char *d, uint8_t *s) {
char *m = "0123456789ABCDEF";
char *t = d;
char *e = d + 40;
while (d < e) {
*d++ = m[*s >> 4];
*d++ = m[*s++ & 15];
}
*d = 0;
return t;
}
/* This is the entry point into this worker thread /* This is the entry point into this worker thread
It grabs tasks from mutex_tasklist and delivers results back It grabs tasks from mutex_tasklist and delivers results back
@ -87,22 +97,28 @@ static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_torrent *torre
case TASK_FULLSCRAPE: case TASK_FULLSCRAPE:
default: default:
/* push hash as bencoded string */ /* push hash as bencoded string */
*r++='2'; *r++='0'; *r++=':'; *r++ = '2';
memcpy( r, hash, sizeof(ot_hash) ); r += sizeof(ot_hash); *r++ = '0';
*r++ = ':';
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", seed_count, down_count, peer_count - seed_count); r += sprintf(r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", seed_count, down_count, peer_count - seed_count);
break; break;
case TASK_FULLSCRAPE_TPB_ASCII: case TASK_FULLSCRAPE_TPB_ASCII:
to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); to_hex(r, *hash);
r += 2 * sizeof(ot_hash);
r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count); r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count);
break; break;
case TASK_FULLSCRAPE_TPB_ASCII_PLUS: case TASK_FULLSCRAPE_TPB_ASCII_PLUS:
to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); to_hex(r, *hash);
r += 2 * sizeof(ot_hash);
r += sprintf(r, ":%zd:%zd:%zd\n", seed_count, peer_count - seed_count, down_count); r += sprintf(r, ":%zd:%zd:%zd\n", seed_count, peer_count - seed_count, down_count);
break; break;
case TASK_FULLSCRAPE_TPB_BINARY: case TASK_FULLSCRAPE_TPB_BINARY:
memcpy( r, *hash, sizeof(ot_hash) ); r += sizeof(ot_hash); memcpy(r, *hash, sizeof(ot_hash));
r += sizeof(ot_hash);
*(uint32_t *)(r + 0) = htonl((uint32_t)seed_count); *(uint32_t *)(r + 0) = htonl((uint32_t)seed_count);
*(uint32_t *)(r + 4) = htonl((uint32_t)(peer_count - seed_count)); *(uint32_t *)(r + 4) = htonl((uint32_t)(peer_count - seed_count));
r += 8; r += 8;
@ -112,7 +128,8 @@ static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_torrent *torre
r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count); r += sprintf(r, ":%zd:%zd\n", seed_count, peer_count - seed_count);
break; break;
case TASK_FULLSCRAPE_TRACKERSTATE: case TASK_FULLSCRAPE_TRACKERSTATE:
to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); to_hex(r, *hash);
r += 2 * sizeof(ot_hash);
r += sprintf(r, ":%zd:%zd\n", torrent->peer_list6->base, down_count); r += sprintf(r, ":%zd:%zd\n", torrent->peer_list6->base, down_count);
break; break;
} }

2
ot_fullscrape.h

@ -8,6 +8,8 @@
#ifdef WANT_FULLSCRAPE #ifdef WANT_FULLSCRAPE
#include "ot_mutex.h"
void fullscrape_init(); void fullscrape_init();
void fullscrape_deinit(); void fullscrape_deinit();
void fullscrape_deliver(int64 sock, ot_tasktype tasktype); void fullscrape_deliver(int64 sock, ot_tasktype tasktype);

250
ot_http.c

@ -4,31 +4,31 @@
$id$ */ $id$ */
/* System */ /* System */
#include <sys/types.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <stdlib.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h>
/* Libowfat */ /* Libowfat */
#include "byte.h"
#include "array.h" #include "array.h"
#include "byte.h"
#include "case.h"
#include "iob.h" #include "iob.h"
#include "ip6.h" #include "ip6.h"
#include "scan.h" #include "scan.h"
#include "case.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "ot_accesslist.h"
#include "ot_mutex.h" #include "ot_fullscrape.h"
#include "ot_http.h" #include "ot_http.h"
#include "ot_iovec.h" #include "ot_iovec.h"
#include "scan_urlencoded_query.h" #include "ot_mutex.h"
#include "ot_fullscrape.h"
#include "ot_stats.h" #include "ot_stats.h"
#include "ot_accesslist.h" #include "scan_urlencoded_query.h"
#include "trackerlogic.h"
#define OT_MAXMULTISCRAPE_COUNT 64 #define OT_MAXMULTISCRAPE_COUNT 64
#define OT_BATCH_LIMIT (1024 * 1024 * 16) #define OT_BATCH_LIMIT (1024 * 1024 * 16)
@ -37,15 +37,16 @@ extern char *g_redirecturl;
char *g_stats_path; char *g_stats_path;
ssize_t g_stats_path_len; ssize_t g_stats_path_len;
enum { enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 };
SUCCESS_HTTP_HEADER_LENGTH = 80,
SUCCESS_HTTP_SIZE_OFF = 17 };
static void http_senddata(const int64 sock, struct ot_workstruct *ws) { static void http_senddata(const int64 sock, struct ot_workstruct *ws) {
struct http_data *cookie = io_getcookie(sock); struct http_data *cookie = io_getcookie(sock);
ssize_t written_size; ssize_t written_size;
if( !cookie ) { io_close(sock); return; } if (!cookie) {
io_close(sock);
return;
}
/* whoever sends data is not interested in its input-array */ /* whoever sends data is not interested in its input-array */
if (ws->keep_alive && ws->header_size != ws->request_size) { if (ws->keep_alive && ws->header_size != ws->request_size) {
@ -61,7 +62,9 @@ static void http_senddata( const int64 sock, struct ot_workstruct *ws ) {
written_size = write(sock, ws->reply, ws->reply_size); written_size = write(sock, ws->reply, ws->reply_size);
if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) {
array_reset(&cookie->request); array_reset(&cookie->request);
free( cookie ); io_close( sock ); return; free(cookie);
io_close(sock);
return;
} }
if (written_size < ws->reply_size) { if (written_size < ws->reply_size) {
@ -70,7 +73,8 @@ static void http_senddata( const int64 sock, struct ot_workstruct *ws ) {
if (!(outbuf = malloc(ws->reply_size - written_size))) { if (!(outbuf = malloc(ws->reply_size - written_size))) {
array_reset(&cookie->request); array_reset(&cookie->request);
free(cookie); io_close( sock ); free(cookie);
io_close(sock);
return; return;
} }
@ -85,7 +89,8 @@ static void http_senddata( const int64 sock, struct ot_workstruct *ws ) {
/* writeable short data sockets just have a tcp timeout */ /* writeable short data sockets just have a tcp timeout */
if (!ws->keep_alive) { if (!ws->keep_alive) {
taia_uint( &t, 0 ); io_timeout( sock, t ); taia_uint(&t, 0);
io_timeout(sock, t);
io_dontwantread(sock); io_dontwantread(sock);
} }
io_wantwrite(sock); io_wantwrite(sock);
@ -110,7 +115,8 @@ ssize_t http_issue_error( const int64 sock, struct ot_workstruct *ws, int code )
if (code == CODE_HTTPERROR_302) if (code == CODE_HTTPERROR_302)
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); 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, G_OUTBUF_SIZE, "HTTP/1.0 %s\r\nContent-Type: text/html\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\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);
@ -155,7 +161,8 @@ ssize_t http_sendiovecdata( const int64 sock, struct ot_workstruct *ws, int iove
header_size = asprintf(&header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n%sContent-Length: %zd\r\n\r\n", encoding, size); header_size = asprintf(&header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n%sContent-Length: %zd\r\n\r\n", encoding, size);
else { else {
if (!(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) { if (!(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) {
header_size = asprintf( &header, "HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\n%sTransfer-Encoding: chunked\r\n\r\n%zx\r\n", encoding, size ); header_size =
asprintf(&header, "HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\n%sTransfer-Encoding: chunked\r\n\r\n%zx\r\n", encoding, size);
cookie->flag |= STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; cookie->flag |= STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER;
} else } else
header_size = asprintf(&header, "%zx\r\n", size); header_size = asprintf(&header, "%zx\r\n", size);
@ -203,29 +210,43 @@ ssize_t http_sendiovecdata( const int64 sock, struct ot_workstruct *ws, int iove
} }
/* writeable sockets timeout after 10 minutes */ /* writeable sockets timeout after 10 minutes */
taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); taia_now(&t);
taia_addsec(&t, &t, OT_CLIENT_TIMEOUT_SEND);
io_timeout(sock, t); io_timeout(sock, t);
io_wantwrite(sock); io_wantwrite(sock);
return 0; return 0;
} }
static ssize_t http_handle_stats(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { static ssize_t http_handle_stats(const int64 sock, struct ot_workstruct *ws, char *read_ptr) {
static const ot_keywords keywords_main[] = static const ot_keywords keywords_main[] = {{"mode", 1}, {"format", 2}, {"info_hash", 3}, {NULL, -3}};
{ { "mode", 1 }, {"format", 2 }, {"info_hash", 3}, { NULL, -3 } }; static const ot_keywords keywords_mode[] = {{"peer", TASK_STATS_PEERS},
static const ot_keywords keywords_mode[] = {"conn", TASK_STATS_CONNS},
{ { "peer", TASK_STATS_PEERS }, { "conn", TASK_STATS_CONNS }, { "scrp", TASK_STATS_SCRAPE }, { "udp4", TASK_STATS_UDP }, { "tcp4", TASK_STATS_TCP }, {"scrp", TASK_STATS_SCRAPE},
{ "busy", TASK_STATS_BUSY_NETWORKS }, { "torr", TASK_STATS_TORRENTS }, { "fscr", TASK_STATS_FULLSCRAPE }, {"udp4", TASK_STATS_UDP},
{ "s24s", TASK_STATS_SLASH24S }, { "tpbs", TASK_STATS_TPB }, { "herr", TASK_STATS_HTTPERRORS }, { "completed", TASK_STATS_COMPLETED }, {"tcp4", TASK_STATS_TCP},
{ "top100", TASK_STATS_TOP100 }, { "top10", TASK_STATS_TOP10 }, { "renew", TASK_STATS_RENEW }, { "syncs", TASK_STATS_SYNCS }, { "version", TASK_STATS_VERSION }, {"busy", TASK_STATS_BUSY_NETWORKS},
{ "everything", TASK_STATS_EVERYTHING }, { "statedump", TASK_FULLSCRAPE_TRACKERSTATE }, { "fulllog", TASK_STATS_FULLLOG }, {"torr", TASK_STATS_TORRENTS},
{"fscr", TASK_STATS_FULLSCRAPE},
{"s24s", TASK_STATS_SLASH24S},
{"tpbs", TASK_STATS_TPB},
{"herr", TASK_STATS_HTTPERRORS},
{"completed", TASK_STATS_COMPLETED},
{"top100", TASK_STATS_TOP100},
{"top10", TASK_STATS_TOP10},
{"renew", TASK_STATS_RENEW},
{"syncs", TASK_STATS_SYNCS},
{"version", TASK_STATS_VERSION},
{"everything", TASK_STATS_EVERYTHING},
{"statedump", TASK_FULLSCRAPE_TRACKERSTATE},
{"fulllog", TASK_STATS_FULLLOG},
{"woodpeckers", TASK_STATS_WOODPECKERS}, {"woodpeckers", TASK_STATS_WOODPECKERS},
#ifdef WANT_LOG_NUMWANT #ifdef WANT_LOG_NUMWANT
{"numwants", TASK_STATS_NUMWANTS}, {"numwants", TASK_STATS_NUMWANTS},
#endif #endif
{NULL, -3}}; {NULL, -3}};
static const ot_keywords keywords_format[] = static const ot_keywords keywords_format[] = {{"bin", TASK_FULLSCRAPE_TPB_BINARY}, {"ben", TASK_FULLSCRAPE},
{ { "bin", TASK_FULLSCRAPE_TPB_BINARY }, { "ben", TASK_FULLSCRAPE }, { "url", TASK_FULLSCRAPE_TPB_URLENCODED }, {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII},
{ "txt", TASK_FULLSCRAPE_TPB_ASCII }, { "txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS }, { NULL, -3 } }; {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}};
int mode = TASK_STATS_PEERS, scanon = 1, format = 0; int mode = TASK_STATS_PEERS, scanon = 1, format = 0;
@ -238,22 +259,31 @@ static const ot_keywords keywords_format[] =
while (scanon) { while (scanon) {
switch (scan_find_keywords(keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM)) { switch (scan_find_keywords(keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM)) {
case -2: scanon = 0; break; /* TERMINATOR */ case -2:
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ scanon = 0;
case -3: scan_urlencoded_skipvalue( &read_ptr ); break; break; /* TERMINATOR */
case -1:
HTTPERROR_400_PARAM; /* PARSE ERROR */
case -3:
scan_urlencoded_skipvalue(&read_ptr);
break;
case 1: /* matched "mode" */ case 1: /* matched "mode" */
if( ( mode = scan_find_keywords( keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; if ((mode = scan_find_keywords(keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0)
HTTPERROR_400_PARAM;
break; break;
case 2: /* matched "format" */ case 2: /* matched "format" */
if( ( format = scan_find_keywords( keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; if ((format = scan_find_keywords(keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0)
HTTPERROR_400_PARAM;
break; break;
case 3: HTTPERROR_400_PARAM; /* If the stats URL was mistakenly added as announce URL, return a 400 */ case 3:
HTTPERROR_400_PARAM; /* If the stats URL was mistakenly added as announce URL, return a 400 */
} }
} }
#ifdef WANT_FULLSCRAPE #ifdef WANT_FULLSCRAPE
if (mode == TASK_FULLSCRAPE_TRACKERSTATE) { if (mode == TASK_FULLSCRAPE_TRACKERSTATE) {
format = mode; mode = TASK_STATS_TPB; format = mode;
mode = TASK_STATS_TPB;
} }
if (mode == TASK_STATS_TPB) { if (mode == TASK_STATS_TPB) {
@ -274,7 +304,8 @@ static const ot_keywords keywords_format[] =
cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
/* Clients waiting for us should not easily timeout */ /* Clients waiting for us should not easily timeout */
taia_uint( &t, 0 ); io_timeout( sock, t ); taia_uint(&t, 0);
io_timeout(sock, t);
fullscrape_deliver(sock, format); fullscrape_deliver(sock, format);
io_dontwantread(sock); io_dontwantread(sock);
return ws->reply_size = -2; return ws->reply_size = -2;
@ -285,7 +316,8 @@ static const ot_keywords keywords_format[] =
if ((mode & TASK_CLASS_MASK) == TASK_STATS) { if ((mode & TASK_CLASS_MASK) == TASK_STATS) {
tai6464 t; tai6464 t;
/* Complex stats also include expensive memory debugging tools */ /* Complex stats also include expensive memory debugging tools */
taia_uint( &t, 0 ); io_timeout( sock, t ); taia_uint(&t, 0);
io_timeout(sock, t);
stats_deliver(sock, mode); stats_deliver(sock, mode);
return ws->reply_size = -2; return ws->reply_size = -2;
} }
@ -297,7 +329,10 @@ static const ot_keywords keywords_format[] =
#ifdef WANT_MODEST_FULLSCRAPES #ifdef WANT_MODEST_FULLSCRAPES
static pthread_mutex_t g_modest_fullscrape_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_modest_fullscrape_mutex = PTHREAD_MUTEX_INITIALIZER;
static ot_vector g_modest_fullscrape_timeouts; static ot_vector g_modest_fullscrape_timeouts;
typedef struct { ot_ip6 ip; ot_time last_fullscrape; } ot_scrape_log; typedef struct {
ot_ip6 ip;
ot_time last_fullscrape;
} ot_scrape_log;
#endif #endif
#ifdef WANT_FULLSCRAPE #ifdef WANT_FULLSCRAPE
@ -348,7 +383,8 @@ static ssize_t http_handle_fullscrape( const int64 sock, struct ot_workstruct *w
/* Pass this task to the worker thread */ /* Pass this task to the worker thread */
cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
/* Clients waiting for us should not easily timeout */ /* Clients waiting for us should not easily timeout */
taia_uint( &t, 0 ); io_timeout( sock, t ); taia_uint(&t, 0);
io_timeout(sock, t);
fullscrape_deliver(sock, TASK_FULLSCRAPE | format); fullscrape_deliver(sock, TASK_FULLSCRAPE | format);
io_dontwantread(sock); io_dontwantread(sock);
return ws->reply_size = -2; return ws->reply_size = -2;
@ -363,16 +399,23 @@ static ssize_t http_handle_scrape( const int64 sock, struct ot_workstruct *ws, c
/* This is to hack around stupid clients that send "scrape ?info_hash" */ /* This is to hack around stupid clients that send "scrape ?info_hash" */
if (read_ptr[-1] != '?') { if (read_ptr[-1] != '?') {
while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; while ((*read_ptr != '?') && (*read_ptr != '\n'))
if( *read_ptr == '\n' ) HTTPERROR_400_PARAM; ++read_ptr;
if (*read_ptr == '\n')
HTTPERROR_400_PARAM;
++read_ptr; ++read_ptr;
} }
while (scanon) { while (scanon) {
switch (scan_find_keywords(keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM)) { switch (scan_find_keywords(keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM)) {
case -2: scanon = 0; break; /* TERMINATOR */ case -2:
default: HTTPERROR_400_PARAM; /* PARSE ERROR */ scanon = 0;
case -3: scan_urlencoded_skipvalue( &read_ptr ); break; break; /* TERMINATOR */
default:
HTTPERROR_400_PARAM; /* PARSE ERROR */
case -3:
scan_urlencoded_skipvalue(&read_ptr);
break;
case 1: /* matched "info_hash" */ case 1: /* matched "info_hash" */
/* ignore this, when we have less than 20 bytes */ /* ignore this, when we have less than 20 bytes */
if (scan_urlencoded_query(&read_ptr, (char *)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE) != (ssize_t)sizeof(ot_hash)) if (scan_urlencoded_query(&read_ptr, (char *)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE) != (ssize_t)sizeof(ot_hash))
@ -382,7 +425,8 @@ static ssize_t http_handle_scrape( const int64 sock, struct ot_workstruct *ws, c
} }
/* No info_hash found? Inform user */ /* No info_hash found? Inform user */
if( !numwant ) HTTPERROR_400_PARAM; if (!numwant)
HTTPERROR_400_PARAM;
/* Limit number of hashes to process */ /* Limit number of hashes to process */
if (numwant > OT_MAXMULTISCRAPE_COUNT) if (numwant > OT_MAXMULTISCRAPE_COUNT)
@ -403,10 +447,13 @@ static char* http_header( char *data, size_t byte_count, char *header ) {
size_t i; size_t i;
long sl = strlen(header); long sl = strlen(header);
for (i = 0; i + sl + 2 < byte_count; ++i) { for (i = 0; i + sl + 2 < byte_count; ++i) {
if( data[i] != '\n' || data[ i + sl + 1] != ':' ) continue; if (data[i] != '\n' || data[i + sl + 1] != ':')
if( !case_equalb( data + i + 1, sl, header ) ) continue; continue;
if (!case_equalb(data + i + 1, sl, header))
continue;
data += i + sl + 2; data += i + sl + 2;
while( *data == ' ' || *data == '\t' ) ++data; while (*data == ' ' || *data == '\t')
++data;
return data; return data;
} }
return 0; return 0;
@ -420,8 +467,7 @@ static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "even
#ifdef WANT_FULLLOG_NETWORKS #ifdef WANT_FULLLOG_NETWORKS
{"lognet", 8}, {"lognet", 8},
#endif #endif
{ "peer_id", 9 }, {"peer_id", 9}, {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 sock, struct ot_workstruct *ws, char *read_ptr) { static ssize_t http_handle_announce(const int64 sock, struct ot_workstruct *ws, char *read_ptr) {
int numwant, tmp, scanon; int numwant, tmp, scanon;
@ -432,8 +478,10 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
/* This is to hack around stupid clients that send "announce ?info_hash" */ /* This is to hack around stupid clients that send "announce ?info_hash" */
if (read_ptr[-1] != '?') { if (read_ptr[-1] != '?') {
while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; while ((*read_ptr != '?') && (*read_ptr != '\n'))
if( *read_ptr == '\n' ) HTTPERROR_400_PARAM; ++read_ptr;
if (*read_ptr == '\n')
HTTPERROR_400_PARAM;
++read_ptr; ++read_ptr;
} }
@ -459,22 +507,33 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
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:
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ scanon = 0;
case -3: scan_urlencoded_skipvalue( &read_ptr ); break; break; /* TERMINATOR */
case -1:
HTTPERROR_400_PARAM; /* PARSE ERROR */
case -3:
scan_urlencoded_skipvalue(&read_ptr);
break;
case 1: /* matched "port" */ case 1: /* matched "port" */
len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE);
if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM; if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp) || (tmp > 0xffff))
port = htons( tmp ); OT_SETPORT( &ws->peer, &port ); HTTPERROR_400_PARAM;
port = htons(tmp);
OT_SETPORT(&ws->peer, &port);
break; break;
case 2: /* matched "left" */ case 2: /* matched "left" */
if( ( len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; if ((len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0)
if( scan_fixed_int( write_ptr, len, &tmp ) ) tmp = 0; HTTPERROR_400_PARAM;
if( !tmp ) OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_SEEDING; if (scan_fixed_int(write_ptr, len, &tmp))
tmp = 0;
if (!tmp)
OT_PEERFLAG(&ws->peer) |= PEER_FLAG_SEEDING;
break; break;
case 3: /* matched "event" */ case 3: /* matched "event" */
switch (scan_find_keywords(keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE)) { switch (scan_find_keywords(keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE)) {
case -1: HTTPERROR_400_PARAM; case -1:
HTTPERROR_400_PARAM;
case 1: /* matched "completed" */ case 1: /* matched "completed" */
OT_PEERFLAG(&ws->peer) |= PEER_FLAG_COMPLETED; OT_PEERFLAG(&ws->peer) |= PEER_FLAG_COMPLETED;
break; break;
@ -487,19 +546,26 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
break; break;
case 4: /* matched "numwant" */ case 4: /* matched "numwant" */
len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE);
if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &numwant ) ) HTTPERROR_400_PARAM; if ((len <= 0) || scan_fixed_int(write_ptr, len, &numwant))
if( numwant < 0 ) numwant = 50; HTTPERROR_400_PARAM;
if( numwant > 200 ) numwant = 200; if (numwant < 0)
numwant = 50;
if (numwant > 200)
numwant = 200;
break; break;
case 5: /* matched "compact" */ case 5: /* matched "compact" */
len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE);
if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) ) HTTPERROR_400_PARAM; if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp))
if( !tmp ) HTTPERROR_400_COMPACT; HTTPERROR_400_PARAM;
if (!tmp)
HTTPERROR_400_COMPACT;
break; break;
case 6: /* matched "info_hash" */ case 6: /* matched "info_hash" */
if( ws->hash ) HTTPERROR_400_DOUBLEHASH; if (ws->hash)
HTTPERROR_400_DOUBLEHASH;
/* ignore this, when we have less than 20 bytes */ /* ignore this, when we have less than 20 bytes */
if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; if (scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20)
HTTPERROR_400_PARAM;
ws->hash = (ot_hash *)write_ptr; ws->hash = (ot_hash *)write_ptr;
break; break;
#ifdef WANT_IP_FROM_QUERY_STRING #ifdef WANT_IP_FROM_QUERY_STRING
@ -508,10 +574,10 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply + 16; char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply + 16;
len = scan_urlencoded_query(&read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE); len = scan_urlencoded_query(&read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE);
tmp_buf2[len] = 0; tmp_buf2[len] = 0;
if( ( len <= 0 ) || !scan_ip6( tmp_buf2, tmp_buf1 ) ) HTTPERROR_400_PARAM; if ((len <= 0) || !scan_ip6(tmp_buf2, tmp_buf1))
HTTPERROR_400_PARAM;
OT_SETIP(&ws->peer, tmp_buf1); OT_SETIP(&ws->peer, tmp_buf1);
} } break;
break;
#endif #endif
#ifdef WANT_FULLLOG_NETWORKS #ifdef WANT_FULLLOG_NETWORKS
case 8: /* matched "lognet" */ case 8: /* matched "lognet" */
@ -523,18 +589,21 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
len = scan_urlencoded_query(&read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE); len = scan_urlencoded_query(&read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE);
tmp_buf[len] = 0; tmp_buf[len] = 0;
if( len <= 0 ) HTTPERROR_400_PARAM; if (len <= 0)
HTTPERROR_400_PARAM;
if (*tmp_buf == '-') { if (*tmp_buf == '-') {
loglist_reset(); loglist_reset();
return ws->reply_size = sprintf(ws->reply, "Successfully removed.\n"); return ws->reply_size = sprintf(ws->reply, "Successfully removed.\n");
} }
parsed = scan_ip6(tmp_buf, net.address); parsed = scan_ip6(tmp_buf, net.address);
if( !parsed ) HTTPERROR_400_PARAM; if (!parsed)
HTTPERROR_400_PARAM;
if (tmp_buf[parsed++] != '/') if (tmp_buf[parsed++] != '/')
bits = 128; bits = 128;
else { else {
parsed = scan_short(tmp_buf + parsed, &bits); parsed = scan_short(tmp_buf + parsed, &bits);
if( !parsed ) HTTPERROR_400_PARAM; if (!parsed)
HTTPERROR_400_PARAM;
if (ip6_isv4mapped(net.address)) if (ip6_isv4mapped(net.address))
bits += 96; bits += 96;
} }
@ -542,12 +611,12 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
loglist_add_network(&net); loglist_add_network(&net);
return ws->reply_size = sprintf(ws->reply, "Successfully added.\n"); return ws->reply_size = sprintf(ws->reply, "Successfully added.\n");
//} //}
} } break;
break;
#endif #endif
case 9: /* matched "peer_id" */ case 9: /* matched "peer_id" */
/* ignore this, when we have less than 20 bytes */ /* ignore this, when we have less than 20 bytes */
if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; if (scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20)
HTTPERROR_400_PARAM;
ws->peer_id = write_ptr; ws->peer_id = write_ptr;
break; break;
} }
@ -614,10 +683,12 @@ ssize_t http_handle_request( const int64 sock, struct ot_workstruct *ws ) {
ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH; ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH;
/* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */
if( memcmp( read_ptr, "GET /", 5) ) HTTPERROR_400; if (memcmp(read_ptr, "GET /", 5))
HTTPERROR_400;
/* Skip leading '/' */ /* Skip leading '/' */
for( read_ptr+=4; *read_ptr == '/'; ++read_ptr); for (read_ptr += 4; *read_ptr == '/'; ++read_ptr)
;
/* Try to parse the request. /* Try to parse the request.
In reality we abandoned requiring the url to be correct. This now In reality we abandoned requiring the url to be correct. This now
@ -626,8 +697,10 @@ ssize_t http_handle_request( const int64 sock, struct ot_workstruct *ws ) {
len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_PATH); len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_PATH);
/* If parsing returned an error, leave with not found */ /* If parsing returned an error, leave with not found */
if( g_redirecturl && ( len == -2 ) ) HTTPERROR_302; if (g_redirecturl && (len == -2))
if( len <= 0 ) HTTPERROR_404; HTTPERROR_302;
if (len <= 0)
HTTPERROR_404;
/* This is the hardcore match for announce*/ /* This is the hardcore match for announce*/
if ((*write_ptr == 'a') || (*write_ptr == '?')) if ((*write_ptr == 'a') || (*write_ptr == '?'))
@ -649,13 +722,16 @@ ssize_t http_handle_request( const int64 sock, struct ot_workstruct *ws ) {
ws->keep_alive = 0; ws->keep_alive = 0;
#ifdef WANT_KEEPALIVE #ifdef WANT_KEEPALIVE
read_ptr = http_header(ws->request, ws->header_size, "connection"); read_ptr = http_header(ws->request, ws->header_size, "connection");
if( read_ptr && ( *read_ptr == 'K' || *read_ptr == 'k' ) ) ws->keep_alive = 1; if (read_ptr && (*read_ptr == 'K' || *read_ptr == 'k'))
ws->keep_alive = 1;
#endif #endif
/* If routines handled sending themselves, just return */ /* If routines handled sending themselves, just return */
if( ws->reply_size == -2 ) return 0; if (ws->reply_size == -2)
return 0;
/* If routine failed, let http error take over */ /* If routine failed, let http error take over */
if( ws->reply_size <= 0 ) HTTPERROR_500; if (ws->reply_size <= 0)
HTTPERROR_500;
/* This one is rather ugly, so I take you step by step through it. /* This one is rather ugly, so I take you step by step through it.

5
ot_iovec.c

@ -4,10 +4,10 @@
$id$ */ $id$ */
/* System */ /* System */
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <sys/types.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h>
/* Libowfat */ /* Libowfat */
@ -54,7 +54,6 @@ void *iovec_append( int *iovec_entries, struct iovec **iovector, struct iovec *a
return new_vec; return new_vec;
} }
void iovec_free(int *iovec_entries, struct iovec **iovector) { void iovec_free(int *iovec_entries, struct iovec **iovector) {
int i; int i;
for (i = 0; i < *iovec_entries; ++i) for (i = 0; i < *iovec_entries; ++i)

32
ot_livesync.c

@ -4,25 +4,25 @@
$id$ */ $id$ */
/* System */ /* System */
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
/* Libowfat */ /* Libowfat */
#include "socket.h"
#include "ndelay.h"
#include "byte.h" #include "byte.h"
#include "ip6.h" #include "ip6.h"
#include "ndelay.h"
#include "socket.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_livesync.h"
#include "ot_accesslist.h" #include "ot_accesslist.h"
#include "ot_stats.h" #include "ot_livesync.h"
#include "ot_mutex.h" #include "ot_mutex.h"
#include "ot_stats.h"
#include "trackerlogic.h"
#ifdef WANT_SYNC_LIVE #ifdef WANT_SYNC_LIVE
@ -142,7 +142,8 @@ static void livesync_handle_peersync( struct ot_workstruct *ws, size_t peer_size
memcpy(&ws->peer, ws->request + off + sizeof(ot_hash), peer_size); memcpy(&ws->peer, ws->request + off + sizeof(ot_hash), peer_size);
ws->hash = (ot_hash *)(ws->request + off); ws->hash = (ot_hash *)(ws->request + off);
if( !g_opentracker_running ) return; if (!g_opentracker_running)
return;
if (OT_PEERFLAG(ws->peer) & PEER_FLAG_STOPPED) if (OT_PEERFLAG(ws->peer) & PEER_FLAG_STOPPED)
remove_peer_from_torrent(FLAG_MCA, ws); remove_peer_from_torrent(FLAG_MCA, ws);
@ -152,9 +153,7 @@ static void livesync_handle_peersync( struct ot_workstruct *ws, size_t peer_size
off += sizeof(ot_hash) + peer_size; off += sizeof(ot_hash) + peer_size;
} }
stats_issue_event(EVENT_SYNC, 0, stats_issue_event(EVENT_SYNC, 0, (ws->request_size - sizeof(g_tracker_id) - sizeof(uint32_t)) / ((ssize_t)sizeof(ot_hash) + peer_size));
(ws->request_size - sizeof( g_tracker_id ) - sizeof( uint32_t ) ) /
((ssize_t)sizeof( ot_hash ) + peer_size));
} }
/* 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
@ -163,15 +162,13 @@ static void livesync_handle_peersync( struct ot_workstruct *ws, size_t peer_size
void livesync_ticker() { void livesync_ticker() {
/* livesync_issue_peersync sets g_next_packet_time */ /* livesync_issue_peersync sets g_next_packet_time */
pthread_mutex_lock(&g_outbuf_mutex); pthread_mutex_lock(&g_outbuf_mutex);
if( g_now_seconds > g_v6_buf.next_packet_time && if (g_now_seconds > g_v6_buf.next_packet_time && g_v6_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t))
g_v6_buf.fill > sizeof( g_tracker_id ) + sizeof( uint32_t ) )
livesync_issue_peersync(&g_v6_buf); livesync_issue_peersync(&g_v6_buf);
else else
pthread_mutex_unlock(&g_outbuf_mutex); pthread_mutex_unlock(&g_outbuf_mutex);
pthread_mutex_lock(&g_outbuf_mutex); pthread_mutex_lock(&g_outbuf_mutex);
if( g_now_seconds > g_v4_buf.next_packet_time && if (g_now_seconds > g_v4_buf.next_packet_time && g_v4_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t))
g_v4_buf.fill > sizeof( g_tracker_id ) + sizeof( uint32_t ) )
livesync_issue_peersync(&g_v4_buf); livesync_issue_peersync(&g_v4_buf);
else else
pthread_mutex_unlock(&g_outbuf_mutex); pthread_mutex_unlock(&g_outbuf_mutex);
@ -199,7 +196,8 @@ void livesync_tell( struct ot_workstruct *ws ) {
static void *livesync_worker(void *args) { static void *livesync_worker(void *args) {
struct ot_workstruct ws; struct ot_workstruct ws;
ot_ip6 in_ip; uint16_t in_port; ot_ip6 in_ip;
uint16_t in_port;
(void)args; (void)args;

11
ot_mutex.c

@ -16,10 +16,10 @@
#include "uint32.h" #include "uint32.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_iovec.h" #include "ot_iovec.h"
#include "ot_mutex.h" #include "ot_mutex.h"
#include "ot_stats.h" #include "ot_stats.h"
#include "trackerlogic.h"
/* #define MTX_DBG( STRING ) fprintf( stderr, STRING ) */ /* #define MTX_DBG( STRING ) fprintf( stderr, STRING ) */
#define MTX_DBG(STRING) #define MTX_DBG(STRING)
@ -37,9 +37,7 @@ ot_vector *mutex_bucket_lock( int bucket ) {
return all_torrents + bucket; return all_torrents + bucket;
} }
ot_vector *mutex_bucket_lock_by_hash( ot_hash const hash ) { ot_vector *mutex_bucket_lock_by_hash(ot_hash const hash) { return mutex_bucket_lock(uint32_read_big((const char *)hash) >> OT_BUCKET_COUNT_SHIFT); }
return mutex_bucket_lock( uint32_read_big( (const char*)hash ) >> OT_BUCKET_COUNT_SHIFT );
}
void mutex_bucket_unlock(int bucket, int delta_torrentcount) { void mutex_bucket_unlock(int bucket, int delta_torrentcount) {
pthread_mutex_unlock(bucket_mutex + bucket); pthread_mutex_unlock(bucket_mutex + bucket);
@ -50,9 +48,7 @@ void mutex_bucket_unlock_by_hash( ot_hash const 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() { return g_torrent_count; }
return g_torrent_count;
}
/* TaskQueue Magic */ /* TaskQueue Magic */
@ -223,7 +219,6 @@ int mutex_workqueue_pushchunked(ot_taskid taskid, struct iovec *iovec) {
return task ? 0 : -1; return task ? 0 : -1;
} }
int64 mutex_workqueue_popresult(int *iovec_entries, struct iovec **iovec, int *is_partial) { int64 mutex_workqueue_popresult(int *iovec_entries, struct iovec **iovec, int *is_partial) {
struct ot_task **task; struct ot_task **task;
int64 sock = -1; int64 sock = -1;

1
ot_mutex.h

@ -7,6 +7,7 @@
#define OT_MUTEX_H__ #define OT_MUTEX_H__
#include <sys/uio.h> #include <sys/uio.h>
#include "trackerlogic.h"
void mutex_init(void); void mutex_init(void);
void mutex_deinit(void); void mutex_deinit(void);

283
ot_stats.c

@ -4,16 +4,16 @@
$id$ */ $id$ */
/* System */ /* System */
#include <stdlib.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/types.h> #include <inttypes.h>
#include <sys/uio.h> #include <pthread.h>
#include <sys/mman.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <pthread.h> #include <sys/mman.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
#include <inttypes.h>
#ifdef WANT_SYSLOGS #ifdef WANT_SYSLOGS
#include <syslog.h> #include <syslog.h>
#endif #endif
@ -25,11 +25,11 @@
#include "ip6.h" #include "ip6.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "ot_accesslist.h"
#include "ot_mutex.h"
#include "ot_iovec.h" #include "ot_iovec.h"
#include "ot_mutex.h"
#include "ot_stats.h" #include "ot_stats.h"
#include "ot_accesslist.h" #include "trackerlogic.h"
#ifndef NO_FULLSCRAPE_LOGGING #ifndef NO_FULLSCRAPE_LOGGING
#define LOG_TO_STDERR(...) fprintf(stderr, __VA_ARGS__) #define LOG_TO_STDERR(...) fprintf(stderr, __VA_ARGS__)
@ -42,21 +42,23 @@ static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype
#define OT_STATS_TMPSIZE 8192 #define OT_STATS_TMPSIZE 8192
/* Clumsy counters... to be rethought */ /* Clumsy counters... to be rethought */
static unsigned long long ot_overall_tcp_connections = 0; static unsigned long long ot_overall_tcp_connections;
static unsigned long long ot_overall_udp_connections = 0; static unsigned long long ot_overall_udp_connections;
static unsigned long long ot_overall_tcp_successfulannounces = 0; static unsigned long long ot_overall_tcp_successfulannounces;
static unsigned long long ot_overall_udp_successfulannounces = 0; static unsigned long long ot_overall_udp_successfulannounces;
static unsigned long long ot_overall_tcp_successfulscrapes = 0; static unsigned long long ot_overall_tcp_successfulscrapes;
static unsigned long long ot_overall_udp_successfulscrapes = 0; static unsigned long long ot_overall_udp_successfulscrapes;
static unsigned long long ot_overall_udp_connectionidmissmatches = 0; static unsigned long long ot_overall_udp_connectionidmissmatches;
static unsigned long long ot_overall_tcp_connects = 0; static unsigned long long ot_overall_tcp_connects;
static unsigned long long ot_overall_udp_connects = 0; static unsigned long long ot_overall_udp_connects;
static unsigned long long ot_overall_completed = 0; static unsigned long long ot_overall_completed;
static unsigned long long ot_full_scrape_count = 0; static unsigned long long ot_full_scrape_count;
static unsigned long long ot_full_scrape_request_count = 0; static unsigned long long ot_full_scrape_request_count;
static unsigned long long ot_full_scrape_size = 0; static unsigned long long ot_full_scrape_size;
static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT];
static char * ot_failed_request_names[] = { "302 Redirect", "400 Parse Error", "400 Invalid Parameter", "400 Invalid Parameter (compact=0)", "400 Not Modest", "402 Payment Required", "403 Access Denied", "404 Not found", "500 Internal Server Error" }; static char *ot_failed_request_names[] = {
"302 Redirect", "400 Parse Error", "400 Invalid Parameter", "400 Invalid Parameter (compact=0)", "400 Not Modest",
"402 Payment Required", "403 Access Denied", "404 Not found", "500 Internal Server Error"};
static unsigned long long ot_renewed[OT_PEER_TIMEOUT]; static unsigned long long ot_renewed[OT_PEER_TIMEOUT];
static unsigned long long ot_overall_sync_count; static unsigned long long ot_overall_sync_count;
static unsigned long long ot_overall_stall_count; static unsigned long long ot_overall_stall_count;
@ -130,11 +132,13 @@ static int stats_shift_down_network_count( stats_network_node **node, int depth,
return rest; return rest;
} }
static size_t stats_get_highscore_networks( stats_network_node *node, int depth, ot_ip6 node_value, size_t *scores, ot_ip6 *networks, int network_count, int limit ) { static size_t stats_get_highscore_networks(stats_network_node *node, int depth, ot_ip6 node_value, size_t *scores, ot_ip6 *networks, int network_count,
int limit) {
size_t score = 0; size_t score = 0;
int i; int i;
if( !node ) return 0; if (!node)
return 0;
if (depth < limit) { if (depth < limit) {
for (i = 0; i < STATS_NETWORK_NODE_COUNT; ++i) for (i = 0; i < STATS_NETWORK_NODE_COUNT; ++i)
@ -170,10 +174,12 @@ static size_t stats_get_highscore_networks( stats_network_node *node, int depth,
score += node_score; score += node_score;
if( node_score <= scores[0] ) continue; if (node_score <= scores[0])
continue;
__STR(node_value, depth, i); __STR(node_value, depth, i);
while( j < network_count && node_score > scores[j] ) ++j; while (j < network_count && node_score > scores[j])
++j;
--j; --j;
memcpy(scores, scores + 1, j * sizeof(*scores)); memcpy(scores, scores + 1, j * sizeof(*scores));
@ -294,9 +300,22 @@ static int torrent_statter( ot_torrent *torrent, uintptr_t data ) {
} }
/* Converter function from memory to human readable hex strings */ /* Converter function from memory to human readable hex strings */
static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} static char *to_hex(char *d, uint8_t *s) {
char *m = "0123456789ABCDEF";
char *t = d;
char *e = d + 40;
while (d < e) {
*d++ = m[*s >> 4];
*d++ = m[*s++ & 15];
}
*d = 0;
return t;
}
typedef struct { size_t val; ot_hash hash; } ot_record; typedef struct {
size_t val;
ot_hash hash;
} ot_record;
/* Fetches stats from tracker */ /* Fetches stats from tracker */
size_t stats_top_txt(char *reply, int amount) { size_t stats_top_txt(char *reply, int amount) {
@ -351,72 +370,42 @@ size_t stats_top_txt( char * reply, int amount ) {
return r - reply; return r - reply;
} }
static unsigned long events_per_time( unsigned long long events, time_t t ) { static unsigned long events_per_time(unsigned long long events, time_t t) { return events / ((unsigned int)t ? (unsigned int)t : 1); }
return events / ( (unsigned int)t ? (unsigned int)t : 1 );
}
static size_t stats_connections_mrtg(char *reply) { static size_t stats_connections_mrtg(char *reply) {
ot_time t = time(NULL) - ot_start_time; ot_time t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.",
"%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.",
ot_overall_tcp_connections + ot_overall_udp_connections, ot_overall_tcp_connections + ot_overall_udp_connections,
ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600),
(int)t,
(int)(t / 3600),
events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t), events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t),
events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
);
} }
static size_t stats_udpconnections_mrtg(char *reply) { static size_t stats_udpconnections_mrtg(char *reply) {
ot_time t = time(NULL) - ot_start_time; ot_time t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", ot_overall_udp_connections,
"%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), events_per_time(ot_overall_udp_connections, t),
ot_overall_udp_connections, events_per_time(ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
ot_overall_udp_successfulannounces+ot_overall_udp_connects,
(int)t,
(int)(t / 3600),
events_per_time( ot_overall_udp_connections, t ),
events_per_time( ot_overall_udp_successfulannounces+ot_overall_udp_connects, t )
);
} }
static size_t stats_tcpconnections_mrtg(char *reply) { static size_t stats_tcpconnections_mrtg(char *reply) {
time_t t = time(NULL) - ot_start_time; time_t t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", ot_overall_tcp_connections,
"%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", ot_overall_tcp_successfulannounces, (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections, t),
ot_overall_tcp_connections, events_per_time(ot_overall_tcp_successfulannounces, t));
ot_overall_tcp_successfulannounces,
(int)t,
(int)(t / 3600),
events_per_time( ot_overall_tcp_connections, t ),
events_per_time( ot_overall_tcp_successfulannounces, t )
);
} }
static size_t stats_scrape_mrtg(char *reply) { static size_t stats_scrape_mrtg(char *reply) {
time_t t = time(NULL) - ot_start_time; time_t t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", ot_overall_tcp_successfulscrapes,
"%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", ot_overall_udp_successfulscrapes, (int)t, (int)(t / 3600),
ot_overall_tcp_successfulscrapes, events_per_time((ot_overall_tcp_successfulscrapes + ot_overall_udp_successfulscrapes), t));
ot_overall_udp_successfulscrapes,
(int)t,
(int)(t / 3600),
events_per_time( (ot_overall_tcp_successfulscrapes+ot_overall_udp_successfulscrapes), t )
);
} }
static size_t stats_fullscrapes_mrtg(char *reply) { static size_t stats_fullscrapes_mrtg(char *reply) {
ot_time t = time(NULL) - ot_start_time; ot_time t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", ot_full_scrape_count * 1000,
"%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", ot_full_scrape_size, (int)t, (int)(t / 3600), events_per_time(ot_full_scrape_count, t), events_per_time(ot_full_scrape_size, t));
ot_full_scrape_count * 1000,
ot_full_scrape_size,
(int)t,
(int)(t / 3600),
events_per_time( ot_full_scrape_count, t ),
events_per_time( ot_full_scrape_size, t )
);
} }
static size_t stats_peers_mrtg(char *reply) { static size_t stats_peers_mrtg(char *reply) {
@ -424,29 +413,19 @@ static size_t stats_peers_mrtg( char * reply ) {
iterate_all_torrents(torrent_statter, (uintptr_t)&stats); iterate_all_torrents(torrent_statter, (uintptr_t)&stats);
return sprintf( reply, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", return sprintf(reply, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", stats.peer_count, stats.seed_count, stats.torrent_count);
stats.peer_count,
stats.seed_count,
stats.torrent_count
);
} }
static size_t stats_torrents_mrtg( char * reply ) static size_t stats_torrents_mrtg(char *reply) {
{
size_t torrent_count = mutex_get_torrent_count(); size_t torrent_count = mutex_get_torrent_count();
return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", return sprintf(reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", torrent_count, (size_t)0, torrent_count);
torrent_count,
(size_t)0,
torrent_count
);
} }
static size_t stats_httperrors_txt(char *reply) { static size_t stats_httperrors_txt(char *reply) {
return sprintf( reply, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n", return sprintf(reply, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n", ot_failed_request_counts[0],
ot_failed_request_counts[0], ot_failed_request_counts[1], ot_failed_request_counts[2], ot_failed_request_counts[1], ot_failed_request_counts[2], ot_failed_request_counts[3], ot_failed_request_counts[4],
ot_failed_request_counts[3], ot_failed_request_counts[4], ot_failed_request_counts[5], ot_failed_request_counts[5], ot_failed_request_counts[6]);
ot_failed_request_counts[6] );
} }
static size_t stats_return_renew_bucket(char *reply) { static size_t stats_return_renew_bucket(char *reply) {
@ -460,28 +439,16 @@ static size_t stats_return_renew_bucket( char * reply ) {
static size_t stats_return_sync_mrtg(char *reply) { static size_t stats_return_sync_mrtg(char *reply) {
ot_time t = time(NULL) - ot_start_time; ot_time t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", ot_overall_sync_count, 0LL, (int)t,
"%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", (int)(t / 3600), events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t),
ot_overall_sync_count, events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
0LL,
(int)t,
(int)(t / 3600),
events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ),
events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t )
);
} }
static size_t stats_return_completed_mrtg(char *reply) { static size_t stats_return_completed_mrtg(char *reply) {
ot_time t = time(NULL) - ot_start_time; ot_time t = time(NULL) - ot_start_time;
return sprintf( reply, return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker, %lu completed/h.", ot_overall_completed, 0LL, (int)t, (int)(t / 3600),
"%llu\n%llu\n%i seconds (%i hours)\nopentracker, %lu completed/h.", events_per_time(ot_overall_completed, t / 3600));
ot_overall_completed,
0LL,
(int)t,
(int)(t / 3600),
events_per_time( ot_overall_completed, t / 3600 )
);
} }
#ifdef WANT_LOG_NUMWANT #ifdef WANT_LOG_NUMWANT
@ -505,7 +472,8 @@ static void stats_return_fulllog( int *iovec_entries, struct iovec **iovector, c
while (loglist) { while (loglist) {
if (r + (loglist->size + 64) >= re) { if (r + (loglist->size + 64) >= re) {
r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 32 * OT_STATS_TMPSIZE); r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 32 * OT_STATS_TMPSIZE);
if( !r ) return; if (!r)
return;
re = r + 32 * OT_STATS_TMPSIZE; re = r + 32 * OT_STATS_TMPSIZE;
} }
r += sprintf(r, "%08ld: ", loglist->time); r += sprintf(r, "%08ld: ", loglist->time);
@ -537,7 +505,9 @@ static size_t stats_return_everything( char * reply ) {
r += sprintf(r, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); r += sprintf(r, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
r += sprintf(r, "<stats>\n"); r += sprintf(r, "<stats>\n");
r += sprintf(r, " <tracker_id>%" PRIu32 "</tracker_id>\n", g_tracker_id); r += sprintf(r, " <tracker_id>%" PRIu32 "</tracker_id>\n", g_tracker_id);
r += sprintf( r, " <version>\n" ); r += stats_return_tracker_version( r ); r += sprintf( r, " </version>\n" ); r += sprintf(r, " <version>\n");
r += stats_return_tracker_version(r);
r += sprintf(r, " </version>\n");
r += sprintf(r, " <uptime>%llu</uptime>\n", (unsigned long long)(time(NULL) - ot_start_time)); r += sprintf(r, " <uptime>%llu</uptime>\n", (unsigned long long)(time(NULL) - ot_start_time));
r += sprintf(r, " <torrents>\n"); r += sprintf(r, " <torrents>\n");
r += sprintf(r, " <count_mutex>%zd</count_mutex>\n", mutex_get_torrent_count()); r += sprintf(r, " <count_mutex>%zd</count_mutex>\n", mutex_get_torrent_count());
@ -547,8 +517,13 @@ static size_t stats_return_everything( char * reply ) {
r += sprintf(r, " <seeds>\n <count>%llu</count>\n </seeds>\n", stats.seed_count); r += sprintf(r, " <seeds>\n <count>%llu</count>\n </seeds>\n", stats.seed_count);
r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed); r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed);
r += sprintf(r, " <connections>\n"); r += sprintf(r, " <connections>\n");
r += sprintf( r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n", ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes ); r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n",
r += sprintf( r, " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n", ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes, ot_overall_udp_connectionidmissmatches ); ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes);
r += sprintf(
r,
" <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n",
ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes,
ot_overall_udp_connectionidmissmatches);
r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count); r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count);
r += sprintf(r, " </connections>\n"); r += sprintf(r, " </connections>\n");
r += sprintf(r, " <debug>\n"); r += sprintf(r, " <debug>\n");
@ -566,15 +541,13 @@ static size_t stats_return_everything( char * reply ) {
return r - reply; return r - reply;
} }
extern const char 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_opentracker_c, *g_version_accesslist_c, *g_version_clean_c, *g_version_fullscrape_c, *g_version_http_c, *g_version_mutex_c, *g_version_stats_c, *g_version_udp_c, *g_version_vector_c, *g_version_scan_urlencoded_query_c, *g_version_trackerlogic_c,
*g_version_iovec_c, *g_version_mutex_c, *g_version_stats_c, *g_version_udp_c, *g_version_vector_c, *g_version_livesync_c, *g_version_rijndael_c;
*g_version_scan_urlencoded_query_c, *g_version_trackerlogic_c, *g_version_livesync_c, *g_version_rijndael_c;
size_t stats_return_tracker_version(char *reply) { size_t stats_return_tracker_version(char *reply) {
return sprintf( reply, "%s%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_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, g_version_http_c, g_version_http_c, g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c,
g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c,
g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c, g_version_rijndael_c); g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c, g_version_rijndael_c);
} }
@ -619,22 +592,38 @@ static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype
return; return;
switch (mode & TASK_TASK_MASK) { switch (mode & TASK_TASK_MASK) {
case TASK_STATS_TORRENTS: r += stats_torrents_mrtg( r ); break; case TASK_STATS_TORRENTS:
case TASK_STATS_PEERS: r += stats_peers_mrtg( r ); break; r += stats_torrents_mrtg(r);
case TASK_STATS_SLASH24S: r += stats_slash24s_txt( r, 128 ); break; break;
case TASK_STATS_TOP10: r += stats_top_txt( r, 10 ); break; case TASK_STATS_PEERS:
r += stats_peers_mrtg(r);
break;
case TASK_STATS_SLASH24S:
r += stats_slash24s_txt(r, 128);
break;
case TASK_STATS_TOP10:
r += stats_top_txt(r, 10);
break;
case TASK_STATS_TOP100: case TASK_STATS_TOP100:
r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE); r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE);
if( !r ) return; if (!r)
r += stats_top_txt( r, 100 ); break; return;
case TASK_STATS_EVERYTHING: r = iovec_fix_increase_or_free( iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT ); r += stats_top_txt(r, 100);
if( !r ) return; break;
r += stats_return_everything( r ); break; case TASK_STATS_EVERYTHING:
r = iovec_fix_increase_or_free(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT);
if (!r)
return;
r += stats_return_everything(r);
break;
#ifdef WANT_SPOT_WOODPECKER #ifdef WANT_SPOT_WOODPECKER
case TASK_STATS_WOODPECKERS: r += stats_return_woodpeckers( r, 128 ); break; case TASK_STATS_WOODPECKERS:
r += stats_return_woodpeckers(r, 128);
break;
#endif #endif
#ifdef WANT_FULLLOG_NETWORKS #ifdef WANT_FULLLOG_NETWORKS
case TASK_STATS_FULLLOG: stats_return_fulllog( iovec_entries, iovector, r ); case TASK_STATS_FULLLOG:
stats_return_fulllog(iovec_entries, iovector, r);
return; return;
#endif #endif
default: default:
@ -647,16 +636,25 @@ static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype
void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_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++;
#ifdef WANT_LOG_NETWORKS #ifdef WANT_LOG_NETWORKS
stat_increase_network_count(&stats_network_counters_root, 0, event_data); stat_increase_network_count(&stats_network_counters_root, 0, event_data);
#endif #endif
break; break;
case EVENT_ANNOUNCE: case EVENT_ANNOUNCE:
if( proto == FLAG_TCP ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; if (proto == FLAG_TCP)
ot_overall_tcp_successfulannounces++;
else
ot_overall_udp_successfulannounces++;
break; break;
case EVENT_CONNECT: case EVENT_CONNECT:
if( proto == FLAG_TCP ) ot_overall_tcp_connects++; else ot_overall_udp_connects++; if (proto == FLAG_TCP)
ot_overall_tcp_connects++;
else
ot_overall_udp_connects++;
break; break;
case EVENT_COMPLETED: case EVENT_COMPLETED:
#ifdef WANT_SYSLOGS #ifdef WANT_SYSLOGS
@ -689,14 +687,16 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event
ot_overall_completed++; ot_overall_completed++;
break; break;
case EVENT_SCRAPE: case EVENT_SCRAPE:
if( proto == FLAG_TCP ) ot_overall_tcp_successfulscrapes++; else ot_overall_udp_successfulscrapes++; if (proto == FLAG_TCP)
ot_overall_tcp_successfulscrapes++;
else
ot_overall_udp_successfulscrapes++;
break; break;
case EVENT_FULLSCRAPE: case EVENT_FULLSCRAPE:
ot_full_scrape_count++; ot_full_scrape_count++;
ot_full_scrape_size += event_data; ot_full_scrape_size += event_data;
break; break;
case EVENT_FULLSCRAPE_REQUEST: case EVENT_FULLSCRAPE_REQUEST: {
{
ot_ip6 *ip = (ot_ip6 *)event_data; /* ugly hack to transfer ip to stats */ ot_ip6 *ip = (ot_ip6 *)event_data; /* ugly hack to transfer ip to stats */
char _debug[512]; char _debug[512];
int off = snprintf(_debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time) / 60); int off = snprintf(_debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time) / 60);
@ -704,10 +704,8 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event
off += snprintf(_debug + off, sizeof(_debug) - off, " - FULL SCRAPE\n"); off += snprintf(_debug + off, sizeof(_debug) - off, " - FULL SCRAPE\n");
(void)write(2, _debug, off); (void)write(2, _debug, off);
ot_full_scrape_request_count++; ot_full_scrape_request_count++;
} } break;
break; case EVENT_FULLSCRAPE_REQUEST_GZIP: {
case EVENT_FULLSCRAPE_REQUEST_GZIP:
{
ot_ip6 *ip = (ot_ip6 *)event_data; /* ugly hack to transfer ip to stats */ ot_ip6 *ip = (ot_ip6 *)event_data; /* ugly hack to transfer ip to stats */
char _debug[512]; char _debug[512];
int off = snprintf(_debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time) / 60); int off = snprintf(_debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time) / 60);
@ -715,8 +713,7 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event
off += snprintf(_debug + off, sizeof(_debug) - off, " - FULL SCRAPE\n"); off += snprintf(_debug + off, sizeof(_debug) - off, " - FULL SCRAPE\n");
(void)write(2, _debug, off); (void)write(2, _debug, off);
ot_full_scrape_request_count++; ot_full_scrape_request_count++;
} } break;
break;
case EVENT_FAILED: case EVENT_FAILED:
ot_failed_request_counts[event_data]++; ot_failed_request_counts[event_data]++;
break; break;
@ -767,9 +764,7 @@ static void * stats_worker( void * args ) {
return NULL; return NULL;
} }
void stats_deliver( int64 sock, int tasktype ) { void stats_deliver(int64 sock, int tasktype) { mutex_workqueue_pushtask(sock, tasktype); }
mutex_workqueue_pushtask( sock, tasktype );
}
static pthread_t thread_id; static pthread_t thread_id;
void stats_init() { void stats_init() {

2
ot_stats.h

@ -6,6 +6,8 @@
#ifndef OT_STATS_H__ #ifndef OT_STATS_H__
#define OT_STATS_H__ #define OT_STATS_H__
#include "trackerlogic.h"
typedef enum { typedef enum {
EVENT_ACCEPT, EVENT_ACCEPT,
EVENT_READ, EVENT_READ,

37
ot_udp.c

@ -4,22 +4,22 @@
$id$ */ $id$ */
/* System */ /* System */
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Libowfat */ /* Libowfat */
#include "socket.h"
#include "io.h" #include "io.h"
#include "ip6.h" #include "ip6.h"
#include "socket.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_udp.h"
#include "ot_stats.h"
#include "ot_rijndael.h" #include "ot_rijndael.h"
#include "ot_stats.h"
#include "ot_udp.h"
#include "trackerlogic.h"
#if 0 #if 0
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 };
@ -63,7 +63,8 @@ static void udp_make_connectionid( uint32_t connid[2], const ot_ip6 remoteip, in
} }
memcpy(plain, remoteip, sizeof(plain)); memcpy(plain, remoteip, sizeof(plain));
for( i=0; i<4; ++i ) plain[i] ^= g_key_of_the_hour[age]; for (i = 0; i < 4; ++i)
plain[i] ^= g_key_of_the_hour[age];
rijndaelEncrypt128(g_rijndael_round_key, (uint8_t *)remoteip, (uint8_t *)crypt); rijndaelEncrypt128(g_rijndael_round_key, (uint8_t *)remoteip, (uint8_t *)crypt);
connid[0] = crypt[0] ^ crypt[1]; connid[0] = crypt[0] ^ crypt[1];
connid[1] = crypt[2] ^ crypt[3]; connid[1] = crypt[2] ^ crypt[3];
@ -81,7 +82,8 @@ int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
size_t byte_count, scrape_count; size_t byte_count, scrape_count;
byte_count = socket_recv6(serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid); byte_count = socket_recv6(serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid);
if( !byte_count ) return 0; if (!byte_count)
return 0;
stats_issue_event(EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip); stats_issue_event(EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip);
stats_issue_event(EVENT_READ, FLAG_UDP, byte_count); stats_issue_event(EVENT_READ, FLAG_UDP, byte_count);
@ -112,7 +114,8 @@ int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
udp_make_connectionid(connid, remoteip, 1); udp_make_connectionid(connid, remoteip, 1);
if (inpacket[0] != connid[0] || inpacket[1] != connid[1]) { if (inpacket[0] != connid[0] || inpacket[1] != connid[1]) {
const size_t s = sizeof("Connection ID missmatch."); const size_t s = sizeof("Connection ID missmatch.");
outpacket[0] = htonl( 3 ); outpacket[1] = inpacket[3]; outpacket[0] = htonl(3);
outpacket[1] = inpacket[3];
memcpy(&outpacket[2], "Connection ID missmatch.", s); memcpy(&outpacket[2], "Connection ID missmatch.", s);
socket_send6(serversocket, ws->outbuf, 8 + s, remoteip, remoteport, 0); socket_send6(serversocket, ws->outbuf, 8 + s, remoteip, remoteport, 0);
stats_issue_event(EVENT_CONNID_MISSMATCH, FLAG_UDP, 8 + s); stats_issue_event(EVENT_CONNID_MISSMATCH, FLAG_UDP, 8 + s);
@ -151,9 +154,14 @@ int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
OT_PEERFLAG(ws->peer) = 0; OT_PEERFLAG(ws->peer) = 0;
switch (event) { switch (event) {
case 1: OT_PEERFLAG( ws->peer ) |= PEER_FLAG_COMPLETED; break; case 1:
case 3: OT_PEERFLAG( ws->peer ) |= PEER_FLAG_STOPPED; break; OT_PEERFLAG(ws->peer) |= PEER_FLAG_COMPLETED;
default: break; break;
case 3:
OT_PEERFLAG(ws->peer) |= PEER_FLAG_STOPPED;
break;
default:
break;
} }
if (!left) if (!left)
@ -169,7 +177,8 @@ int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
/* Limit amount of peers to OT_MAX_PEERS_UDP */ /* Limit amount of peers to OT_MAX_PEERS_UDP */
uint32_t numwant = ntohl(inpacket[92 / 4]); uint32_t numwant = ntohl(inpacket[92 / 4]);
size_t max_peers = ip6_isv4mapped(remoteip) ? OT_MAX_PEERS_UDP4 : OT_MAX_PEERS_UDP6; size_t max_peers = ip6_isv4mapped(remoteip) ? OT_MAX_PEERS_UDP4 : OT_MAX_PEERS_UDP6;
if (numwant > max_peers) numwant = max_peers; if (numwant > max_peers)
numwant = max_peers;
ws->reply = ws->outbuf + 8; ws->reply = ws->outbuf + 8;
ws->reply_size = 8 + add_peer_to_torrent_and_return_peers(FLAG_UDP, ws, numwant); ws->reply_size = 8 + add_peer_to_torrent_and_return_peers(FLAG_UDP, ws, numwant);

54
ot_vector.c

@ -4,33 +4,27 @@
$id$ */ $id$ */
/* System */ /* System */
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <stdint.h>
#include <stddef.h>
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h" #include "trackerlogic.h"
#include "ot_vector.h"
/* Libowfat */ /* Libowfat */
#include "uint32.h"
#include "uint16.h" #include "uint16.h"
#include "uint32.h"
static int vector_compare_peer6(const void *peer1, const void *peer2 ) { static int vector_compare_peer6(const void *peer1, const void *peer2) { return memcmp(peer1, peer2, OT_PEER_COMPARE_SIZE6); }
return memcmp( peer1, peer2, OT_PEER_COMPARE_SIZE6 ); static int vector_compare_peer4(const void *peer1, const void *peer2) { return memcmp(peer1, peer2, OT_PEER_COMPARE_SIZE4); }
}
static int vector_compare_peer4(const void *peer1, const void *peer2 ) {
return memcmp( peer1, peer2, OT_PEER_COMPARE_SIZE4 );
}
/* 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
no exact match is found. In that case it sets exactmatch 0 and gives no exact match is found. In that case it sets exactmatch 0 and gives
calling functions the chance to insert data calling functions the chance to insert data
*/ */
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 interval = member_count; size_t interval = member_count;
while (interval) { while (interval) {
@ -54,7 +48,8 @@ void *binary_search( const void * const key, const void * base, const size_t mem
static uint8_t vector_hash_peer(ot_peer const *peer, size_t compare_size, int bucket_count) { static uint8_t vector_hash_peer(ot_peer const *peer, size_t compare_size, int bucket_count) {
unsigned int hash = 5381; unsigned int hash = 5381;
uint8_t *p = (uint8_t *)peer; uint8_t *p = (uint8_t *)peer;
while( compare_size-- ) hash += (hash<<5) + *(p++); while (compare_size--)
hash += (hash << 5) + *(p++);
return hash % bucket_count; return hash % bucket_count;
} }
@ -68,12 +63,14 @@ static uint8_t vector_hash_peer( ot_peer const *peer, size_t compare_size, int b
void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch) { void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch) {
uint8_t *match = binary_search(key, vector->data, vector->size, member_size, compare_size, exactmatch); uint8_t *match = binary_search(key, vector->data, vector->size, member_size, compare_size, exactmatch);
if( *exactmatch ) return match; if (*exactmatch)
return match;
if (vector->size + 1 > vector->space) { if (vector->size + 1 > vector->space) {
size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS;
uint8_t *new_data = realloc(vector->data, new_space * member_size); uint8_t *new_data = realloc(vector->data, new_space * member_size);
if( !new_data ) return NULL; if (!new_data)
return NULL;
/* Adjust pointer if it moved by realloc */ /* Adjust pointer if it moved by realloc */
match = new_data + (match - (uint8_t *)vector->data); match = new_data + (match - (uint8_t *)vector->data);
@ -96,7 +93,8 @@ ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer const *peer, siz
vector = ((ot_vector *)vector->data) + vector_hash_peer(peer, compare_size, vector->size); vector = ((ot_vector *)vector->data) + vector_hash_peer(peer, compare_size, vector->size);
match = binary_search(peer, vector->data, vector->size, peer_size, compare_size, exactmatch); match = binary_search(peer, vector->data, vector->size, peer_size, compare_size, exactmatch);
if( *exactmatch ) return match; if (*exactmatch)
return match;
/* This is the amount of bytes that needs to be pushed backwards by peer_size bytes to make room for new peer */ /* This is the amount of bytes that needs to be pushed backwards by peer_size bytes to make room for new peer */
end = (ot_peer *)vector->data + vector->size * peer_size; end = (ot_peer *)vector->data + vector->size * peer_size;
@ -107,7 +105,8 @@ ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer const *peer, siz
size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS;
ot_peer *new_data = realloc(vector->data, new_space * peer_size); ot_peer *new_data = realloc(vector->data, new_space * peer_size);
if( !new_data ) return NULL; if (!new_data)
return NULL;
/* Adjust pointer if it moved by realloc */ /* Adjust pointer if it moved by realloc */
match = new_data + offset; match = new_data + offset;
@ -132,7 +131,8 @@ int vector_remove_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size
ot_peer *match, *end; ot_peer *match, *end;
size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size);
if( !vector->size ) return 0; if (!vector->size)
return 0;
/* If space is zero but size is set, we're dealing with a list of vector->size buckets */ /* If space is zero but size is set, we're dealing with a list of vector->size buckets */
if (vector->space < vector->size) if (vector->space < vector->size)
@ -140,7 +140,8 @@ int vector_remove_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size
end = ((ot_peer *)vector->data) + peer_size * vector->size; end = ((ot_peer *)vector->data) + peer_size * vector->size;
match = (ot_peer *)binary_search(peer, vector->data, vector->size, peer_size, compare_size, &exactmatch); match = (ot_peer *)binary_search(peer, vector->data, vector->size, peer_size, compare_size, &exactmatch);
if( !exactmatch ) return 0; if (!exactmatch)
return 0;
was_seeder = (OT_PEERFLAG_D(match, peer_size) & PEER_FLAG_SEEDING) ? 2 : 1; was_seeder = (OT_PEERFLAG_D(match, peer_size) & PEER_FLAG_SEEDING) ? 2 : 1;
memmove(match, match + peer_size, end - match - peer_size); memmove(match, match + peer_size, end - match - peer_size);
@ -153,7 +154,8 @@ int vector_remove_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size
void vector_remove_torrent(ot_vector *vector, ot_torrent *match) { void vector_remove_torrent(ot_vector *vector, ot_torrent *match) {
ot_torrent *end = ((ot_torrent *)vector->data) + vector->size; ot_torrent *end = ((ot_torrent *)vector->data) + vector->size;
if( !vector->size ) return; if (!vector->size)
return;
/* If this is being called after a unsuccessful malloc() for peer_list /* If this is being called after a unsuccessful malloc() for peer_list
in add_peer_to_torrent, match->peer_list actually might be NULL */ in add_peer_to_torrent, match->peer_list actually might be NULL */
@ -177,8 +179,7 @@ void vector_clean_list( ot_vector * vector, int num_buckets ) {
void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size) { void vector_redistribute_buckets(ot_peerlist *peer_list, size_t peer_size) {
int tmp, bucket, bucket_size_new, num_buckets_new, num_buckets_old = 1; int tmp, bucket, bucket_size_new, num_buckets_new, num_buckets_old = 1;
ot_vector *bucket_list_new, *bucket_list_old = &peer_list->peers; ot_vector *bucket_list_new, *bucket_list_old = &peer_list->peers;
int (*sort_func)(const void *, const void *) = int (*sort_func)(const void *, const void *) = peer_size == OT_PEER_SIZE6 ? &vector_compare_peer6 : &vector_compare_peer4;
peer_size == OT_PEER_SIZE6 ? &vector_compare_peer6 : &vector_compare_peer4;
if (OT_PEERLIST_HASBUCKETS(peer_list)) { if (OT_PEERLIST_HASBUCKETS(peer_list)) {
num_buckets_old = peer_list->peers.size; num_buckets_old = peer_list->peers.size;
@ -205,7 +206,8 @@ void vector_redistribute_buckets( ot_peerlist * peer_list, size_t peer_size ) {
/* Assume near perfect distribution */ /* Assume near perfect distribution */
bucket_list_new = malloc(num_buckets_new * sizeof(ot_vector)); bucket_list_new = malloc(num_buckets_new * sizeof(ot_vector));
if( !bucket_list_new) return; if (!bucket_list_new)
return;
bzero(bucket_list_new, num_buckets_new * sizeof(ot_vector)); bzero(bucket_list_new, num_buckets_new * sizeof(ot_vector));
tmp = peer_list->peer_count / num_buckets_new; tmp = peer_list->peer_count / num_buckets_new;
@ -231,7 +233,8 @@ void vector_redistribute_buckets( ot_peerlist * peer_list, size_t peer_size ) {
bucket_dest += vector_hash_peer(peers_old, OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size), num_buckets_new); bucket_dest += vector_hash_peer(peers_old, OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size), num_buckets_new);
if (bucket_dest->size + 1 > bucket_dest->space) { if (bucket_dest->size + 1 > bucket_dest->space) {
void *tmp = realloc(bucket_dest->data, peer_size * OT_VECTOR_GROW_RATIO * bucket_dest->space); void *tmp = realloc(bucket_dest->data, peer_size * OT_VECTOR_GROW_RATIO * bucket_dest->space);
if( !tmp ) return vector_clean_list( bucket_list_new, num_buckets_new ); if (!tmp)
return vector_clean_list(bucket_list_new, num_buckets_new);
bucket_dest->data = tmp; bucket_dest->data = tmp;
bucket_dest->space *= OT_VECTOR_GROW_RATIO; bucket_dest->space *= OT_VECTOR_GROW_RATIO;
} }
@ -272,8 +275,7 @@ void vector_fixup_peers( ot_vector * vector, size_t peer_size ) {
return; return;
} }
while( ( vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && while ((vector->size * OT_VECTOR_SHRINK_THRESH < vector->space) && (vector->space >= OT_VECTOR_SHRINK_RATIO * OT_VECTOR_MIN_MEMBERS)) {
( vector->space >= OT_VECTOR_SHRINK_RATIO * OT_VECTOR_MIN_MEMBERS ) ) {
vector->space /= OT_VECTOR_SHRINK_RATIO; vector->space /= OT_VECTOR_SHRINK_RATIO;
need_fix++; need_fix++;
} }

3
ot_vector.h

@ -21,8 +21,7 @@ typedef struct {
size_t space; size_t space;
} ot_vector; } ot_vector;
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 );
void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch); void *vector_find_or_insert(ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch);
ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch); ot_peer *vector_find_or_insert_peer(ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch);

59
scan_urlencoded_query.c

@ -45,9 +45,13 @@ static const unsigned char is_unreserved[256] = {
/* Do a fast nibble to hex representation conversion */ /* Do a fast nibble to hex representation conversion */
static unsigned char fromhex(unsigned char x) { static unsigned char fromhex(unsigned char x) {
x-='0'; if( x<=9) return x; x -= '0';
x&=~0x20; x-='A'-'0'; if (x <= 9)
if( x<6 ) return x+10; return x;
x &= ~0x20;
x -= 'A' - '0';
if (x < 6)
return x + 10;
return 0xff; return 0xff;
} }
@ -58,11 +62,13 @@ void scan_urlencoded_skipvalue( char **string ) {
/* Since we are asked to skip the 'value', we assume to stop at /* Since we are asked to skip the 'value', we assume to stop at
terminators for a 'value' string position */ terminators for a 'value' string position */
while( ( f = is_unreserved[ *s++ ] ) & SCAN_SEARCHPATH_VALUE ); while ((f = is_unreserved[*s++]) & SCAN_SEARCHPATH_VALUE)
;
/* If we stopped at a hard terminator like \0 or \n, make the /* If we stopped at a hard terminator like \0 or \n, make the
next scan_urlencoded_query encounter it again */ next scan_urlencoded_query encounter it again */
if( f & SCAN_SEARCHPATH_TERMINATOR ) --s; if (f & SCAN_SEARCHPATH_TERMINATOR)
--s;
*string = (char *)s; *string = (char *)s;
} }
@ -71,8 +77,10 @@ int scan_find_keywords( const ot_keywords * keywords, char **string, SCAN_SEARCH
char *deststring = *string; char *deststring = *string;
ssize_t match_length = scan_urlencoded_query(string, deststring, flags); ssize_t match_length = scan_urlencoded_query(string, deststring, flags);
if( match_length < 0 ) return match_length; if (match_length < 0)
if( match_length == 0 ) return -3; return match_length;
if (match_length == 0)
return -3;
while (keywords->key) { while (keywords->key) {
if (!strncmp(keywords->key, deststring, match_length) && !keywords->key[match_length]) if (!strncmp(keywords->key, deststring, match_length) && !keywords->key[match_length])
@ -96,8 +104,10 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F
/* When encountering an url escaped character, try to decode */ /* When encountering an url escaped character, try to decode */
if (c == '%') { if (c == '%') {
if( ( b = fromhex(*s++) ) == 0xff ) return -1; if ((b = fromhex(*s++)) == 0xff)
if( ( c = fromhex(*s++) ) == 0xff ) return -1; return -1;
if ((c = fromhex(*s++)) == 0xff)
return -1;
c |= (b << 4); c |= (b << 4);
} }
@ -106,22 +116,30 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F
} }
switch (c) { switch (c) {
case 0: case '\r': case '\n': case ' ': case 0:
case '\r':
case '\n':
case ' ':
/* If we started scanning on a hard terminator, indicate we've finished */ /* If we started scanning on a hard terminator, indicate we've finished */
if( d == (unsigned char*)deststring ) return -2; if (d == (unsigned char *)deststring)
return -2;
/* Else make the next call to scan_urlencoded_param encounter it again */ /* Else make the next call to scan_urlencoded_param encounter it again */
--s; --s;
break; break;
case '?': case '?':
if( flags != SCAN_PATH ) return -1; if (flags != SCAN_PATH)
return -1;
break; break;
case '=': case '=':
if( flags != SCAN_SEARCHPATH_PARAM ) return -1; if (flags != SCAN_SEARCHPATH_PARAM)
return -1;
break; break;
case '&': case '&':
if( flags == SCAN_PATH ) return -1; if (flags == SCAN_PATH)
if( flags == SCAN_SEARCHPATH_PARAM ) --s; return -1;
if (flags == SCAN_SEARCHPATH_PARAM)
--s;
break; break;
default: default:
return -1; return -1;
@ -134,9 +152,14 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F
ssize_t scan_fixed_int(char *data, size_t len, int *tmp) { ssize_t scan_fixed_int(char *data, size_t len, int *tmp) {
int minus = 0; int minus = 0;
*tmp = 0; *tmp = 0;
if( *data == '-' ) --len, ++data, ++minus; if (*data == '-')
while( (len > 0) && (*data >= '0') && (*data <= '9') ) { --len; *tmp = 10**tmp + *data++-'0'; } --len, ++data, ++minus;
if( minus ) *tmp = -*tmp; while ((len > 0) && (*data >= '0') && (*data <= '9')) {
--len;
*tmp = 10 * *tmp + *data++ - '0';
}
if (minus)
*tmp = -*tmp;
return len; return len;
} }

74
trackerlogic.c

@ -4,31 +4,31 @@
$id$ */ $id$ */
/* System */ /* System */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Libowfat */ /* Libowfat */
#include "array.h"
#include "byte.h" #include "byte.h"
#include "io.h" #include "io.h"
#include "iob.h" #include "iob.h"
#include "ip6.h" #include "ip6.h"
#include "array.h"
/* Opentracker */ /* Opentracker */
#include "trackerlogic.h"
#include "ot_vector.h"
#include "ot_mutex.h"
#include "ot_stats.h"
#include "ot_clean.h"
#include "ot_http.h"
#include "ot_accesslist.h" #include "ot_accesslist.h"
#include "ot_clean.h"
#include "ot_fullscrape.h" #include "ot_fullscrape.h"
#include "ot_http.h"
#include "ot_livesync.h" #include "ot_livesync.h"
#include "ot_mutex.h"
#include "ot_stats.h"
#include "ot_vector.h"
#include "trackerlogic.h"
/* Forward declaration */ /* Forward declaration */
size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto); size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto);
@ -59,8 +59,7 @@ void add_torrent_from_saved_state( ot_hash const hash, ot_time base, size_t down
byte_zero(torrent, sizeof(ot_torrent)); byte_zero(torrent, sizeof(ot_torrent));
memcpy(torrent->hash, hash, sizeof(ot_hash)); memcpy(torrent->hash, hash, sizeof(ot_hash));
if( !( torrent->peer_list6 = malloc( sizeof (ot_peerlist) ) ) || if (!(torrent->peer_list6 = malloc(sizeof(ot_peerlist))) || !(torrent->peer_list4 = malloc(sizeof(ot_peerlist)))) {
!( torrent->peer_list4 = malloc( sizeof (ot_peerlist) ) ) ) {
vector_remove_torrent(torrents_list, torrent); vector_remove_torrent(torrents_list, torrent);
return mutex_bucket_unlock_by_hash(hash, 0); return mutex_bucket_unlock_by_hash(hash, 0);
} }
@ -105,8 +104,7 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr
byte_zero(torrent, sizeof(ot_torrent)); byte_zero(torrent, sizeof(ot_torrent));
memcpy(torrent->hash, *ws->hash, sizeof(ot_hash)); memcpy(torrent->hash, *ws->hash, sizeof(ot_hash));
if( !( torrent->peer_list6 = malloc( sizeof (ot_peerlist) ) ) || if (!(torrent->peer_list6 = malloc(sizeof(ot_peerlist))) || !(torrent->peer_list4 = malloc(sizeof(ot_peerlist)))) {
!( torrent->peer_list4 = malloc( sizeof (ot_peerlist) ) ) ) {
vector_remove_torrent(torrents_list, torrent); vector_remove_torrent(torrents_list, torrent);
mutex_bucket_unlock_by_hash(*ws->hash, 0); mutex_bucket_unlock_by_hash(*ws->hash, 0);
return 0; return 0;
@ -242,7 +240,10 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee
/* Make fixpoint arithmetic as exact as possible */ /* Make fixpoint arithmetic as exact as possible */
#define MAXPRECBIT (1 << (8 * sizeof(int) - 3)) #define MAXPRECBIT (1 << (8 * sizeof(int) - 3))
while( !(shifted_pc & MAXPRECBIT ) ) { shifted_pc <<= 1; shift++; } while (!(shifted_pc & MAXPRECBIT)) {
shifted_pc <<= 1;
shift++;
}
shifted_step = shifted_pc / amount; shifted_step = shifted_pc / amount;
#undef MAXPRECBIT #undef MAXPRECBIT
@ -254,8 +255,7 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee
ot_peer *peer; ot_peer *peer;
/* This is the aliased, non shifted range, next value may fall into */ /* This is the aliased, non shifted range, next value may fall into */
unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - unsigned int diff = (((amount + 1) * shifted_step) >> shift) - ((amount * shifted_step) >> shift);
( ( amount * shifted_step ) >> shift );
bucket_offset += 1 + nrand48(ws->rand48_state) % diff; bucket_offset += 1 + nrand48(ws->rand48_state) % diff;
while (bucket_offset >= bucket_list[bucket_index].size) { while (bucket_offset >= bucket_list[bucket_index].size) {
@ -341,7 +341,8 @@ static size_t return_peers_for_torrent_tcp( struct ot_workstruct * ws, ot_torren
++amount_v4; ++amount_v4;
} }
r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie", seed_count, down_count, peer_count, erval, erval/2 ); r +=
sprintf(r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie", seed_count, down_count, peer_count, erval, erval / 2);
if (amount_v4) { if (amount_v4) {
r += sprintf(r, PEERS_BENCODED4 "%zd:", OT_PEER_COMPARE_SIZE4 * amount_v4); r += sprintf(r, PEERS_BENCODED4 "%zd:", OT_PEER_COMPARE_SIZE4 * amount_v4);
@ -394,8 +395,7 @@ size_t return_udp_scrape_for_torrent( ot_hash const hash, char *reply ) {
} else { } else {
r[0] = htonl(torrent->peer_list6->seed_count + torrent->peer_list4->seed_count); r[0] = htonl(torrent->peer_list6->seed_count + torrent->peer_list4->seed_count);
r[1] = htonl(torrent->peer_list6->down_count + torrent->peer_list4->down_count); r[1] = htonl(torrent->peer_list6->down_count + torrent->peer_list4->down_count);
r[2] = htonl( torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - r[2] = htonl(torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->seed_count - torrent->peer_list4->seed_count);
torrent->peer_list6->seed_count - torrent->peer_list4->seed_count);
} }
} }
mutex_bucket_unlock_by_hash(hash, delta_torrentcount); mutex_bucket_unlock_by_hash(hash, delta_torrentcount);
@ -420,19 +420,21 @@ size_t return_tcp_scrape_for_torrent( ot_hash const *hash_list, int amount, char
vector_remove_torrent(torrents_list, torrent); vector_remove_torrent(torrents_list, torrent);
delta_torrentcount = -1; delta_torrentcount = -1;
} else { } else {
*r++='2';*r++='0';*r++=':'; *r++ = '2';
memcpy( r, hash, sizeof(ot_hash) ); r+=sizeof(ot_hash); *r++ = '0';
r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", *r++ = ':';
torrent->peer_list6->seed_count + torrent->peer_list4->seed_count, memcpy(r, hash, sizeof(ot_hash));
r += sizeof(ot_hash);
r += sprintf(r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", torrent->peer_list6->seed_count + torrent->peer_list4->seed_count,
torrent->peer_list6->down_count + torrent->peer_list4->down_count, torrent->peer_list6->down_count + torrent->peer_list4->down_count,
torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->seed_count - torrent->peer_list4->seed_count);
torrent->peer_list6->seed_count - torrent->peer_list4->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';
return r - reply; return r - reply;
} }
@ -456,19 +458,22 @@ size_t remove_peer_from_torrent( PROTO_FLAG proto, struct ot_workstruct *ws ) {
if (exactmatch) { if (exactmatch) {
peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4;
switch (vector_remove_peer(&peer_list->peers, peer_src, peer_size)) { switch (vector_remove_peer(&peer_list->peers, peer_src, peer_size)) {
case 2: peer_list->seed_count--; /* Intentional fallthrough */ case 2:
case 1: peer_list->peer_count--; /* Intentional fallthrough */ peer_list->seed_count--; /* Intentional fallthrough */
default: break; case 1:
peer_list->peer_count--; /* Intentional fallthrough */
default:
break;
} }
peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count;
seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count;
} }
if (proto == FLAG_TCP) { if (proto == FLAG_TCP) {
int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM;
ws->reply_size = sprintf( ws->reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s0:e", seed_count, peer_count - seed_count, erval, erval / 2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4 ); ws->reply_size = sprintf(ws->reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s0:e", seed_count, peer_count - seed_count, erval,
erval / 2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4);
} }
/* Handle UDP reply */ /* Handle UDP reply */
@ -496,7 +501,8 @@ void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data
break; break;
mutex_bucket_unlock(bucket, 0); mutex_bucket_unlock(bucket, 0);
if( !g_opentracker_running ) return; if (!g_opentracker_running)
return;
} }
} }

15
trackerlogic.h

@ -6,11 +6,11 @@
#ifndef OT_TRACKERLOGIC_H__ #ifndef OT_TRACKERLOGIC_H__
#define OT_TRACKERLOGIC_H__ #define OT_TRACKERLOGIC_H__
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#if defined(__linux__) && defined(WANT_ARC4RANDOM) #if defined(__linux__) && defined(WANT_ARC4RANDOM)
#include <bsd/stdlib.h> #include <bsd/stdlib.h>
@ -22,8 +22,10 @@
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]; typedef char ot_ip6[16];
typedef struct { ot_ip6 address; int bits; } typedef struct {
ot_net; ot_ip6 address;
int bits;
} ot_net;
/* List of peers should fit in a single UDP packet (around 1200 bytes) */ /* List of peers should fit in a single UDP packet (around 1200 bytes) */
#define OT_MAX_PEERS_UDP6 66 #define OT_MAX_PEERS_UDP6 66
#define OT_MAX_PEERS_UDP4 200 #define OT_MAX_PEERS_UDP4 200
@ -44,7 +46,8 @@ typedef struct { ot_ip6 address; int bits; }
#define OT_TORRENT_TIMEOUT_HOURS 24 #define OT_TORRENT_TIMEOUT_HOURS 24
#define OT_TORRENT_TIMEOUT (60 * OT_TORRENT_TIMEOUT_HOURS) #define OT_TORRENT_TIMEOUT (60 * OT_TORRENT_TIMEOUT_HOURS)
#define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( nrand48(ws->rand48_state) % OT_CLIENT_REQUEST_VARIATION ) ) #define OT_CLIENT_REQUEST_INTERVAL_RANDOM \
(OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION / 2 + (int)(nrand48(ws->rand48_state) % OT_CLIENT_REQUEST_VARIATION))
/* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not /* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not
fullscrape more frequently than this amount in seconds */ fullscrape more frequently than this amount in seconds */

Loading…
Cancel
Save