diff options
| author | erdgeist <> | 2007-12-03 00:58:18 +0000 |
|---|---|---|
| committer | erdgeist <> | 2007-12-03 00:58:18 +0000 |
| commit | fd4116140788b3e2b023eaf0bf223a429ec3f36d (patch) | |
| tree | 7834b98f7e3409b3c661128eaa7bf22f8e6a2663 | |
| parent | b0e4ebbbf2a3235077c6d607ef881b6791597087 (diff) | |
Finally split up the opentracker.c cruft into ot_http.c, ot_accesslist.c and just leave in socket handling and parameter parsing
| -rw-r--r-- | opentracker.c | 656 |
1 files changed, 38 insertions, 618 deletions
diff --git a/opentracker.c b/opentracker.c index debb868..cd6205c 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -6,9 +6,8 @@ | |||
| 6 | /* System */ | 6 | /* System */ |
| 7 | #include <string.h> | 7 | #include <string.h> |
| 8 | #include <sys/types.h> | 8 | #include <sys/types.h> |
| 9 | #include <sys/stat.h> | ||
| 10 | #include <sys/socket.h> | 9 | #include <sys/socket.h> |
| 11 | #include <arpa/inet.h> | 10 | //#include <arpa/inet.h> |
| 12 | #include <unistd.h> | 11 | #include <unistd.h> |
| 13 | #include <stdlib.h> | 12 | #include <stdlib.h> |
| 14 | #include <errno.h> | 13 | #include <errno.h> |
| @@ -20,605 +19,35 @@ | |||
| 20 | #include "socket.h" | 19 | #include "socket.h" |
| 21 | #include "io.h" | 20 | #include "io.h" |
| 22 | #include "iob.h" | 21 | #include "iob.h" |
| 23 | #include "buffer.h" | ||
| 24 | #include "array.h" | 22 | #include "array.h" |
| 25 | #include "byte.h" | ||
| 26 | #include "case.h" | ||
| 27 | #include "fmt.h" | 23 | #include "fmt.h" |
| 28 | #include "str.h" | ||
| 29 | #include "scan.h" | 24 | #include "scan.h" |
| 30 | #include "ip4.h" | 25 | #include "ip4.h" |
| 31 | 26 | ||
| 32 | /* Opentracker */ | 27 | /* Opentracker */ |
| 33 | #include "trackerlogic.h" | 28 | #include "trackerlogic.h" |
| 34 | #include "scan_urlencoded_query.h" | ||
| 35 | #include "ot_stats.h" | ||
| 36 | #include "ot_sync.h" | ||
| 37 | #include "ot_udp.h" | ||
| 38 | #include "ot_fullscrape.h" | ||
| 39 | #include "ot_iovec.h" | 29 | #include "ot_iovec.h" |
| 40 | #include "ot_accesslist.h" | ||
| 41 | #include "ot_mutex.h" | 30 | #include "ot_mutex.h" |
| 31 | #include "ot_http.h" | ||
| 32 | #include "ot_udp.h" | ||
| 42 | #include "ot_clean.h" | 33 | #include "ot_clean.h" |
| 34 | #include "ot_accesslist.h" | ||
| 35 | #include "ot_stats.h" | ||
| 43 | 36 | ||
| 44 | /* Globals */ | 37 | /* Globals */ |
| 45 | static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80; | ||
| 46 | static const size_t SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING = 32; | ||
| 47 | static const size_t SUCCESS_HTTP_SIZE_OFF = 17; | ||
| 48 | static uint32_t g_adminip_addresses[OT_ADMINIP_MAX]; | ||
| 49 | static unsigned int g_adminip_count = 0; | ||
| 50 | static time_t ot_last_clean_time; | ||
| 51 | time_t ot_start_time; | ||
| 52 | time_t g_now; | 38 | time_t g_now; |
| 53 | 39 | ||
| 54 | #ifndef WANT_TRACKER_SYNC | ||
| 55 | #define add_peer_to_torrent(A,B,C) add_peer_to_torrent(A,B) | ||
| 56 | #endif | ||
| 57 | |||
| 58 | #ifndef NO_FULLSCRAPE_LOGGING | ||
| 59 | #define LOG_TO_STDERR( ... ) fprintf( stderr, __VA_ARGS__ ) | ||
| 60 | #else | ||
| 61 | #define LOG_TO_STDERR( ... ) | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /* To always have space for error messages ;) */ | 40 | /* To always have space for error messages ;) */ |
| 65 | static char static_inbuf[8192]; | 41 | static char static_inbuf[8192]; |
| 66 | static char static_outbuf[8192]; | ||
| 67 | |||
| 68 | #define OT_MAXMULTISCRAPE_COUNT 64 | ||
| 69 | static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT]; | ||
| 70 | |||
| 71 | static char *FLAG_TCP = "TCP"; | ||
| 72 | static char *FLAG_UDP = "UDP"; | ||
| 73 | static size_t ot_sockets_count = 0; | ||
| 74 | |||
| 75 | #ifdef _DEBUG_HTTPERROR | ||
| 76 | static char debug_request[8192]; | ||
| 77 | #endif | ||
| 78 | 42 | ||
| 79 | typedef enum { | 43 | static char *FLAG_TCP = "T"; |
| 80 | STRUCT_HTTP_FLAG_ARRAY_USED = 1, | 44 | static char *FLAG_UDP = "U"; |
| 81 | STRUCT_HTTP_FLAG_IOB_USED = 2, | ||
| 82 | STRUCT_HTTP_FLAG_WAITINGFORTASK = 4, | ||
| 83 | STRUCT_HTTP_FLAG_GZIP = 8, | ||
| 84 | STRUCT_HTTP_FLAG_BZIP2 = 16 | ||
| 85 | } STRUCT_HTTP_FLAG; | ||
| 86 | |||
| 87 | struct http_data { | ||
| 88 | union { | ||
| 89 | array request; | ||
| 90 | io_batch batch; | ||
| 91 | }; | ||
| 92 | unsigned char ip[4]; | ||
| 93 | STRUCT_HTTP_FLAG flag; | ||
| 94 | }; | ||
| 95 | #define NOTBLESSED( h ) (!bsearch( &h->ip, g_adminip_addresses, g_adminip_count, 4, ot_ip_compare )) | ||
| 96 | static int ot_ip_compare( const void *a, const void *b ) { return memcmp( a,b,4 ); } | ||
| 97 | |||
| 98 | /* Prototypes */ | ||
| 99 | |||
| 100 | int main( int argc, char **argv ); | ||
| 101 | |||
| 102 | static void httperror( const int64 s, const char *title, const char *message ); | ||
| 103 | static void httpresponse( const int64 s, char *data, size_t l ); | ||
| 104 | |||
| 105 | static void sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector ); | ||
| 106 | static void senddata( const int64 s, char *buffer, const size_t size ); | ||
| 107 | |||
| 108 | static void server_mainloop( ); | ||
| 109 | static void handle_timeouted( void ); | ||
| 110 | static void handle_accept( const int64 serversocket ); | ||
| 111 | static void handle_read( const int64 clientsocket ); | ||
| 112 | static void handle_write( const int64 clientsocket ); | ||
| 113 | |||
| 114 | static void ot_try_bind( char ip[4], uint16 port, int is_tcp ); | ||
| 115 | |||
| 116 | static void usage( char *name ); | ||
| 117 | static void help( char *name ); | ||
| 118 | |||
| 119 | static void carp( const char *routine ); | ||
| 120 | static void panic( const char *routine ); | ||
| 121 | static void signal_handler( int s ); | ||
| 122 | |||
| 123 | #define HTTPERROR_400 return httperror( s, "400 Invalid Request", "This server only understands GET." ) | ||
| 124 | #define HTTPERROR_400_PARAM return httperror( s, "400 Invalid Request", "Invalid parameter" ) | ||
| 125 | #define HTTPERROR_400_COMPACT return httperror( s, "400 Invalid Request", "This server only delivers compact results." ) | ||
| 126 | #define HTTPERROR_403_IP return httperror( s, "403 Access Denied", "Your ip address is not allowed to administrate this server." ) | ||
| 127 | #define HTTPERROR_404 return httperror( s, "404 Not Found", "No such file or directory." ) | ||
| 128 | #define HTTPERROR_500 return httperror( s, "500 Internal Server Error", "A server error has occured. Please retry later." ) | ||
| 129 | |||
| 130 | /* End of prototypes */ | ||
| 131 | |||
| 132 | static void carp( const char *routine ) { | ||
| 133 | buffer_puts( buffer_2, routine ); | ||
| 134 | buffer_puts( buffer_2, ": " ); | ||
| 135 | buffer_puterror( buffer_2 ); | ||
| 136 | buffer_putnlflush( buffer_2 ); | ||
| 137 | } | ||
| 138 | 45 | ||
| 139 | static void panic( const char *routine ) { | 46 | static void panic( const char *routine ) { |
| 140 | carp( routine ); | 47 | fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); |
| 141 | exit( 111 ); | 48 | exit( 111 ); |
| 142 | } | 49 | } |
| 143 | 50 | ||
| 144 | static void httperror( const int64 s, const char *title, const char *message ) { | ||
| 145 | size_t reply_size = sprintf( static_outbuf, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n", | ||
| 146 | title, strlen(message)+strlen(title)+16-4,title+4); | ||
| 147 | #ifdef _DEBUG_HTTPERROR | ||
| 148 | fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request ); | ||
| 149 | #endif | ||
| 150 | senddata(s,static_outbuf,reply_size); | ||
| 151 | } | ||
| 152 | |||
| 153 | static void sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector ) { | ||
| 154 | struct http_data *h = io_getcookie( s ); | ||
| 155 | char *header; | ||
| 156 | int i; | ||
| 157 | size_t header_size, size = iovec_length( &iovec_entries, &iovector ); | ||
| 158 | tai6464 t; | ||
| 159 | |||
| 160 | /* No cookie? Bad socket. Leave. */ | ||
| 161 | if( !h ) { | ||
| 162 | iovec_free( &iovec_entries, &iovector ); | ||
| 163 | HTTPERROR_500; | ||
| 164 | } | ||
| 165 | |||
| 166 | /* If this socket collected request in a buffer, | ||
| 167 | free it now */ | ||
| 168 | if( h->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) { | ||
| 169 | h->flag &= ~STRUCT_HTTP_FLAG_ARRAY_USED; | ||
| 170 | array_reset( &h->request ); | ||
| 171 | } | ||
| 172 | |||
| 173 | /* If we came here, wait for the answer is over */ | ||
| 174 | h->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; | ||
| 175 | |||
| 176 | /* Our answers never are 0 vectors. Return an error. */ | ||
| 177 | if( !iovec_entries ) { | ||
| 178 | HTTPERROR_500; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* Prepare space for http header */ | ||
| 182 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING ); | ||
| 183 | if( !header ) { | ||
| 184 | iovec_free( &iovec_entries, &iovector ); | ||
| 185 | HTTPERROR_500; | ||
| 186 | } | ||
| 187 | |||
| 188 | if( h->flag & STRUCT_HTTP_FLAG_GZIP ) | ||
| 189 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: gzip\r\nContent-Length: %zd\r\n\r\n", size ); | ||
| 190 | else if( h->flag & STRUCT_HTTP_FLAG_BZIP2 ) | ||
| 191 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: bzip2\r\nContent-Length: %zd\r\n\r\n", size ); | ||
| 192 | else | ||
| 193 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size ); | ||
| 194 | |||
| 195 | iob_reset( &h->batch ); | ||
| 196 | iob_addbuf_free( &h->batch, header, header_size ); | ||
| 197 | |||
| 198 | /* Will move to ot_iovec.c */ | ||
| 199 | for( i=0; i<iovec_entries; ++i ) | ||
| 200 | iob_addbuf_munmap( &h->batch, iovector[i].iov_base, iovector[i].iov_len ); | ||
| 201 | free( iovector ); | ||
| 202 | |||
| 203 | h->flag |= STRUCT_HTTP_FLAG_IOB_USED; | ||
| 204 | |||
| 205 | /* writeable sockets timeout after twice the pool timeout | ||
| 206 | which defaults to 5 minutes (e.g. after 10 minutes) */ | ||
| 207 | taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); | ||
| 208 | io_timeout( s, t ); | ||
| 209 | io_dontwantread( s ); | ||
| 210 | io_wantwrite( s ); | ||
| 211 | } | ||
| 212 | |||
| 213 | static void senddata( const int64 s, char *buffer, size_t size ) { | ||
| 214 | struct http_data *h = io_getcookie( s ); | ||
| 215 | ssize_t written_size; | ||
| 216 | |||
| 217 | /* whoever sends data is not interested in its input-array */ | ||
| 218 | if( h && ( h->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) ) { | ||
| 219 | h->flag &= ~STRUCT_HTTP_FLAG_ARRAY_USED; | ||
| 220 | array_reset( &h->request ); | ||
| 221 | } | ||
| 222 | |||
| 223 | written_size = write( s, buffer, size ); | ||
| 224 | if( ( written_size < 0 ) || ( (size_t)written_size == size ) ) { | ||
| 225 | free( h ); io_close( s ); | ||
| 226 | } else { | ||
| 227 | char * outbuf; | ||
| 228 | tai6464 t; | ||
| 229 | |||
| 230 | if( !h ) return; | ||
| 231 | if( !( outbuf = malloc( size - written_size ) ) ) { | ||
| 232 | free(h); io_close( s ); | ||
| 233 | return; | ||
| 234 | } | ||
| 235 | |||
| 236 | iob_reset( &h->batch ); | ||
| 237 | memmove( outbuf, buffer + written_size, size - written_size ); | ||
| 238 | iob_addbuf_free( &h->batch, outbuf, size - written_size ); | ||
| 239 | h->flag |= STRUCT_HTTP_FLAG_IOB_USED; | ||
| 240 | |||
| 241 | /* writeable short data sockets just have a tcp timeout */ | ||
| 242 | taia_uint( &t, 0 ); io_timeout( s, t ); | ||
| 243 | io_dontwantread( s ); | ||
| 244 | io_wantwrite( s ); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | static void httpresponse( const int64 s, char *data, size_t l ) { | ||
| 249 | struct http_data* h = io_getcookie( s ); | ||
| 250 | char *c, *d=data; | ||
| 251 | ot_peer peer; | ||
| 252 | ot_torrent *torrent; | ||
| 253 | ot_hash *hash = NULL; | ||
| 254 | int numwant, tmp, scanon, mode; | ||
| 255 | ot_tasktype format = TASK_FULLSCRAPE; | ||
| 256 | unsigned short port = htons(6881); | ||
| 257 | ssize_t len; | ||
| 258 | size_t reply_size = 0, reply_off; | ||
| 259 | tai6464 t; | ||
| 260 | |||
| 261 | /* Touch l and d in case it is unused */ | ||
| 262 | l = l; d = d; | ||
| 263 | |||
| 264 | #ifdef _DEBUG_HTTPERROR | ||
| 265 | if( l >= sizeof( debug_request ) ) | ||
| 266 | l = sizeof( debug_request) - 1; | ||
| 267 | memcpy( debug_request, data, l ); | ||
| 268 | debug_request[ l ] = 0; | ||
| 269 | #endif | ||
| 270 | |||
| 271 | /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ | ||
| 272 | if( byte_diff( data, 5, "GET /") ) HTTPERROR_400; | ||
| 273 | |||
| 274 | /* Query string MUST terminate with SP -- we know that theres at least a '\n' where this search terminates */ | ||
| 275 | for( c = data + 5; *c!=' ' && *c != '\t' && *c != '\n' && *c != '\r'; ++c ) ; | ||
| 276 | if( *c != ' ' ) HTTPERROR_400; | ||
| 277 | |||
| 278 | /* Skip leading '/' */ | ||
| 279 | for( c = data+4; *c == '/'; ++c); | ||
| 280 | |||
| 281 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { | ||
| 282 | #ifdef WANT_TRACKER_SYNC | ||
| 283 | /****************************** | ||
| 284 | * S Y N C * | ||
| 285 | ******************************/ | ||
| 286 | case 4: /* sync ? */ | ||
| 287 | if( *data == 'a' ) goto ANNOUNCE_WORKAROUND; | ||
| 288 | if( !byte_diff( data, 2, "sc" ) ) goto SCRAPE_WORKAROUND; | ||
| 289 | if( byte_diff( data, 4, "sync") ) HTTPERROR_404; | ||
| 290 | if( NOTBLESSED( h ) ) HTTPERROR_403_IP; | ||
| 291 | |||
| 292 | LOG_TO_STDERR( "sync: %d.%d.%d.%d\n", h->ip[0], h->ip[1], h->ip[2], h->ip[3] ); | ||
| 293 | |||
| 294 | mode = SYNC_OUT; | ||
| 295 | scanon = 1; | ||
| 296 | |||
| 297 | while( scanon ) { | ||
| 298 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | ||
| 299 | case -2: scanon = 0; break; /* TERMINATOR */ | ||
| 300 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ | ||
| 301 | default: scan_urlencoded_skipvalue( &c ); break; | ||
| 302 | case 9: | ||
| 303 | if(byte_diff(data,9,"changeset")) { | ||
| 304 | scan_urlencoded_skipvalue( &c ); | ||
| 305 | continue; | ||
| 306 | } | ||
| 307 | /* ignore this, when we dont at least see "d4:syncdee" */ | ||
| 308 | if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) < 10 ) HTTPERROR_400_PARAM; | ||
| 309 | if( add_changeset_to_tracker( (ot_byte*)data, len ) ) HTTPERROR_400_PARAM; | ||
| 310 | mode = SYNC_IN; | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | if( mode == SYNC_OUT ) { | ||
| 316 | /* Pass this task to the worker thread */ | ||
| 317 | h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | ||
| 318 | sync_deliver( s ); | ||
| 319 | io_dontwantread( s ); | ||
| 320 | return; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* Simple but proof for now */ | ||
| 324 | memmove( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "OK", 2); | ||
| 325 | reply_size = 2; | ||
| 326 | |||
| 327 | break; | ||
| 328 | #endif | ||
| 329 | /****************************** | ||
| 330 | * S T A T S * | ||
| 331 | ******************************/ | ||
| 332 | case 5: /* stats ? */ | ||
| 333 | if( *data == 'a' ) goto ANNOUNCE_WORKAROUND; | ||
| 334 | if( !byte_diff( data, 2, "sc" ) ) goto SCRAPE_WORKAROUND; | ||
| 335 | if( byte_diff(data,5,"stats")) HTTPERROR_404; | ||
| 336 | scanon = 1; | ||
| 337 | mode = TASK_STATS_PEERS; | ||
| 338 | |||
| 339 | while( scanon ) { | ||
| 340 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | ||
| 341 | case -2: scanon = 0; break; /* TERMINATOR */ | ||
| 342 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ | ||
| 343 | default: scan_urlencoded_skipvalue( &c ); break; | ||
| 344 | case 4: | ||
| 345 | if( byte_diff(data,4,"mode")) { | ||
| 346 | scan_urlencoded_skipvalue( &c ); | ||
| 347 | continue; | ||
| 348 | } | ||
| 349 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 4 ) HTTPERROR_400_PARAM; | ||
| 350 | if( !byte_diff(data,4,"peer")) | ||
| 351 | mode = TASK_STATS_PEERS; | ||
| 352 | else if( !byte_diff(data,4,"conn")) | ||
| 353 | mode = TASK_STATS_CONNS; | ||
| 354 | else if( !byte_diff(data,4,"scrp")) | ||
| 355 | mode = TASK_STATS_SCRAPE; | ||
| 356 | else if( !byte_diff(data,4,"top5")) | ||
| 357 | mode = TASK_STATS_TOP5; | ||
| 358 | else if( !byte_diff(data,4,"fscr")) | ||
| 359 | mode = TASK_STATS_FULLSCRAPE; | ||
| 360 | else if( !byte_diff(data,4,"tcp4")) | ||
| 361 | mode = TASK_STATS_TCP; | ||
| 362 | else if( !byte_diff(data,4,"udp4")) | ||
| 363 | mode = TASK_STATS_UDP; | ||
| 364 | else if( !byte_diff(data,4,"s24s")) | ||
| 365 | mode = TASK_STATS_SLASH24S; | ||
| 366 | else if( !byte_diff(data,4,"tpbs")) | ||
| 367 | mode = TASK_STATS_TPB; | ||
| 368 | else | ||
| 369 | HTTPERROR_400_PARAM; | ||
| 370 | break; | ||
| 371 | case 6: | ||
| 372 | if( byte_diff(data,6,"format")) { | ||
| 373 | scan_urlencoded_skipvalue( &c ); | ||
| 374 | continue; | ||
| 375 | } | ||
| 376 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 3 ) HTTPERROR_400_PARAM; | ||
| 377 | if( !byte_diff(data,3,"bin")) | ||
| 378 | format = TASK_FULLSCRAPE_TPB_BINARY; | ||
| 379 | else if( !byte_diff(data,3,"ben")) | ||
| 380 | format = TASK_FULLSCRAPE; | ||
| 381 | else if( !byte_diff(data,3,"url")) | ||
| 382 | format = TASK_FULLSCRAPE_TPB_URLENCODED; | ||
| 383 | else if( !byte_diff(data,3,"txt")) | ||
| 384 | format = TASK_FULLSCRAPE_TPB_ASCII; | ||
| 385 | else | ||
| 386 | HTTPERROR_400_PARAM; | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | if( mode == TASK_STATS_TPB ) { | ||
| 392 | #ifdef WANT_COMPRESSION_GZIP | ||
| 393 | d[l-1] = 0; | ||
| 394 | if( strstr( d, "gzip" ) ) { | ||
| 395 | h->flag |= STRUCT_HTTP_FLAG_GZIP; | ||
| 396 | format |= TASK_FLAG_GZIP; | ||
| 397 | } | ||
| 398 | #endif | ||
| 399 | /* Pass this task to the worker thread */ | ||
| 400 | h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | ||
| 401 | |||
| 402 | /* Clients waiting for us should not easily timeout */ | ||
| 403 | taia_uint( &t, 0 ); io_timeout( s, t ); | ||
| 404 | fullscrape_deliver( s, format ); | ||
| 405 | io_dontwantread( s ); | ||
| 406 | return; | ||
| 407 | } | ||
| 408 | |||
| 409 | // default format for now | ||
| 410 | if( !( reply_size = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500; | ||
| 411 | break; | ||
| 412 | |||
| 413 | /****************************** | ||
| 414 | * S C R A P E * | ||
| 415 | ******************************/ | ||
| 416 | case 6: /* scrape ? */ | ||
| 417 | if( *data == 'a' ) goto ANNOUNCE_WORKAROUND; | ||
| 418 | if( byte_diff( data, 6, "scrape") ) HTTPERROR_404; | ||
| 419 | |||
| 420 | /* Full scrape... you might want to limit that */ | ||
| 421 | if( !byte_diff( data, 12, "scrape HTTP/" ) ) { | ||
| 422 | format = 0; | ||
| 423 | #ifdef WANT_COMPRESSION_GZIP | ||
| 424 | d[l-1] = 0; | ||
| 425 | if( strstr( d, "gzip" ) ) { | ||
| 426 | h->flag |= STRUCT_HTTP_FLAG_GZIP; | ||
| 427 | format = TASK_FLAG_GZIP; | ||
| 428 | LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE GZIP\n", (unsigned int)(g_now - ot_start_time), h->ip[0], h->ip[1], h->ip[2], h->ip[3] ); | ||
| 429 | } else | ||
| 430 | #endif | ||
| 431 | LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE\n", (unsigned int)(g_now - ot_start_time), h->ip[0], h->ip[1], h->ip[2], h->ip[3] ); | ||
| 432 | |||
| 433 | #ifdef _DEBUG_HTTPERROR | ||
| 434 | write( 2, debug_request, l ); | ||
| 435 | #endif | ||
| 436 | |||
| 437 | /* Pass this task to the worker thread */ | ||
| 438 | h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | ||
| 439 | /* Clients waiting for us should not easily timeout */ | ||
| 440 | taia_uint( &t, 0 ); io_timeout( s, t ); | ||
| 441 | fullscrape_deliver( s, TASK_FULLSCRAPE | format ); | ||
| 442 | io_dontwantread( s ); | ||
| 443 | return; | ||
| 444 | } | ||
| 445 | |||
| 446 | SCRAPE_WORKAROUND: | ||
| 447 | |||
| 448 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ | ||
| 449 | if( c[-1] != '?' ) { | ||
| 450 | while( ( *c != '?' ) && ( *c != '\n' ) ) ++c; | ||
| 451 | if( *c == '\n' ) HTTPERROR_400_PARAM; | ||
| 452 | ++c; | ||
| 453 | } | ||
| 454 | |||
| 455 | scanon = 1; | ||
| 456 | numwant = 0; | ||
| 457 | while( scanon ) { | ||
| 458 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | ||
| 459 | case -2: scanon = 0; break; /* TERMINATOR */ | ||
| 460 | case -1: | ||
| 461 | if( numwant ) | ||
| 462 | goto UTORRENT1600_WORKAROUND; | ||
| 463 | HTTPERROR_400_PARAM; /* PARSE ERROR */ | ||
| 464 | default: scan_urlencoded_skipvalue( &c ); break; | ||
| 465 | case 9: | ||
| 466 | if(byte_diff(data,9,"info_hash")) { | ||
| 467 | scan_urlencoded_skipvalue( &c ); | ||
| 468 | continue; | ||
| 469 | } | ||
| 470 | /* ignore this, when we have less than 20 bytes */ | ||
| 471 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) ) { | ||
| 472 | #ifdef WANT_UTORRENT1600_WORKAROUND | ||
| 473 | if( data[20] != '?' ) | ||
| 474 | #endif | ||
| 475 | HTTPERROR_400_PARAM; | ||
| 476 | } | ||
| 477 | if( numwant < OT_MAXMULTISCRAPE_COUNT ) | ||
| 478 | memmove( multiscrape_buf + numwant++, data, sizeof(ot_hash) ); | ||
| 479 | break; | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | UTORRENT1600_WORKAROUND: | ||
| 484 | |||
| 485 | /* No info_hash found? Inform user */ | ||
| 486 | if( !numwant ) HTTPERROR_400_PARAM; | ||
| 487 | |||
| 488 | /* Enough for http header + whole scrape string */ | ||
| 489 | if( !( reply_size = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500; | ||
| 490 | stats_issue_event( EVENT_SCRAPE, 1, reply_size ); | ||
| 491 | break; | ||
| 492 | /****************************** | ||
| 493 | * A N N O U N C E * | ||
| 494 | ******************************/ | ||
| 495 | case 8: | ||
| 496 | if( !byte_diff( data, 2, "sc" ) ) goto SCRAPE_WORKAROUND; | ||
| 497 | if( *data != 'a' ) HTTPERROR_404; | ||
| 498 | |||
| 499 | ANNOUNCE_WORKAROUND: | ||
| 500 | |||
| 501 | /* This is to hack around stupid clients that send "announce ?info_hash" */ | ||
| 502 | if( c[-1] != '?' ) { | ||
| 503 | while( ( *c != '?' ) && ( *c != '\n' ) ) ++c; | ||
| 504 | if( *c == '\n' ) HTTPERROR_400_PARAM; | ||
| 505 | ++c; | ||
| 506 | } | ||
| 507 | |||
| 508 | OT_SETIP( &peer, ((struct http_data*)io_getcookie( s ) )->ip ); | ||
| 509 | OT_SETPORT( &peer, &port ); | ||
| 510 | OT_FLAG( &peer ) = 0; | ||
| 511 | numwant = 50; | ||
| 512 | scanon = 1; | ||
| 513 | |||
| 514 | while( scanon ) { | ||
| 515 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | ||
| 516 | case -2: scanon = 0; break; /* TERMINATOR */ | ||
| 517 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ | ||
| 518 | default: scan_urlencoded_skipvalue( &c ); break; | ||
| 519 | #ifdef WANT_IP_FROM_QUERY_STRING | ||
| 520 | case 2: | ||
| 521 | if(!byte_diff(data,2,"ip")) { | ||
| 522 | unsigned char ip[4]; | ||
| 523 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 524 | if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) HTTPERROR_400_PARAM; | ||
| 525 | OT_SETIP( &peer, ip ); | ||
| 526 | } else | ||
| 527 | scan_urlencoded_skipvalue( &c ); | ||
| 528 | break; | ||
| 529 | #endif | ||
| 530 | case 4: | ||
| 531 | if( !byte_diff( data, 4, "port" ) ) { | ||
| 532 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 533 | if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM; | ||
| 534 | port = htons( tmp ); OT_SETPORT( &peer, &port ); | ||
| 535 | } else if( !byte_diff( data, 4, "left" ) ) { | ||
| 536 | if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; | ||
| 537 | if( scan_fixed_int( data, len, &tmp ) ) tmp = 0; | ||
| 538 | if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING; | ||
| 539 | } else | ||
| 540 | scan_urlencoded_skipvalue( &c ); | ||
| 541 | break; | ||
| 542 | case 5: | ||
| 543 | if( byte_diff( data, 5, "event" ) ) | ||
| 544 | scan_urlencoded_skipvalue( &c ); | ||
| 545 | else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { | ||
| 546 | case -1: | ||
| 547 | HTTPERROR_400_PARAM; | ||
| 548 | case 7: | ||
| 549 | if( !byte_diff( data, 7, "stopped" ) ) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED; | ||
| 550 | break; | ||
| 551 | case 9: | ||
| 552 | if( !byte_diff( data, 9, "completed" ) ) OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED; | ||
| 553 | default: /* Fall through intended */ | ||
| 554 | break; | ||
| 555 | } | ||
| 556 | break; | ||
| 557 | case 7: | ||
| 558 | if(!byte_diff(data,7,"numwant")) { | ||
| 559 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 560 | if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) HTTPERROR_400_PARAM; | ||
| 561 | if( numwant < 0 ) numwant = 50; | ||
| 562 | if( numwant > 200 ) numwant = 200; | ||
| 563 | } else if(!byte_diff(data,7,"compact")) { | ||
| 564 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 565 | if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) HTTPERROR_400_PARAM; | ||
| 566 | if( !tmp ) HTTPERROR_400_COMPACT; | ||
| 567 | } else | ||
| 568 | scan_urlencoded_skipvalue( &c ); | ||
| 569 | break; | ||
| 570 | case 9: | ||
| 571 | if(byte_diff(data,9,"info_hash")) { | ||
| 572 | scan_urlencoded_skipvalue( &c ); | ||
| 573 | continue; | ||
| 574 | } | ||
| 575 | /* ignore this, when we have less than 20 bytes */ | ||
| 576 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; | ||
| 577 | hash = (ot_hash*)data; | ||
| 578 | break; | ||
| 579 | } | ||
| 580 | } | ||
| 581 | |||
| 582 | /* Scanned whole query string */ | ||
| 583 | if( !hash ) { | ||
| 584 | reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d14:failure reason81:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" ); | ||
| 585 | break; | ||
| 586 | } | ||
| 587 | if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) | ||
| 588 | reply_size = remove_peer_from_torrent( hash, &peer, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ); | ||
| 589 | else { | ||
| 590 | torrent = add_peer_to_torrent( hash, &peer, 0 ); | ||
| 591 | if( !torrent || !( reply_size = return_peers_for_torrent( hash, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500; | ||
| 592 | } | ||
| 593 | stats_issue_event( EVENT_ANNOUNCE, 1, reply_size); | ||
| 594 | break; | ||
| 595 | default: | ||
| 596 | if( ( *data == 'a' ) || ( *data == '?' ) ) goto ANNOUNCE_WORKAROUND; | ||
| 597 | if( !byte_diff( data, 2, "sc" ) ) goto SCRAPE_WORKAROUND; | ||
| 598 | HTTPERROR_404; | ||
| 599 | } | ||
| 600 | |||
| 601 | if( !reply_size ) HTTPERROR_500; | ||
| 602 | |||
| 603 | /* This one is rather ugly, so I take you step by step through it. | ||
| 604 | |||
| 605 | 1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to | ||
| 606 | write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our static buffer, which is enough for the static string | ||
| 607 | plus dynamic space needed to expand our Content-Length value. We reserve SUCCESS_HTTP_SIZE_OFF for its expansion and calculate | ||
| 608 | the space NOT needed to expand in reply_off | ||
| 609 | */ | ||
| 610 | reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_outbuf, 0, "%zd", reply_size ); | ||
| 611 | |||
| 612 | /* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete | ||
| 613 | packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */ | ||
| 614 | reply_size += 1 + sprintf( static_outbuf + reply_off, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", reply_size ); | ||
| 615 | |||
| 616 | /* 3. Finally we join both blocks neatly */ | ||
| 617 | static_outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n'; | ||
| 618 | |||
| 619 | senddata( s, static_outbuf + reply_off, reply_size ); | ||
| 620 | } | ||
| 621 | |||
| 622 | static void signal_handler( int s ) { | 51 | static void signal_handler( int s ) { |
| 623 | if( s == SIGINT ) { | 52 | if( s == SIGINT ) { |
| 624 | signal( SIGINT, SIG_IGN); | 53 | signal( SIGINT, SIG_IGN); |
| @@ -674,36 +103,37 @@ static void handle_dead( const int64 socket ) { | |||
| 674 | io_close( socket ); | 103 | io_close( socket ); |
| 675 | } | 104 | } |
| 676 | 105 | ||
| 677 | static void handle_read( const int64 clientsocket ) { | 106 | static ssize_t handle_read( const int64 clientsocket ) { |
| 678 | struct http_data* h = io_getcookie( clientsocket ); | 107 | struct http_data* h = io_getcookie( clientsocket ); |
| 679 | ssize_t l; | 108 | ssize_t l; |
| 680 | 109 | ||
| 681 | if( ( l = io_tryread( clientsocket, static_inbuf, sizeof static_inbuf ) ) <= 0 ) | 110 | if( ( l = io_tryread( clientsocket, static_inbuf, sizeof static_inbuf ) ) <= 0 ) { |
| 682 | return handle_dead( clientsocket ); | 111 | handle_dead( clientsocket ); |
| 683 | 112 | return 0; | |
| 684 | #ifdef _DEBUG_HTTPERROR | 113 | } |
| 685 | memcpy( debug_request, "500!\0", 5 ); | ||
| 686 | #endif | ||
| 687 | 114 | ||
| 688 | /* If we get the whole request in one packet, handle it without copying */ | 115 | /* If we get the whole request in one packet, handle it without copying */ |
| 689 | if( !array_start( &h->request ) ) { | 116 | if( !array_start( &h->request ) ) { |
| 690 | if( memchr( static_inbuf, '\n', l ) ) | 117 | if( memchr( static_inbuf, '\n', l ) ) |
| 691 | return httpresponse( clientsocket, static_inbuf, l ); | 118 | return http_handle_request( clientsocket, static_inbuf, l ); |
| 692 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 119 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
| 693 | return array_catb( &h->request, static_inbuf, l ); | 120 | array_catb( &h->request, static_inbuf, l ); |
| 121 | return 0; | ||
| 694 | } | 122 | } |
| 695 | 123 | ||
| 696 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 124 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
| 697 | array_catb( &h->request, static_inbuf, l ); | 125 | array_catb( &h->request, static_inbuf, l ); |
| 698 | 126 | ||
| 699 | if( array_failed( &h->request ) ) | 127 | if( array_failed( &h->request ) ) |
| 700 | return httperror( clientsocket, "500 Server Error", "Request too long."); | 128 | return http_issue_error( clientsocket, "500 Server Error", "Request too long."); |
| 701 | 129 | ||
| 702 | if( ( array_bytes( &h->request ) > 8192 ) && NOTBLESSED( h ) ) | 130 | if( ( array_bytes( &h->request ) > 8192 ) && !accesslist_isblessed( (char*)&h->ip, OT_PERMISSION_MAY_SYNC ) ) |
| 703 | return httperror( clientsocket, "500 request too long", "You sent too much headers"); | 131 | return http_issue_error( clientsocket, "500 request too long", "You sent too much headers"); |
| 704 | 132 | ||
| 705 | if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) ) | 133 | if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) ) |
| 706 | return httpresponse( clientsocket, array_start( &h->request ), array_bytes( &h->request ) ); | 134 | return http_handle_request( clientsocket, array_start( &h->request ), array_bytes( &h->request ) ); |
| 135 | |||
| 136 | return 0; | ||
| 707 | } | 137 | } |
| 708 | 138 | ||
| 709 | static void handle_write( const int64 clientsocket ) { | 139 | static void handle_write( const int64 clientsocket ) { |
| @@ -732,7 +162,7 @@ static void handle_accept( const int64 serversocket ) { | |||
| 732 | io_setcookie( i, h ); | 162 | io_setcookie( i, h ); |
| 733 | io_wantread( i ); | 163 | io_wantread( i ); |
| 734 | 164 | ||
| 735 | byte_zero( h, sizeof( struct http_data ) ); | 165 | memset( h, 0, sizeof( struct http_data ) ); |
| 736 | memmove( h->ip, ip, sizeof( ip ) ); | 166 | memmove( h->ip, ip, sizeof( ip ) ); |
| 737 | 167 | ||
| 738 | stats_issue_event( EVENT_ACCEPT, 1, 0); | 168 | stats_issue_event( EVENT_ACCEPT, 1, 0); |
| @@ -748,16 +178,11 @@ static void handle_accept( const int64 serversocket ) { | |||
| 748 | io_eagain( serversocket ); | 178 | io_eagain( serversocket ); |
| 749 | } | 179 | } |
| 750 | 180 | ||
| 751 | static void handle_timeouted( void ) { | ||
| 752 | int64 i; | ||
| 753 | while( ( i = io_timeouted() ) != -1 ) | ||
| 754 | handle_dead( i ); | ||
| 755 | } | ||
| 756 | |||
| 757 | static void server_mainloop( ) { | 181 | static void server_mainloop( ) { |
| 758 | time_t next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; | 182 | static time_t ot_last_clean_time; |
| 759 | struct iovec *iovector; | 183 | time_t next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; |
| 760 | int iovec_entries; | 184 | struct iovec *iovector; |
| 185 | int iovec_entries; | ||
| 761 | 186 | ||
| 762 | for( ; ; ) { | 187 | for( ; ; ) { |
| 763 | int64 i; | 188 | int64 i; |
| @@ -775,13 +200,14 @@ static void server_mainloop( ) { | |||
| 775 | } | 200 | } |
| 776 | 201 | ||
| 777 | while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 ) | 202 | while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 ) |
| 778 | sendiovecdata( i, iovec_entries, iovector ); | 203 | http_sendiovecdata( i, iovec_entries, iovector ); |
| 779 | 204 | ||
| 780 | while( ( i = io_canwrite( ) ) != -1 ) | 205 | while( ( i = io_canwrite( ) ) != -1 ) |
| 781 | handle_write( i ); | 206 | handle_write( i ); |
| 782 | 207 | ||
| 783 | if( g_now > next_timeout_check ) { | 208 | if( g_now > next_timeout_check ) { |
| 784 | handle_timeouted( ); | 209 | while( ( i = io_timeouted() ) != -1 ) |
| 210 | handle_dead( i ); | ||
| 785 | next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; | 211 | next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; |
| 786 | } | 212 | } |
| 787 | 213 | ||
| @@ -811,15 +237,13 @@ static void ot_try_bind( char ip[4], uint16 port, int is_tcp ) { | |||
| 811 | io_setcookie( s, is_tcp ? FLAG_TCP : FLAG_UDP ); | 237 | io_setcookie( s, is_tcp ? FLAG_TCP : FLAG_UDP ); |
| 812 | 238 | ||
| 813 | io_wantread( s ); | 239 | io_wantread( s ); |
| 814 | |||
| 815 | ++ot_sockets_count; | ||
| 816 | } | 240 | } |
| 817 | 241 | ||
| 818 | int main( int argc, char **argv ) { | 242 | int main( int argc, char **argv ) { |
| 819 | struct passwd *pws = NULL; | 243 | struct passwd *pws = NULL; |
| 820 | char serverip[4] = {0,0,0,0}; | 244 | char serverip[4] = {0,0,0,0}, tmpip[4]; |
| 821 | char *serverdir = "."; | 245 | char *serverdir = "."; |
| 822 | int scanon = 1; | 246 | int bound = 0, scanon = 1; |
| 823 | #ifdef WANT_ACCESS_CONTROL | 247 | #ifdef WANT_ACCESS_CONTROL |
| 824 | char *accesslist_filename = NULL; | 248 | char *accesslist_filename = NULL; |
| 825 | #endif | 249 | #endif |
| @@ -839,12 +263,12 @@ int main( int argc, char **argv ) { | |||
| 839 | #elif defined( WANT_CLOSED_TRACKER ) | 263 | #elif defined( WANT_CLOSED_TRACKER ) |
| 840 | case 'w': accesslist_filename = optarg; break; | 264 | case 'w': accesslist_filename = optarg; break; |
| 841 | #endif | 265 | #endif |
| 842 | case 'p': ot_try_bind( serverip, (uint16)atol( optarg ), 1 ); break; | 266 | case 'p': ot_try_bind( serverip, (uint16)atol( optarg ), 1 ); bound++; break; |
| 843 | case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); break; | 267 | case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); bound++; break; |
| 844 | case 'd': serverdir = optarg; break; | 268 | case 'd': serverdir = optarg; break; |
| 845 | case 'A': | 269 | case 'A': |
| 846 | if( g_adminip_count < OT_ADMINIP_MAX ) | 270 | scan_ip4( optarg, tmpip ); |
| 847 | scan_ip4( optarg, (char*)(g_adminip_addresses + g_adminip_count++) ); | 271 | accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */ |
| 848 | break; | 272 | break; |
| 849 | case 'h': help( argv[0] ); exit( 0 ); | 273 | case 'h': help( argv[0] ); exit( 0 ); |
| 850 | default: | 274 | default: |
| @@ -852,11 +276,8 @@ int main( int argc, char **argv ) { | |||
| 852 | } | 276 | } |
| 853 | } | 277 | } |
| 854 | 278 | ||
| 855 | /* Sort our admin ips for quick lookup */ | ||
| 856 | qsort( g_adminip_addresses, g_adminip_count, 4, ot_ip_compare ); | ||
| 857 | |||
| 858 | /* Bind to our default tcp/udp ports */ | 279 | /* Bind to our default tcp/udp ports */ |
| 859 | if( !ot_sockets_count ) { | 280 | if( !bound) { |
| 860 | ot_try_bind( serverip, 6969, 1 ); | 281 | ot_try_bind( serverip, 6969, 1 ); |
| 861 | ot_try_bind( serverip, 6969, 0 ); | 282 | ot_try_bind( serverip, 6969, 0 ); |
| 862 | } | 283 | } |
| @@ -881,8 +302,7 @@ int main( int argc, char **argv ) { | |||
| 881 | if( trackerlogic_init( serverdir ) == -1 ) | 302 | if( trackerlogic_init( serverdir ) == -1 ) |
| 882 | panic( "Logic not started" ); | 303 | panic( "Logic not started" ); |
| 883 | 304 | ||
| 884 | g_now = ot_start_time = time( NULL ); | 305 | g_now = time( NULL ); |
| 885 | ot_last_clean_time = NOW; | ||
| 886 | alarm(5); | 306 | alarm(5); |
| 887 | 307 | ||
| 888 | server_mainloop( ); | 308 | server_mainloop( ); |
