summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c140
1 files changed, 70 insertions, 70 deletions
diff --git a/ot_http.c b/ot_http.c
index 08ecc13..3ccdb84 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -35,50 +35,50 @@ enum {
35 SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32, 35 SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING = 32,
36 SUCCESS_HTTP_SIZE_OFF = 17 }; 36 SUCCESS_HTTP_SIZE_OFF = 17 };
37 37
38static void http_senddata( const int64 client_socket, struct ot_workstruct *ws ) { 38static void http_senddata( const int64 sock, struct ot_workstruct *ws ) {
39 struct http_data *h = io_getcookie( client_socket ); 39 struct http_data *cookie = io_getcookie( sock );
40 ssize_t written_size; 40 ssize_t written_size;
41 41
42 /* whoever sends data is not interested in its input-array */ 42 /* whoever sends data is not interested in its input-array */
43 if( h && ( h->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) ) { 43 if( cookie && ( cookie->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) ) {
44 h->flag &= ~STRUCT_HTTP_FLAG_ARRAY_USED; 44 cookie->flag &= ~STRUCT_HTTP_FLAG_ARRAY_USED;
45 array_reset( &h->data.request ); 45 array_reset( &cookie->data.request );
46 } 46 }
47 47
48 written_size = write( client_socket, ws->reply, ws->reply_size ); 48 written_size = write( sock, ws->reply, ws->reply_size );
49 if( ( written_size < 0 ) || ( written_size == ws->reply_size ) ) { 49 if( ( written_size < 0 ) || ( written_size == ws->reply_size ) ) {
50 free( h ); io_close( client_socket ); 50 free( cookie ); io_close( sock );
51 } else { 51 } else {
52 char * outbuf; 52 char * outbuf;
53 tai6464 t; 53 tai6464 t;
54 54
55 if( !h ) return; 55 if( !cookie ) return;
56 if( !( outbuf = malloc( ws->reply_size - written_size ) ) ) { 56 if( !( outbuf = malloc( ws->reply_size - written_size ) ) ) {
57 free(h); io_close( client_socket ); 57 free(cookie); io_close( sock );
58 return; 58 return;
59 } 59 }
60 60
61 iob_reset( &h->data.batch ); 61 iob_reset( &cookie->data.batch );
62 memcpy( outbuf, ws->reply + written_size, ws->reply_size - written_size ); 62 memcpy( outbuf, ws->reply + written_size, ws->reply_size - written_size );
63 iob_addbuf_free( &h->data.batch, outbuf, ws->reply_size - written_size ); 63 iob_addbuf_free( &cookie->data.batch, outbuf, ws->reply_size - written_size );
64 h->flag |= STRUCT_HTTP_FLAG_IOB_USED; 64 cookie->flag |= STRUCT_HTTP_FLAG_IOB_USED;
65 65
66 /* writeable short data sockets just have a tcp timeout */ 66 /* writeable short data sockets just have a tcp timeout */
67 taia_uint( &t, 0 ); io_timeout( client_socket, t ); 67 taia_uint( &t, 0 ); io_timeout( sock, t );
68 io_dontwantread( client_socket ); 68 io_dontwantread( sock );
69 io_wantwrite( client_socket ); 69 io_wantwrite( sock );
70 } 70 }
71} 71}
72 72
73#define HTTPERROR_302 return http_issue_error( client_socket, ws, CODE_HTTPERROR_302 ) 73#define HTTPERROR_302 return http_issue_error( sock, ws, CODE_HTTPERROR_302 )
74#define HTTPERROR_400 return http_issue_error( client_socket, ws, CODE_HTTPERROR_400 ) 74#define HTTPERROR_400 return http_issue_error( sock, ws, CODE_HTTPERROR_400 )
75#define HTTPERROR_400_PARAM return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM ) 75#define HTTPERROR_400_PARAM return http_issue_error( sock, ws, CODE_HTTPERROR_400_PARAM )
76#define HTTPERROR_400_COMPACT return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_COMPACT ) 76#define HTTPERROR_400_COMPACT return http_issue_error( sock, ws, CODE_HTTPERROR_400_COMPACT )
77#define HTTPERROR_400_DOUBLEHASH return http_issue_error( client_socket, ws, CODE_HTTPERROR_400_PARAM ) 77#define HTTPERROR_400_DOUBLEHASH return http_issue_error( sock, ws, CODE_HTTPERROR_400_PARAM )
78#define HTTPERROR_403_IP return http_issue_error( client_socket, ws, CODE_HTTPERROR_403_IP ) 78#define HTTPERROR_403_IP return http_issue_error( sock, ws, CODE_HTTPERROR_403_IP )
79#define HTTPERROR_404 return http_issue_error( client_socket, ws, CODE_HTTPERROR_404 ) 79#define HTTPERROR_404 return http_issue_error( sock, ws, CODE_HTTPERROR_404 )
80#define HTTPERROR_500 return http_issue_error( client_socket, ws, CODE_HTTPERROR_500 ) 80#define HTTPERROR_500 return http_issue_error( sock, ws, CODE_HTTPERROR_500 )
81ssize_t http_issue_error( const int64 client_socket, struct ot_workstruct *ws, int code ) { 81ssize_t http_issue_error( const int64 sock, struct ot_workstruct *ws, int code ) {
82 char *error_code[] = { "302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", 82 char *error_code[] = { "302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request",
83 "403 Access Denied", "404 Not Found", "500 Internal Server Error" }; 83 "403 Access Denied", "404 Not Found", "500 Internal Server Error" };
84 char *title = error_code[code]; 84 char *title = error_code[code];
@@ -93,32 +93,32 @@ ssize_t http_issue_error( const int64 client_socket, struct ot_workstruct *ws, i
93 fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf ); 93 fprintf( stderr, "DEBUG: invalid request was: %s\n", ws->debugbuf );
94#endif 94#endif
95 stats_issue_event( EVENT_FAILED, FLAG_TCP, code ); 95 stats_issue_event( EVENT_FAILED, FLAG_TCP, code );
96 http_senddata( client_socket, ws ); 96 http_senddata( sock, ws );
97 return ws->reply_size = -2; 97 return ws->reply_size = -2;
98} 98}
99 99
100ssize_t http_sendiovecdata( const int64 client_socket, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector ) { 100ssize_t http_sendiovecdata( const int64 sock, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector ) {
101 struct http_data *h = io_getcookie( client_socket ); 101 struct http_data *cookie = io_getcookie( sock );
102 char *header; 102 char *header;
103 int i; 103 int i;
104 size_t header_size, size = iovec_length( &iovec_entries, &iovector ); 104 size_t header_size, size = iovec_length( &iovec_entries, &iovector );
105 tai6464 t; 105 tai6464 t;
106 106
107 /* No cookie? Bad socket. Leave. */ 107 /* No cookie? Bad socket. Leave. */
108 if( !h ) { 108 if( !cookie ) {
109 iovec_free( &iovec_entries, &iovector ); 109 iovec_free( &iovec_entries, &iovector );
110 HTTPERROR_500; 110 HTTPERROR_500;
111 } 111 }
112 112
113 /* If this socket collected request in a buffer, 113 /* If this socket collected request in a buffer,
114 free it now */ 114 free it now */
115 if( h->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) { 115 if( cookie->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) {
116 h->flag &= ~STRUCT_HTTP_FLAG_ARRAY_USED; 116 cookie->flag &= ~STRUCT_HTTP_FLAG_ARRAY_USED;
117 array_reset( &h->data.request ); 117 array_reset( &cookie->data.request );
118 } 118 }
119 119
120 /* If we came here, wait for the answer is over */ 120 /* If we came here, wait for the answer is over */
121 h->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; 121 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK;
122 122
123 /* Our answers never are 0 vectors. Return an error. */ 123 /* Our answers never are 0 vectors. Return an error. */
124 if( !iovec_entries ) { 124 if( !iovec_entries ) {
@@ -132,32 +132,32 @@ ssize_t http_sendiovecdata( const int64 client_socket, struct ot_workstruct *ws,
132 HTTPERROR_500; 132 HTTPERROR_500;
133 } 133 }
134 134
135 if( h->flag & STRUCT_HTTP_FLAG_GZIP ) 135 if( cookie->flag & STRUCT_HTTP_FLAG_GZIP )
136 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: gzip\r\nContent-Length: %zd\r\n\r\n", size ); 136 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: gzip\r\nContent-Length: %zd\r\n\r\n", size );
137 else if( h->flag & STRUCT_HTTP_FLAG_BZIP2 ) 137 else if( cookie->flag & STRUCT_HTTP_FLAG_BZIP2 )
138 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: bzip2\r\nContent-Length: %zd\r\n\r\n", size ); 138 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: bzip2\r\nContent-Length: %zd\r\n\r\n", size );
139 else 139 else
140 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size ); 140 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size );
141 141
142 iob_reset( &h->data.batch ); 142 iob_reset( &cookie->data.batch );
143 iob_addbuf_free( &h->data.batch, header, header_size ); 143 iob_addbuf_free( &cookie->data.batch, header, header_size );
144 144
145 /* Will move to ot_iovec.c */ 145 /* Will move to ot_iovec.c */
146 for( i=0; i<iovec_entries; ++i ) 146 for( i=0; i<iovec_entries; ++i )
147 iob_addbuf_munmap( &h->data.batch, iovector[i].iov_base, iovector[i].iov_len ); 147 iob_addbuf_munmap( &cookie->data.batch, iovector[i].iov_base, iovector[i].iov_len );
148 free( iovector ); 148 free( iovector );
149 149
150 h->flag |= STRUCT_HTTP_FLAG_IOB_USED; 150 cookie->flag |= STRUCT_HTTP_FLAG_IOB_USED;
151 151
152 /* writeable sockets timeout after 10 minutes */ 152 /* writeable sockets timeout after 10 minutes */
153 taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); 153 taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND );
154 io_timeout( client_socket, t ); 154 io_timeout( sock, t );
155 io_dontwantread( client_socket ); 155 io_dontwantread( sock );
156 io_wantwrite( client_socket ); 156 io_wantwrite( sock );
157 return 0; 157 return 0;
158} 158}
159 159
160static ssize_t http_handle_stats( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { 160static ssize_t http_handle_stats( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) {
161static const ot_keywords keywords_main[] = 161static const ot_keywords keywords_main[] =
162 { { "mode", 1 }, {"format", 2 }, { NULL, -3 } }; 162 { { "mode", 1 }, {"format", 2 }, { NULL, -3 } };
163static const ot_keywords keywords_mode[] = 163static const ot_keywords keywords_mode[] =
@@ -173,9 +173,9 @@ static const ot_keywords keywords_format[] =
173 int mode = TASK_STATS_PEERS, scanon = 1, format = 0; 173 int mode = TASK_STATS_PEERS, scanon = 1, format = 0;
174 174
175#ifdef WANT_RESTRICT_STATS 175#ifdef WANT_RESTRICT_STATS
176 struct http_data *h = io_getcookie( client_socket ); 176 struct http_data *cookie = io_getcookie( sock );
177 177
178 if( !h || !accesslist_isblessed( h->ip, OT_PERMISSION_MAY_STAT ) ) 178 if( !cookie || !accesslist_isblessed( cookie->ip, OT_PERMISSION_MAY_STAT ) )
179 HTTPERROR_403_IP; 179 HTTPERROR_403_IP;
180#endif 180#endif
181 181
@@ -195,22 +195,22 @@ static const ot_keywords keywords_format[] =
195 195
196#ifdef WANT_FULLSCRAPE 196#ifdef WANT_FULLSCRAPE
197 if( mode == TASK_STATS_TPB ) { 197 if( mode == TASK_STATS_TPB ) {
198 struct http_data* h = io_getcookie( client_socket ); 198 struct http_data* cookie = io_getcookie( sock );
199 tai6464 t; 199 tai6464 t;
200#ifdef WANT_COMPRESSION_GZIP 200#ifdef WANT_COMPRESSION_GZIP
201 ws->request[ws->request_size] = 0; 201 ws->request[ws->request_size] = 0;
202 if( strstr( read_ptr - 1, "gzip" ) ) { 202 if( strstr( read_ptr - 1, "gzip" ) ) {
203 h->flag |= STRUCT_HTTP_FLAG_GZIP; 203 cookie->flag |= STRUCT_HTTP_FLAG_GZIP;
204 format |= TASK_FLAG_GZIP; 204 format |= TASK_FLAG_GZIP;
205 } 205 }
206#endif 206#endif
207 /* Pass this task to the worker thread */ 207 /* Pass this task to the worker thread */
208 h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; 208 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK;
209 209
210 /* Clients waiting for us should not easily timeout */ 210 /* Clients waiting for us should not easily timeout */
211 taia_uint( &t, 0 ); io_timeout( client_socket, t ); 211 taia_uint( &t, 0 ); io_timeout( sock, t );
212 fullscrape_deliver( client_socket, format ); 212 fullscrape_deliver( sock, format );
213 io_dontwantread( client_socket ); 213 io_dontwantread( sock );
214 return ws->reply_size = -2; 214 return ws->reply_size = -2;
215 } 215 }
216#endif 216#endif
@@ -219,8 +219,8 @@ static const ot_keywords keywords_format[] =
219 if( ( mode & TASK_CLASS_MASK ) == TASK_STATS ) { 219 if( ( mode & TASK_CLASS_MASK ) == TASK_STATS ) {
220 tai6464 t; 220 tai6464 t;
221 /* Complex stats also include expensive memory debugging tools */ 221 /* Complex stats also include expensive memory debugging tools */
222 taia_uint( &t, 0 ); io_timeout( client_socket, t ); 222 taia_uint( &t, 0 ); io_timeout( sock, t );
223 stats_deliver( client_socket, mode ); 223 stats_deliver( sock, mode );
224 return ws->reply_size = -2; 224 return ws->reply_size = -2;
225 } 225 }
226 226
@@ -231,36 +231,36 @@ static const ot_keywords keywords_format[] =
231} 231}
232 232
233#ifdef WANT_FULLSCRAPE 233#ifdef WANT_FULLSCRAPE
234static ssize_t http_handle_fullscrape( const int64 client_socket, struct ot_workstruct *ws ) { 234static ssize_t http_handle_fullscrape( const int64 sock, struct ot_workstruct *ws ) {
235 struct http_data* h = io_getcookie( client_socket ); 235 struct http_data* cookie = io_getcookie( sock );
236 int format = 0; 236 int format = 0;
237 tai6464 t; 237 tai6464 t;
238 238
239#ifdef WANT_COMPRESSION_GZIP 239#ifdef WANT_COMPRESSION_GZIP
240 ws->request[ws->request_size-1] = 0; 240 ws->request[ws->request_size-1] = 0;
241 if( strstr( ws->request, "gzip" ) ) { 241 if( strstr( ws->request, "gzip" ) ) {
242 h->flag |= STRUCT_HTTP_FLAG_GZIP; 242 cookie->flag |= STRUCT_HTTP_FLAG_GZIP;
243 format = TASK_FLAG_GZIP; 243 format = TASK_FLAG_GZIP;
244 stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, 0, (uintptr_t)h->ip ); 244 stats_issue_event( EVENT_FULLSCRAPE_REQUEST_GZIP, 0, (uintptr_t)cookie->ip );
245 } else 245 } else
246#endif 246#endif
247 stats_issue_event( EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)h->ip ); 247 stats_issue_event( EVENT_FULLSCRAPE_REQUEST, 0, (uintptr_t)cookie->ip );
248 248
249#ifdef _DEBUG_HTTPERROR 249#ifdef _DEBUG_HTTPERROR
250write( 2, ws->debugbuf, G_DEBUGBUF_SIZE ); 250write( 2, ws->debugbuf, G_DEBUGBUF_SIZE );
251#endif 251#endif
252 252
253 /* Pass this task to the worker thread */ 253 /* Pass this task to the worker thread */
254 h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; 254 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK;
255 /* Clients waiting for us should not easily timeout */ 255 /* Clients waiting for us should not easily timeout */
256 taia_uint( &t, 0 ); io_timeout( client_socket, t ); 256 taia_uint( &t, 0 ); io_timeout( sock, t );
257 fullscrape_deliver( client_socket, TASK_FULLSCRAPE | format ); 257 fullscrape_deliver( sock, TASK_FULLSCRAPE | format );
258 io_dontwantread( client_socket ); 258 io_dontwantread( sock );
259 return ws->reply_size = -2; 259 return ws->reply_size = -2;
260} 260}
261#endif 261#endif
262 262
263static ssize_t http_handle_scrape( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { 263static ssize_t http_handle_scrape( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) {
264 static const ot_keywords keywords_scrape[] = { { "info_hash", 1 }, { NULL, -3 } }; 264 static const ot_keywords keywords_scrape[] = { { "info_hash", 1 }, { NULL, -3 } };
265 265
266 ot_hash * multiscrape_buf = (ot_hash*)ws->request; 266 ot_hash * multiscrape_buf = (ot_hash*)ws->request;
@@ -305,7 +305,7 @@ static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "even
305#endif 305#endif
306{ NULL, -3 } }; 306{ NULL, -3 } };
307static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } }; 307static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } };
308static ssize_t http_handle_announce( const int64 client_socket, struct ot_workstruct *ws, char *read_ptr ) { 308static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) {
309 int numwant, tmp, scanon; 309 int numwant, tmp, scanon;
310 ot_peer peer; 310 ot_peer peer;
311 ot_hash *hash = NULL; 311 ot_hash *hash = NULL;
@@ -320,7 +320,7 @@ static ssize_t http_handle_announce( const int64 client_socket, struct ot_workst
320 ++read_ptr; 320 ++read_ptr;
321 } 321 }
322 322
323 OT_SETIP( &peer, ((struct http_data*)io_getcookie( client_socket ) )->ip ); 323 OT_SETIP( &peer, ((struct http_data*)io_getcookie( sock ) )->ip );
324 OT_SETPORT( &peer, &port ); 324 OT_SETPORT( &peer, &port );
325 OT_PEERFLAG( &peer ) = 0; 325 OT_PEERFLAG( &peer ) = 0;
326 numwant = 50; 326 numwant = 50;
@@ -400,7 +400,7 @@ static ssize_t http_handle_announce( const int64 client_socket, struct ot_workst
400 return ws->reply_size; 400 return ws->reply_size;
401} 401}
402 402
403ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws ) { 403ssize_t http_handle_request( const int64 sock, struct ot_workstruct *ws ) {
404 ssize_t reply_off, len; 404 ssize_t reply_off, len;
405 char *read_ptr = ws->request, *write_ptr; 405 char *read_ptr = ws->request, *write_ptr;
406 406
@@ -433,17 +433,17 @@ ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws
433 433
434 /* This is the hardcore match for announce*/ 434 /* This is the hardcore match for announce*/
435 if( ( *write_ptr == 'a' ) || ( *write_ptr == '?' ) ) 435 if( ( *write_ptr == 'a' ) || ( *write_ptr == '?' ) )
436 http_handle_announce( client_socket, ws, read_ptr ); 436 http_handle_announce( sock, ws, read_ptr );
437#ifdef WANT_FULLSCRAPE 437#ifdef WANT_FULLSCRAPE
438 else if( !memcmp( write_ptr, "scrape HTTP/", 12 ) ) 438 else if( !memcmp( write_ptr, "scrape HTTP/", 12 ) )
439 http_handle_fullscrape( client_socket, ws ); 439 http_handle_fullscrape( sock, ws );
440#endif 440#endif
441 /* This is the hardcore match for scrape */ 441 /* This is the hardcore match for scrape */
442 else if( !memcmp( write_ptr, "sc", 2 ) ) 442 else if( !memcmp( write_ptr, "sc", 2 ) )
443 http_handle_scrape( client_socket, ws, read_ptr ); 443 http_handle_scrape( sock, ws, read_ptr );
444 /* All the rest is matched the standard way */ 444 /* All the rest is matched the standard way */
445 else if( !memcmp( write_ptr, "stats", 5) ) 445 else if( !memcmp( write_ptr, "stats", 5) )
446 http_handle_stats( client_socket, ws, read_ptr ); 446 http_handle_stats( sock, ws, read_ptr );
447 else 447 else
448 HTTPERROR_404; 448 HTTPERROR_404;
449 449
@@ -469,7 +469,7 @@ ssize_t http_handle_request( const int64 client_socket, struct ot_workstruct *ws
469 /* 3. Finally we join both blocks neatly */ 469 /* 3. Finally we join both blocks neatly */
470 ws->outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n'; 470 ws->outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
471 471
472 http_senddata( client_socket, ws ); 472 http_senddata( sock, ws );
473 return ws->reply_size; 473 return ws->reply_size;
474} 474}
475 475