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