summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2009-01-05 18:05:38 +0000
committerDirk Engling <erdgeist@erdgeist.org>2009-01-05 18:05:38 +0000
commitb2ca1649229ff3388fd71e713bdc133384fa2a05 (patch)
tree554d34dde6735d9d18baf4116a4aea0b84d64f91
parent823f93a96f596b5e27cea61279b531e0a5c1547a (diff)
downloadopentracker-b2ca1649229ff3388fd71e713bdc133384fa2a05.tar.gz
opentracker-b2ca1649229ff3388fd71e713bdc133384fa2a05.zip
* http and udp routines now use thread local buffers passed in workstruct containers. In other words they do not use static_buffer anymore and are considered to be thread safe.
* the new workstruct also introduces a well defined buffer and result passing path * a new function scan_find_keywords is a wrapper around scan_urlencoded_query that maps keys in url to values passed in an array of ot_keywords structs * this new function cleans up much of url parameter parsing work, where read_ptr and write_ptr have been introduced rather than the confusing char *c, *data variables * I now use memcmp instead of byte_diff to allow compiler to optimize constant size string compares * got rid of UTORRENT_1600_WORKAROUND * livesync_ticker is now only called from one (currently main) thread to avoid race conditions
-rw-r--r--Makefile5
-rw-r--r--opentracker.c71
-rw-r--r--ot_http.c456
-rw-r--r--ot_http.h6
-rw-r--r--ot_livesync.c5
-rw-r--r--ot_udp.c31
-rw-r--r--ot_udp.h2
-rw-r--r--scan_urlencoded_query.c25
-rw-r--r--scan_urlencoded_query.h16
-rw-r--r--trackerlogic.h25
10 files changed, 317 insertions, 325 deletions
diff --git a/Makefile b/Makefile
index a36c1a0..1851fde 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.54 2009/01/02 07:55:11 erdgeist Exp $
+# $Id: Makefile,v 1.55 2009/01/05 18:05:38 erdgeist Exp $
CC?=gcc
@@ -24,7 +24,6 @@ BINDIR?=$(PREFIX)/bin
#FEATURES+=-DWANT_SYNC_LIVE
#FEATURES+=-DWANT_SYNC_SCRAPE
-#FEATURES+=-DWANT_UTORRENT1600_WORKAROUND
#FEATURES+=-DWANT_IP_FROM_QUERY_STRING
#FEATURES+=-DWANT_COMPRESSION_GZIP
#FEATURES+=-DWANT_LOG_NETWORKS
@@ -37,7 +36,7 @@ FEATURES+=-DWANT_FULLSCRAPE
OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage
OPTS_production=-Os
-CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra #-pedantic -ansi
+CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra #-ansi -pedantic
LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz
BINARY =opentracker
diff --git a/opentracker.c b/opentracker.c
index 62e8c1f..ad2f3af 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -2,7 +2,7 @@
It is considered beerware. Prost. Skol. Cheers or whatever.
Some of the stuff below is stolen from Fefes example libowfat httpd.
- $Id: opentracker.c,v 1.208 2009/01/03 03:25:37 erdgeist Exp $ */
+ $Id: opentracker.c,v 1.209 2009/01/05 18:05:39 erdgeist Exp $ */
/* System */
#include <stdlib.h>
@@ -41,9 +41,6 @@ volatile int g_opentracker_running = 1;
static char * g_serverdir = NULL;
-/* To always have space for error messages ;) */
-static char static_inbuf[8192];
-
static void panic( const char *routine ) {
fprintf( stderr, "%s: %s\n", routine, strerror(errno) );
exit( 111 );
@@ -107,37 +104,44 @@ static void handle_dead( const int64 socket ) {
io_close( socket );
}
-static ssize_t handle_read( const int64 clientsocket ) {
+static ssize_t handle_read( const int64 clientsocket, struct ot_workstruct *ws ) {
struct http_data* h = io_getcookie( clientsocket );
ssize_t l;
- if( ( l = io_tryread( clientsocket, static_inbuf, sizeof static_inbuf ) ) <= 0 ) {
+ if( ( l = io_tryread( clientsocket, ws->inbuf, ws->inbuf_size ) ) <= 0 ) {
handle_dead( clientsocket );
return 0;
}
/* If we get the whole request in one packet, handle it without copying */
if( !array_start( &h->data.request ) ) {
- if( memchr( static_inbuf, '\n', l ) )
- return http_handle_request( clientsocket, static_inbuf, l );
+ if( memchr( ws->inbuf, '\n', l ) ) {
+ ws->request = ws->inbuf;
+ ws->request_size = l;
+ return http_handle_request( clientsocket, ws );
+ }
+
+ /* ... else take a copy */
h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED;
- array_catb( &h->data.request, static_inbuf, l );
+ array_catb( &h->data.request, ws->inbuf, l );
return 0;
}
h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED;
- array_catb( &h->data.request, static_inbuf, l );
+ array_catb( &h->data.request, ws->inbuf, l );
if( array_failed( &h->data.request ) )
- return http_issue_error( clientsocket, CODE_HTTPERROR_500 );
+ return http_issue_error( clientsocket, ws, CODE_HTTPERROR_500 );
if( array_bytes( &h->data.request ) > 8192 )
- return http_issue_error( clientsocket, CODE_HTTPERROR_500 );
+ return http_issue_error( clientsocket, ws, CODE_HTTPERROR_500 );
- if( memchr( array_start( &h->data.request ), '\n', array_bytes( &h->data.request ) ) )
- return http_handle_request( clientsocket, array_start( &h->data.request ), array_bytes( &h->data.request ) );
+ if( !memchr( array_start( &h->data.request ), '\n', array_bytes( &h->data.request ) ) )
+ return 0;
- return 0;
+ ws->request = array_start( &h->data.request );
+ ws->request_size = array_bytes( &h->data.request );
+ return http_handle_request( clientsocket, ws );
}
static void handle_write( const int64 clientsocket ) {
@@ -183,9 +187,25 @@ static void handle_accept( const int64 serversocket ) {
}
static void server_mainloop( ) {
- time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
- struct iovec *iovector;
- int iovec_entries;
+ struct ot_workstruct ws;
+ time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
+ struct iovec *iovector;
+ int iovec_entries;
+
+ /* Initialize our "thread local storage" */
+ ws.inbuf = malloc( THREAD_INBUF_SIZE );
+ ws.outbuf = malloc( THREAD_OUTBUF_SIZE );
+#ifdef _DEBUG_HTTPERROR
+ ws.debugbuf= malloc( THREAD_INBUF_SIZE );
+#endif
+ if( !ws.inbuf || !ws.outbuf )
+ panic( "Initializing worker failed" );
+
+ ws.inbuf_size = THREAD_INBUF_SIZE;
+ ws.outbuf_size = THREAD_OUTBUF_SIZE;
+#ifdef _DEBUG_HTTPERROR
+ ws.debugbuf_size= THREAD_INBUF_SIZE;
+#endif
for( ; ; ) {
int64 i;
@@ -197,13 +217,13 @@ static void server_mainloop( ) {
if( (intptr_t)cookie == FLAG_TCP )
handle_accept( i );
else if( (intptr_t)cookie == FLAG_UDP )
- handle_udp4( i );
+ handle_udp4( i, &ws );
else
- handle_read( i );
+ handle_read( i, &ws );
}
while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 )
- http_sendiovecdata( i, iovec_entries, iovector );
+ http_sendiovecdata( i, &ws, iovec_entries, iovector );
while( ( i = io_canwrite( ) ) != -1 )
handle_write( i );
@@ -431,7 +451,12 @@ while( scanon ) {
break;
case 'f': bound += parse_configfile( optarg ); break;
case 'h': help( argv[0] ); exit( 0 );
- case 'v': stats_return_tracker_version( static_inbuf ); fputs( static_inbuf, stderr ); exit( 0 );
+ case 'v': {
+ char buffer[8192];
+ stats_return_tracker_version( buffer );
+ fputs( buffer, stderr );
+ exit( 0 );
+ }
default:
case '?': usage( argv[0] ); exit( 1 );
}
@@ -463,4 +488,4 @@ while( scanon ) {
return 0;
}
-const char *g_version_opentracker_c = "$Source: /home/cvsroot/opentracker/opentracker.c,v $: $Revision: 1.208 $\n";
+const char *g_version_opentracker_c = "$Source: /home/cvsroot/opentracker/opentracker.c,v $: $Revision: 1.209 $\n";
diff --git a/ot_http.c b/ot_http.c
index a4f2e25..cb30447 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -27,26 +27,19 @@
#include "ot_accesslist.h"
#define OT_MAXMULTISCRAPE_COUNT 64
-static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT];
extern char *g_redirecturl;
enum {
SUCCESS_HTTP_HEADER_LENGTH = 80,
- SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING = 32,
+ SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32,
SUCCESS_HTTP_SIZE_OFF = 17 };
-/* Our static output buffer */
-static char static_outbuf[8192];
-#ifdef _DEBUG_HTTPERROR
-static char debug_request[8192];
-#endif
-
#ifdef _DEBUG_PEERID
size_t g_this_peerid_len = 0;
char *g_this_peerid_data = NULL;
#endif
-static void http_senddata( const int64 client_socket, char *buffer, size_t size ) {
+static void http_senddata( const int64 client_socket, struct ot_workstruct *ws ) {
struct http_data *h = io_getcookie( client_socket );
ssize_t written_size;
@@ -56,22 +49,22 @@ static void http_senddata( const int64 client_socket, char *buffer, size_t size
array_reset( &h->data.request );
}
- written_size = write( client_socket, buffer, size );
- if( ( written_size < 0 ) || ( (size_t)written_size == size ) ) {
+ written_size = write( client_socket, ws->reply, ws->reply_size );
+ if( ( written_size < 0 ) || ( written_size == ws->reply_size ) ) {
free( h ); io_close( client_socket );
} else {
char * outbuf;
tai6464 t;
if( !h ) return;
- if( !( outbuf = malloc( size - written_size ) ) ) {
+ if( !( outbuf = malloc( ws->reply_size - written_size ) ) ) {
free(h); io_close( client_socket );
return;
}
iob_reset( &h->data.batch );
- memmove( outbuf, buffer + written_size, size - written_size );
- iob_addbuf_free( &h->data.batch, outbuf, size - written_size );
+ memmove( outbuf, ws->reply + written_size, ws->reply_size - written_size );
+ iob_addbuf_free( &h->data.batch, outbuf, ws->reply_size - written_size );
h->flag |= STRUCT_HTTP_FLAG_IOB_USED;
/* 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
}
}
-#define HTTPERROR_302 return http_issue_error( client_socket, CODE_HTTPERROR_302 )
-#define HTTPERROR_400 return http_issue_error( client_socket, CODE_HTTPERROR_400 )
-#define HTTPERROR_400_PARAM return http_issue_error( client_socket, CODE_HTTPERROR_400_PARAM )
-#define HTTPERROR_400_COMPACT return http_issue_error( client_socket, CODE_HTTPERROR_400_COMPACT )
-#define HTTPERROR_403_IP return http_issue_error( client_socket, CODE_HTTPERROR_403_IP )
-#define HTTPERROR_404 return http_issue_error( client_socket, CODE_HTTPERROR_404 )
-#define HTTPERROR_500 return http_issue_error( client_socket, CODE_HTTPERROR_500 )
-ssize_t http_issue_error( const int64 client_socket, int code ) {
+#define HTTPERROR_302 return http_issue_error( client_socket, ws, CODE_HTTPERROR_302 )
+#define HTTPERROR_400 return http_issue_error( client_socket, ws, CODE_HTTPERROR_400 )
+#define HTTPERROR_400_PARAM return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM )
+#define HTTPERROR_400_COMPACT return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_COMPACT )
+#define HTTPERROR_400_DOUBLEHASH return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM )
+#define HTTPERROR_403_IP return http_issue_error( client_socket, ws, CODE_HTTPERROR_403_IP )
+#define HTTPERROR_404 return http_issue_error( client_socket, ws, CODE_HTTPERROR_404 )
+#define HTTPERROR_500 return http_issue_error( client_socket, ws, CODE_HTTPERROR_500 )
+ssize_t http_issue_error( const int64 client_socket, struct ot_workstruct *ws, int code ) {
char *error_code[] = { "302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request",
"403 Access Denied", "404 Not Found", "500 Internal Server Error" };
- char *title = error_code[code];
- size_t reply_size;
+ char *title = error_code[code];
+ ws->reply = ws->outbuf;
if( code == CODE_HTTPERROR_302 )
- reply_size = sprintf( static_outbuf, "HTTP/1.0 302 Found\r\nContent-Length: 0\r\nLocation: %s\r\n\r\n", g_redirecturl );
+ 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 );
else
- 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);
+ 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);
#ifdef _DEBUG_HTTPERROR
- fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request );
+ fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf );
#endif
stats_issue_event( EVENT_FAILED, FLAG_TCP, code );
- http_senddata( client_socket, static_outbuf, reply_size);
- return -2;
+ http_senddata( client_socket, ws );
+ return ws->reply_size = -2;
}
-ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct iovec *iovector ) {
+ssize_t http_sendiovecdata( const int64 client_socket, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector ) {
struct http_data *h = io_getcookie( client_socket );
char *header;
int i;
@@ -136,7 +130,7 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct
}
/* Prepare space for http header */
- header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING );
+ header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING );
if( !header ) {
iovec_free( &iovec_entries, &iovector );
HTTPERROR_500;
@@ -159,7 +153,7 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct
h->flag |= STRUCT_HTTP_FLAG_IOB_USED;
- /* writeable sockets timeout after 10 minutes) */
+ /* writeable sockets timeout after 10 minutes */
taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND );
io_timeout( client_socket, t );
io_dontwantread( client_socket );
@@ -167,9 +161,21 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct
return 0;
}
-static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d, size_t l ) {
- char *c = data;
+static ssize_t http_handle_stats( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) {
+static const ot_keywords keywords_main[] =
+ { { "mode", 1 }, {"format", 2 }, { NULL, -3 } };
+static const ot_keywords keywords_mode[] =
+ { { "peer", TASK_STATS_PEERS }, { "conn", TASK_STATS_CONNS }, { "scrp", TASK_STATS_SCRAPE }, { "udp4", TASK_STATS_UDP },
+ { "busy", TASK_STATS_BUSY_NETWORKS }, { "torr", TASK_STATS_TORRENTS }, { "fscr", TASK_STATS_FULLSCRAPE },
+ { "s24s", TASK_STATS_SLASH24S }, { "tpbs", TASK_STATS_TPB }, { "herr", TASK_STATS_HTTPERRORS },
+ { "top10", TASK_STATS_TOP10 }, { "renew", TASK_STATS_RENEW }, { "syncs", TASK_STATS_SYNCS }, { "version", TASK_STATS_VERSION },
+ { "startstop", TASK_STATS_STARTSTOP }, { "toraddrem", TASK_STATS_TORADDREM }, { NULL, -3 } };
+static const ot_keywords keywords_format[] =
+ { { "bin", TASK_FULLSCRAPE_TPB_BINARY }, { "ben", TASK_FULLSCRAPE }, { "url", TASK_FULLSCRAPE_TPB_URLENCODED },
+ { "txt", TASK_FULLSCRAPE_TPB_ASCII }, { NULL, -3 } };
+
int mode = TASK_STATS_PEERS, scanon = 1, format = 0;
+
#ifdef WANT_RESTRICT_STATS
struct http_data *h = io_getcookie( client_socket );
@@ -178,97 +184,26 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d
#endif
while( scanon ) {
- switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
+ switch( scan_find_keywords( keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) {
case -2: scanon = 0; break; /* TERMINATOR */
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
- default: scan_urlencoded_skipvalue( &c ); break;
- case 4:
- if( byte_diff(data,4,"mode")) {
- scan_urlencoded_skipvalue( &c );
- continue;
- }
- switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
- case 4:
- if( !byte_diff(data,4,"peer"))
- mode = TASK_STATS_PEERS;
- else if( !byte_diff(data,4,"conn"))
- mode = TASK_STATS_CONNS;
- else if( !byte_diff(data,4,"scrp"))
- mode = TASK_STATS_SCRAPE;
- else if( !byte_diff(data,4,"tcp4"))
- mode = TASK_STATS_TCP;
- else if( !byte_diff(data,4,"udp4"))
- mode = TASK_STATS_UDP;
- else if( !byte_diff(data,4,"busy"))
- mode = TASK_STATS_BUSY_NETWORKS;
- else if( !byte_diff(data,4,"torr"))
- mode = TASK_STATS_TORRENTS;
- else if( !byte_diff(data,4,"fscr"))
- mode = TASK_STATS_FULLSCRAPE;
- else if( !byte_diff(data,4,"s24s"))
- mode = TASK_STATS_SLASH24S;
- else if( !byte_diff(data,4,"tpbs"))
- mode = TASK_STATS_TPB;
- else if( !byte_diff(data,4,"herr"))
- mode = TASK_STATS_HTTPERRORS;
- else
- HTTPERROR_400_PARAM;
- break;
- case 5:
- if( !byte_diff(data,5,"top10"))
- mode = TASK_STATS_TOP10;
- else if( !byte_diff(data,5,"renew"))
- mode = TASK_STATS_RENEW;
- else if( !byte_diff(data,5,"syncs"))
- mode = TASK_STATS_SYNCS;
- else
- HTTPERROR_400_PARAM;
- break;
- case 7:
- if( !byte_diff(data,7,"version"))
- mode = TASK_STATS_VERSION;
- else
- HTTPERROR_400_PARAM;
- break;
- case 9:
- if( !byte_diff(data,9,"startstop"))
- mode = TASK_STATS_STARTSTOP;
- else if( !byte_diff(data,9,"toraddrem"))
- mode = TASK_STATS_TORADDREM;
- else
- HTTPERROR_400_PARAM;
- break;
- }
+ case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
+ case 1: /* matched "mode" */
+ if( ( mode = scan_find_keywords( keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
break;
- case 6:
- if( byte_diff(data,6,"format")) {
- scan_urlencoded_skipvalue( &c );
- continue;
- }
- if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 3 ) HTTPERROR_400_PARAM;
- if( !byte_diff(data,3,"bin"))
- format = TASK_FULLSCRAPE_TPB_BINARY;
- else if( !byte_diff(data,3,"ben"))
- format = TASK_FULLSCRAPE;
- else if( !byte_diff(data,3,"url"))
- format = TASK_FULLSCRAPE_TPB_URLENCODED;
- else if( !byte_diff(data,3,"txt"))
- format = TASK_FULLSCRAPE_TPB_ASCII;
- else
- HTTPERROR_400_PARAM;
+ case 2: /* matched "format" */
+ if( ( format = scan_find_keywords( keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
break;
}
}
- /* Touch variable */
- d=d;
#ifdef WANT_FULLSCRAPE
if( mode == TASK_STATS_TPB ) {
struct http_data* h = io_getcookie( client_socket );
tai6464 t;
#ifdef WANT_COMPRESSION_GZIP
- d[l-1] = 0;
- if( strstr( d, "gzip" ) ) {
+ ws->request[ws->request_size] = 0;
+ if( strstr( read_ptr - 1, "gzip" ) ) {
h->flag |= STRUCT_HTTP_FLAG_GZIP;
format |= TASK_FLAG_GZIP;
}
@@ -280,7 +215,7 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d
taia_uint( &t, 0 ); io_timeout( client_socket, t );
fullscrape_deliver( client_socket, format );
io_dontwantread( client_socket );
- return -2;
+ return ws->reply_size = -2;
}
#endif
@@ -290,27 +225,24 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d
/* Complex stats also include expensive memory debugging tools */
taia_uint( &t, 0 ); io_timeout( client_socket, t );
stats_deliver( client_socket, mode );
- return -2;
+ return ws->reply_size = -2;
}
/* Simple stats can be answerred immediately */
- if( !( l = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500;
+ if( !( ws->reply_size = return_stats_for_tracker( ws->reply, mode, 0 ) ) ) HTTPERROR_500;
- return l;
+ return ws->reply_size;
}
#ifdef WANT_FULLSCRAPE
-static ssize_t http_handle_fullscrape( const int64 client_socket, char *d, size_t l ) {
+static ssize_t http_handle_fullscrape( const int64 client_socket, struct ot_workstruct *ws ) {
struct http_data* h = io_getcookie( client_socket );
int format = 0;
tai6464 t;
- /* Touch variables */
- d=d;l=l;
-
#ifdef WANT_COMPRESSION_GZIP
- d[l-1] = 0;
- if( strstr( d, "gzip" ) ) {
+ ws->request[ws->request_size-1] = 0;
+ if( strstr( ws->request, "gzip" ) ) {
h->flag |= STRUCT_HTTP_FLAG_GZIP;
format = TASK_FLAG_GZIP;
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_
stats_issue_event( EVENT_FULLSCRAPE_REQUEST, *(int*)h->ip, 0 );
#ifdef _DEBUG_HTTPERROR
-write( 2, debug_request, l );
+write( 2, ws->debugbuf, ws->debugbuf_size );
#endif
/* Pass this task to the worker thread */
@@ -328,72 +260,70 @@ write( 2, debug_request, l );
taia_uint( &t, 0 ); io_timeout( client_socket, t );
fullscrape_deliver( client_socket, TASK_FULLSCRAPE | format );
io_dontwantread( client_socket );
- return -2;
+ return ws->reply_size = -2;
}
#endif
+static ssize_t http_handle_scrape( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) {
+ static const ot_keywords keywords_scrape[] = { { "info_hash", 1 }, { NULL, -3 } };
-static ssize_t http_handle_scrape( const int64 client_socket, char *data ) {
+ ot_hash * multiscrape_buf = (ot_hash*)ws->request;
int scanon = 1, numwant = 0;
- char *c = data;
- size_t l;
/* This is to hack around stupid clients that send "scrape ?info_hash" */
- if( c[-1] != '?' ) {
- while( ( *c != '?' ) && ( *c != '\n' ) ) ++c;
- if( *c == '\n' ) HTTPERROR_400_PARAM;
- ++c;
+ if( read_ptr[-1] != '?' ) {
+ while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr;
+ if( *read_ptr == '\n' ) HTTPERROR_400_PARAM;
+ ++read_ptr;
}
while( scanon ) {
- switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
+ switch( scan_find_keywords( keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) {
case -2: scanon = 0; break; /* TERMINATOR */
- case -1:
- if( numwant )
- goto UTORRENT1600_WORKAROUND;
- HTTPERROR_400_PARAM; /* PARSE ERROR */
- default: scan_urlencoded_skipvalue( &c ); break;
- case 9:
- if(byte_diff(data,9,"info_hash")) {
- scan_urlencoded_skipvalue( &c );
- continue;
- }
+ default: HTTPERROR_400_PARAM; /* PARSE ERROR */
+ case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
+ case 1: /* matched "info_hash" */
/* ignore this, when we have less than 20 bytes */
- if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) ) {
-#ifdef WANT_UTORRENT1600_WORKAROUND
- if( data[20] != '?' )
-#endif
+ if( scan_urlencoded_query( &read_ptr, (char*)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) )
HTTPERROR_400_PARAM;
- }
- if( numwant < OT_MAXMULTISCRAPE_COUNT )
- memmove( multiscrape_buf + numwant++, data, sizeof(ot_hash) );
break;
}
}
-UTORRENT1600_WORKAROUND:
-
/* No info_hash found? Inform user */
if( !numwant ) HTTPERROR_400_PARAM;
+
+ /* Limit number of hashes to process */
+ if( numwant > OT_MAXMULTISCRAPE_COUNT )
+ numwant = OT_MAXMULTISCRAPE_COUNT;
/* Enough for http header + whole scrape string */
- if( !( l = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500;
- stats_issue_event( EVENT_SCRAPE, FLAG_TCP, l );
- return l;
+ if( !( ws->reply_size = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, ws->reply ) ) ) HTTPERROR_500;
+ stats_issue_event( EVENT_SCRAPE, FLAG_TCP, ws->reply_size );
+ return ws->reply_size;
}
-static ssize_t http_handle_announce( const int64 client_socket, char *data ) {
- char *c = data;
- int numwant, tmp, scanon;
- ot_peer peer;
- ot_hash *hash = NULL;
+static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "event", 3 }, { "numwant", 4 }, { "compact", 5 }, { "info_hash", 6 },
+#ifdef WANT_IP_FROM_QUERY_STRING
+{ "ip", 7 },
+#endif
+#ifdef _DEBUG_PEERID
+{ "peer_id", 8 },
+#endif
+{ NULL, -3 } };
+static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } };
+static ssize_t http_handle_announce( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) {
+ int numwant, tmp, scanon;
+ ot_peer peer;
+ ot_hash *hash = NULL;
unsigned short port = htons(6881);
- ssize_t len;
-
+ char *write_ptr;
+ ssize_t len;
+
/* This is to hack around stupid clients that send "announce ?info_hash" */
- if( c[-1] != '?' ) {
- while( ( *c != '?' ) && ( *c != '\n' ) ) ++c;
- if( *c == '\n' ) HTTPERROR_400_PARAM;
- ++c;
+ if( read_ptr[-1] != '?' ) {
+ while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr;
+ if( *read_ptr == '\n' ) HTTPERROR_400_PARAM;
+ ++read_ptr;
}
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 ) {
scanon = 1;
#ifdef _DEBUG_PEERID
- g_this_peerid_data = NULL;
+ ws->peer_id = NULL;
#endif
while( scanon ) {
- switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
+ switch( scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) {
case -2: scanon = 0; break; /* TERMINATOR */
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
- default: scan_urlencoded_skipvalue( &c ); break;
-#ifdef WANT_IP_FROM_QUERY_STRING
- case 2:
- if(!byte_diff(data,2,"ip")) {
- unsigned char ip[4];
- len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
- if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) HTTPERROR_400_PARAM;
- OT_SETIP( &peer, ip );
- } else
- scan_urlencoded_skipvalue( &c );
- break;
-#endif
- case 4:
- if( !byte_diff( data, 4, "port" ) ) {
- len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
- if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM;
- port = htons( tmp ); OT_SETPORT( &peer, &port );
- } else if( !byte_diff( data, 4, "left" ) ) {
- if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
- if( scan_fixed_int( data, len, &tmp ) ) tmp = 0;
- if( !tmp ) OT_PEERFLAG( &peer ) |= PEER_FLAG_SEEDING;
- } else
- scan_urlencoded_skipvalue( &c );
+ case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
+ case 1: /* matched "port" */
+ len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
+ if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM;
+ port = htons( tmp ); OT_SETPORT( &peer, &port );
break;
- case 5:
- if( byte_diff( data, 5, "event" ) )
- scan_urlencoded_skipvalue( &c );
- else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
- case -1:
- HTTPERROR_400_PARAM;
- case 7:
- if( !byte_diff( data, 7, "stopped" ) ) OT_PEERFLAG( &peer ) |= PEER_FLAG_STOPPED;
- break;
- case 9:
- if( !byte_diff( data, 9, "completed" ) ) OT_PEERFLAG( &peer ) |= PEER_FLAG_COMPLETED;
- default: /* Fall through intended */
- break;
+ case 2: /* matched "left" */
+ if( ( len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
+ if( scan_fixed_int( write_ptr, len, &tmp ) ) tmp = 0;
+ if( !tmp ) OT_PEERFLAG( &peer ) |= PEER_FLAG_SEEDING;
+ break;
+ case 3: /* matched "event" */
+ switch( scan_find_keywords( keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) {
+ case -1: HTTPERROR_400_PARAM;
+ case 1: /* matched "completed" */
+ OT_PEERFLAG( &peer ) |= PEER_FLAG_COMPLETED;
+ break;
+ case 2: /* matched "stopped" */
+ OT_PEERFLAG( &peer ) |= PEER_FLAG_STOPPED;
+ break;
+ default:
+ break;
}
break;
- case 7:
- if(!byte_diff(data,7,"numwant")) {
- len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
- if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) HTTPERROR_400_PARAM;
- if( numwant < 0 ) numwant = 50;
- if( numwant > 200 ) numwant = 200;
- } else if(!byte_diff(data,7,"compact")) {
- len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
- if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) HTTPERROR_400_PARAM;
- if( !tmp ) HTTPERROR_400_COMPACT;
- } else
-#ifdef _DEBUG_PEERID
- if(!byte_diff(data,7,"peer_id")) {
- g_this_peerid_len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
- g_this_peerid_data = g_this_peerid_len > 0 ? data : 0;
- } else
-#endif
- scan_urlencoded_skipvalue( &c );
+ case 4: /* matched "numwant" */
+ len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
+ if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &numwant ) ) HTTPERROR_400_PARAM;
+ if( numwant < 0 ) numwant = 50;
+ if( numwant > 200 ) numwant = 200;
break;
- case 9:
- if(byte_diff(data,9,"info_hash")) {
- scan_urlencoded_skipvalue( &c );
- continue;
- }
+ case 5: /* matched "compact" */
+ len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
+ if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) ) HTTPERROR_400_PARAM;
+ if( !tmp ) HTTPERROR_400_COMPACT;
+ break;
+ case 6: /* matched "info_hash" */
+ if( hash ) HTTPERROR_400_DOUBLEHASH;
/* ignore this, when we have less than 20 bytes */
- if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
- hash = (ot_hash*)data;
+ if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
+ hash = (ot_hash*)write_ptr;
+ break;
+#ifdef WANT_IP_FROM_QUERY_STRING
+ case 7: /* matched "ip" */
+ len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
+ if( ( len <= 0 ) || scan_fixed_ip( write_ptr, len, (unsigned char*)/*tmp*/ws->reply ) ) HTTPERROR_400_PARAM;
+ OT_SETIP( &peer, /*tmp*/ws->reply );
break;
+#endif
+#ifdef _DEBUG_PEERID
+ case 8: /* matched "peer_id" */
+ ws->peer_id_size = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
+ ws->peer_id = ws->peer_id_size > 0 ? write_ptr : 0;
+ break;
+#endif
}
}
/* Scanned whole query string */
if( !hash )
- 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" );
+ return ws->reply_size = sprintf( ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" );
if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED )
- len = remove_peer_from_torrent( hash, &peer, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, FLAG_TCP );
+ ws->reply_size = remove_peer_from_torrent( hash, &peer, ws->reply, FLAG_TCP );
else
- len = add_peer_to_torrent_and_return_peers(hash, &peer, FLAG_TCP, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf);
+ ws->reply_size = add_peer_to_torrent_and_return_peers(hash, &peer, FLAG_TCP, numwant, ws->reply );
- if( !len ) HTTPERROR_500;
+ if( !ws->reply_size ) HTTPERROR_500;
- stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, len);
- return len;
+ stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, ws->reply_size);
+ return ws->reply_size;
}
-ssize_t http_handle_request( const int64 client_socket, char *data, size_t recv_length ) {
- char *c, *recv_header=data;
- ssize_t reply_size = 0, reply_off, len;
+ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws ) {
+ ssize_t reply_off, len;
+ char *read_ptr = ws->request, *write_ptr;
#ifdef _DEBUG_HTTPERROR
- if( recv_length >= sizeof( debug_request ) )
- recv_length = sizeof( debug_request) - 1;
- memmove( debug_request, recv_header, recv_length );
- debug_request[ recv_length ] = 0;
+ reply_off = ws->request_size;
+ if( ws->request_size >= (ssize_t)ws->debugbuf_size )
+ reply_off = ws->debugbuf_size - 1;
+ memmove( ws->debugbuf, ws->request, reply_off );
+ ws->debugbuf[ reply_off ] = 0;
#endif
+ /* Tell subroutines where to put reply data */
+ ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH;
+
/* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */
- if( byte_diff( data, 5, "GET /") ) HTTPERROR_400;
+ if( memcmp( read_ptr, "GET /", 5) ) HTTPERROR_400;
/* Skip leading '/' */
- for( c = data+4; *c == '/'; ++c);
+ for( read_ptr+=4; *read_ptr == '/'; ++read_ptr);
/* Try to parse the request.
In reality we abandoned requiring the url to be correct. This now
only decodes url encoded characters, we check for announces and
scrapes by looking for "a*" or "sc" */
- len = scan_urlencoded_query( &c, data = c, SCAN_PATH );
+ len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_PATH );
/* If parsing returned an error, leave with not found */
if( g_redirecturl && ( len == -2 ) ) HTTPERROR_302;
if( len <= 0 ) HTTPERROR_404;
/* This is the hardcore match for announce*/
- if( ( *data == 'a' ) || ( *data == '?' ) )
- reply_size = http_handle_announce( client_socket, c );
+ if( ( *write_ptr == 'a' ) || ( *write_ptr == '?' ) )
+ http_handle_announce( client_socket, ws, read_ptr );
#ifdef WANT_FULLSCRAPE
- else if( !byte_diff( data, 12, "scrape HTTP/" ) )
- reply_size = http_handle_fullscrape( client_socket, recv_header, recv_length );
+ else if( !memcmp( write_ptr, "scrape HTTP/", 12 ) )
+ http_handle_fullscrape( client_socket, ws );
#endif
/* This is the hardcore match for scrape */
- else if( !byte_diff( data, 2, "sc" ) )
- reply_size = http_handle_scrape( client_socket, c );
+ else if( !memcmp( write_ptr, "sc", 2 ) )
+ http_handle_scrape( client_socket, ws, read_ptr );
/* All the rest is matched the standard way */
- else switch( len ) {
- case 5: /* stats ? */
- if( byte_diff( data, 5, "stats") ) HTTPERROR_404;
- reply_size = http_handle_stats( client_socket, c, recv_header, recv_length );
- break;
- default:
+ else if( !memcmp( write_ptr, "stats", 5) )
+ http_handle_stats( client_socket, ws, read_ptr );
+ else
HTTPERROR_404;
- }
/* If routines handled sending themselves, just return */
- if( reply_size == -2 ) return 0;
+ if( ws->reply_size == -2 ) return 0;
/* If routine failed, let http error take over */
- if( reply_size == -1 ) HTTPERROR_500;
+ if( ws->reply_size == -1 ) HTTPERROR_500;
/* This one is rather ugly, so I take you step by step through it.
1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to
- write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our static buffer, which is enough for the static string
+ write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our work buffer, which is enough for the static string
plus dynamic space needed to expand our Content-Length value. We reserve SUCCESS_HTTP_SIZE_OFF for its expansion and calculate
the space NOT needed to expand in reply_off
*/
- reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_outbuf, 0, "%zd", reply_size );
-
+ reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( ws->outbuf, 0, "%zd", ws->reply_size );
+ ws->reply = ws->outbuf + reply_off;
+
/* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete
packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */
- 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 );
+ 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 );
/* 3. Finally we join both blocks neatly */
- static_outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
-
- http_senddata( client_socket, static_outbuf + reply_off, reply_size );
- return reply_size;
+ ws->outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
+
+ http_senddata( client_socket, ws );
+ return ws->reply_size;
}
-const char *g_version_http_c = "$Source: /home/cvsroot/opentracker/ot_http.c,v $: $Revision: 1.25 $\n";
+const char *g_version_http_c = "$Source: /home/cvsroot/opentracker/ot_http.c,v $: $Revision: 1.26 $\n";
diff --git a/ot_http.h b/ot_http.h
index cd8c3cb..18e8156 100644
--- a/ot_http.h
+++ b/ot_http.h
@@ -23,8 +23,8 @@ struct http_data {
STRUCT_HTTP_FLAG flag;
};
-ssize_t http_handle_request( const int64 s, char *data, size_t l );
-ssize_t http_sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector );
-ssize_t http_issue_error( const int64 s, int code );
+ssize_t http_handle_request( const int64 s, struct ot_workstruct *ws );
+ssize_t http_sendiovecdata( const int64 s, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector );
+ssize_t http_issue_error( const int64 s, struct ot_workstruct *ws, int code );
#endif
diff --git a/ot_livesync.c b/ot_livesync.c
index 5347fbe..782d9bd 100644
--- a/ot_livesync.c
+++ b/ot_livesync.c
@@ -400,9 +400,6 @@ static void * livesync_worker( void * args ) {
default:
break;
}
-
- /* Handle outstanding requests */
- livesync_ticker( );
}
/* Never returns. */
@@ -410,4 +407,4 @@ static void * livesync_worker( void * args ) {
}
#endif
-const char *g_version_livesync_c = "$Source: /home/cvsroot/opentracker/ot_livesync.c,v $: $Revision: 1.11 $\n";
+const char *g_version_livesync_c = "$Source: /home/cvsroot/opentracker/ot_livesync.c,v $: $Revision: 1.12 $\n";
diff --git a/ot_udp.c b/ot_udp.c
index b9dbe8f..7052444 100644
--- a/ot_udp.c
+++ b/ot_udp.c
@@ -17,9 +17,6 @@
#include "ot_udp.h"
#include "ot_stats.h"
-static char static_inbuf[8192];
-static char static_outbuf[8192];
-
static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff };
static void udp_make_connectionid( uint32_t * connid, const char * remoteip ) {
@@ -39,17 +36,17 @@ static int udp_test_connectionid( const uint32_t * const connid, const char * re
}
/* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */
-void handle_udp4( int64 serversocket ) {
+void handle_udp4( int64 serversocket, struct ot_workstruct *ws ) {
ot_peer peer;
ot_hash *hash = NULL;
char remoteip[4];
- uint32_t *inpacket = (uint32_t*)static_inbuf;
- uint32_t *outpacket = (uint32_t*)static_outbuf;
+ uint32_t *inpacket = (uint32_t*)ws->inbuf;
+ uint32_t *outpacket = (uint32_t*)ws->outbuf;
uint32_t numwant, left, event;
uint16_t port, remoteport;
size_t r, r_out;
- r = socket_recv4( serversocket, static_inbuf, sizeof( static_inbuf ), remoteip, &remoteport);
+ r = socket_recv4( serversocket, ws->inbuf, ws->inbuf_size, remoteip, &remoteport);
stats_issue_event( EVENT_ACCEPT, FLAG_UDP, ntohl(*(uint32_t*)remoteip) );
stats_issue_event( EVENT_READ, FLAG_UDP, r );
@@ -58,8 +55,6 @@ void handle_udp4( int64 serversocket ) {
if( r < 16 )
return;
-/* fprintf( stderr, "UDP Connection id: %16llX\n", *(uint64_t*)inpacket ); */
-
switch( ntohl( inpacket[2] ) ) {
case 0: /* This is a connect action */
/* look for udp bittorrent magic id */
@@ -70,7 +65,7 @@ void handle_udp4( int64 serversocket ) {
outpacket[1] = inpacket[3];
udp_make_connectionid( outpacket + 2, remoteip );
- socket_send4( serversocket, static_outbuf, 16, remoteip, remoteport );
+ socket_send4( serversocket, ws->outbuf, 16, remoteip, remoteport );
stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 );
break;
case 1: /* This is an announce action */
@@ -88,8 +83,8 @@ void handle_udp4( int64 serversocket ) {
if (numwant > 200) numwant = 200;
event = ntohl( inpacket[80/4] );
- port = *(uint16_t*)( static_inbuf + 96 );
- hash = (ot_hash*)( static_inbuf + 16 );
+ port = *(uint16_t*)( ((char*)inpacket) + 96 );
+ hash = (ot_hash*)( ((char*)inpacket) + 16 );
OT_SETIP( &peer, remoteip );
OT_SETPORT( &peer, &port );
@@ -108,11 +103,11 @@ void handle_udp4( int64 serversocket ) {
outpacket[1] = inpacket[12/4];
if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */
- r = remove_peer_from_torrent( hash, &peer, static_outbuf, FLAG_UDP );
+ r = remove_peer_from_torrent( hash, &peer, ws->outbuf, FLAG_UDP );
else
- r = 8 + add_peer_to_torrent_and_return_peers( hash, &peer, FLAG_UDP, numwant, static_outbuf + 8 );
+ r = 8 + add_peer_to_torrent_and_return_peers( hash, &peer, FLAG_UDP, numwant, ((char*)outpacket) + 8 );
- socket_send4( serversocket, static_outbuf, r, remoteip, remoteport );
+ socket_send4( serversocket, ws->outbuf, r, remoteip, remoteport );
stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r );
break;
@@ -124,9 +119,9 @@ void handle_udp4( int64 serversocket ) {
outpacket[1] = inpacket[12/4];
for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ )
- return_udp_scrape_for_torrent( (ot_hash*)( static_inbuf + 16 + 20 * r_out ), static_outbuf + 8 + 12 * r_out );
+ return_udp_scrape_for_torrent( (ot_hash*)( ((char*)inpacket) + 16 + 20 * r_out ), ((char*)outpacket) + 8 + 12 * r_out );
- socket_send4( serversocket, static_outbuf, 8 + 12 * r_out, remoteip, remoteport );
+ socket_send4( serversocket, ws->outbuf, 8 + 12 * r_out, remoteip, remoteport );
stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r );
break;
}
@@ -136,4 +131,4 @@ void udp_init( ) {
}
-const char *g_version_udp_c = "$Source: /home/cvsroot/opentracker/ot_udp.c,v $: $Revision: 1.19 $\n";
+const char *g_version_udp_c = "$Source: /home/cvsroot/opentracker/ot_udp.c,v $: $Revision: 1.20 $\n";
diff --git a/ot_udp.h b/ot_udp.h
index c5f3959..c146392 100644
--- a/ot_udp.h
+++ b/ot_udp.h
@@ -6,6 +6,6 @@
#ifndef __OT_UDP_H__
#define __OT_UDP_H__
-void handle_udp4( int64 serversocket );
+void handle_udp4( int64 serversocket, struct ot_workstruct *ws );
#endif
diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c
index 0bccd00..693a437 100644
--- a/scan_urlencoded_query.c
+++ b/scan_urlencoded_query.c
@@ -9,6 +9,9 @@
/* Libwofat */
#include "scan.h"
+/* System */
+#include <string.h>
+
/* Idea is to do a in place replacement or guarantee at least
strlen( string ) bytes in deststring
watch http://www.ietf.org/rfc/rfc2396.txt
@@ -64,6 +67,22 @@ void scan_urlencoded_skipvalue( char **string ) {
*string = (char*)s;
}
+int scan_find_keywords( const ot_keywords * keywords, char **string, SCAN_SEARCHPATH_FLAG flags) {
+ char *deststring = *string;
+ ssize_t match_length = scan_urlencoded_query(string, deststring, flags );
+
+ if( match_length < 0 ) return match_length;
+ if( match_length == 0 ) return -3;
+
+ while( keywords->key ) {
+ if( !memcmp( keywords->key, deststring, match_length ) )
+ return keywords->value;
+ keywords++;
+ }
+
+ return -3;
+}
+
ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) {
const unsigned char* s=*(const unsigned char**) string;
unsigned char *d = (unsigned char*)deststring;
@@ -95,9 +114,7 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F
--s;
break;
case '?':
- /* XXX to help us parse path?param=value?param=value?... sent by ĀµTorrent 1600
- do not return an error but silently terminate
- if( flags != SCAN_PATH ) return -1; */
+ if( flags != SCAN_PATH ) return -1;
break;
case '=':
if( flags != SCAN_SEARCHPATH_PARAM ) return -1;
@@ -140,4 +157,4 @@ ssize_t scan_fixed_ip( char *data, size_t len, unsigned char ip[4] ) {
return len;
}
-const char *g_version_scan_urlencoded_query_c = "$Source: /home/cvsroot/opentracker/scan_urlencoded_query.c,v $: $Revision: 1.28 $\n";
+const char *g_version_scan_urlencoded_query_c = "$Source: /home/cvsroot/opentracker/scan_urlencoded_query.c,v $: $Revision: 1.29 $\n";
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 @@
#include <sys/types.h>
+typedef struct {
+ char *key;
+ int value;
+} ot_keywords;
+
typedef enum {
SCAN_PATH = 1,
SCAN_SEARCHPATH_PARAM = 2,
@@ -21,9 +26,20 @@ typedef enum {
flags determines, what to parse
returns number of valid converted characters in deststring
or -1 for parse error
+ or -2 for terminator found
*/
ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags);
+/* string in: pointer to source
+ out: pointer to next scan position
+ flags determines, what to parse
+ returns value for matched keyword
+ or -1 for parse error
+ or -2 for terminator found
+ or -3 for no keyword matched
+ */
+int scan_find_keywords( const ot_keywords * keywords, char **string, SCAN_SEARCHPATH_FLAG flags);
+
/* string in: pointer to value of a param=value pair to skip
out: pointer to next scan position on return
*/
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 {
};
#define OT_PEERLIST_HASBUCKETS(peer_list) ((peer_list) && ((peer_list)->peers.size > (peer_list)->peers.space))
+struct ot_workstruct {
+ /* Thread specific, static */
+#define THREAD_INBUF_SIZE 8192
+ char *inbuf;
+ size_t inbuf_size;
+#define THREAD_OUTBUF_SIZE 8192
+ char *outbuf;
+ size_t outbuf_size;
+#ifdef _DEBUG_HTTPERROR
+#define THREAD_DEBUGBUF_SIZE 8192
+ char *debugbuf;
+ size_t debugbuf_size;
+#endif
+
+ /* HTTP specific, non static */
+ char *request;
+ ssize_t request_size;
+ char *reply;
+ ssize_t reply_size;
+#ifdef _DEBUG_PEERID
+ char *peer_id;
+ ssize_t peer_id_size;
+#endif
+};
+
/*
Exported functions
*/