mirror of
git://erdgeist.org/opentracker
synced 2025-03-14 10:34:41 +08:00
* 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
This commit is contained in:
parent
8bdc0d73f6
commit
779d6c235f
3
Makefile
3
Makefile
@ -24,7 +24,6 @@ BINDIR?=$(PREFIX)/bin
|
|||||||
|
|
||||||
#FEATURES+=-DWANT_SYNC_LIVE
|
#FEATURES+=-DWANT_SYNC_LIVE
|
||||||
#FEATURES+=-DWANT_SYNC_SCRAPE
|
#FEATURES+=-DWANT_SYNC_SCRAPE
|
||||||
#FEATURES+=-DWANT_UTORRENT1600_WORKAROUND
|
|
||||||
#FEATURES+=-DWANT_IP_FROM_QUERY_STRING
|
#FEATURES+=-DWANT_IP_FROM_QUERY_STRING
|
||||||
#FEATURES+=-DWANT_COMPRESSION_GZIP
|
#FEATURES+=-DWANT_COMPRESSION_GZIP
|
||||||
#FEATURES+=-DWANT_LOG_NETWORKS
|
#FEATURES+=-DWANT_LOG_NETWORKS
|
||||||
@ -37,7 +36,7 @@ FEATURES+=-DWANT_FULLSCRAPE
|
|||||||
OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage
|
OPTS_debug=-D_DEBUG -g -ggdb # -pg -fprofile-arcs -ftest-coverage
|
||||||
OPTS_production=-Os
|
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
|
LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lz
|
||||||
|
|
||||||
BINARY =opentracker
|
BINARY =opentracker
|
||||||
|
@ -41,9 +41,6 @@ volatile int g_opentracker_running = 1;
|
|||||||
|
|
||||||
static char * g_serverdir = NULL;
|
static char * g_serverdir = NULL;
|
||||||
|
|
||||||
/* To always have space for error messages ;) */
|
|
||||||
static char static_inbuf[8192];
|
|
||||||
|
|
||||||
static void panic( const char *routine ) {
|
static void panic( const char *routine ) {
|
||||||
fprintf( stderr, "%s: %s\n", routine, strerror(errno) );
|
fprintf( stderr, "%s: %s\n", routine, strerror(errno) );
|
||||||
exit( 111 );
|
exit( 111 );
|
||||||
@ -107,37 +104,44 @@ static void handle_dead( const int64 socket ) {
|
|||||||
io_close( 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 );
|
struct http_data* h = io_getcookie( clientsocket );
|
||||||
ssize_t l;
|
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 );
|
handle_dead( clientsocket );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we get the whole request in one packet, handle it without copying */
|
/* If we get the whole request in one packet, handle it without copying */
|
||||||
if( !array_start( &h->data.request ) ) {
|
if( !array_start( &h->data.request ) ) {
|
||||||
if( memchr( static_inbuf, '\n', l ) )
|
if( memchr( ws->inbuf, '\n', l ) ) {
|
||||||
return http_handle_request( clientsocket, static_inbuf, 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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED;
|
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 ) )
|
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 )
|
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 ) {
|
static void handle_write( const int64 clientsocket ) {
|
||||||
@ -183,10 +187,26 @@ static void handle_accept( const int64 serversocket ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void server_mainloop( ) {
|
static void server_mainloop( ) {
|
||||||
|
struct ot_workstruct ws;
|
||||||
time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
|
time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
|
||||||
struct iovec *iovector;
|
struct iovec *iovector;
|
||||||
int iovec_entries;
|
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( ; ; ) {
|
for( ; ; ) {
|
||||||
int64 i;
|
int64 i;
|
||||||
|
|
||||||
@ -197,13 +217,13 @@ static void server_mainloop( ) {
|
|||||||
if( (intptr_t)cookie == FLAG_TCP )
|
if( (intptr_t)cookie == FLAG_TCP )
|
||||||
handle_accept( i );
|
handle_accept( i );
|
||||||
else if( (intptr_t)cookie == FLAG_UDP )
|
else if( (intptr_t)cookie == FLAG_UDP )
|
||||||
handle_udp4( i );
|
handle_udp4( i, &ws );
|
||||||
else
|
else
|
||||||
handle_read( i );
|
handle_read( i, &ws );
|
||||||
}
|
}
|
||||||
|
|
||||||
while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 )
|
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 )
|
while( ( i = io_canwrite( ) ) != -1 )
|
||||||
handle_write( i );
|
handle_write( i );
|
||||||
@ -431,7 +451,12 @@ while( scanon ) {
|
|||||||
break;
|
break;
|
||||||
case 'f': bound += parse_configfile( optarg ); break;
|
case 'f': bound += parse_configfile( optarg ); break;
|
||||||
case 'h': help( argv[0] ); exit( 0 );
|
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:
|
default:
|
||||||
case '?': usage( argv[0] ); exit( 1 );
|
case '?': usage( argv[0] ); exit( 1 );
|
||||||
}
|
}
|
||||||
|
424
ot_http.c
424
ot_http.c
@ -27,26 +27,19 @@
|
|||||||
#include "ot_accesslist.h"
|
#include "ot_accesslist.h"
|
||||||
|
|
||||||
#define OT_MAXMULTISCRAPE_COUNT 64
|
#define OT_MAXMULTISCRAPE_COUNT 64
|
||||||
static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT];
|
|
||||||
extern char *g_redirecturl;
|
extern char *g_redirecturl;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SUCCESS_HTTP_HEADER_LENGTH = 80,
|
SUCCESS_HTTP_HEADER_LENGTH = 80,
|
||||||
SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING = 32,
|
SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32,
|
||||||
SUCCESS_HTTP_SIZE_OFF = 17 };
|
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
|
#ifdef _DEBUG_PEERID
|
||||||
size_t g_this_peerid_len = 0;
|
size_t g_this_peerid_len = 0;
|
||||||
char *g_this_peerid_data = NULL;
|
char *g_this_peerid_data = NULL;
|
||||||
#endif
|
#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 );
|
struct http_data *h = io_getcookie( client_socket );
|
||||||
ssize_t written_size;
|
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 );
|
array_reset( &h->data.request );
|
||||||
}
|
}
|
||||||
|
|
||||||
written_size = write( client_socket, buffer, size );
|
written_size = write( client_socket, ws->reply, ws->reply_size );
|
||||||
if( ( written_size < 0 ) || ( (size_t)written_size == size ) ) {
|
if( ( written_size < 0 ) || ( written_size == ws->reply_size ) ) {
|
||||||
free( h ); io_close( client_socket );
|
free( h ); io_close( client_socket );
|
||||||
} else {
|
} else {
|
||||||
char * outbuf;
|
char * outbuf;
|
||||||
tai6464 t;
|
tai6464 t;
|
||||||
|
|
||||||
if( !h ) return;
|
if( !h ) return;
|
||||||
if( !( outbuf = malloc( size - written_size ) ) ) {
|
if( !( outbuf = malloc( ws->reply_size - written_size ) ) ) {
|
||||||
free(h); io_close( client_socket );
|
free(h); io_close( client_socket );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
iob_reset( &h->data.batch );
|
iob_reset( &h->data.batch );
|
||||||
memmove( outbuf, buffer + written_size, size - written_size );
|
memmove( outbuf, ws->reply + written_size, ws->reply_size - written_size );
|
||||||
iob_addbuf_free( &h->data.batch, outbuf, size - written_size );
|
iob_addbuf_free( &h->data.batch, outbuf, ws->reply_size - written_size );
|
||||||
h->flag |= STRUCT_HTTP_FLAG_IOB_USED;
|
h->flag |= STRUCT_HTTP_FLAG_IOB_USED;
|
||||||
|
|
||||||
/* writeable short data sockets just have a tcp timeout */
|
/* 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_302 return http_issue_error( client_socket, ws, CODE_HTTPERROR_302 )
|
||||||
#define HTTPERROR_400 return http_issue_error( client_socket, CODE_HTTPERROR_400 )
|
#define HTTPERROR_400 return http_issue_error( client_socket, ws, CODE_HTTPERROR_400 )
|
||||||
#define HTTPERROR_400_PARAM return http_issue_error( client_socket, CODE_HTTPERROR_400_PARAM )
|
#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, CODE_HTTPERROR_400_COMPACT )
|
#define HTTPERROR_400_COMPACT return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_COMPACT )
|
||||||
#define HTTPERROR_403_IP return http_issue_error( client_socket, CODE_HTTPERROR_403_IP )
|
#define HTTPERROR_400_DOUBLEHASH return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM )
|
||||||
#define HTTPERROR_404 return http_issue_error( client_socket, CODE_HTTPERROR_404 )
|
#define HTTPERROR_403_IP return http_issue_error( client_socket, ws, CODE_HTTPERROR_403_IP )
|
||||||
#define HTTPERROR_500 return http_issue_error( client_socket, CODE_HTTPERROR_500 )
|
#define HTTPERROR_404 return http_issue_error( client_socket, ws, CODE_HTTPERROR_404 )
|
||||||
ssize_t http_issue_error( const int64 client_socket, int code ) {
|
#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",
|
char *error_code[] = { "302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request",
|
||||||
"403 Access Denied", "404 Not Found", "500 Internal Server Error" };
|
"403 Access Denied", "404 Not Found", "500 Internal Server Error" };
|
||||||
char *title = error_code[code];
|
char *title = error_code[code];
|
||||||
size_t reply_size;
|
|
||||||
|
|
||||||
|
ws->reply = ws->outbuf;
|
||||||
if( code == CODE_HTTPERROR_302 )
|
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
|
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
|
#ifdef _DEBUG_HTTPERROR
|
||||||
fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request );
|
fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf );
|
||||||
#endif
|
#endif
|
||||||
stats_issue_event( EVENT_FAILED, FLAG_TCP, code );
|
stats_issue_event( EVENT_FAILED, FLAG_TCP, code );
|
||||||
http_senddata( client_socket, static_outbuf, reply_size);
|
http_senddata( client_socket, ws );
|
||||||
return -2;
|
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 );
|
struct http_data *h = io_getcookie( client_socket );
|
||||||
char *header;
|
char *header;
|
||||||
int i;
|
int i;
|
||||||
@ -136,7 +130,7 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare space for http header */
|
/* 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 ) {
|
if( !header ) {
|
||||||
iovec_free( &iovec_entries, &iovector );
|
iovec_free( &iovec_entries, &iovector );
|
||||||
HTTPERROR_500;
|
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;
|
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 );
|
taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND );
|
||||||
io_timeout( client_socket, t );
|
io_timeout( client_socket, t );
|
||||||
io_dontwantread( client_socket );
|
io_dontwantread( client_socket );
|
||||||
@ -167,9 +161,21 @@ ssize_t http_sendiovecdata( const int64 client_socket, int iovec_entries, struct
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d, size_t l ) {
|
static ssize_t http_handle_stats( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) {
|
||||||
char *c = data;
|
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;
|
int mode = TASK_STATS_PEERS, scanon = 1, format = 0;
|
||||||
|
|
||||||
#ifdef WANT_RESTRICT_STATS
|
#ifdef WANT_RESTRICT_STATS
|
||||||
struct http_data *h = io_getcookie( client_socket );
|
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
|
#endif
|
||||||
|
|
||||||
while( scanon ) {
|
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 -2: scanon = 0; break; /* TERMINATOR */
|
||||||
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
|
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
|
||||||
default: scan_urlencoded_skipvalue( &c ); break;
|
case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
|
||||||
case 4:
|
case 1: /* matched "mode" */
|
||||||
if( byte_diff(data,4,"mode")) {
|
if( ( mode = scan_find_keywords( keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
|
||||||
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;
|
break;
|
||||||
case 5:
|
case 2: /* matched "format" */
|
||||||
if( !byte_diff(data,5,"top10"))
|
if( ( format = scan_find_keywords( keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Touch variable */
|
|
||||||
d=d;
|
|
||||||
#ifdef WANT_FULLSCRAPE
|
#ifdef WANT_FULLSCRAPE
|
||||||
if( mode == TASK_STATS_TPB ) {
|
if( mode == TASK_STATS_TPB ) {
|
||||||
struct http_data* h = io_getcookie( client_socket );
|
struct http_data* h = io_getcookie( client_socket );
|
||||||
tai6464 t;
|
tai6464 t;
|
||||||
#ifdef WANT_COMPRESSION_GZIP
|
#ifdef WANT_COMPRESSION_GZIP
|
||||||
d[l-1] = 0;
|
ws->request[ws->request_size] = 0;
|
||||||
if( strstr( d, "gzip" ) ) {
|
if( strstr( read_ptr - 1, "gzip" ) ) {
|
||||||
h->flag |= STRUCT_HTTP_FLAG_GZIP;
|
h->flag |= STRUCT_HTTP_FLAG_GZIP;
|
||||||
format |= TASK_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 );
|
taia_uint( &t, 0 ); io_timeout( client_socket, t );
|
||||||
fullscrape_deliver( client_socket, format );
|
fullscrape_deliver( client_socket, format );
|
||||||
io_dontwantread( client_socket );
|
io_dontwantread( client_socket );
|
||||||
return -2;
|
return ws->reply_size = -2;
|
||||||
}
|
}
|
||||||
#endif
|
#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 */
|
/* Complex stats also include expensive memory debugging tools */
|
||||||
taia_uint( &t, 0 ); io_timeout( client_socket, t );
|
taia_uint( &t, 0 ); io_timeout( client_socket, t );
|
||||||
stats_deliver( client_socket, mode );
|
stats_deliver( client_socket, mode );
|
||||||
return -2;
|
return ws->reply_size = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple stats can be answerred immediately */
|
/* 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
|
#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 );
|
struct http_data* h = io_getcookie( client_socket );
|
||||||
int format = 0;
|
int format = 0;
|
||||||
tai6464 t;
|
tai6464 t;
|
||||||
|
|
||||||
/* Touch variables */
|
|
||||||
d=d;l=l;
|
|
||||||
|
|
||||||
#ifdef WANT_COMPRESSION_GZIP
|
#ifdef WANT_COMPRESSION_GZIP
|
||||||
d[l-1] = 0;
|
ws->request[ws->request_size-1] = 0;
|
||||||
if( strstr( d, "gzip" ) ) {
|
if( strstr( ws->request, "gzip" ) ) {
|
||||||
h->flag |= STRUCT_HTTP_FLAG_GZIP;
|
h->flag |= STRUCT_HTTP_FLAG_GZIP;
|
||||||
format = TASK_FLAG_GZIP;
|
format = TASK_FLAG_GZIP;
|
||||||
stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, *(int*)h->ip, 0 );
|
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 );
|
stats_issue_event( EVENT_FULLSCRAPE_REQUEST, *(int*)h->ip, 0 );
|
||||||
|
|
||||||
#ifdef _DEBUG_HTTPERROR
|
#ifdef _DEBUG_HTTPERROR
|
||||||
write( 2, debug_request, l );
|
write( 2, ws->debugbuf, ws->debugbuf_size );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Pass this task to the worker thread */
|
/* 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 );
|
taia_uint( &t, 0 ); io_timeout( client_socket, t );
|
||||||
fullscrape_deliver( client_socket, TASK_FULLSCRAPE | format );
|
fullscrape_deliver( client_socket, TASK_FULLSCRAPE | format );
|
||||||
io_dontwantread( client_socket );
|
io_dontwantread( client_socket );
|
||||||
return -2;
|
return ws->reply_size = -2;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
int scanon = 1, numwant = 0;
|
||||||
char *c = data;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
/* This is to hack around stupid clients that send "scrape ?info_hash" */
|
/* This is to hack around stupid clients that send "scrape ?info_hash" */
|
||||||
if( c[-1] != '?' ) {
|
if( read_ptr[-1] != '?' ) {
|
||||||
while( ( *c != '?' ) && ( *c != '\n' ) ) ++c;
|
while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr;
|
||||||
if( *c == '\n' ) HTTPERROR_400_PARAM;
|
if( *read_ptr == '\n' ) HTTPERROR_400_PARAM;
|
||||||
++c;
|
++read_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( scanon ) {
|
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 -2: scanon = 0; break; /* TERMINATOR */
|
||||||
case -1:
|
default: HTTPERROR_400_PARAM; /* PARSE ERROR */
|
||||||
if( numwant )
|
case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
|
||||||
goto UTORRENT1600_WORKAROUND;
|
case 1: /* matched "info_hash" */
|
||||||
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;
|
|
||||||
}
|
|
||||||
/* ignore this, when we have less than 20 bytes */
|
/* ignore this, when we have less than 20 bytes */
|
||||||
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) ) {
|
if( scan_urlencoded_query( &read_ptr, (char*)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE ) != (ssize_t)sizeof(ot_hash) )
|
||||||
#ifdef WANT_UTORRENT1600_WORKAROUND
|
|
||||||
if( data[20] != '?' )
|
|
||||||
#endif
|
|
||||||
HTTPERROR_400_PARAM;
|
HTTPERROR_400_PARAM;
|
||||||
}
|
|
||||||
if( numwant < OT_MAXMULTISCRAPE_COUNT )
|
|
||||||
memmove( multiscrape_buf + numwant++, data, sizeof(ot_hash) );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UTORRENT1600_WORKAROUND:
|
|
||||||
|
|
||||||
/* No info_hash found? Inform user */
|
/* No info_hash found? Inform user */
|
||||||
if( !numwant ) HTTPERROR_400_PARAM;
|
if( !numwant ) HTTPERROR_400_PARAM;
|
||||||
|
|
||||||
|
/* Limit number of hashes to process */
|
||||||
|
if( numwant > OT_MAXMULTISCRAPE_COUNT )
|
||||||
|
numwant = OT_MAXMULTISCRAPE_COUNT;
|
||||||
|
|
||||||
/* Enough for http header + whole scrape string */
|
/* 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;
|
if( !( ws->reply_size = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, ws->reply ) ) ) HTTPERROR_500;
|
||||||
stats_issue_event( EVENT_SCRAPE, FLAG_TCP, l );
|
stats_issue_event( EVENT_SCRAPE, FLAG_TCP, ws->reply_size );
|
||||||
return l;
|
return ws->reply_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t http_handle_announce( const int64 client_socket, char *data ) {
|
static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "event", 3 }, { "numwant", 4 }, { "compact", 5 }, { "info_hash", 6 },
|
||||||
char *c = data;
|
#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;
|
int numwant, tmp, scanon;
|
||||||
ot_peer peer;
|
ot_peer peer;
|
||||||
ot_hash *hash = NULL;
|
ot_hash *hash = NULL;
|
||||||
unsigned short port = htons(6881);
|
unsigned short port = htons(6881);
|
||||||
|
char *write_ptr;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
/* This is to hack around stupid clients that send "announce ?info_hash" */
|
/* This is to hack around stupid clients that send "announce ?info_hash" */
|
||||||
if( c[-1] != '?' ) {
|
if( read_ptr[-1] != '?' ) {
|
||||||
while( ( *c != '?' ) && ( *c != '\n' ) ) ++c;
|
while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr;
|
||||||
if( *c == '\n' ) HTTPERROR_400_PARAM;
|
if( *read_ptr == '\n' ) HTTPERROR_400_PARAM;
|
||||||
++c;
|
++read_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
OT_SETIP( &peer, ((struct http_data*)io_getcookie( client_socket ) )->ip );
|
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;
|
scanon = 1;
|
||||||
|
|
||||||
#ifdef _DEBUG_PEERID
|
#ifdef _DEBUG_PEERID
|
||||||
g_this_peerid_data = NULL;
|
ws->peer_id = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while( scanon ) {
|
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 -2: scanon = 0; break; /* TERMINATOR */
|
||||||
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
|
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
|
||||||
default: scan_urlencoded_skipvalue( &c ); break;
|
case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
|
||||||
#ifdef WANT_IP_FROM_QUERY_STRING
|
case 1: /* matched "port" */
|
||||||
case 2:
|
len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
|
||||||
if(!byte_diff(data,2,"ip")) {
|
if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM;
|
||||||
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 );
|
port = htons( tmp ); OT_SETPORT( &peer, &port );
|
||||||
} else if( !byte_diff( data, 4, "left" ) ) {
|
break;
|
||||||
if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
|
case 2: /* matched "left" */
|
||||||
if( scan_fixed_int( data, len, &tmp ) ) tmp = 0;
|
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;
|
if( !tmp ) OT_PEERFLAG( &peer ) |= PEER_FLAG_SEEDING;
|
||||||
} else
|
|
||||||
scan_urlencoded_skipvalue( &c );
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 3: /* matched "event" */
|
||||||
if( byte_diff( data, 5, "event" ) )
|
switch( scan_find_keywords( keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) {
|
||||||
scan_urlencoded_skipvalue( &c );
|
case -1: HTTPERROR_400_PARAM;
|
||||||
else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
|
case 1: /* matched "completed" */
|
||||||
case -1:
|
OT_PEERFLAG( &peer ) |= PEER_FLAG_COMPLETED;
|
||||||
HTTPERROR_400_PARAM;
|
|
||||||
case 7:
|
|
||||||
if( !byte_diff( data, 7, "stopped" ) ) OT_PEERFLAG( &peer ) |= PEER_FLAG_STOPPED;
|
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 2: /* matched "stopped" */
|
||||||
if( !byte_diff( data, 9, "completed" ) ) OT_PEERFLAG( &peer ) |= PEER_FLAG_COMPLETED;
|
OT_PEERFLAG( &peer ) |= PEER_FLAG_STOPPED;
|
||||||
default: /* Fall through intended */
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 4: /* matched "numwant" */
|
||||||
if(!byte_diff(data,7,"numwant")) {
|
len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
|
||||||
len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &numwant ) ) HTTPERROR_400_PARAM;
|
||||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) HTTPERROR_400_PARAM;
|
|
||||||
if( numwant < 0 ) numwant = 50;
|
if( numwant < 0 ) numwant = 50;
|
||||||
if( numwant > 200 ) numwant = 200;
|
if( numwant > 200 ) numwant = 200;
|
||||||
} else if(!byte_diff(data,7,"compact")) {
|
break;
|
||||||
len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
case 5: /* matched "compact" */
|
||||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) HTTPERROR_400_PARAM;
|
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;
|
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 );
|
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 6: /* matched "info_hash" */
|
||||||
if(byte_diff(data,9,"info_hash")) {
|
if( hash ) HTTPERROR_400_DOUBLEHASH;
|
||||||
scan_urlencoded_skipvalue( &c );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* ignore this, when we have less than 20 bytes */
|
/* ignore this, when we have less than 20 bytes */
|
||||||
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
|
if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
|
||||||
hash = (ot_hash*)data;
|
hash = (ot_hash*)write_ptr;
|
||||||
break;
|
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 */
|
/* Scanned whole query string */
|
||||||
if( !hash )
|
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 )
|
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
|
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);
|
stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, ws->reply_size);
|
||||||
return len;
|
return ws->reply_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t http_handle_request( const int64 client_socket, char *data, size_t recv_length ) {
|
ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws ) {
|
||||||
char *c, *recv_header=data;
|
ssize_t reply_off, len;
|
||||||
ssize_t reply_size = 0, reply_off, len;
|
char *read_ptr = ws->request, *write_ptr;
|
||||||
|
|
||||||
#ifdef _DEBUG_HTTPERROR
|
#ifdef _DEBUG_HTTPERROR
|
||||||
if( recv_length >= sizeof( debug_request ) )
|
reply_off = ws->request_size;
|
||||||
recv_length = sizeof( debug_request) - 1;
|
if( ws->request_size >= (ssize_t)ws->debugbuf_size )
|
||||||
memmove( debug_request, recv_header, recv_length );
|
reply_off = ws->debugbuf_size - 1;
|
||||||
debug_request[ recv_length ] = 0;
|
memmove( ws->debugbuf, ws->request, reply_off );
|
||||||
|
ws->debugbuf[ reply_off ] = 0;
|
||||||
#endif
|
#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 */
|
/* 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 '/' */
|
/* Skip leading '/' */
|
||||||
for( c = data+4; *c == '/'; ++c);
|
for( read_ptr+=4; *read_ptr == '/'; ++read_ptr);
|
||||||
|
|
||||||
/* Try to parse the request.
|
/* Try to parse the request.
|
||||||
In reality we abandoned requiring the url to be correct. This now
|
In reality we abandoned requiring the url to be correct. This now
|
||||||
only decodes url encoded characters, we check for announces and
|
only decodes url encoded characters, we check for announces and
|
||||||
scrapes by looking for "a*" or "sc" */
|
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 parsing returned an error, leave with not found */
|
||||||
if( g_redirecturl && ( len == -2 ) ) HTTPERROR_302;
|
if( g_redirecturl && ( len == -2 ) ) HTTPERROR_302;
|
||||||
if( len <= 0 ) HTTPERROR_404;
|
if( len <= 0 ) HTTPERROR_404;
|
||||||
|
|
||||||
/* This is the hardcore match for announce*/
|
/* This is the hardcore match for announce*/
|
||||||
if( ( *data == 'a' ) || ( *data == '?' ) )
|
if( ( *write_ptr == 'a' ) || ( *write_ptr == '?' ) )
|
||||||
reply_size = http_handle_announce( client_socket, c );
|
http_handle_announce( client_socket, ws, read_ptr );
|
||||||
#ifdef WANT_FULLSCRAPE
|
#ifdef WANT_FULLSCRAPE
|
||||||
else if( !byte_diff( data, 12, "scrape HTTP/" ) )
|
else if( !memcmp( write_ptr, "scrape HTTP/", 12 ) )
|
||||||
reply_size = http_handle_fullscrape( client_socket, recv_header, recv_length );
|
http_handle_fullscrape( client_socket, ws );
|
||||||
#endif
|
#endif
|
||||||
/* This is the hardcore match for scrape */
|
/* This is the hardcore match for scrape */
|
||||||
else if( !byte_diff( data, 2, "sc" ) )
|
else if( !memcmp( write_ptr, "sc", 2 ) )
|
||||||
reply_size = http_handle_scrape( client_socket, c );
|
http_handle_scrape( client_socket, ws, read_ptr );
|
||||||
/* All the rest is matched the standard way */
|
/* All the rest is matched the standard way */
|
||||||
else switch( len ) {
|
else if( !memcmp( write_ptr, "stats", 5) )
|
||||||
case 5: /* stats ? */
|
http_handle_stats( client_socket, ws, read_ptr );
|
||||||
if( byte_diff( data, 5, "stats") ) HTTPERROR_404;
|
else
|
||||||
reply_size = http_handle_stats( client_socket, c, recv_header, recv_length );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
HTTPERROR_404;
|
HTTPERROR_404;
|
||||||
}
|
|
||||||
|
|
||||||
/* If routines handled sending themselves, just return */
|
/* 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 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.
|
/* 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
|
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
|
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
|
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
|
/* 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 */
|
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 */
|
/* 3. Finally we join both blocks neatly */
|
||||||
static_outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
|
ws->outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
|
||||||
|
|
||||||
http_senddata( client_socket, static_outbuf + reply_off, reply_size );
|
http_senddata( client_socket, ws );
|
||||||
return reply_size;
|
return ws->reply_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *g_version_http_c = "$Source$: $Revision$\n";
|
const char *g_version_http_c = "$Source$: $Revision$\n";
|
||||||
|
@ -23,8 +23,8 @@ struct http_data {
|
|||||||
STRUCT_HTTP_FLAG flag;
|
STRUCT_HTTP_FLAG flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
ssize_t http_handle_request( const int64 s, char *data, size_t l );
|
ssize_t http_handle_request( const int64 s, struct ot_workstruct *ws );
|
||||||
ssize_t http_sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector );
|
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, int code );
|
ssize_t http_issue_error( const int64 s, struct ot_workstruct *ws, int code );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -400,9 +400,6 @@ static void * livesync_worker( void * args ) {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle outstanding requests */
|
|
||||||
livesync_ticker( );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Never returns. */
|
/* Never returns. */
|
||||||
|
29
ot_udp.c
29
ot_udp.c
@ -17,9 +17,6 @@
|
|||||||
#include "ot_udp.h"
|
#include "ot_udp.h"
|
||||||
#include "ot_stats.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 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 ) {
|
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 */
|
/* 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_peer peer;
|
||||||
ot_hash *hash = NULL;
|
ot_hash *hash = NULL;
|
||||||
char remoteip[4];
|
char remoteip[4];
|
||||||
uint32_t *inpacket = (uint32_t*)static_inbuf;
|
uint32_t *inpacket = (uint32_t*)ws->inbuf;
|
||||||
uint32_t *outpacket = (uint32_t*)static_outbuf;
|
uint32_t *outpacket = (uint32_t*)ws->outbuf;
|
||||||
uint32_t numwant, left, event;
|
uint32_t numwant, left, event;
|
||||||
uint16_t port, remoteport;
|
uint16_t port, remoteport;
|
||||||
size_t r, r_out;
|
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_ACCEPT, FLAG_UDP, ntohl(*(uint32_t*)remoteip) );
|
||||||
stats_issue_event( EVENT_READ, FLAG_UDP, r );
|
stats_issue_event( EVENT_READ, FLAG_UDP, r );
|
||||||
@ -58,8 +55,6 @@ void handle_udp4( int64 serversocket ) {
|
|||||||
if( r < 16 )
|
if( r < 16 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* fprintf( stderr, "UDP Connection id: %16llX\n", *(uint64_t*)inpacket ); */
|
|
||||||
|
|
||||||
switch( ntohl( inpacket[2] ) ) {
|
switch( ntohl( inpacket[2] ) ) {
|
||||||
case 0: /* This is a connect action */
|
case 0: /* This is a connect action */
|
||||||
/* look for udp bittorrent magic id */
|
/* look for udp bittorrent magic id */
|
||||||
@ -70,7 +65,7 @@ void handle_udp4( int64 serversocket ) {
|
|||||||
outpacket[1] = inpacket[3];
|
outpacket[1] = inpacket[3];
|
||||||
udp_make_connectionid( outpacket + 2, remoteip );
|
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 );
|
stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 );
|
||||||
break;
|
break;
|
||||||
case 1: /* This is an announce action */
|
case 1: /* This is an announce action */
|
||||||
@ -88,8 +83,8 @@ void handle_udp4( int64 serversocket ) {
|
|||||||
if (numwant > 200) numwant = 200;
|
if (numwant > 200) numwant = 200;
|
||||||
|
|
||||||
event = ntohl( inpacket[80/4] );
|
event = ntohl( inpacket[80/4] );
|
||||||
port = *(uint16_t*)( static_inbuf + 96 );
|
port = *(uint16_t*)( ((char*)inpacket) + 96 );
|
||||||
hash = (ot_hash*)( static_inbuf + 16 );
|
hash = (ot_hash*)( ((char*)inpacket) + 16 );
|
||||||
|
|
||||||
OT_SETIP( &peer, remoteip );
|
OT_SETIP( &peer, remoteip );
|
||||||
OT_SETPORT( &peer, &port );
|
OT_SETPORT( &peer, &port );
|
||||||
@ -108,11 +103,11 @@ void handle_udp4( int64 serversocket ) {
|
|||||||
outpacket[1] = inpacket[12/4];
|
outpacket[1] = inpacket[12/4];
|
||||||
|
|
||||||
if( OT_PEERFLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */
|
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
|
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 );
|
stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, r );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -124,9 +119,9 @@ void handle_udp4( int64 serversocket ) {
|
|||||||
outpacket[1] = inpacket[12/4];
|
outpacket[1] = inpacket[12/4];
|
||||||
|
|
||||||
for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ )
|
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 );
|
stats_issue_event( EVENT_SCRAPE, FLAG_UDP, r );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
2
ot_udp.h
2
ot_udp.h
@ -6,6 +6,6 @@
|
|||||||
#ifndef __OT_UDP_H__
|
#ifndef __OT_UDP_H__
|
||||||
#define __OT_UDP_H__
|
#define __OT_UDP_H__
|
||||||
|
|
||||||
void handle_udp4( int64 serversocket );
|
void handle_udp4( int64 serversocket, struct ot_workstruct *ws );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
/* Libwofat */
|
/* Libwofat */
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
|
/* System */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* Idea is to do a in place replacement or guarantee at least
|
/* Idea is to do a in place replacement or guarantee at least
|
||||||
strlen( string ) bytes in deststring
|
strlen( string ) bytes in deststring
|
||||||
watch http://www.ietf.org/rfc/rfc2396.txt
|
watch http://www.ietf.org/rfc/rfc2396.txt
|
||||||
@ -64,6 +67,22 @@ void scan_urlencoded_skipvalue( char **string ) {
|
|||||||
*string = (char*)s;
|
*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) {
|
ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags) {
|
||||||
const unsigned char* s=*(const unsigned char**) string;
|
const unsigned char* s=*(const unsigned char**) string;
|
||||||
unsigned char *d = (unsigned char*)deststring;
|
unsigned char *d = (unsigned char*)deststring;
|
||||||
@ -95,9 +114,7 @@ ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_F
|
|||||||
--s;
|
--s;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
/* XXX to help us parse path?param=value?param=value?... sent by µTorrent 1600
|
if( flags != SCAN_PATH ) return -1;
|
||||||
do not return an error but silently terminate
|
|
||||||
if( flags != SCAN_PATH ) return -1; */
|
|
||||||
break;
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
if( flags != SCAN_SEARCHPATH_PARAM ) return -1;
|
if( flags != SCAN_SEARCHPATH_PARAM ) return -1;
|
||||||
|
@ -8,6 +8,11 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *key;
|
||||||
|
int value;
|
||||||
|
} ot_keywords;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SCAN_PATH = 1,
|
SCAN_PATH = 1,
|
||||||
SCAN_SEARCHPATH_PARAM = 2,
|
SCAN_SEARCHPATH_PARAM = 2,
|
||||||
@ -21,9 +26,20 @@ typedef enum {
|
|||||||
flags determines, what to parse
|
flags determines, what to parse
|
||||||
returns number of valid converted characters in deststring
|
returns number of valid converted characters in deststring
|
||||||
or -1 for parse error
|
or -1 for parse error
|
||||||
|
or -2 for terminator found
|
||||||
*/
|
*/
|
||||||
ssize_t scan_urlencoded_query(char **string, char *deststring, SCAN_SEARCHPATH_FLAG flags);
|
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
|
/* string in: pointer to value of a param=value pair to skip
|
||||||
out: pointer to next scan position on return
|
out: pointer to next scan position on return
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +96,31 @@ struct ot_peerlist {
|
|||||||
};
|
};
|
||||||
#define OT_PEERLIST_HASBUCKETS(peer_list) ((peer_list) && ((peer_list)->peers.size > (peer_list)->peers.space))
|
#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
|
Exported functions
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user