|
|
@ -58,15 +58,15 @@ static void panic(const char* routine) { |
|
|
|
|
|
|
|
|
|
|
|
struct http_data { |
|
|
|
struct http_data { |
|
|
|
union { |
|
|
|
union { |
|
|
|
array r; |
|
|
|
array request; |
|
|
|
io_batch batch; |
|
|
|
io_batch batch; |
|
|
|
}; |
|
|
|
}; |
|
|
|
unsigned char ip[4]; |
|
|
|
unsigned char ip[4]; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
int header_complete(struct http_data* r) { |
|
|
|
int header_complete( struct http_data* h ) { |
|
|
|
int l = array_bytes(&r->r), i; |
|
|
|
int l = array_bytes( &h->request ), i; |
|
|
|
const char* c = array_start(&r->r); |
|
|
|
const char* c = array_start( &h->request ); |
|
|
|
|
|
|
|
|
|
|
|
for( i=0; i+1<l; ++i) { |
|
|
|
for( i=0; i+1<l; ++i) { |
|
|
|
if( c[i]=='\n' && c[i+1]=='\n') return i+2; |
|
|
|
if( c[i]=='\n' && c[i+1]=='\n') return i+2; |
|
|
@ -81,7 +81,7 @@ void sendmallocdata( int64 s, struct http_data *h, char * buffer, size_t size ) |
|
|
|
size_t header_size; |
|
|
|
size_t header_size; |
|
|
|
|
|
|
|
|
|
|
|
if( !h ) { free( buffer); return; } |
|
|
|
if( !h ) { free( buffer); return; } |
|
|
|
array_reset(&h->r); |
|
|
|
array_reset( &h->request ); |
|
|
|
|
|
|
|
|
|
|
|
header = malloc( SUCCESS_HTTP_HEADER_LENGTH ); |
|
|
|
header = malloc( SUCCESS_HTTP_HEADER_LENGTH ); |
|
|
|
if( !header ) { free( buffer ); return; } |
|
|
|
if( !header ) { free( buffer ); return; } |
|
|
@ -98,11 +98,13 @@ void sendmallocdata( int64 s, struct http_data *h, char * buffer, size_t size ) |
|
|
|
io_wantwrite( s ); |
|
|
|
io_wantwrite( s ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* whoever sends data is not interested in its input-array */ |
|
|
|
|
|
|
|
void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) { |
|
|
|
void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) { |
|
|
|
size_t written_size; |
|
|
|
size_t written_size; |
|
|
|
|
|
|
|
|
|
|
|
if( h ) array_reset(&h->r); |
|
|
|
/* whoever sends data is not interested in its input-array */ |
|
|
|
|
|
|
|
if( h ) |
|
|
|
|
|
|
|
array_reset( &h->request ); |
|
|
|
|
|
|
|
|
|
|
|
written_size = write( s, buffer, size ); |
|
|
|
written_size = write( s, buffer, size ); |
|
|
|
if( ( written_size < 0 ) || ( written_size == size ) ) { |
|
|
|
if( ( written_size < 0 ) || ( written_size == size ) ) { |
|
|
|
#ifdef _DEBUG_FDS |
|
|
|
#ifdef _DEBUG_FDS |
|
|
@ -143,24 +145,7 @@ void httperror(int64 s,struct http_data* h,const char* title,const char* message |
|
|
|
senddata(s,h,static_scratch,reply_size); |
|
|
|
senddata(s,h,static_scratch,reply_size); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char* http_header(struct http_data* r,const char* h) { |
|
|
|
void httpresponse( int64 s, struct http_data* h) { |
|
|
|
int i, l = array_bytes(&r->r); |
|
|
|
|
|
|
|
int sl = strlen(h); |
|
|
|
|
|
|
|
const char* c = array_start(&r->r); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i=0; i+sl+2<l; ++i) { |
|
|
|
|
|
|
|
if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') { |
|
|
|
|
|
|
|
c+=i+sl+1; |
|
|
|
|
|
|
|
if (*c==' ' || *c=='\t') ++c; |
|
|
|
|
|
|
|
return c; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void httpresponse(int64 s,struct http_data* h) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *c, *data; |
|
|
|
char *c, *data; |
|
|
|
ot_peer peer; |
|
|
|
ot_peer peer; |
|
|
|
ot_torrent *torrent; |
|
|
|
ot_torrent *torrent; |
|
|
@ -169,11 +154,11 @@ void httpresponse(int64 s,struct http_data* h) |
|
|
|
unsigned short port = htons(6881); |
|
|
|
unsigned short port = htons(6881); |
|
|
|
size_t reply_size = 0; |
|
|
|
size_t reply_size = 0; |
|
|
|
|
|
|
|
|
|
|
|
array_cat0(&h->r); |
|
|
|
array_cat0( &h->request ); |
|
|
|
c = array_start(&h->r); |
|
|
|
c = array_start( &h->request ); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG_HTTPERROR |
|
|
|
#ifdef _DEBUG_HTTPERROR |
|
|
|
memcpy( debug_request, array_start(&h->r), array_bytes(&h->r) ); |
|
|
|
memcpy( debug_request, array_start( &h->request ), array_bytes( &h->request ) ); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if( byte_diff( c, 4, "GET ") ) { |
|
|
|
if( byte_diff( c, 4, "GET ") ) { |
|
|
@ -190,7 +175,7 @@ e400: |
|
|
|
while( *c == '/' ) ++c; |
|
|
|
while( *c == '/' ) ++c; |
|
|
|
|
|
|
|
|
|
|
|
switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { |
|
|
|
switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { |
|
|
|
case 5: /* scrape ? */ |
|
|
|
case 5: /* stats ? */ |
|
|
|
if( byte_diff(data,5,"stats")) |
|
|
|
if( byte_diff(data,5,"stats")) |
|
|
|
goto e404; |
|
|
|
goto e404; |
|
|
|
scanon = 1; |
|
|
|
scanon = 1; |
|
|
@ -408,7 +393,8 @@ e404: |
|
|
|
|
|
|
|
|
|
|
|
senddata( s, h, static_scratch + reply_off, reply_size ); |
|
|
|
senddata( s, h, static_scratch + reply_off, reply_size ); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if( h ) array_reset(&h->r); |
|
|
|
if( h ) |
|
|
|
|
|
|
|
array_reset( &h->request ); |
|
|
|
#ifdef _DEBUG_FDS |
|
|
|
#ifdef _DEBUG_FDS |
|
|
|
if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" ); |
|
|
|
if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" ); |
|
|
|
fd_debug_space[s] = 0; |
|
|
|
fd_debug_space[s] = 0; |
|
|
@ -476,7 +462,7 @@ void handle_read( int64 clientsocket ) { |
|
|
|
|
|
|
|
|
|
|
|
if( l <= 0 ) { |
|
|
|
if( l <= 0 ) { |
|
|
|
if( h ) { |
|
|
|
if( h ) { |
|
|
|
array_reset(&h->r); |
|
|
|
array_reset( &h->request ); |
|
|
|
free( h ); |
|
|
|
free( h ); |
|
|
|
} |
|
|
|
} |
|
|
|
#ifdef _DEBUG_FDS |
|
|
|
#ifdef _DEBUG_FDS |
|
|
@ -487,15 +473,15 @@ void handle_read( int64 clientsocket ) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
array_catb(&h->r,static_scratch,l); |
|
|
|
array_catb( &h->request, static_scratch, l ); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG_HTTPERROR |
|
|
|
#ifdef _DEBUG_HTTPERROR |
|
|
|
memcpy( debug_request, "500!\0", 5 ); |
|
|
|
memcpy( debug_request, "500!\0", 5 ); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if( array_failed(&h->r)) |
|
|
|
if( array_failed( &h->request ) ) |
|
|
|
httperror( clientsocket, h, "500 Server Error", "Request too long."); |
|
|
|
httperror( clientsocket, h, "500 Server Error", "Request too long."); |
|
|
|
else if (array_bytes(&h->r)>8192) |
|
|
|
else if( array_bytes( &h->request ) > 8192 ) |
|
|
|
httperror( clientsocket, h, "500 request too long", "You sent too much headers"); |
|
|
|
httperror( clientsocket, h, "500 request too long", "You sent too much headers"); |
|
|
|
else if( ( l = header_complete( h ) ) ) |
|
|
|
else if( ( l = header_complete( h ) ) ) |
|
|
|
httpresponse( clientsocket, h); |
|
|
|
httpresponse( clientsocket, h); |
|
|
@ -525,7 +511,7 @@ void handle_accept( int64 serversocket ) { |
|
|
|
while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) { |
|
|
|
while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) { |
|
|
|
|
|
|
|
|
|
|
|
if( !io_fd( i ) || |
|
|
|
if( !io_fd( i ) || |
|
|
|
!(h = (struct http_data*)malloc(sizeof(struct http_data))) ) { |
|
|
|
!( h = (struct http_data*)malloc( sizeof struct http_data ) ) ) { |
|
|
|
io_close( i ); |
|
|
|
io_close( i ); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
@ -559,7 +545,7 @@ void handle_timeouted( ) { |
|
|
|
while( ( i = io_timeouted() ) != -1 ) { |
|
|
|
while( ( i = io_timeouted() ) != -1 ) { |
|
|
|
struct http_data* h=io_getcookie( i ); |
|
|
|
struct http_data* h=io_getcookie( i ); |
|
|
|
if( h ) { |
|
|
|
if( h ) { |
|
|
|
array_reset( &h->r ); |
|
|
|
array_reset( &h->request ); |
|
|
|
free( h ); |
|
|
|
free( h ); |
|
|
|
} |
|
|
|
} |
|
|
|
#ifdef _DEBUG_FDS |
|
|
|
#ifdef _DEBUG_FDS |
|
|
|