diff options
| author | erdgeist <> | 2006-12-08 20:07:26 +0000 |
|---|---|---|
| committer | erdgeist <> | 2006-12-08 20:07:26 +0000 |
| commit | 83e339bbe05e150c819f8e5a90ebe5d6861b4b34 (patch) | |
| tree | 5e9808848537bee7df96d2a008ce9bb6c5482bc8 | |
| parent | 2adf4fb28af99dd72c6b2fc816bcc11e5dde1ffc (diff) | |
hooks into scanning functions built
| -rw-r--r-- | opentracker.c | 477 |
1 files changed, 236 insertions, 241 deletions
diff --git a/opentracker.c b/opentracker.c index d2df803..4a421cc 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -36,272 +36,267 @@ struct http_data { | |||
| 36 | 36 | ||
| 37 | int header_complete(struct http_data* r) | 37 | int header_complete(struct http_data* r) |
| 38 | { | 38 | { |
| 39 | long i; | 39 | long i; |
| 40 | 40 | ||
| 41 | long l = array_bytes(&r->r); | 41 | long l = array_bytes(&r->r); |
| 42 | const char* c = array_start(&r->r); | 42 | const char* c = array_start(&r->r); |
| 43 | 43 | ||
| 44 | for (i=0; i+1<l; ++i) | 44 | for (i=0; i+1<l; ++i) |
| 45 | { | 45 | { |
| 46 | if (c[i]=='\n' && c[i+1]=='\n') | 46 | if (c[i]=='\n' && c[i+1]=='\n') |
| 47 | return i+2; | 47 | return i+2; |
| 48 | 48 | ||
| 49 | if (i+3<l && c[i]=='\r' && c[i+1]=='\n' && c[i+2]=='\r' && c[i+3]=='\n') | 49 | if (i+3<l && c[i]=='\r' && c[i+1]=='\n' && c[i+2]=='\r' && c[i+3]=='\n') |
| 50 | return i+4; | 50 | return i+4; |
| 51 | } | 51 | } |
| 52 | return 0; | 52 | return 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void httperror(struct http_data* r,const char* title,const char* message) | 55 | void httperror(struct http_data* r,const char* title,const char* message) |
| 56 | { | 56 | { |
| 57 | char* c; | 57 | char* c; |
| 58 | c=r->hdrbuf=(char*)malloc(strlen(message)+strlen(title)+200); | 58 | c=r->hdrbuf=(char*)malloc(strlen(message)+strlen(title)+200); |
| 59 | 59 | ||
| 60 | if (!c) | 60 | if (!c) |
| 61 | { | 61 | { |
| 62 | r->hdrbuf="HTTP/1.0 500 internal error\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nout of memory\n"; | 62 | r->hdrbuf="HTTP/1.0 500 internal error\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nout of memory\n"; |
| 63 | r->hlen=strlen(r->hdrbuf); | 63 | r->hlen=strlen(r->hdrbuf); |
| 64 | } | 64 | } |
| 65 | else | 65 | else |
| 66 | { | 66 | { |
| 67 | c+=fmt_str(c,"HTTP/1.0 "); | 67 | c+=fmt_str(c,"HTTP/1.0 "); |
| 68 | c+=fmt_str(c,title); | 68 | c+=fmt_str(c,title); |
| 69 | c+=fmt_str(c,"\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: "); | 69 | c+=fmt_str(c,"\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: "); |
| 70 | c+=fmt_ulong(c,strlen(message)+strlen(title)+16-4); | 70 | c+=fmt_ulong(c,strlen(message)+strlen(title)+16-4); |
| 71 | c+=fmt_str(c,"\r\n\r\n<title>"); | 71 | c+=fmt_str(c,"\r\n\r\n<title>"); |
| 72 | c+=fmt_str(c,title+4); | 72 | c+=fmt_str(c,title+4); |
| 73 | c+=fmt_str(c,"</title>\n"); | 73 | c+=fmt_str(c,"</title>\n"); |
| 74 | r->hlen=c - r->hdrbuf; | 74 | r->hlen=c - r->hdrbuf; |
| 75 | } | 75 | } |
| 76 | iob_addbuf(&r->iob,r->hdrbuf,r->hlen); | 76 | iob_addbuf(&r->iob,r->hdrbuf,r->hlen); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | // bestimmten http parameter auslesen und adresse zurueckgeben | 79 | // bestimmten http parameter auslesen und adresse zurueckgeben |
| 80 | 80 | ||
| 81 | const char* http_header(struct http_data* r,const char* h) | 81 | const char* http_header(struct http_data* r,const char* h) |
| 82 | { | 82 | { |
| 83 | long i; | 83 | long i; |
| 84 | 84 | ||
| 85 | long l = array_bytes(&r->r); | 85 | long l = array_bytes(&r->r); |
| 86 | long sl = strlen(h); | 86 | long sl = strlen(h); |
| 87 | const char* c = array_start(&r->r); | 87 | const char* c = array_start(&r->r); |
| 88 | 88 | ||
| 89 | for (i=0; i+sl+2<l; ++i) | 89 | for (i=0; i+sl+2<l; ++i) |
| 90 | { | 90 | { |
| 91 | if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') | 91 | if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') |
| 92 | { | 92 | { |
| 93 | c+=i+sl+1; | 93 | c+=i+sl+1; |
| 94 | if (*c==' ' || *c=='\t') ++c; | 94 | if (*c==' ' || *c=='\t') ++c; |
| 95 | return c; | 95 | return c; |
| 96 | } | 96 | } |
| 97 | return 0; | 97 | return 0; |
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void httpresponse(struct http_data* h,int64 s) | 101 | void httpresponse(struct http_data* h,int64 s) |
| 102 | { | 102 | { |
| 103 | char* c; | 103 | char* c; |
| 104 | array_cat0(&h->r); | 104 | array_cat0(&h->r); |
| 105 | 105 | ||
| 106 | c = array_start(&h->r); | 106 | c = array_start(&h->r); |
| 107 | 107 | ||
| 108 | if (byte_diff(c,4,"GET ")) | 108 | if (byte_diff(c,4,"GET ")) |
| 109 | { | 109 | { |
| 110 | e400: | 110 | e400: |
| 111 | httperror(h,"400 Invalid Request","This server only understands GET."); | 111 | httperror(h,"400 Invalid Request","This server only understands GET."); |
| 112 | } | 112 | } |
| 113 | else | 113 | else |
| 114 | { | 114 | { |
| 115 | char *d; | 115 | char *d; |
| 116 | int64 fd; | 116 | int64 fd; |
| 117 | struct stat s; | 117 | struct stat s; |
| 118 | 118 | ||
| 119 | // expect 'GET /uri?nnbjhg HTTP/1.*' | 119 | // expect 'GET /uri?nnbjhg HTTP/1.*' |
| 120 | c+=4; | 120 | c+=4; |
| 121 | 121 | ||
| 122 | for (d=c; *d!=' '&&*d!='\t'&&*d!='\n'&&*d!='\r'; ++d) ; | 122 | for (d=c; *d!=' '&&*d!='\t'&&*d!='\n'&&*d!='\r'; ++d) ; |
| 123 | 123 | ||
| 124 | if (*d!=' ') goto e400; | 124 | if (*d!=' ') goto e400; |
| 125 | *d=0; | 125 | *d=0; |
| 126 | if (c[0]!='/') goto e404; | 126 | if (c[0]!='/') goto e404; |
| 127 | while (c[1]=='/') ++c; | 127 | while (c[1]=='/') ++c; |
| 128 | 128 | ||
| 129 | if (!byte_diff(c,9,"announce?")) | 129 | data = c; |
| 130 | { | 130 | switch( scan_urlencoded_query( &c, data, SCAN_PATH ) ) { |
| 131 | // info_hash, left, port, numwant, compact | 131 | case 6: /* scrape ? */ |
| 132 | struct ot_peer peer; | 132 | if (!byte_diff(c,6,"scrape")) |
| 133 | goto 404; | ||
| 134 | break; | ||
| 135 | case 9: | ||
| 136 | if( !byte_diff(c,8,"announce")) | ||
| 137 | goto 404; | ||
| 138 | else { | ||
| 139 | // info_hash, left, port, numwant, compact | ||
| 140 | struct ot_peer peer; | ||
| 133 | ot_hash hash; | 141 | ot_hash hash; |
| 134 | byte_copy( peer.ip, h->ip, 4); | 142 | byte_copy( peer.ip, h->ip, 4); |
| 135 | peer.port = 6881; | 143 | peer.port = 6881; |
| 136 | 144 | ||
| 137 | c+=9; | 145 | while( NOCHAMSCANNEN ) { |
| 138 | while( *c!=' ' ) { | 146 | data = c; |
| 139 | if(!byte_diff(c,10,"info_hash=")) | 147 | switch( scan_urlencoded_query( &c, data, SCAN_SEARCHPATH_PARAM ) ) { |
| 140 | { | 148 | case -1: /* error */ |
| 141 | size_t destlen = 20; | 149 | httperror(h,"404 Not Found","No such file or directory."); |
| 142 | // String is expected to be URL encoded, so expect | 150 | goto e404; |
| 143 | // (%[0-9A-F][0-9A-F]){20} | 151 | case 4: |
| 144 | 152 | if(!byte_diff(c,4,"port")) | |
| 145 | int s = scan_urlencoded( c+10, hash, &destlen); | 153 | /* scan int */ |
| 146 | if( c[s+10] != '&' ) | 154 | else if(!byte_diff(c,4,"left")) |
| 147 | goto e_parse; | 155 | /* scan int */ |
| 148 | 156 | break; | |
| 149 | } | 157 | case 7: |
| 150 | else if(!byte_diff(c,8,"numwant=")) | 158 | if(!byte_diff(c,7,"numwant")) |
| 151 | { | 159 | /* scan int */ |
| 152 | 160 | else if(!byte_diff(c,7,"compact")) | |
| 153 | } | 161 | /* scan flag */ |
| 154 | else if(!byte_diff(c,8,"compact=")) | 162 | break; |
| 155 | { | 163 | case 9: /* info_hash */ |
| 156 | 164 | if(!byte_diff(c,9,"info_hash")) | |
| 157 | } | 165 | /* scan 20 bytes */ |
| 158 | else if(!byte_diff(c,5,"port=")) | 166 | break; |
| 159 | { | 167 | } |
| 160 | 168 | } | |
| 161 | } | 169 | break; |
| 162 | else if(!byte_diff(c,5,"left=")) | 170 | default: /* neither scrape nor announce */ |
| 163 | { | 171 | httperror(h,"404 Not Found","No such file or directory."); |
| 164 | 172 | goto e404; | |
| 165 | } | 173 | } |
| 166 | 174 | ||
| 167 | while( *++c!=' ' && *c!='&'); | 175 | c=h->hdrbuf=(char*)malloc(500); |
| 168 | } | 176 | c+=fmt_str(c,"HTTP/1.1 Coming Up\r\nContent-Type: text/plain"); |
| 169 | } | 177 | c+=fmt_str(c,"\r\nContent-Length: "); |
| 170 | else if (!byte_diff(c,7,"scrape?")) | 178 | /* ANSWER SIZE*/ |
| 171 | { | 179 | c+=fmt_ulonglong(c,s.st_size); |
| 172 | 180 | c+=fmt_str(c,"\r\nLast-Modified: "); | |
| 173 | } | 181 | /* MODIFY DATE */ |
| 174 | else | 182 | c+=fmt_httpdate(c,s.st_mtime); |
| 175 | { | 183 | c+=fmt_str(c,"\r\nConnection: close\r\n\r\n"); |
| 176 | httperror(h,"404 Not Found","No such file or directory."); | 184 | iob_addbuf(&h->iob,h->hdrbuf,c - h->hdrbuf); |
| 177 | goto e404; | 185 | iob_addbuf(&h->iob,tracker_answer, tzracker_answer_size); |
| 178 | } | 186 | } |
| 179 | |||
| 180 | c=h->hdrbuf=(char*)malloc(500); | ||
| 181 | c+=fmt_str(c,"HTTP/1.1 Coming Up\r\nContent-Type: text/plain"); | ||
| 182 | c+=fmt_str(c,"\r\nContent-Length: "); | ||
| 183 | /* ANSWER SIZE*/ | ||
| 184 | c+=fmt_ulonglong(c,s.st_size); | ||
| 185 | c+=fmt_str(c,"\r\nLast-Modified: "); | ||
| 186 | /* MODIFY DATE */ | ||
| 187 | c+=fmt_httpdate(c,s.st_mtime); | ||
| 188 | c+=fmt_str(c,"\r\nConnection: close\r\n\r\n"); | ||
| 189 | iob_addbuf(&h->iob,h->hdrbuf,c - h->hdrbuf); | ||
| 190 | iob_addbuf(&h->iob,tracker_answer, tzracker_answer_size); | ||
| 191 | } | ||
| 192 | e404: | 187 | e404: |
| 193 | io_dontwantread(s); | 188 | io_dontwantread(s); |
| 194 | io_wantwrite(s); | 189 | io_wantwrite(s); |
| 195 | } | 190 | } |
| 196 | 191 | ||
| 197 | int main() | 192 | int main() |
| 198 | { | 193 | { |
| 199 | int s=socket_tcp6(); | 194 | int s=socket_tcp6(); |
| 200 | uint32 scope_id; | 195 | uint32 scope_id; |
| 201 | char ip[16]; | 196 | char ip[16]; |
| 202 | uint16 port; | 197 | uint16 port; |
| 203 | 198 | ||
| 204 | if (socket_bind6_reuse(s,V6any,8000,0)==-1) | 199 | if (socket_bind6_reuse(s,V6any,8000,0)==-1) |
| 205 | panic("socket_bind6_reuse"); | 200 | panic("socket_bind6_reuse"); |
| 206 | 201 | ||
| 207 | if (socket_listen(s,16)==-1) | 202 | if (socket_listen(s,16)==-1) |
| 208 | panic("socket_listen"); | 203 | panic("socket_listen"); |
| 209 | 204 | ||
| 210 | if (!io_fd(s)) | 205 | if (!io_fd(s)) |
| 211 | panic("io_fd"); | 206 | panic("io_fd"); |
| 212 | 207 | ||
| 213 | io_wantread(s); | 208 | io_wantread(s); |
| 214 | 209 | ||
| 215 | for (;;) | 210 | for (;;) |
| 216 | { | 211 | { |
| 217 | int64 i; | 212 | int64 i; |
| 218 | io_wait(); | 213 | io_wait(); |
| 219 | 214 | ||
| 220 | while ((i=io_canread())!=-1) | 215 | while ((i=io_canread())!=-1) |
| 221 | { | 216 | { |
| 222 | if (i==s) // ist es der serversocket? | 217 | if (i==s) // ist es der serversocket? |
| 223 | { | 218 | { |
| 224 | int n; | 219 | int n; |
| 225 | while ((n=socket_accept6(s,ip,&port,&scope_id))!=-1) | 220 | while ((n=socket_accept6(s,ip,&port,&scope_id))!=-1) |
| 226 | { | 221 | { |
| 227 | if (io_fd(n)) | 222 | if (io_fd(n)) |
| 228 | { | 223 | { |
| 229 | struct http_data* h=(struct http_data*)malloc(sizeof(struct http_data)); | 224 | struct http_data* h=(struct http_data*)malloc(sizeof(struct http_data)); |
| 230 | io_wantread(n); | 225 | io_wantread(n); |
| 231 | 226 | ||
| 232 | if (h) | 227 | if (h) |
| 233 | { | 228 | { |
| 234 | byte_zero(h,sizeof(struct http_data)); | 229 | byte_zero(h,sizeof(struct http_data)); |
| 235 | byte_copy(h->ip,ip,sizeof(ip)); | 230 | byte_copy(h->ip,ip,sizeof(ip)); |
| 236 | io_setcookie(n,h); | 231 | io_setcookie(n,h); |
| 237 | } else | 232 | } else |
| 238 | io_close(n); | 233 | io_close(n); |
| 239 | } else | 234 | } else |
| 240 | io_close(n); | 235 | io_close(n); |
| 241 | buffer_putnlflush(buffer_2); | 236 | buffer_putnlflush(buffer_2); |
| 242 | } | 237 | } |
| 243 | if (errno==EAGAIN) | 238 | if (errno==EAGAIN) |
| 244 | io_eagain(s); | 239 | io_eagain(s); |
| 245 | else | 240 | else |
| 246 | carp("socket_accept6"); | 241 | carp("socket_accept6"); |
| 247 | } | 242 | } |
| 248 | else | 243 | else |
| 249 | { | 244 | { |
| 250 | char buf[8192]; | 245 | char buf[8192]; |
| 251 | struct http_data* h=io_getcookie(i); | 246 | struct http_data* h=io_getcookie(i); |
| 252 | 247 | ||
| 253 | int l=io_tryread(i,buf,sizeof buf); | 248 | int l=io_tryread(i,buf,sizeof buf); |
| 254 | if (l<=0) | 249 | if (l<=0) |
| 255 | { | 250 | { |
| 256 | if (h) | 251 | if (h) |
| 257 | { | 252 | { |
| 258 | array_reset(&h->r); | 253 | array_reset(&h->r); |
| 259 | iob_reset(&h->iob); | 254 | iob_reset(&h->iob); |
| 260 | free(h->hdrbuf); h->hdrbuf=0; | 255 | free(h->hdrbuf); h->hdrbuf=0; |
| 261 | } | 256 | } |
| 262 | io_close(i); | 257 | io_close(i); |
| 263 | } | 258 | } |
| 264 | else | 259 | else |
| 265 | { | 260 | { |
| 266 | array_catb(&h->r,buf,l); | 261 | array_catb(&h->r,buf,l); |
| 267 | 262 | ||
| 268 | if (array_failed(&h->r)) | 263 | if (array_failed(&h->r)) |
| 269 | { | 264 | { |
| 270 | httperror(h,"500 Server Error","request too long."); | 265 | httperror(h,"500 Server Error","request too long."); |
| 271 | emerge: | 266 | emerge: |
| 272 | io_dontwantread(i); | 267 | io_dontwantread(i); |
| 273 | io_wantwrite(i); | 268 | io_wantwrite(i); |
| 274 | } | 269 | } |
| 275 | else if (array_bytes(&h->r)>8192) | 270 | else if (array_bytes(&h->r)>8192) |
| 276 | { | 271 | { |
| 277 | httperror(h,"500 request too long","You sent too much headers"); | 272 | httperror(h,"500 request too long","You sent too much headers"); |
| 278 | goto emerge; | 273 | goto emerge; |
| 279 | } | 274 | } |
| 280 | else if ((l=header_complete(h))) | 275 | else if ((l=header_complete(h))) |
| 281 | { | 276 | { |
| 282 | httpresponse(h,i); | 277 | httpresponse(h,i); |
| 283 | } | 278 | } |
| 284 | } | 279 | } |
| 285 | } | 280 | } |
| 286 | } | 281 | } |
| 287 | 282 | ||
| 288 | while ((i=io_canwrite())!=-1) | 283 | while ((i=io_canwrite())!=-1) |
| 289 | { | 284 | { |
| 290 | struct http_data* h=io_getcookie(i); | 285 | struct http_data* h=io_getcookie(i); |
| 291 | 286 | ||
| 292 | int64 r=iob_send(i,&h->iob); | 287 | int64 r=iob_send(i,&h->iob); |
| 293 | 288 | ||
| 294 | if (r==-1) | 289 | if (r==-1) |
| 295 | io_eagain(i); | 290 | io_eagain(i); |
| 296 | else | 291 | else |
| 297 | if (r<=0) | 292 | if (r<=0) |
| 298 | { | 293 | { |
| 299 | array_trunc(&h->r); | 294 | array_trunc(&h->r); |
| 300 | iob_reset(&h->iob); | 295 | iob_reset(&h->iob); |
| 301 | free(h->hdrbuf); h->hdrbuf=0; | 296 | free(h->hdrbuf); h->hdrbuf=0; |
| 302 | io_close(i); | 297 | io_close(i); |
| 303 | } | 298 | } |
| 304 | } | 299 | } |
| 305 | } | 300 | } |
| 306 | return 0; | 301 | return 0; |
| 307 | } | 302 | } |
