diff options
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | opentracker.c | 67 | ||||
| -rw-r--r-- | ot_http.c | 454 | ||||
| -rw-r--r-- | ot_http.h | 6 | ||||
| -rw-r--r-- | ot_livesync.c | 3 | ||||
| -rw-r--r-- | ot_udp.c | 29 | ||||
| -rw-r--r-- | ot_udp.h | 2 | ||||
| -rw-r--r-- | scan_urlencoded_query.c | 23 | ||||
| -rw-r--r-- | scan_urlencoded_query.h | 16 | ||||
| -rw-r--r-- | trackerlogic.h | 25 |
10 files changed, 310 insertions, 318 deletions
| @@ -24,7 +24,6 @@ BINDIR?=$(PREFIX)/bin | |||
| 24 | 24 | ||
| 25 | #FEATURES+=-DWANT_SYNC_LIVE | 25 | #FEATURES+=-DWANT_SYNC_LIVE |
| 26 | #FEATURES+=-DWANT_SYNC_SCRAPE | 26 | #FEATURES+=-DWANT_SYNC_SCRAPE |
| 27 | #FEATURES+=-DWANT_UTORRENT1600_WORKAROUND | ||
| 28 | #FEATURES+=-DWANT_IP_FROM_QUERY_STRING | 27 | #FEATURES+=-DWANT_IP_FROM_QUERY_STRING |
| 29 | #FEATURES+=-DWANT_COMPRESSION_GZIP | 28 | #FEATURES+=-DWANT_COMPRESSION_GZIP |
| 30 | #FEATURES+=-DWANT_LOG_NETWORKS | 29 | #FEATURES+=-DWANT_LOG_NETWORKS |
| @@ -37,7 +36,7 @@ FEATURES+=-DWANT_FULLSCRAPE | |||
| 37 | OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage | 36 | OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage |
| 38 | OPTS_production=-Os | 37 | OPTS_production=-Os |
| 39 | 38 | ||
| 40 | CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra #-pedantic -ansi | 39 | CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra #-ansi -pedantic |
| 41 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz | 40 | LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz |
| 42 | 41 | ||
| 43 | BINARY =opentracker | 42 | BINARY =opentracker |
diff --git a/opentracker.c b/opentracker.c index bce5be0..8a4126c 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -41,9 +41,6 @@ volatile int g_opentracker_running = 1; | |||
| 41 | 41 | ||
| 42 | static char * g_serverdir = NULL; | 42 | static char * g_serverdir = NULL; |
| 43 | 43 | ||
| 44 | /* To always have space for error messages ;) */ | ||
| 45 | static char static_inbuf[8192]; | ||
| 46 | |||
| 47 | static void panic( const char *routine ) { | 44 | static void panic( const char *routine ) { |
| 48 | fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); | 45 | fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); |
| 49 | exit( 111 ); | 46 | exit( 111 ); |
| @@ -107,37 +104,44 @@ static void handle_dead( const int64 socket ) { | |||
| 107 | io_close( socket ); | 104 | io_close( socket ); |
| 108 | } | 105 | } |
| 109 | 106 | ||
| 110 | static ssize_t handle_read( const int64 clientsocket ) { | 107 | static ssize_t handle_read( const int64 clientsocket, struct ot_workstruct *ws ) { |
| 111 | struct http_data* h = io_getcookie( clientsocket ); | 108 | struct http_data* h = io_getcookie( clientsocket ); |
| 112 | ssize_t l; | 109 | ssize_t l; |
| 113 | 110 | ||
| 114 | if( ( l = io_tryread( clientsocket, static_inbuf, sizeof static_inbuf ) ) <= 0 ) { | 111 | if( ( l = io_tryread( clientsocket, ws->inbuf, ws->inbuf_size ) ) <= 0 ) { |
| 115 | handle_dead( clientsocket ); | 112 | handle_dead( clientsocket ); |
| 116 | return 0; | 113 | return 0; |
| 117 | } | 114 | } |
| 118 | 115 | ||
| 119 | /* If we get the whole request in one packet, handle it without copying */ | 116 | /* If we get the whole request in one packet, handle it without copying */ |
| 120 | if( !array_start( &h->data.request ) ) { | 117 | if( !array_start( &h->data.request ) ) { |
| 121 | if( memchr( static_inbuf, '\n', l ) ) | 118 | if( memchr( ws->inbuf, '\n', l ) ) { |
| 122 | return http_handle_request( clientsocket, static_inbuf, l ); | 119 | ws->request = ws->inbuf; |
| 120 | ws->request_size = l; | ||
| 121 | return http_handle_request( clientsocket, ws ); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* ... else take a copy */ | ||
| 123 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 125 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
| 124 | array_catb( &h->data.request, static_inbuf, l ); | 126 | array_catb( &h->data.request, ws->inbuf, l ); |
| 125 | return 0; | 127 | return 0; |
| 126 | } | 128 | } |
| 127 | 129 | ||
| 128 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 130 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
| 129 | array_catb( &h->data.request, static_inbuf, l ); | 131 | array_catb( &h->data.request, ws->inbuf, l ); |
| 130 | 132 | ||
| 131 | if( array_failed( &h->data.request ) ) | 133 | if( array_failed( &h->data.request ) ) |
| 132 | return http_issue_error( clientsocket, CODE_HTTPERROR_500 ); | 134 | return http_issue_error( clientsocket, ws, CODE_HTTPERROR_500 ); |
| 133 | 135 | ||
| 134 | if( array_bytes( &h->data.request ) > 8192 ) | 136 | if( array_bytes( &h->data.request ) > 8192 ) |
| 135 | return http_issue_error( clientsocket, CODE_HTTPERROR_500 ); | 137 | return http_issue_error( clientsocket, ws, CODE_HTTPERROR_500 ); |
| 136 | 138 | ||
| 137 | if( memchr( array_start( &h->data.request ), '\n', array_bytes( &h->data.request ) ) ) | 139 | if( !memchr( array_start( &h->data.request ), '\n', array_bytes( &h->data.request ) ) ) |
| 138 | return http_handle_request( clientsocket, array_start( &h->data.request ), array_bytes( &h->data.request ) ); | 140 | return 0; |
| 139 | 141 | ||
| 140 | return 0; | 142 | ws->request = array_start( &h->data.request ); |
| 143 | ws->request_size = array_bytes( &h->data.request ); | ||
| 144 | return http_handle_request( clientsocket, ws ); | ||
| 141 | } | 145 | } |
| 142 | 146 | ||
| 143 | static void handle_write( const int64 clientsocket ) { | 147 | static void handle_write( const int64 clientsocket ) { |
| @@ -183,9 +187,25 @@ static void handle_accept( const int64 serversocket ) { | |||
| 183 | } | 187 | } |
| 184 | 188 | ||
| 185 | static void server_mainloop( ) { | 189 | static void server_mainloop( ) { |
| 186 | time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; | 190 | struct ot_workstruct ws; |
| 187 | struct iovec *iovector; | 191 | time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; |
| 188 | int iovec_entries; | 192 | struct iovec *iovector; |
| 193 | int iovec_entries; | ||
| 194 | |||
| 195 | /* Initialize our "thread local storage" */ | ||
| 196 | ws.inbuf = malloc( THREAD_INBUF_SIZE ); | ||
| 197 | ws.outbuf = malloc( THREAD_OUTBUF_SIZE ); | ||
| 198 | #ifdef _DEBUG_HTTPERROR | ||
| 199 | ws.debugbuf= malloc( THREAD_INBUF_SIZE ); | ||
| 200 | #endif | ||
| 201 | if( !ws.inbuf || !ws.outbuf ) | ||
| 202 | panic( "Initializing worker failed" ); | ||
| 203 | |||
| 204 | ws.inbuf_size = THREAD_INBUF_SIZE; | ||
| 205 | ws.outbuf_size = THREAD_OUTBUF_SIZE; | ||
| 206 | #ifdef _DEBUG_HTTPERROR | ||
| 207 | ws.debugbuf_size= THREAD_INBUF_SIZE; | ||
| 208 | #endif | ||
| 189 | 209 | ||
| 190 | for( ; ; ) { | 210 | for( ; ; ) { |
| 191 | int64 i; | 211 | int64 i; |
| @@ -197,13 +217,13 @@ static void server_mainloop( ) { | |||
| 197 | if( (intptr_t)cookie == FLAG_TCP ) | 217 | if( (intptr_t)cookie == FLAG_TCP ) |
| 198 | handle_accept( i ); | 218 | handle_accept( i ); |
| 199 | else if( (intptr_t)cookie == FLAG_UDP ) | 219 | else if( (intptr_t)cookie == FLAG_UDP ) |
| 200 | handle_udp4( i ); | 220 | handle_udp4( i, &ws ); |
| 201 | else | 221 | else |
| 202 | handle_read( i ); | 222 | handle_read( i, &ws ); |
| 203 | } | 223 | } |
| 204 | 224 | ||
| 205 | while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 ) | 225 | while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 ) |
| 206 | http_sendiovecdata( i, iovec_entries, iovector ); | 226 | http_sendiovecdata( i, &ws, iovec_entries, iovector ); |
| 207 | 227 | ||
| 208 | while( ( i = io_canwrite( ) ) != -1 ) | 228 | while( ( i = io_canwrite( ) ) != -1 ) |
| 209 | handle_write( i ); | 229 | handle_write( i ); |
| @@ -431,7 +451,12 @@ while( scanon ) { | |||
| 431 | break; | 451 | break; |
| 432 | case 'f': bound += parse_configfile( optarg ); break; | 452 | case 'f': bound += parse_configfile( optarg ); break; |
| 433 | case 'h': help( argv[0] ); exit( 0 ); | 453 | case 'h': help( argv[0] ); exit( 0 ); |
| 434 | case 'v': stats_return_tracker_version( static_inbuf ); fputs( static_inbuf, stderr ); exit( 0 ); | 454 | case 'v': { |
| 455 | char buffer[8192]; | ||
| 456 | stats_return_tracker_version( buffer ); | ||
| 457 | fputs( buffer, stderr ); | ||
| 458 | exit( 0 ); | ||
| 459 | } | ||
| 435 | default: | 460 | default: |
| 436 | case '?': usage( argv[0] ); exit( 1 ); | 461 | case '?': usage( argv[0] ); exit( 1 ); |
| 437 | } | 462 | } |
| @@ -27,26 +27,19 @@ | |||
| 27 | #include "ot_accesslist.h" | 27 | #include "ot_accesslist.h" |
| 28 | 28 | ||
| 29 | #define OT_MAXMULTISCRAPE_COUNT 64 | 29 | #define OT_MAXMULTISCRAPE_COUNT 64 |
| 30 | static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT]; | ||
| 31 | extern char *g_redirecturl; | 30 | extern char *g_redirecturl; |
| 32 | 31 | ||
| 33 | enum { | 32 | enum { |
| 34 | SUCCESS_HTTP_HEADER_LENGTH = 80, | 33 | SUCCESS_HTTP_HEADER_LENGTH = 80, |
| 35 | SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING = 32, | 34 | SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32, |
| 36 | SUCCESS_HTTP_SIZE_OFF = 17 }; | 35 | SUCCESS_HTTP_SIZE_OFF = 17 }; |
| 37 | 36 | ||
| 38 | /* Our static output buffer */ | ||
| 39 | static char static_outbuf[8192]; | ||
| 40 | #ifdef _DEBUG_HTTPERROR | ||
| 41 | static char debug_request[8192]; | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #ifdef _DEBUG_PEERID | 37 | #ifdef _DEBUG_PEERID |
| 45 | size_t g_this_peerid_len = 0; | 38 | size_t g_this_peerid_len = 0; |
| 46 | char *g_this_peerid_data = NULL; | 39 | char *g_this_peerid_data = NULL; |
| 47 | #endif | 40 | #endif |
| 48 | 41 | ||
| 49 | static void http_senddata( const int64 client_socket, char *buffer, size_t size ) { | 42 | static void http_senddata( const int64 client_socket, struct ot_workstruct *ws ) { |
| 50 | struct http_data *h = io_getcookie( client_socket ); | 43 | struct http_data *h = io_getcookie( client_socket ); |
| 51 | ssize_t written_size; | 44 | ssize_t written_size; |
| 52 | 45 | ||
| @@ -56,22 +49,22 @@ static void http_senddata( const int64 client_socket, char *buffer, size_t size | |||
| 56 | array_reset( &h->data.request ); | 49 | array_reset( &h->data.request ); |
| 57 | } | 50 | } |
| 58 | 51 | ||
| 59 | written_size = write( client_socket, buffer, size ); | 52 | written_size = write( client_socket, ws->reply, ws->reply_size ); |
| 60 | if( ( written_size < 0 ) || ( (size_t)written_size == size ) ) { | 53 | if( ( written_size < 0 ) || ( written_size == ws->reply_size ) ) { |
| 61 | free( h ); io_close( client_socket ); | 54 | free( h ); io_close( client_socket ); |
| 62 | } else { | 55 | } else { |
| 63 | char * outbuf; | 56 | char * outbuf; |
| 64 | tai6464 t; | 57 | tai6464 t; |
| 65 | 58 | ||
| 66 | if( !h ) return; | 59 | if( !h ) return; |
| 67 | if( !( outbuf = malloc( size - written_size ) ) ) { | 60 | if( !( outbuf = malloc( ws->reply_size - written_size ) ) ) { |
| 68 | free(h); io_close( client_socket ); | 61 | free(h); io_close( client_socket ); |
| 69 | return; | 62 | return; |
| 70 | } | 63 | } |
| 71 | 64 | ||
| 72 | iob_reset( &h->data.batch ); | 65 | iob_reset( &h->data.batch ); |
| 73 | memmove( outbuf, buffer + written_size, size - written_size ); | 66 | memmove( outbuf, ws->reply + written_size, ws->reply_size - written_size ); |
| 74 | iob_addbuf_free( &h->data.batch, outbuf, size - written_size ); | 67 | iob_addbuf_free( &h->data.batch, outbuf, ws->reply_size - written_size ); |
| 75 | h->flag |= STRUCT_HTTP_FLAG_IOB_USED; | 68 | h->flag |= STRUCT_HTTP_FLAG_IOB_USED; |
| 76 | 69 | ||
| 77 | /* writeable short data sockets just have a tcp timeout */ | 70 | /* writeable short data sockets just have a tcp timeout */ |
| @@ -81,33 +74,34 @@ static void http_senddata( const int64 client_socket, char *buffer, size_t size | |||
| 81 | } | 74 | } |
| 82 | } | 75 | } |
| 83 | 76 | ||
| 84 | #define HTTPERROR_302 return http_issue_error( client_socket, CODE_HTTPERROR_302 ) | 77 | #define HTTPERROR_302 return http_issue_error( client_socket, ws, CODE_HTTPERROR_302 ) |
| 85 | #define HTTPERROR_400 return http_issue_error( client_socket, CODE_HTTPERROR_400 ) | 78 | #define HTTPERROR_400 return http_issue_error( client_socket, ws, CODE_HTTPERROR_400 ) |
| 86 | #define HTTPERROR_400_PARAM return http_issue_error( client_socket, CODE_HTTPERROR_400_PARAM ) | 79 | #define HTTPERROR_400_PARAM return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM ) |
| 87 | #define HTTPERROR_400_COMPACT return http_issue_error( client_socket, CODE_HTTPERROR_400_COMPACT ) | 80 | #define HTTPERROR_400_COMPACT return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_COMPACT ) |
| 88 | #define HTTPERROR_403_IP return http_issue_error( client_socket, CODE_HTTPERROR_403_IP ) | 81 | #define HTTPERROR_400_DOUBLEHASH return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM ) |
| 89 | #define HTTPERROR_404 return http_issue_error( client_socket, CODE_HTTPERROR_404 ) | 82 | #define HTTPERROR_403_IP return http_issue_error( client_socket, ws, CODE_HTTPERROR_403_IP ) |
| 90 | #define HTTPERROR_500 return http_issue_error( client_socket, CODE_HTTPERROR_500 ) | 83 | #define HTTPERROR_404 return http_issue_error( client_socket, ws, CODE_HTTPERROR_404 ) |
| 91 | ssize_t http_issue_error( const int64 client_socket, int code ) { | 84 | #define HTTPERROR_500 return http_issue_error( client_socket, ws, CODE_HTTPERROR_500 ) |
| 85 | ssize_t http_issue_error( const int64 client_socket, struct ot_workstruct *ws, int code ) { | ||
| 92 | char *error_code[] = { "302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", | 86 | char *error_code[] = { "302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", |
| 93 | "403 Access Denied", "404 Not Found", "500 Internal Server Error" }; | 87 | "403 Access Denied", "404 Not Found", "500 Internal Server Error" }; |
| 94 | char *title = error_code[code]; | 88 | char *title = error_code[code]; |
| 95 | size_t reply_size; | ||
| 96 | 89 | ||
| 90 | ws->reply = ws->outbuf; | ||
| 97 | if( code == CODE_HTTPERROR_302 ) | 91 | if( code == CODE_HTTPERROR_302 ) |
| 98 | reply_size = sprintf( static_outbuf, "HTTP/1.0 302 Found\r\nContent-Length: 0\r\nLocation: %s\r\n\r\n", g_redirecturl ); | 92 | ws->reply_size = snprintf( ws->reply, ws->outbuf_size, "HTTP/1.0 302 Found\r\nContent-Length: 0\r\nLocation: %s\r\n\r\n", g_redirecturl ); |
| 99 | else | 93 | else |
| 100 | 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", title, strlen(title)+16-4,title+4); | 94 | ws->reply_size = snprintf( ws->reply, ws->outbuf_size, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n", title, strlen(title)+16-4,title+4); |
| 101 | 95 | ||
| 102 | #ifdef _DEBUG_HTTPERROR | 96 | #ifdef _DEBUG_HTTPERROR |
| 103 | fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request ); | 97 | fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf ); |
| 104 | #endif | 98 | #endif |
| 105 | stats_issue_event( EVENT_FAILED, FLAG_TCP, code ); | 99 | stats_issue_event( EVENT_FAILED, FLAG_TCP, code ); |
| 106 | http_senddata( client_socket, static_outbuf, reply_size); | 100 | http_senddata( client_socket, ws ); |
| 107 | return -2; | 101 | return ws->reply_size = -2; |
| 108 | } | 102 | } |
| 109 | 103 | ||
| 110 | ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct iovec *iovector ) { | 104 | ssize_t http_sendiovecdata( const int64 client_socket, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector ) { |
| 111 | struct http_data *h = io_getcookie( client_socket ); | 105 | struct http_data *h = io_getcookie( client_socket ); |
| 112 | char *header; | 106 | char *header; |
| 113 | int i; | 107 | int i; |
| @@ -136,7 +130,7 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct | |||
| 136 | } | 130 | } |
| 137 | 131 | ||
| 138 | /* Prepare space for http header */ | 132 | /* Prepare space for http header */ |
| 139 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING ); | 133 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING ); |
| 140 | if( !header ) { | 134 | if( !header ) { |
| 141 | iovec_free( &iovec_entries, &iovector ); | 135 | iovec_free( &iovec_entries, &iovector ); |
| 142 | HTTPERROR_500; | 136 | HTTPERROR_500; |
| @@ -159,7 +153,7 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct | |||
| 159 | 153 | ||
| 160 | h->flag |= STRUCT_HTTP_FLAG_IOB_USED; | 154 | h->flag |= STRUCT_HTTP_FLAG_IOB_USED; |
| 161 | 155 | ||
| 162 | /* writeable sockets timeout after 10 minutes) */ | 156 | /* writeable sockets timeout after 10 minutes */ |
| 163 | taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); | 157 | taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); |
| 164 | io_timeout( client_socket, t ); | 158 | io_timeout( client_socket, t ); |
| 165 | io_dontwantread( client_socket ); | 159 | io_dontwantread( client_socket ); |
| @@ -167,9 +161,21 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct | |||
| 167 | return 0; | 161 | return 0; |
| 168 | } | 162 | } |
| 169 | 163 | ||
| 170 | static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d, size_t l ) { | 164 | static ssize_t http_handle_stats( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { |
| 171 | char *c = data; | 165 | static const ot_keywords keywords_main[] = |
| 166 | { { "mode", 1 }, {"format", 2 }, { NULL, -3 } }; | ||
| 167 | static const ot_keywords keywords_mode[] = | ||
| 168 | { { "peer", TASK_STATS_PEERS }, { "conn", TASK_STATS_CONNS }, { "scrp", TASK_STATS_SCRAPE }, { "udp4", TASK_STATS_UDP }, | ||
| 169 | { "busy", TASK_STATS_BUSY_NETWORKS }, { "torr", TASK_STATS_TORRENTS }, { "fscr", TASK_STATS_FULLSCRAPE }, | ||
| 170 | { "s24s", TASK_STATS_SLASH24S }, { "tpbs", TASK_STATS_TPB }, { "herr", TASK_STATS_HTTPERRORS }, | ||
| 171 | { "top10", TASK_STATS_TOP10 }, { "renew", TASK_STATS_RENEW }, { "syncs", TASK_STATS_SYNCS }, { "version", TASK_STATS_VERSION }, | ||
| 172 | { "startstop", TASK_STATS_STARTSTOP }, { "toraddrem", TASK_STATS_TORADDREM }, { NULL, -3 } }; | ||
| 173 | static const ot_keywords keywords_format[] = | ||
| 174 | { { "bin", TASK_FULLSCRAPE_TPB_BINARY }, { "ben", TASK_FULLSCRAPE }, { "url", TASK_FULLSCRAPE_TPB_URLENCODED }, | ||
| 175 | { "txt", TASK_FULLSCRAPE_TPB_ASCII }, { NULL, -3 } }; | ||
| 176 | |||
| 172 | int mode = TASK_STATS_PEERS, scanon = 1, format = 0; | 177 | int mode = TASK_STATS_PEERS, scanon = 1, format = 0; |
| 178 | |||
| 173 | #ifdef WANT_RESTRICT_STATS | 179 | #ifdef WANT_RESTRICT_STATS |
| 174 | struct http_data *h = io_getcookie( client_socket ); | 180 | struct http_data *h = io_getcookie( client_socket ); |
| 175 | 181 | ||
| @@ -178,97 +184,26 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d | |||
| 178 | #endif | 184 | #endif |
| 179 | 185 | ||
| 180 | while( scanon ) { | 186 | while( scanon ) { |
| 181 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | 187 | switch( scan_find_keywords( keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) { |
| 182 | case -2: scanon = 0; break; /* TERMINATOR */ | 188 | case -2: scanon = 0; break; /* TERMINATOR */ |
| 183 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ | 189 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ |
| 184 | default: scan_urlencoded_skipvalue( &c ); break; | 190 | case -3: scan_urlencoded_skipvalue( &read_ptr ); break; |
| 185 | case 4: | 191 | case 1: /* matched "mode" */ |
| 186 | if( byte_diff(data,4,"mode")) { | 192 | if( ( mode = scan_find_keywords( keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; |
| 187 | scan_urlencoded_skipvalue( &c ); | ||
| 188 | continue; | ||
| 189 | } | ||
| 190 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { | ||
| 191 | case 4: | ||
| 192 | if( !byte_diff(data,4,"peer")) | ||
| 193 | mode = TASK_STATS_PEERS; | ||
| 194 | else if( !byte_diff(data,4,"conn")) | ||
| 195 | mode = TASK_STATS_CONNS; | ||
| 196 | else if( !byte_diff(data,4,"scrp")) | ||
| 197 | mode = TASK_STATS_SCRAPE; | ||
| 198 | else if( !byte_diff(data,4,"tcp4")) | ||
| 199 | mode = TASK_STATS_TCP; | ||
| 200 | else if( !byte_diff(data,4,"udp4")) | ||
| 201 | mode = TASK_STATS_UDP; | ||
| 202 | else if( !byte_diff(data,4,"busy")) | ||
| 203 | mode = TASK_STATS_BUSY_NETWORKS; | ||
| 204 | else if( !byte_diff(data,4,"torr")) | ||
| 205 | mode = TASK_STATS_TORRENTS; | ||
| 206 | else if( !byte_diff(data,4,"fscr")) | ||
| 207 | mode = TASK_STATS_FULLSCRAPE; | ||
| 208 | else if( !byte_diff(data,4,"s24s")) | ||
| 209 | mode = TASK_STATS_SLASH24S; | ||
| 210 | else if( !byte_diff(data,4,"tpbs")) | ||
| 211 | mode = TASK_STATS_TPB; | ||
| 212 | else if( !byte_diff(data,4,"herr")) | ||
| 213 | mode = TASK_STATS_HTTPERRORS; | ||
| 214 | else | ||
| 215 | HTTPERROR_400_PARAM; | ||
| 216 | break; | ||
| 217 | case 5: | ||
| 218 | if( !byte_diff(data,5,"top10")) | ||
| 219 | mode = TASK_STATS_TOP10; | ||
| 220 | else if( !byte_diff(data,5,"renew")) | ||
| 221 | mode = TASK_STATS_RENEW; | ||
| 222 | else if( !byte_diff(data,5,"syncs")) | ||
| 223 | mode = TASK_STATS_SYNCS; | ||
| 224 | else | ||
| 225 | HTTPERROR_400_PARAM; | ||
| 226 | break; | ||
| 227 | case 7: | ||
| 228 | if( !byte_diff(data,7,"version")) | ||
| 229 | mode = TASK_STATS_VERSION; | ||
| 230 | else | ||
| 231 | HTTPERROR_400_PARAM; | ||
| 232 | break; | ||
| 233 | case 9: | ||
| 234 | if( !byte_diff(data,9,"startstop")) | ||
| 235 | mode = TASK_STATS_STARTSTOP; | ||
| 236 | else if( !byte_diff(data,9,"toraddrem")) | ||
| 237 | mode = TASK_STATS_TORADDREM; | ||
| 238 | else | ||
| 239 | HTTPERROR_400_PARAM; | ||
| 240 | break; | ||
| 241 | } | ||
| 242 | break; | 193 | break; |
| 243 | case 6: | 194 | case 2: /* matched "format" */ |
| 244 | if( byte_diff(data,6,"format")) { | 195 | if( ( format = scan_find_keywords( keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; |
| 245 | scan_urlencoded_skipvalue( &c ); | ||
| 246 | continue; | ||
| 247 | } | ||
| 248 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 3 ) HTTPERROR_400_PARAM; | ||
| 249 | if( !byte_diff(data,3,"bin")) | ||
| 250 | format = TASK_FULLSCRAPE_TPB_BINARY; | ||
| 251 | else if( !byte_diff(data,3,"ben")) | ||
| 252 | format = TASK_FULLSCRAPE; | ||
| 253 | else if( !byte_diff(data,3,"url")) | ||
| 254 | format = TASK_FULLSCRAPE_TPB_URLENCODED; | ||
| 255 | else if( !byte_diff(data,3,"txt")) | ||
| 256 | format = TASK_FULLSCRAPE_TPB_ASCII; | ||
| 257 | else | ||
| 258 | HTTPERROR_400_PARAM; | ||
| 259 | break; | 196 | break; |
| 260 | } | 197 | } |
| 261 | } | 198 | } |
| 262 | 199 | ||
| 263 | /* Touch variable */ | ||
| 264 | d=d; | ||
| 265 | #ifdef WANT_FULLSCRAPE | 200 | #ifdef WANT_FULLSCRAPE |
| 266 | if( mode == TASK_STATS_TPB ) { | 201 | if( mode == TASK_STATS_TPB ) { |
| 267 | struct http_data* h = io_getcookie( client_socket ); | 202 | struct http_data* h = io_getcookie( client_socket ); |
| 268 | tai6464 t; | 203 | tai6464 t; |
| 269 | #ifdef WANT_COMPRESSION_GZIP | 204 | #ifdef WANT_COMPRESSION_GZIP |
| 270 | d[l-1] = 0; | 205 | ws->request[ws->request_size] = 0; |
| 271 | if( strstr( d, "gzip" ) ) { | 206 | if( strstr( read_ptr - 1, "gzip" ) ) { |
| 272 | h->flag |= STRUCT_HTTP_FLAG_GZIP; | 207 | h->flag |= STRUCT_HTTP_FLAG_GZIP; |
| 273 | format |= TASK_FLAG_GZIP; | 208 | format |= TASK_FLAG_GZIP; |
| 274 | } | 209 | } |
| @@ -280,7 +215,7 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d | |||
| 280 | taia_uint( &t, 0 ); io_timeout( client_socket, t ); | 215 | taia_uint( &t, 0 ); io_timeout( client_socket, t ); |
| 281 | fullscrape_deliver( client_socket, format ); | 216 | fullscrape_deliver( client_socket, format ); |
| 282 | io_dontwantread( client_socket ); | 217 | io_dontwantread( client_socket ); |
| 283 | return -2; | 218 | return ws->reply_size = -2; |
| 284 | } | 219 | } |
| 285 | #endif | 220 | #endif |
| 286 | 221 | ||
| @@ -290,27 +225,24 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d | |||
| 290 | /* Complex stats also include expensive memory debugging tools */ | 225 | /* Complex stats also include expensive memory debugging tools */ |
| 291 | taia_uint( &t, 0 ); io_timeout( client_socket, t ); | 226 | taia_uint( &t, 0 ); io_timeout( client_socket, t ); |
| 292 | stats_deliver( client_socket, mode ); | 227 | stats_deliver( client_socket, mode ); |
| 293 | return -2; | 228 | return ws->reply_size = -2; |
| 294 | } | 229 | } |
| 295 | 230 | ||
| 296 | /* Simple stats can be answerred immediately */ | 231 | /* Simple stats can be answerred immediately */ |
| 297 | if( !( l = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500; | 232 | if( !( ws->reply_size = return_stats_for_tracker( ws->reply, mode, 0 ) ) ) HTTPERROR_500; |
| 298 | 233 | ||
| 299 | return l; | 234 | return ws->reply_size; |
| 300 | } | 235 | } |
| 301 | 236 | ||
| 302 | #ifdef WANT_FULLSCRAPE | 237 | #ifdef WANT_FULLSCRAPE |
| 303 | static ssize_t http_handle_fullscrape( const int64 client_socket, char *d, size_t l ) { | 238 | static ssize_t http_handle_fullscrape( const int64 client_socket, struct ot_workstruct *ws ) { |
| 304 | struct http_data* h = io_getcookie( client_socket ); | 239 | struct http_data* h = io_getcookie( client_socket ); |
| 305 | int format = 0; | 240 | int format = 0; |
| 306 | tai6464 t; | 241 | tai6464 t; |
| 307 | 242 | ||
| 308 | /* Touch variables */ | ||
| 309 | d=d;l=l; | ||
| 310 | |||
| 311 | #ifdef WANT_COMPRESSION_GZIP | 243 | #ifdef WANT_COMPRESSION_GZIP |
| 312 | d[l-1] = 0; | 244 | ws->request[ws->request_size-1] = 0; |
| 313 | if( strstr( d, "gzip" ) ) { | 245 | if( strstr( ws->request, "gzip" ) ) { |
| 314 | h->flag |= STRUCT_HTTP_FLAG_GZIP; | 246 | h->flag |= STRUCT_HTTP_FLAG_GZIP; |
| 315 | format = TASK_FLAG_GZIP; | 247 | format = TASK_FLAG_GZIP; |
| 316 | stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, *(int*)h->ip, 0 ); | 248 | stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, *(int*)h->ip, 0 ); |
| @@ -319,7 +251,7 @@ static ssize_t http_handle_fullscrape( const int64 client_socket, char *d, size_ | |||
| 319 | stats_issue_event( EVENT_FULLSCRAPE_REQUEST, *(int*)h->ip, 0 ); | 251 | stats_issue_event( EVENT_FULLSCRAPE_REQUEST, *(int*)h->ip, 0 ); |
| 320 | 252 | ||
| 321 | #ifdef _DEBUG_HTTPERROR | 253 | #ifdef _DEBUG_HTTPERROR |
| 322 | write( 2, debug_request, l ); | 254 | write( 2, ws->debugbuf, ws->debugbuf_size ); |
| 323 | #endif | 255 | #endif |
| 324 | 256 | ||
| 325 | /* Pass this task to the worker thread */ | 257 | /* Pass this task to the worker thread */ |
| @@ -328,72 +260,70 @@ write( 2, debug_request, l ); | |||
| 328 | taia_uint( &t, 0 ); io_timeout( client_socket, t ); | 260 | taia_uint( &t, 0 ); io_timeout( client_socket, t ); |
| 329 | fullscrape_deliver( client_socket, TASK_FULLSCRAPE | format ); | 261 | fullscrape_deliver( client_socket, TASK_FULLSCRAPE | format ); |
| 330 | io_dontwantread( client_socket ); | 262 | io_dontwantread( client_socket ); |
| 331 | return -2; | 263 | return ws->reply_size = -2; |
| 332 | } | 264 | } |
| 333 | #endif | 265 | #endif |
| 266 | static ssize_t http_handle_scrape( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { | ||
| 267 | static const ot_keywords keywords_scrape[] = { { "info_hash", 1 }, { NULL, -3 } }; | ||
| 334 | 268 | ||
| 335 | static ssize_t http_handle_scrape( const int64 client_socket, char *data ) { | 269 | ot_hash * multiscrape_buf = (ot_hash*)ws->request; |
| 336 | int scanon = 1, numwant = 0; | 270 | int scanon = 1, numwant = 0; |
| 337 | char *c = data; | ||
| 338 | size_t l; | ||
| 339 | 271 | ||
| 340 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ | 272 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ |
| 341 | if( c[-1] != '?' ) { | 273 | if( read_ptr[-1] != '?' ) { |
| 342 | while( ( *c != '?' ) && ( *c != '\n' ) ) ++c; | 274 | while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; |
| 343 | if( *c == '\n' ) HTTPERROR_400_PARAM; | 275 | if( *read_ptr == '\n' ) HTTPERROR_400_PARAM; |
| 344 | ++c; | 276 | ++read_ptr; |
| 345 | } | 277 | } |
| 346 | 278 | ||
| 347 | while( scanon ) { | 279 | while( scanon ) { |
| 348 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | 280 | switch( scan_find_keywords( keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) { |
| 349 | case -2: scanon = 0; break; /* TERMINATOR */ | 281 | case -2: scanon = 0; break; /* TERMINATOR */ |
| 350 | case -1: | 282 | default: HTTPERROR_400_PARAM; /* PARSE ERROR */ |
| 351 | if( numwant ) | 283 | case -3: scan_urlencoded_skipvalue( &read_ptr ); break; |
| 352 | goto UTORRENT1600_WORKAROUND; | 284 | case 1: /* matched "info_hash" */ |
| 353 | HTTPERROR_400_PARAM; /* PARSE ERROR */ | ||
| 354 | default: scan_urlencoded_skipvalue( &c ); break; | ||
| 355 | case 9: | ||
| 356 | if(byte_diff(data,9,"info_hash")) { | ||
| 357 | scan_urlencoded_skipvalue( &c ); | ||
| 358 | continue; | ||
| 359 | } | ||
| 360 | /* ignore this, when we have less than 20 bytes */ | 285 | /* ignore this, when we have less than 20 bytes */ |
| 361 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) ) { | 286 | if( scan_urlencoded_query( &read_ptr, (char*)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) ) |
| 362 | #ifdef WANT_UTORRENT1600_WORKAROUND | ||
| 363 | if( data[20] != '?' ) | ||
| 364 | #endif | ||
| 365 | HTTPERROR_400_PARAM; | 287 | HTTPERROR_400_PARAM; |
| 366 | } | ||
| 367 | if( numwant < OT_MAXMULTISCRAPE_COUNT ) | ||
| 368 | memmove( multiscrape_buf + numwant++, data, sizeof(ot_hash) ); | ||
| 369 | break; | 288 | break; |
| 370 | } | 289 | } |
| 371 | } | 290 | } |
| 372 | 291 | ||
| 373 | UTORRENT1600_WORKAROUND: | ||
| 374 | |||
| 375 | /* No info_hash found? Inform user */ | 292 | /* No info_hash found? Inform user */ |
| 376 | if( !numwant ) HTTPERROR_400_PARAM; | 293 | if( !numwant ) HTTPERROR_400_PARAM; |
| 294 | |||
| 295 | /* Limit number of hashes to process */ | ||
| 296 | if( numwant > OT_MAXMULTISCRAPE_COUNT ) | ||
| 297 | numwant = OT_MAXMULTISCRAPE_COUNT; | ||
| 377 | 298 | ||
| 378 | /* Enough for http header + whole scrape string */ | 299 | /* Enough for http header + whole scrape string */ |
| 379 | if( !( l = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500; | 300 | if( !( ws->reply_size = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, ws->reply ) ) ) HTTPERROR_500; |
| 380 | stats_issue_event( EVENT_SCRAPE, FLAG_TCP, l ); | 301 | stats_issue_event( EVENT_SCRAPE, FLAG_TCP, ws->reply_size ); |
| 381 | return l; | 302 | return ws->reply_size; |
| 382 | } | 303 | } |
| 383 | 304 | ||
| 384 | static ssize_t http_handle_announce( const int64 client_socket, char *data ) { | 305 | static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "event", 3 }, { "numwant", 4 }, { "compact", 5 }, { "info_hash", 6 }, |
| 385 | char *c = data; | 306 | #ifdef WANT_IP_FROM_QUERY_STRING |
| 386 | int numwant, tmp, scanon; | 307 | { "ip", 7 }, |
| 387 | ot_peer peer; | 308 | #endif |
| 388 | ot_hash *hash = NULL; | 309 | #ifdef _DEBUG_PEERID |
| 310 | { "peer_id", 8 }, | ||
| 311 | #endif | ||
| 312 | { NULL, -3 } }; | ||
| 313 | static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } }; | ||
| 314 | static ssize_t http_handle_announce( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { | ||
| 315 | int numwant, tmp, scanon; | ||
| 316 | ot_peer peer; | ||
| 317 | ot_hash *hash = NULL; | ||
| 389 | unsigned short port = htons(6881); | 318 | unsigned short port = htons(6881); |
| 390 | ssize_t len; | 319 | char *write_ptr; |
| 391 | 320 | ssize_t len; | |
| 321 | |||
| 392 | /* This is to hack around stupid clients that send "announce ?info_hash" */ | 322 | /* This is to hack around stupid clients that send "announce ?info_hash" */ |
| 393 | if( c[-1] != '?' ) { | 323 | if( read_ptr[-1] != '?' ) { |
| 394 | while( ( *c != '?' ) && ( *c != '\n' ) ) ++c; | 324 | while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; |
| 395 | if( *c == '\n' ) HTTPERROR_400_PARAM; | 325 | if( *read_ptr == '\n' ) HTTPERROR_400_PARAM; |
| 396 | ++c; | 326 | ++read_ptr; |
| 397 | } | 327 | } |
| 398 | 328 | ||
| 399 | OT_SETIP( &peer, ((struct http_data*)io_getcookie( client_socket ) )->ip ); | 329 | OT_SETIP( &peer, ((struct http_data*)io_getcookie( client_socket ) )->ip ); |
| @@ -403,168 +333,156 @@ static ssize_t http_handle_announce( const int64 client_socket, char *data ) { | |||
| 403 | scanon = 1; | 333 | scanon = 1; |
| 404 | 334 | ||
| 405 | #ifdef _DEBUG_PEERID | 335 | #ifdef _DEBUG_PEERID |
| 406 | g_this_peerid_data = NULL; | 336 | ws->peer_id = NULL; |
| 407 | #endif | 337 | #endif |
| 408 | 338 | ||
| 409 | while( scanon ) { | 339 | while( scanon ) { |
| 410 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | 340 | switch( scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) { |
| 411 | case -2: scanon = 0; break; /* TERMINATOR */ | 341 | case -2: scanon = 0; break; /* TERMINATOR */ |
| 412 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ | 342 | case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */ |
| 413 | default: scan_urlencoded_skipvalue( &c ); break; | 343 | case -3: scan_urlencoded_skipvalue( &read_ptr ); break; |
| 414 | #ifdef WANT_IP_FROM_QUERY_STRING | 344 | case 1: /* matched "port" */ |
| 415 | case 2: | 345 | len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ); |
| 416 | if(!byte_diff(data,2,"ip")) { | 346 | if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM; |
| 417 | unsigned char ip[4]; | 347 | port = htons( tmp ); OT_SETPORT( &peer, &port ); |
| 418 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 419 | if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) HTTPERROR_400_PARAM; | ||
| 420 | OT_SETIP( &peer, ip ); | ||
| 421 | } else | ||
| 422 | scan_urlencoded_skipvalue( &c ); | ||
| 423 | break; | ||
| 424 | #endif | ||
| 425 | case 4: | ||
| 426 | if( !byte_diff( data, 4, "port" ) ) { | ||
| 427 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 428 | if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM; | ||
| 429 | port = htons( tmp ); OT_SETPORT( &peer, &port ); | ||
| 430 | } else if( !byte_diff( data, 4, "left" ) ) { | ||
| 431 | if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; | ||
| 432 | if( scan_fixed_int( data, len, &tmp ) ) tmp = 0; | ||
| 433 | if( !tmp ) OT_PEERFLAG( &peer ) |= PEER_FLAG_SEEDING; | ||
| 434 | } else | ||
| 435 | scan_urlencoded_skipvalue( &c ); | ||
| 436 | break; | 348 | break; |
| 437 | case 5: | 349 | case 2: /* matched "left" */ |
| 438 | if( byte_diff( data, 5, "event" ) ) | 350 | if( ( len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM; |
| 439 | scan_urlencoded_skipvalue( &c ); | 351 | if( scan_fixed_int( write_ptr, len, &tmp ) ) tmp = 0; |
| 440 | else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { | 352 | if( !tmp ) OT_PEERFLAG( &peer ) |= PEER_FLAG_SEEDING; |
| 441 | case -1: | 353 | break; |
| 442 | HTTPERROR_400_PARAM; | 354 | case 3: /* matched "event" */ |
| 443 | case 7: | 355 | switch( scan_find_keywords( keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) { |
| 444 | if( !byte_diff( data, 7, "stopped" ) ) OT_PEERFLAG( &peer ) |= PEER_FLAG_STOPPED; | 356 | case -1: HTTPERROR_400_PARAM; |
| 445 | break; | 357 | case 1: /* matched "completed" */ |
| 446 | case 9: | 358 | OT_PEERFLAG( &peer ) |= PEER_FLAG_COMPLETED; |
| 447 | if( !byte_diff( data, 9, "completed" ) ) OT_PEERFLAG( &peer ) |= PEER_FLAG_COMPLETED; | 359 | break; |
| 448 | default: /* Fall through intended */ | 360 | case 2: /* matched "stopped" */ |
| 449 | break; | 361 | OT_PEERFLAG( &peer ) |= PEER_FLAG_STOPPED; |
| 362 | break; | ||
| 363 | default: | ||
| 364 | break; | ||
| 450 | } | 365 | } |
| 451 | break; | 366 | break; |
| 452 | case 7: | 367 | case 4: /* matched "numwant" */ |
| 453 | if(!byte_diff(data,7,"numwant")) { | 368 | len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ); |
| 454 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | 369 | if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &numwant ) ) HTTPERROR_400_PARAM; |
| 455 | if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) HTTPERROR_400_PARAM; | 370 | if( numwant < 0 ) numwant = 50; |
| 456 | if( numwant < 0 ) numwant = 50; | 371 | if( numwant > 200 ) numwant = 200; |
| 457 | if( numwant > 200 ) numwant = 200; | ||
| 458 | } else if(!byte_diff(data,7,"compact")) { | ||
| 459 | len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 460 | if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) HTTPERROR_400_PARAM; | ||
| 461 | if( !tmp ) HTTPERROR_400_COMPACT; | ||
| 462 | } else | ||
| 463 | #ifdef _DEBUG_PEERID | ||
| 464 | if(!byte_diff(data,7,"peer_id")) { | ||
| 465 | g_this_peerid_len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); | ||
| 466 | g_this_peerid_data = g_this_peerid_len > 0 ? data : 0; | ||
| 467 | } else | ||
| 468 | #endif | ||
| 469 | scan_urlencoded_skipvalue( &c ); | ||
| 470 | break; | 372 | break; |
| 471 | case 9: | 373 | case 5: /* matched "compact" */ |
| 472 | if(byte_diff(data,9,"info_hash")) { | 374 | len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ); |
| 473 | scan_urlencoded_skipvalue( &c ); | 375 | if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) ) HTTPERROR_400_PARAM; |
| 474 | continue; | 376 | if( !tmp ) HTTPERROR_400_COMPACT; |
| 475 | } | 377 | break; |
| 378 | case 6: /* matched "info_hash" */ | ||
| 379 | if( hash ) HTTPERROR_400_DOUBLEHASH; | ||
| 476 | /* ignore this, when we have less than 20 bytes */ | 380 | /* ignore this, when we have less than 20 bytes */ |
| 477 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; | 381 | if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; |
| 478 | hash = (ot_hash*)data; | 382 | hash = (ot_hash*)write_ptr; |
| 383 | break; | ||
| 384 | #ifdef WANT_IP_FROM_QUERY_STRING | ||
| 385 | case 7: /* matched "ip" */ | ||
| 386 | len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ); | ||
| 387 | if( ( len <= 0 ) || scan_fixed_ip( write_ptr, len, (unsigned char*)/*tmp*/ws->reply ) ) HTTPERROR_400_PARAM; | ||
| 388 | OT_SETIP( &peer, /*tmp*/ws->reply ); | ||
| 479 | break; | 389 | break; |
| 390 | #endif | ||
| 391 | #ifdef _DEBUG_PEERID | ||
| 392 | case 8: /* matched "peer_id" */ | ||
| 393 | ws->peer_id_size = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ); | ||
| 394 | ws->peer_id = ws->peer_id_size > 0 ? write_ptr : 0; | ||
| 395 | break; | ||
| 396 | #endif | ||
| 480 | } | 397 | } |
| 481 | } | 398 | } |
| 482 | 399 | ||
| 483 | /* Scanned whole query string */ | 400 | /* Scanned whole query string */ |
| 484 | if( !hash ) | 401 | if( !hash ) |
| 485 | return sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" ); | 402 | return ws->reply_size = sprintf( ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" ); |
| 486 | 403 | ||
| 487 | if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) | 404 | if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) |
| 488 | len = remove_peer_from_torrent( hash, &peer, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, FLAG_TCP ); | 405 | ws->reply_size = remove_peer_from_torrent( hash, &peer, ws->reply, FLAG_TCP ); |
| 489 | else | 406 | else |
| 490 | len = add_peer_to_torrent_and_return_peers(hash, &peer, FLAG_TCP, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf); | 407 | ws->reply_size = add_peer_to_torrent_and_return_peers(hash, &peer, FLAG_TCP, numwant, ws->reply ); |
| 491 | 408 | ||
| 492 | if( !len ) HTTPERROR_500; | 409 | if( !ws->reply_size ) HTTPERROR_500; |
| 493 | 410 | ||
| 494 | stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, len); | 411 | stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, ws->reply_size); |
| 495 | return len; | 412 | return ws->reply_size; |
| 496 | } | 413 | } |
| 497 | 414 | ||
| 498 | ssize_t http_handle_request( const int64 client_socket, char *data, size_t recv_length ) { | 415 | ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws ) { |
| 499 | char *c, *recv_header=data; | 416 | ssize_t reply_off, len; |
| 500 | ssize_t reply_size = 0, reply_off, len; | 417 | char *read_ptr = ws->request, *write_ptr; |
| 501 | 418 | ||
| 502 | #ifdef _DEBUG_HTTPERROR | 419 | #ifdef _DEBUG_HTTPERROR |
| 503 | if( recv_length >= sizeof( debug_request ) ) | 420 | reply_off = ws->request_size; |
| 504 | recv_length = sizeof( debug_request) - 1; | 421 | if( ws->request_size >= (ssize_t)ws->debugbuf_size ) |
| 505 | memmove( debug_request, recv_header, recv_length ); | 422 | reply_off = ws->debugbuf_size - 1; |
| 506 | debug_request[ recv_length ] = 0; | 423 | memmove( ws->debugbuf, ws->request, reply_off ); |
| 424 | ws->debugbuf[ reply_off ] = 0; | ||
| 507 | #endif | 425 | #endif |
| 508 | 426 | ||
| 427 | /* Tell subroutines where to put reply data */ | ||
| 428 | ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH; | ||
| 429 | |||
| 509 | /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ | 430 | /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ |
| 510 | if( byte_diff( data, 5, "GET /") ) HTTPERROR_400; | 431 | if( memcmp( read_ptr, "GET /", 5) ) HTTPERROR_400; |
| 511 | 432 | ||
| 512 | /* Skip leading '/' */ | 433 | /* Skip leading '/' */ |
| 513 | for( c = data+4; *c == '/'; ++c); | 434 | for( read_ptr+=4; *read_ptr == '/'; ++read_ptr); |
| 514 | 435 | ||
| 515 | /* Try to parse the request. | 436 | /* Try to parse the request. |
| 516 | In reality we abandoned requiring the url to be correct. This now | 437 | In reality we abandoned requiring the url to be correct. This now |
| 517 | only decodes url encoded characters, we check for announces and | 438 | only decodes url encoded characters, we check for announces and |
| 518 | scrapes by looking for "a*" or "sc" */ | 439 | scrapes by looking for "a*" or "sc" */ |
| 519 | len = scan_urlencoded_query( &c, data = c, SCAN_PATH ); | 440 | len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_PATH ); |
| 520 | 441 | ||
| 521 | /* If parsing returned an error, leave with not found */ | 442 | /* If parsing returned an error, leave with not found */ |
| 522 | if( g_redirecturl && ( len == -2 ) ) HTTPERROR_302; | 443 | if( g_redirecturl && ( len == -2 ) ) HTTPERROR_302; |
| 523 | if( len <= 0 ) HTTPERROR_404; | 444 | if( len <= 0 ) HTTPERROR_404; |
| 524 | 445 | ||
| 525 | /* This is the hardcore match for announce*/ | 446 | /* This is the hardcore match for announce*/ |
| 526 | if( ( *data == 'a' ) || ( *data == '?' ) ) | 447 | if( ( *write_ptr == 'a' ) || ( *write_ptr == '?' ) ) |
| 527 | reply_size = http_handle_announce( client_socket, c ); | 448 | http_handle_announce( client_socket, ws, read_ptr ); |
| 528 | #ifdef WANT_FULLSCRAPE | 449 | #ifdef WANT_FULLSCRAPE |
| 529 | else if( !byte_diff( data, 12, "scrape HTTP/" ) ) | 450 | else if( !memcmp( write_ptr, "scrape HTTP/", 12 ) ) |
| 530 | reply_size = http_handle_fullscrape( client_socket, recv_header, recv_length ); | 451 | http_handle_fullscrape( client_socket, ws ); |
| 531 | #endif | 452 | #endif |
| 532 | /* This is the hardcore match for scrape */ | 453 | /* This is the hardcore match for scrape */ |
| 533 | else if( !byte_diff( data, 2, "sc" ) ) | 454 | else if( !memcmp( write_ptr, "sc", 2 ) ) |
| 534 | reply_size = http_handle_scrape( client_socket, c ); | 455 | http_handle_scrape( client_socket, ws, read_ptr ); |
| 535 | /* All the rest is matched the standard way */ | 456 | /* All the rest is matched the standard way */ |
| 536 | else switch( len ) { | 457 | else if( !memcmp( write_ptr, "stats", 5) ) |
| 537 | case 5: /* stats ? */ | 458 | http_handle_stats( client_socket, ws, read_ptr ); |
| 538 | if( byte_diff( data, 5, "stats") ) HTTPERROR_404; | 459 | else |
| 539 | reply_size = http_handle_stats( client_socket, c, recv_header, recv_length ); | ||
| 540 | break; | ||
| 541 | default: | ||
| 542 | HTTPERROR_404; | 460 | HTTPERROR_404; |
| 543 | } | ||
| 544 | 461 | ||
| 545 | /* If routines handled sending themselves, just return */ | 462 | /* If routines handled sending themselves, just return */ |
| 546 | if( reply_size == -2 ) return 0; | 463 | if( ws->reply_size == -2 ) return 0; |
| 547 | /* If routine failed, let http error take over */ | 464 | /* If routine failed, let http error take over */ |
| 548 | if( reply_size == -1 ) HTTPERROR_500; | 465 | if( ws->reply_size == -1 ) HTTPERROR_500; |
| 549 | 466 | ||
| 550 | /* This one is rather ugly, so I take you step by step through it. | 467 | /* This one is rather ugly, so I take you step by step through it. |
| 551 | 468 | ||
| 552 | 1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to | 469 | 1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to |
| 553 | write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our static buffer, which is enough for the static string | 470 | write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our work buffer, which is enough for the static string |
| 554 | plus dynamic space needed to expand our Content-Length value. We reserve SUCCESS_HTTP_SIZE_OFF for its expansion and calculate | 471 | plus dynamic space needed to expand our Content-Length value. We reserve SUCCESS_HTTP_SIZE_OFF for its expansion and calculate |
| 555 | the space NOT needed to expand in reply_off | 472 | the space NOT needed to expand in reply_off |
| 556 | */ | 473 | */ |
| 557 | reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_outbuf, 0, "%zd", reply_size ); | 474 | reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( ws->outbuf, 0, "%zd", ws->reply_size ); |
| 558 | 475 | ws->reply = ws->outbuf + reply_off; | |
| 476 | |||
| 559 | /* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete | 477 | /* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete |
| 560 | packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */ | 478 | packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */ |
| 561 | 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 ); | 479 | ws->reply_size += 1 + sprintf( ws->reply, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", ws->reply_size ); |
| 562 | 480 | ||
| 563 | /* 3. Finally we join both blocks neatly */ | 481 | /* 3. Finally we join both blocks neatly */ |
| 564 | static_outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n'; | 482 | ws->outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n'; |
| 565 | 483 | ||
| 566 | http_senddata( client_socket, static_outbuf + reply_off, reply_size ); | 484 | http_senddata( client_socket, ws ); |
| 567 | return reply_size; | 485 | return ws->reply_size; |
| 568 | } | 486 | } |
| 569 | 487 | ||
| 570 | const char *g_version_http_c = "$Source$: $Revision$\n"; | 488 | const char *g_version_http_c = "$Source$: $Revision$\n"; |
| @@ -23,8 +23,8 @@ struct http_data { | |||
| 23 | STRUCT_HTTP_FLAG flag; | 23 | STRUCT_HTTP_FLAG flag; |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | ssize_t http_handle_request( const int64 s, char *data, size_t l ); | 26 | ssize_t http_handle_request( const int64 s, struct ot_workstruct *ws ); |
| 27 | ssize_t http_sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector ); | 27 | ssize_t http_sendiovecdata( const int64 s, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector ); |
| 28 | ssize_t http_issue_error( const int64 s, int code ); | 28 | ssize_t http_issue_error( const int64 s, struct ot_workstruct *ws, int code ); |
| 29 | 29 | ||
| 30 | #endif | 30 | #endif |
diff --git a/ot_livesync.c b/ot_livesync.c index 47a371a..a47edba 100644 --- a/ot_livesync.c +++ b/ot_livesync.c | |||
| @@ -400,9 +400,6 @@ static void * livesync_worker( void * args ) { | |||
| 400 | default: | 400 | default: |
| 401 | break; | 401 | break; |
| 402 | } | 402 | } |
| 403 | |||
| 404 | /* Handle outstanding requests */ | ||
| 405 | livesync_ticker( ); | ||
| 406 | } | 403 | } |
| 407 | 404 | ||
| 408 | /* Never returns. */ | 405 | /* Never returns. */ |
| @@ -17,9 +17,6 @@ | |||
| 17 | #include "ot_udp.h" | 17 | #include "ot_udp.h" |
| 18 | #include "ot_stats.h" | 18 | #include "ot_stats.h" |
| 19 | 19 | ||
| 20 | static char static_inbuf[8192]; | ||
| 21 | static char static_outbuf[8192]; | ||
| 22 | |||
| 23 | static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff }; | 20 | static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff }; |
| 24 | 21 | ||
| 25 | static void udp_make_connectionid( uint32_t * connid, const char * remoteip ) { | 22 | static void udp_make_connectionid( uint32_t * connid, const char * remoteip ) { |
| @@ -39,17 +36,17 @@ static int udp_test_connectionid( const uint32_t * const connid, const char * re | |||
| 39 | } | 36 | } |
| 40 | 37 | ||
| 41 | /* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */ | 38 | /* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */ |
| 42 | void handle_udp4( int64 serversocket ) { | 39 | void handle_udp4( int64 serversocket, struct ot_workstruct *ws ) { |
| 43 | ot_peer peer; | 40 | ot_peer peer; |
| 44 | ot_hash *hash = NULL; | 41 | ot_hash *hash = NULL; |
| 45 | char remoteip[4]; | 42 | char remoteip[4]; |
| 46 | uint32_t *inpacket = (uint32_t*)static_inbuf; | 43 | uint32_t *inpacket = (uint32_t*)ws->inbuf; |
| 47 | uint32_t *outpacket = (uint32_t*)static_outbuf; | 44 | uint32_t *outpacket = (uint32_t*)ws->outbuf; |
| 48 | uint32_t numwant, left, event; | 45 | uint32_t numwant, left, event; |
| 49 | uint16_t port, remoteport; | 46 | uint16_t port, remoteport; |
| 50 | size_t r, r_out; | 47 | size_t r, r_out; |
| 51 | 48 | ||
| 52 | r = socket_recv4( serversocket, static_inbuf, sizeof( static_inbuf ), remoteip, &remoteport); | 49 | r = socket_recv4( serversocket, ws->inbuf, ws->inbuf_size, remoteip, &remoteport); |
| 53 | 50 | ||
| 54 | stats_issue_event( EVENT_ACCEPT, FLAG_UDP, ntohl(*(uint32_t*)remoteip) ); | 51 | stats_issue_event( EVENT_ACCEPT, FLAG_UDP, ntohl(*(uint32_t*)remoteip) ); |
| 55 | stats_issue_event( EVENT_READ, FLAG_UDP, r ); | 52 | stats_issue_event( EVENT_READ, FLAG_UDP, r ); |
| @@ -58,8 +55,6 @@ void handle_udp4( int64 serversocket ) { | |||
| 58 | if( r < 16 ) | 55 | if( r < 16 ) |
| 59 | return; | 56 | return; |
| 60 | 57 | ||
| 61 | /* fprintf( stderr, "UDP Connection id: %16llX\n", *(uint64_t*)inpacket ); */ | ||
| 62 | |||
| 63 | switch( ntohl( inpacket[2] ) ) { | 58 | switch( ntohl( inpacket[2] ) ) { |
| 64 | case 0: /* This is a connect action */ | 59 | case 0: /* This is a connect action */ |
| 65 | /* look for udp bittorrent magic id */ | 60 | /* look for udp bittorrent magic id */ |
| @@ -70,7 +65,7 @@ void handle_udp4( int64 serversocket ) { | |||
| 70 | outpacket[1] = inpacket[3]; | 65 | outpacket[1] = inpacket[3]; |
| 71 | udp_make_connectionid( outpacket + 2, remoteip ); | 66 | udp_make_connectionid( outpacket + 2, remoteip ); |
| 72 | 67 | ||
| 73 | socket_send4( serversocket, static_outbuf, 16, remoteip, remoteport ); | 68 | socket_send4( serversocket, ws->outbuf, 16, remoteip, remoteport ); |
| 74 | stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 ); | 69 | stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 ); |
| 75 | break; | 70 | break; |
| 76 | case 1: /* This is an announce action */ | 71 | case 1: /* This is an announce action */ |
| @@ -88,8 +83,8 @@ void handle_udp4( int64 serversocket ) { | |||
| 88 | if (numwant > 200) numwant = 200; | 83 | if (numwant > 200) numwant = 200; |
| 89 | 84 | ||
| 90 | event = ntohl( inpacket[80/4] ); | 85 | event = ntohl( inpacket[80/4] ); |
| 91 | port = *(uint16_t*)( static_inbuf + 96 ); | 86 | port = *(uint16_t*)( ((char*)inpacket) + 96 ); |
| 92 | hash = (ot_hash*)( static_inbuf + 16 ); | 87 | hash = (ot_hash*)( ((char*)inpacket) + 16 ); |
| 93 | 88 | ||
| 94 | OT_SETIP( &peer, remoteip ); | 89 | OT_SETIP( &peer, remoteip ); |
| 95 | OT_SETPORT( &peer, &port ); | 90 | OT_SETPORT( &peer, &port ); |
| @@ -108,11 +103,11 @@ void handle_udp4( int64 serversocket ) { | |||
| 108 | outpacket[1] = inpacket[12/4]; | 103 | outpacket[1] = inpacket[12/4]; |
| 109 | 104 | ||
| 110 | if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */ | 105 | if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */ |
| 111 | r = remove_peer_from_torrent( hash, &peer, static_outbuf, FLAG_UDP ); | 106 | r = remove_peer_from_torrent( hash, &peer, ws->outbuf, FLAG_UDP ); |
| 112 | else | 107 | else |
| 113 | r = 8 + add_peer_to_torrent_and_return_peers( hash, &peer, FLAG_UDP, numwant, static_outbuf + 8 ); | 108 | r = 8 + add_peer_to_torrent_and_return_peers( hash, &peer, FLAG_UDP, numwant, ((char*)outpacket) + 8 ); |
| 114 | 109 | ||
| 115 | socket_send4( serversocket, static_outbuf, r, remoteip, remoteport ); | 110 | socket_send4( serversocket, ws->outbuf, r, remoteip, remoteport ); |
| 116 | stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r ); | 111 | stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r ); |
| 117 | break; | 112 | break; |
| 118 | 113 | ||
| @@ -124,9 +119,9 @@ void handle_udp4( int64 serversocket ) { | |||
| 124 | outpacket[1] = inpacket[12/4]; | 119 | outpacket[1] = inpacket[12/4]; |
| 125 | 120 | ||
| 126 | for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ ) | 121 | for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ ) |
| 127 | return_udp_scrape_for_torrent( (ot_hash*)( static_inbuf + 16 + 20 * r_out ), static_outbuf + 8 + 12 * r_out ); | 122 | return_udp_scrape_for_torrent( (ot_hash*)( ((char*)inpacket) + 16 + 20 * r_out ), ((char*)outpacket) + 8 + 12 * r_out ); |
| 128 | 123 | ||
| 129 | socket_send4( serversocket, static_outbuf, 8 + 12 * r_out, remoteip, remoteport ); | 124 | socket_send4( serversocket, ws->outbuf, 8 + 12 * r_out, remoteip, remoteport ); |
| 130 | stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r ); | 125 | stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r ); |
| 131 | break; | 126 | break; |
| 132 | } | 127 | } |
| @@ -6,6 +6,6 @@ | |||
| 6 | #ifndef __OT_UDP_H__ | 6 | #ifndef __OT_UDP_H__ |
| 7 | #define __OT_UDP_H__ | 7 | #define __OT_UDP_H__ |
| 8 | 8 | ||
| 9 | void handle_udp4( int64 serversocket ); | 9 | void handle_udp4( int64 serversocket, struct ot_workstruct *ws ); |
| 10 | 10 | ||
| 11 | #endif | 11 | #endif |
diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c index a17db2a..c3acefc 100644 --- a/scan_urlencoded_query.c +++ b/scan_urlencoded_query.c | |||
| @@ -9,6 +9,9 @@ | |||
| 9 | /* Libwofat */ | 9 | /* Libwofat */ |
| 10 | #include "scan.h" | 10 | #include "scan.h" |
| 11 | 11 | ||
| 12 | /* System */ | ||
| 13 | #include <string.h> | ||
| 14 | |||
| 12 | /* Idea is to do a in place replacement or guarantee at least | 15 | /* Idea is to do a in place replacement or guarantee at least |
| 13 | strlen( string ) bytes in deststring | 16 | strlen( string ) bytes in deststring |
| 14 | watch http://www.ietf.org/rfc/rfc2396.txt | 17 | watch http://www.ietf.org/rfc/rfc2396.txt |
| @@ -64,6 +67,22 @@ void scan_urlencoded_skipvalue( char **string ) { | |||
| 64 | *string = (char*)s; | 67 | *string = (char*)s; |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 70 | int scan_find_keywords( const ot_keywords * keywords, char **string, SCAN_SEARCHPATH_FLAG flags) { | ||
| 71 | char *deststring = *string; | ||
| 72 | ssize_t match_length = scan_urlencoded_query(string, deststring, flags ); | ||
| 73 | |||
| 74 | if( match_length < 0 ) return match_length; | ||
| 75 | if( match_length == 0 ) return -3; | ||
| 76 | |||
| 77 | while( keywords->key ) { | ||
| 78 | if( !memcmp( keywords->key, deststring, match_length ) ) | ||
| 79 | return keywords->value; | ||
| 80 | keywords++; | ||
| 81 | } | ||
| 82 | |||
| 83 | return -3; | ||
| 84 | } | ||
| 85 | |||
| 67 | ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) { | 86 | ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) { |
| 68 | const unsigned char* s=*(const unsigned char**) string; | 87 | const unsigned char* s=*(const unsigned char**) string; |
| 69 | unsigned char *d = (unsigned char*)deststring; | 88 | unsigned char *d = (unsigned char*)deststring; |
| @@ -95,9 +114,7 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F | |||
| 95 | --s; | 114 | --s; |
| 96 | break; | 115 | break; |
| 97 | case '?': | 116 | case '?': |
| 98 | /* XXX to help us parse path?param=value?param=value?... sent by µTorrent 1600 | 117 | if( flags != SCAN_PATH ) return -1; |
| 99 | do not return an error but silently terminate | ||
| 100 | if( flags != SCAN_PATH ) return -1; */ | ||
| 101 | break; | 118 | break; |
| 102 | case '=': | 119 | case '=': |
| 103 | if( flags != SCAN_SEARCHPATH_PARAM ) return -1; | 120 | if( flags != SCAN_SEARCHPATH_PARAM ) return -1; |
diff --git a/scan_urlencoded_query.h b/scan_urlencoded_query.h index 7ff6e42..a0b77af 100644 --- a/scan_urlencoded_query.h +++ b/scan_urlencoded_query.h | |||
| @@ -8,6 +8,11 @@ | |||
| 8 | 8 | ||
| 9 | #include <sys/types.h> | 9 | #include <sys/types.h> |
| 10 | 10 | ||
| 11 | typedef struct { | ||
| 12 | char *key; | ||
| 13 | int value; | ||
| 14 | } ot_keywords; | ||
| 15 | |||
| 11 | typedef enum { | 16 | typedef enum { |
| 12 | SCAN_PATH = 1, | 17 | SCAN_PATH = 1, |
| 13 | SCAN_SEARCHPATH_PARAM = 2, | 18 | SCAN_SEARCHPATH_PARAM = 2, |
| @@ -21,9 +26,20 @@ typedef enum { | |||
| 21 | flags determines, what to parse | 26 | flags determines, what to parse |
| 22 | returns number of valid converted characters in deststring | 27 | returns number of valid converted characters in deststring |
| 23 | or -1 for parse error | 28 | or -1 for parse error |
| 29 | or -2 for terminator found | ||
| 24 | */ | 30 | */ |
| 25 | ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags); | 31 | ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags); |
| 26 | 32 | ||
| 33 | /* string in: pointer to source | ||
| 34 | out: pointer to next scan position | ||
| 35 | flags determines, what to parse | ||
| 36 | returns value for matched keyword | ||
| 37 | or -1 for parse error | ||
| 38 | or -2 for terminator found | ||
| 39 | or -3 for no keyword matched | ||
| 40 | */ | ||
| 41 | int scan_find_keywords( const ot_keywords * keywords, char **string, SCAN_SEARCHPATH_FLAG flags); | ||
| 42 | |||
| 27 | /* string in: pointer to value of a param=value pair to skip | 43 | /* string in: pointer to value of a param=value pair to skip |
| 28 | out: pointer to next scan position on return | 44 | out: pointer to next scan position on return |
| 29 | */ | 45 | */ |
diff --git a/trackerlogic.h b/trackerlogic.h index 34cee3b..eb2906b 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
| @@ -96,6 +96,31 @@ struct ot_peerlist { | |||
| 96 | }; | 96 | }; |
| 97 | #define OT_PEERLIST_HASBUCKETS(peer_list) ((peer_list) && ((peer_list)->peers.size > (peer_list)->peers.space)) | 97 | #define OT_PEERLIST_HASBUCKETS(peer_list) ((peer_list) && ((peer_list)->peers.size > (peer_list)->peers.space)) |
| 98 | 98 | ||
| 99 | struct ot_workstruct { | ||
| 100 | /* Thread specific, static */ | ||
| 101 | #define THREAD_INBUF_SIZE 8192 | ||
| 102 | char *inbuf; | ||
| 103 | size_t inbuf_size; | ||
| 104 | #define THREAD_OUTBUF_SIZE 8192 | ||
| 105 | char *outbuf; | ||
| 106 | size_t outbuf_size; | ||
| 107 | #ifdef _DEBUG_HTTPERROR | ||
| 108 | #define THREAD_DEBUGBUF_SIZE 8192 | ||
| 109 | char *debugbuf; | ||
| 110 | size_t debugbuf_size; | ||
| 111 | #endif | ||
| 112 | |||
| 113 | /* HTTP specific, non static */ | ||
| 114 | char *request; | ||
| 115 | ssize_t request_size; | ||
| 116 | char *reply; | ||
| 117 | ssize_t reply_size; | ||
| 118 | #ifdef _DEBUG_PEERID | ||
| 119 | char *peer_id; | ||
| 120 | ssize_t peer_id_size; | ||
| 121 | #endif | ||
| 122 | }; | ||
| 123 | |||
| 99 | /* | 124 | /* |
| 100 | Exported functions | 125 | Exported functions |
| 101 | */ | 126 | */ |
