summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
authorerdgeist <>2009-01-05 18:05:39 +0000
committererdgeist <>2009-01-05 18:05:39 +0000
commit779d6c235ff8fe5284fd10dc82a9b99e7fa38d06 (patch)
tree043369d2a98a45b902e5d0968e28d78c1771b143 /opentracker.c
parent8bdc0d73f6f0bcaf83b7fb3d39e79e8fa4e6050d (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.c67
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
42static char * g_serverdir = NULL; 42static char * g_serverdir = NULL;
43 43
44/* To always have space for error messages ;) */
45static char static_inbuf[8192];
46
47static void panic( const char *routine ) { 44static 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
110static ssize_t handle_read( const int64 clientsocket ) { 107static 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
143static void handle_write( const int64 clientsocket ) { 147static void handle_write( const int64 clientsocket ) {
@@ -183,9 +187,25 @@ static void handle_accept( const int64 serversocket ) {
183} 187}
184 188
185static void server_mainloop( ) { 189static 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 }