summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <>2007-01-08 00:34:37 +0000
committererdgeist <>2007-01-08 00:34:37 +0000
commitbef60daf2b4a6da2f33572958ddf1ce264fda1b2 (patch)
tree2f02812dc92ab53980a161034fbbda7377e08a44
parent62a6f605595b8a71f4c8654e50408ce69efadcef (diff)
This one breaks all ;) Lets see, what happens
-rw-r--r--opentracker.c173
-rw-r--r--testsuite.sh8
2 files changed, 67 insertions, 114 deletions
diff --git a/opentracker.c b/opentracker.c
index 47e6f8d..0e499fe 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -31,6 +31,8 @@ unsigned long const OT_CLIENT_TIMEOUT = 15;
31static unsigned int ot_overall_connections = 0; 31static unsigned int ot_overall_connections = 0;
32static time_t ot_start_time; 32static time_t ot_start_time;
33static const unsigned int SUCCESS_HTTP_HEADER_LENGTH = 80; 33static const unsigned int SUCCESS_HTTP_HEADER_LENGTH = 80;
34static char reply[8192];
35static size_t reply_size;
34 36
35static void carp(const char* routine) { 37static void carp(const char* routine) {
36 buffer_puts(buffer_2,routine); 38 buffer_puts(buffer_2,routine);
@@ -50,36 +52,40 @@ struct http_data {
50 unsigned long ip; 52 unsigned long ip;
51}; 53};
52 54
53int header_complete(struct http_data* r) 55int header_complete(struct http_data* r) {
54{ 56 long l = array_bytes(&r->r);
55 long i; 57 const char* c = array_start(&r->r);
56 58 long i;
57 long l = array_bytes(&r->r);
58 const char* c = array_start(&r->r);
59 59
60 for (i=0; i+1<l; ++i) 60 for (i=0; i+1<l; ++i) {
61 { 61 if (c[i]=='\n' && c[i+1]=='\n') return i+2;
62 if (c[i]=='\n' && c[i+1]=='\n') 62 if (i+3<l && c[i]=='\r' && c[i+1]=='\n' && c[i+2]=='\r' && c[i+3]=='\n') return i+4;
63 return i+2; 63 }
64 return 0;
65}
64 66
65 if (i+3<l && c[i]=='\r' && c[i+1]=='\n' && c[i+2]=='\r' && c[i+3]=='\n') 67// whoever sends data is not interested in its input-array
66 return i+4; 68void senddata(int64 s,struct http_data* h) {
67 } 69 size_t written_size;
68 return 0; 70
71 if( h ) array_reset(&h->r);
72 written_size = write( s, reply, reply_size );
73 if( ( written_size < 0 ) || ( written_size == reply_size ) ) {
74 free(h); io_close( s );
75 } else {
76 fprintf( stderr, "Should have handled this.\n" );
77 free(h); io_close( s );
78 }
69} 79}
70 80
71void httperror(struct http_data* h,const char* title,const char* message) 81void httperror(int64 s,struct http_data* h,const char* title,const char* message) {
72{ 82 reply_size = sprintf( reply, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n",
73 char* c = (char*)malloc(strlen(message)+strlen(title)+200); 83 title, strlen(message)+strlen(title)+16-4,title+4);
74 if( !c) iob_addbuf(&h->iob, "HTTP/1.0 500 internal error\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nout of memory\n", 90); 84 senddata(s,h);
75 else iob_addbuf_free( &h->iob, c,
76 sprintf( c, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n",
77 title, strlen(message)+strlen(title)+16-4,title+4) );
78} 85}
79 86
80// bestimmten http parameter auslesen und adresse zurueckgeben 87// bestimmten http parameter auslesen und adresse zurueckgeben
81const char* http_header(struct http_data* r,const char* h) 88const char* http_header(struct http_data* r,const char* h) {
82{
83 long i; 89 long i;
84 90
85 long l = array_bytes(&r->r); 91 long l = array_bytes(&r->r);
@@ -99,24 +105,23 @@ const char* http_header(struct http_data* r,const char* h)
99 return 0; 105 return 0;
100} 106}
101 107
102void httpresponse(struct http_data* h,int64 s) 108void httpresponse(int64 s,struct http_data* h)
103{ 109{
104 char *c, *data, *reply = NULL; 110 char *c, *data; // must be enough
105 ot_peer peer; 111 ot_peer peer;
106 ot_torrent *torrent; 112 ot_torrent *torrent;
107 ot_hash *hash = NULL; 113 ot_hash *hash = NULL;
108 int numwant, tmp, scanon; 114 int numwant, tmp, scanon;
109 unsigned short port = htons(6881); 115 unsigned short port = htons(6881);
110 size_t reply_size = 0;
111 116
117 reply_size = 0;
112 array_cat0(&h->r); 118 array_cat0(&h->r);
113 119
114 c = array_start(&h->r); 120 c = array_start(&h->r);
115 121
116 if (byte_diff(c,4,"GET ")) { 122 if (byte_diff(c,4,"GET ")) {
117e400: 123e400:
118 httperror(h,"400 Invalid Request","This server only understands GET."); 124 return httperror(s,h,"400 Invalid Request","This server only understands GET.");
119 goto bailout;
120 } 125 }
121 126
122 c+=4; 127 c+=4;
@@ -147,14 +152,12 @@ e400:
147 continue; 152 continue;
148 } 153 }
149 /* ignore this, when we have less than 20 bytes */ 154 /* ignore this, when we have less than 20 bytes */
150 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { 155 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) {
151 case -1: 156e400_param:
152 goto e404; 157 return httperror(s,h,"400 Invalid Request","Invalid parameter");
153 case 20:
154 hash = (ot_hash*)data; /* Fall through intended */
155 default:
156 continue;
157 } 158 }
159 hash = (ot_hash*)data; /* Fall through intended */
160 break;
158 default: 161 default:
159 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 162 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
160 break; 163 break;
@@ -162,19 +165,12 @@ e400:
162 } 165 }
163 166
164 /* Scanned whole query string, wo */ 167 /* Scanned whole query string, wo */
165 if( !hash ) { 168 if( !hash )
166 httperror(h,"400 Invalid Request","This server only serves specific scrapes."); 169 return httperror(s,h,"400 Invalid Request","This server only serves specific scrapes.");
167 goto bailout;
168 }
169 170
170 // Enough for http header + whole scrape string 171 // Enough for http header + whole scrape string
171 reply = malloc( SUCCESS_HTTP_HEADER_LENGTH + 128 ); 172 if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + reply ) ) <= 0 )
172 if( reply )
173 reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + reply );
174 if( !reply || ( reply_size < 0 ) ) {
175 if( reply ) free( reply );
176 goto e500; 173 goto e500;
177 }
178 break; 174 break;
179 case 8: 175 case 8:
180 if( byte_diff(data,8,"announce")) 176 if( byte_diff(data,8,"announce"))
@@ -198,7 +194,7 @@ e400:
198 if(!byte_diff(data,2,"ip")) { 194 if(!byte_diff(data,2,"ip")) {
199 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 195 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
200 unsigned char ip[4]; 196 unsigned char ip[4];
201 if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e404; 197 if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param;
202 OT_SETIP ( &peer, ip ); 198 OT_SETIP ( &peer, ip );
203 } else 199 } else
204 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 200 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
@@ -207,11 +203,11 @@ e400:
207 case 4: 203 case 4:
208 if(!byte_diff(data,4,"port")) { 204 if(!byte_diff(data,4,"port")) {
209 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 205 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
210 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e404; 206 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param;
211 port = htons( tmp ); OT_SETPORT ( &peer, &port ); 207 port = htons( tmp ); OT_SETPORT ( &peer, &port );
212 } else if(!byte_diff(data,4,"left")) { 208 } else if(!byte_diff(data,4,"left")) {
213 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 209 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
214 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e404; 210 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
215 if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING; 211 if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
216 } else 212 } else
217 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 213 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
@@ -221,7 +217,7 @@ e400:
221 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 217 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
222 else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { 218 else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
223 case -1: 219 case -1:
224 goto e404; 220 goto e400_param;
225 case 7: 221 case 7:
226 if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED; 222 if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED;
227 break; 223 break;
@@ -234,15 +230,13 @@ e400:
234 case 7: 230 case 7:
235 if(!byte_diff(data,7,"numwant")) { 231 if(!byte_diff(data,7,"numwant")) {
236 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 232 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
237 if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e404; 233 if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e400_param;
238 if( numwant > 200 ) numwant = 200; 234 if( numwant > 200 ) numwant = 200;
239 } else if(!byte_diff(data,7,"compact")) { 235 } else if(!byte_diff(data,7,"compact")) {
240 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 236 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
241 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e404; 237 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
242 if( !tmp ) { 238 if( !tmp )
243 httperror(h,"400 Invalid Request","This server only delivers compact results."); 239 return httperror(s,h,"400 Invalid Request","This server only delivers compact results.");
244 goto bailout;
245 }
246 } else 240 } else
247 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 241 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
248 break; 242 break;
@@ -252,14 +246,10 @@ e400:
252 continue; 246 continue;
253 } 247 }
254 /* ignore this, when we have less than 20 bytes */ 248 /* ignore this, when we have less than 20 bytes */
255 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { 249 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 )
256 case -1: 250 goto e400;
257 goto e404; 251 hash = (ot_hash*)data;
258 case 20: 252 break;
259 hash = (ot_hash*)data;
260 default: // Fall through intended
261 continue;
262 }
263 default: 253 default:
264 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 254 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
265 break; 255 break;
@@ -267,34 +257,24 @@ e400:
267 } 257 }
268 258
269 /* Scanned whole query string */ 259 /* Scanned whole query string */
270 if( !hash ) goto e404; 260 if( !hash ) goto e400;
271 261
272 if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) { 262 if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) {
273 remove_peer_from_torrent( hash, &peer ); 263 remove_peer_from_torrent( hash, &peer );
274 reply = malloc( SUCCESS_HTTP_HEADER_LENGTH + 26 );
275 if( !reply )
276 goto e500;
277 MEMMOVE( reply + SUCCESS_HTTP_HEADER_LENGTH, "d15:warning message4:Okaye", reply_size = 26 ); 264 MEMMOVE( reply + SUCCESS_HTTP_HEADER_LENGTH, "d15:warning message4:Okaye", reply_size = 26 );
278 } else { 265 } else {
279 torrent = add_peer_to_torrent( hash, &peer ); 266 torrent = add_peer_to_torrent( hash, &peer );
280 if( !torrent ) { 267 if( !torrent ) {
281e500: 268e500:
282 httperror(h,"500 Internal Server Error","A server error has occured. Please retry later."); 269 return httperror(s,h,"500 Internal Server Error","A server error has occured. Please retry later.");
283 goto bailout;
284 } 270 }
285 reply = malloc( SUCCESS_HTTP_HEADER_LENGTH + numwant * 6 + 128 ); // http header + peerlist + seeder, peers and lametta 80 + n*6+81 a.t.m. 271 if( ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + reply ) ) <= 0 )
286 if( reply )
287 reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + reply );
288 if( !reply || ( reply_size <= 0 ) ) {
289 if( reply ) free( reply );
290 goto e500; 272 goto e500;
291 }
292 } 273 }
293 break; 274 break;
294 case 11: 275 case 11:
295 if( byte_diff(data,11,"mrtg_scrape")) 276 if( byte_diff(data,11,"mrtg_scrape"))
296 goto e404; 277 goto e404;
297 reply = malloc( SUCCESS_HTTP_HEADER_LENGTH + 128 );
298 { 278 {
299 unsigned long seconds_elapsed = time( NULL ) - ot_start_time; 279 unsigned long seconds_elapsed = time( NULL ) - ot_start_time;
300 reply_size = sprintf( reply + SUCCESS_HTTP_HEADER_LENGTH, 280 reply_size = sprintf( reply + SUCCESS_HTTP_HEADER_LENGTH,
@@ -305,31 +285,16 @@ e500:
305 break; 285 break;
306 default: /* neither *scrape nor announce */ 286 default: /* neither *scrape nor announce */
307e404: 287e404:
308 httperror(h,"404 Not Found","No such file or directory."); 288 return httperror(s,h,"404 Not Found","No such file or directory.");
309 goto bailout;
310 } 289 }
311 290
312 if( reply && reply_size ) { 291 if( reply_size ) {
313 MEMMOVE( reply, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: X \r\n\r\n", SUCCESS_HTTP_HEADER_LENGTH ); 292 MEMMOVE( reply, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: X \r\n\r\n", SUCCESS_HTTP_HEADER_LENGTH );
314 fmt_ulonglong( reply+59, (long long)reply_size ); 293 fmt_ulonglong( reply+59, (long long)reply_size );
315 iob_addbuf_free(&h->iob, reply, SUCCESS_HTTP_HEADER_LENGTH + reply_size );
316 } 294 }
317 295 reply_size += SUCCESS_HTTP_HEADER_LENGTH;
318bailout:
319 io_dontwantread(s); 296 io_dontwantread(s);
320 io_wantwrite(s); 297 senddata(s,h);
321
322 reply_size=iob_send(s,&h->iob);
323 if (reply_size==-1) {
324 io_eagain(s);
325 } else
326 if ((reply_size<=0)||(h->iob.bytesleft==0))
327 {
328 array_reset(&h->r);
329 iob_reset(&h->iob);
330 free(h);
331 io_close(s);
332 }
333} 298}
334 299
335void graceful( int s ) { 300void graceful( int s ) {
@@ -468,7 +433,6 @@ allparsed:
468 if (h) 433 if (h)
469 { 434 {
470 array_reset(&h->r); 435 array_reset(&h->r);
471 iob_reset(&h->iob);
472 free(h); 436 free(h);
473 } 437 }
474 io_close(i); 438 io_close(i);
@@ -478,21 +442,11 @@ allparsed:
478 array_catb(&h->r,buf,l); 442 array_catb(&h->r,buf,l);
479 443
480 if (array_failed(&h->r)) 444 if (array_failed(&h->r))
481 { 445 httperror(i,h,"500 Server Error","Request too long.");
482 httperror(h,"500 Server Error","request too long.");
483emerge:
484 io_dontwantread(i);
485 io_wantwrite(i);
486 }
487 else if (array_bytes(&h->r)>8192) 446 else if (array_bytes(&h->r)>8192)
488 { 447 httperror(i,h,"500 request too long","You sent too much headers");
489 httperror(h,"500 request too long","You sent too much headers");
490 goto emerge;
491 }
492 else if ((l=header_complete(h))) 448 else if ((l=header_complete(h)))
493 { 449 httpresponse(i,h);
494 httpresponse(h,i);
495 }
496 } 450 }
497 } 451 }
498 } 452 }
@@ -507,7 +461,6 @@ emerge:
507 else 461 else
508 if ((r<=0)||(h->iob.bytesleft==0)) 462 if ((r<=0)||(h->iob.bytesleft==0))
509 { 463 {
510 array_reset(&h->r);
511 iob_reset(&h->iob); 464 iob_reset(&h->iob);
512 free(h); 465 free(h);
513 io_close(i); 466 io_close(i);
diff --git a/testsuite.sh b/testsuite.sh
index 6b2dad9..1af1499 100644
--- a/testsuite.sh
+++ b/testsuite.sh
@@ -4,9 +4,9 @@ while true; do
4 request_string="GET /announce?info_hash=0123456789012345678%$(printf %02X $(( $RANDOM & 0xff )) )&\ 4 request_string="GET /announce?info_hash=0123456789012345678%$(printf %02X $(( $RANDOM & 0xff )) )&\
5ip=10.1.1.$(( $RANDOM & 0xff ))&port=$(( $RANDOM & 0xff )) HTTP/1.0\n" 5ip=10.1.1.$(( $RANDOM & 0xff ))&port=$(( $RANDOM & 0xff )) HTTP/1.0\n"
6 6
7 echo -e $request_string 7# echo -e $request_string
8 echo 8# echo
9 echo -e $request_string | nc 213.73.88.214 6969 | tr -C "[:print:]" _ 9 echo -e $request_string | nc 23.23.23.182 6969 >/dev/null &
10 echo 10# echo
11 11
12done 12done