|
|
@ -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
|
|
|
|