diff options
| author | erdgeist <> | 2009-01-05 18:05:39 +0000 |
|---|---|---|
| committer | erdgeist <> | 2009-01-05 18:05:39 +0000 |
| commit | 779d6c235ff8fe5284fd10dc82a9b99e7fa38d06 (patch) | |
| tree | 043369d2a98a45b902e5d0968e28d78c1771b143 /opentracker.c | |
| parent | 8bdc0d73f6f0bcaf83b7fb3d39e79e8fa4e6050d (diff) | |
* 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
Diffstat (limited to 'opentracker.c')
| -rw-r--r-- | opentracker.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/opentracker.c b/opentracker.c index bce5be0..8a4126c 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -41,9 +41,6 @@ volatile int g_opentracker_running = 1; | |||
| 41 | 41 | ||
| 42 | static char * g_serverdir = NULL; | 42 | static char * g_serverdir = NULL; |
| 43 | 43 | ||
| 44 | /* To always have space for error messages ;) */ | ||
| 45 | static char static_inbuf[8192]; | ||
| 46 | |||
| 47 | static void panic( const char *routine ) { | 44 | static void panic( const char *routine ) { |
| 48 | fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); | 45 | fprintf( stderr, "%s: %s\n", routine, strerror(errno) ); |
| 49 | exit( 111 ); | 46 | exit( 111 ); |
| @@ -107,37 +104,44 @@ static void handle_dead( const int64 socket ) { | |||
| 107 | io_close( socket ); | 104 | io_close( socket ); |
| 108 | } | 105 | } |
| 109 | 106 | ||
| 110 | static ssize_t handle_read( const int64 clientsocket ) { | 107 | static ssize_t handle_read( const int64 clientsocket, struct ot_workstruct *ws ) { |
| 111 | struct http_data* h = io_getcookie( clientsocket ); | 108 | struct http_data* h = io_getcookie( clientsocket ); |
| 112 | ssize_t l; | 109 | ssize_t l; |
| 113 | 110 | ||
| 114 | if( ( l = io_tryread( clientsocket, static_inbuf, sizeof static_inbuf ) ) <= 0 ) { | 111 | if( ( l = io_tryread( clientsocket, ws->inbuf, ws->inbuf_size ) ) <= 0 ) { |
| 115 | handle_dead( clientsocket ); | 112 | handle_dead( clientsocket ); |
| 116 | return 0; | 113 | return 0; |
| 117 | } | 114 | } |
| 118 | 115 | ||
| 119 | /* If we get the whole request in one packet, handle it without copying */ | 116 | /* If we get the whole request in one packet, handle it without copying */ |
| 120 | if( !array_start( &h->data.request ) ) { | 117 | if( !array_start( &h->data.request ) ) { |
| 121 | if( memchr( static_inbuf, '\n', l ) ) | 118 | if( memchr( ws->inbuf, '\n', l ) ) { |
| 122 | return http_handle_request( clientsocket, static_inbuf, l ); | 119 | ws->request = ws->inbuf; |
| 120 | ws->request_size = l; | ||
| 121 | return http_handle_request( clientsocket, ws ); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* ... else take a copy */ | ||
| 123 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 125 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
| 124 | array_catb( &h->data.request, static_inbuf, l ); | 126 | array_catb( &h->data.request, ws->inbuf, l ); |
| 125 | return 0; | 127 | return 0; |
| 126 | } | 128 | } |
| 127 | 129 | ||
| 128 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 130 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
| 129 | array_catb( &h->data.request, static_inbuf, l ); | 131 | array_catb( &h->data.request, ws->inbuf, l ); |
| 130 | 132 | ||
| 131 | if( array_failed( &h->data.request ) ) | 133 | if( array_failed( &h->data.request ) ) |
| 132 | return http_issue_error( clientsocket, CODE_HTTPERROR_500 ); | 134 | return http_issue_error( clientsocket, ws, CODE_HTTPERROR_500 ); |
| 133 | 135 | ||
| 134 | if( array_bytes( &h->data.request ) > 8192 ) | 136 | if( array_bytes( &h->data.request ) > 8192 ) |
| 135 | return http_issue_error( clientsocket, CODE_HTTPERROR_500 ); | 137 | return http_issue_error( clientsocket, ws, CODE_HTTPERROR_500 ); |
| 136 | 138 | ||
| 137 | if( memchr( array_start( &h->data.request ), '\n', array_bytes( &h->data.request ) ) ) | 139 | if( !memchr( array_start( &h->data.request ), '\n', array_bytes( &h->data.request ) ) ) |
| 138 | return http_handle_request( clientsocket, array_start( &h->data.request ), array_bytes( &h->data.request ) ); | 140 | return 0; |
| 139 | 141 | ||
| 140 | return 0; | 142 | ws->request = array_start( &h->data.request ); |
| 143 | ws->request_size = array_bytes( &h->data.request ); | ||
| 144 | return http_handle_request( clientsocket, ws ); | ||
| 141 | } | 145 | } |
| 142 | 146 | ||
| 143 | static void handle_write( const int64 clientsocket ) { | 147 | static void handle_write( const int64 clientsocket ) { |
| @@ -183,9 +187,25 @@ static void handle_accept( const int64 serversocket ) { | |||
| 183 | } | 187 | } |
| 184 | 188 | ||
| 185 | static void server_mainloop( ) { | 189 | static void server_mainloop( ) { |
| 186 | time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; | 190 | struct ot_workstruct ws; |
| 187 | struct iovec *iovector; | 191 | time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; |
| 188 | int iovec_entries; | 192 | struct iovec *iovector; |
| 193 | int iovec_entries; | ||
| 194 | |||
| 195 | /* Initialize our "thread local storage" */ | ||
| 196 | ws.inbuf = malloc( THREAD_INBUF_SIZE ); | ||
| 197 | ws.outbuf = malloc( THREAD_OUTBUF_SIZE ); | ||
| 198 | #ifdef _DEBUG_HTTPERROR | ||
| 199 | ws.debugbuf= malloc( THREAD_INBUF_SIZE ); | ||
| 200 | #endif | ||
| 201 | if( !ws.inbuf || !ws.outbuf ) | ||
| 202 | panic( "Initializing worker failed" ); | ||
| 203 | |||
| 204 | ws.inbuf_size = THREAD_INBUF_SIZE; | ||
| 205 | ws.outbuf_size = THREAD_OUTBUF_SIZE; | ||
| 206 | #ifdef _DEBUG_HTTPERROR | ||
| 207 | ws.debugbuf_size= THREAD_INBUF_SIZE; | ||
| 208 | #endif | ||
| 189 | 209 | ||
| 190 | for( ; ; ) { | 210 | for( ; ; ) { |
| 191 | int64 i; | 211 | int64 i; |
| @@ -197,13 +217,13 @@ static void server_mainloop( ) { | |||
| 197 | if( (intptr_t)cookie == FLAG_TCP ) | 217 | if( (intptr_t)cookie == FLAG_TCP ) |
| 198 | handle_accept( i ); | 218 | handle_accept( i ); |
| 199 | else if( (intptr_t)cookie == FLAG_UDP ) | 219 | else if( (intptr_t)cookie == FLAG_UDP ) |
| 200 | handle_udp4( i ); | 220 | handle_udp4( i, &ws ); |
| 201 | else | 221 | else |
| 202 | handle_read( i ); | 222 | handle_read( i, &ws ); |
| 203 | } | 223 | } |
| 204 | 224 | ||
| 205 | while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 ) | 225 | while( ( i = mutex_workqueue_popresult( &iovec_entries, &iovector ) ) != -1 ) |
| 206 | http_sendiovecdata( i, iovec_entries, iovector ); | 226 | http_sendiovecdata( i, &ws, iovec_entries, iovector ); |
| 207 | 227 | ||
| 208 | while( ( i = io_canwrite( ) ) != -1 ) | 228 | while( ( i = io_canwrite( ) ) != -1 ) |
| 209 | handle_write( i ); | 229 | handle_write( i ); |
| @@ -431,7 +451,12 @@ while( scanon ) { | |||
| 431 | break; | 451 | break; |
| 432 | case 'f': bound += parse_configfile( optarg ); break; | 452 | case 'f': bound += parse_configfile( optarg ); break; |
| 433 | case 'h': help( argv[0] ); exit( 0 ); | 453 | case 'h': help( argv[0] ); exit( 0 ); |
| 434 | case 'v': stats_return_tracker_version( static_inbuf ); fputs( static_inbuf, stderr ); exit( 0 ); | 454 | case 'v': { |
| 455 | char buffer[8192]; | ||
| 456 | stats_return_tracker_version( buffer ); | ||
| 457 | fputs( buffer, stderr ); | ||
| 458 | exit( 0 ); | ||
| 459 | } | ||
| 435 | default: | 460 | default: |
| 436 | case '?': usage( argv[0] ); exit( 1 ); | 461 | case '?': usage( argv[0] ); exit( 1 ); |
| 437 | } | 462 | } |
