... | ... |
@@ -136,7 +136,7 @@ sbuf_ptr(sbuf *buf) |
136 | 136 |
} |
137 | 137 |
|
138 | 138 |
long |
139 |
-sbuf_add(sbuf *buf, char *data, long datasize) |
|
139 |
+sbuf_add(sbuf *buf, const char *data, long datasize) |
|
140 | 140 |
{ |
141 | 141 |
long added; |
142 | 142 |
if(buf==NULL || data==NULL || buf->used==buf->size) |
... | ... |
@@ -148,7 +148,7 @@ sbuf_add(sbuf *buf, char *data, long datasize) |
148 | 148 |
} |
149 | 149 |
|
150 | 150 |
long |
151 |
-sbuf_addstr(sbuf *buf, char *str) |
|
151 |
+sbuf_addstr(sbuf *buf, const char *str) |
|
152 | 152 |
{ |
153 | 153 |
if(buf==NULL || str==NULL) |
154 | 154 |
return(0); |
... | ... |
@@ -41,8 +41,8 @@ void sbuf_wipe(sbuf *buf); |
41 | 41 |
char *sbuf_getbytes(sbuf *buf, long numbytes); |
42 | 42 |
long sbuf_count(sbuf *buf); |
43 | 43 |
char *sbuf_ptr(sbuf *buf); |
44 |
-long sbuf_add(sbuf *buf, char *data, long datasize); |
|
45 |
-long sbuf_addstr(sbuf *buf, char *str); |
|
44 |
+long sbuf_add(sbuf *buf, const char *data, long datasize); |
|
45 |
+long sbuf_addstr(sbuf *buf, const char *str); |
|
46 | 46 |
long sbuf_unused(sbuf *buf); |
47 | 47 |
char *sbuf_ptrunused(sbuf *buf); |
48 | 48 |
long sbuf_addfromunused(sbuf *buf, long numbytes); |
... | ... |
@@ -12,6 +12,9 @@ |
12 | 12 |
#include <stdlib.h> |
13 | 13 |
#include <unistd.h> |
14 | 14 |
#include <string.h> |
15 |
+#include <sys/types.h> |
|
16 |
+#include <sys/stat.h> |
|
17 |
+#include <fcntl.h> |
|
15 | 18 |
#include "sbuf.h" |
16 | 19 |
#include "socklib.h" |
17 | 20 |
#include "webkernel.h" |
... | ... |
@@ -34,8 +37,10 @@ typedef struct wk_client { |
34 | 37 |
int usedoutbufids; |
35 | 38 |
int outbufids[MAXOUTBUF]; |
36 | 39 |
int serviced; |
37 |
- wk_uri uri; |
|
38 | 40 |
int continuationactive; |
41 |
+ int fdtoserve; |
|
42 |
+ wk_uri uri; |
|
43 |
+ int headerbufid; |
|
39 | 44 |
int keepalive; |
40 | 45 |
} wk_client; |
41 | 46 |
|
... | ... |
@@ -78,7 +83,7 @@ static wk_client *wk_accept(_wk *web); |
78 | 83 |
static wk_client *wk_clientacquire(_wk *web); |
79 | 84 |
static int wk_clientrelease(_wk *web, int connid); |
80 | 85 |
static wk_client *wk_clientget(_wk *web, int connid); |
81 |
-static void wk_clientserviceread(_wk *web, wk_client *client); |
|
86 |
+static int wk_clientserviceread(_wk *web, wk_client *client); |
|
82 | 87 |
|
83 | 88 |
wk * |
84 | 89 |
wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *web,int connid, wk_event event, void *userptr*/), wk_action (*callback_http)(/*wk *web,int connid, wk_uri *uri, void *userptr*/), wk_action (*callback_continuation)(/*wk *web,int connid, wk_uri *uri, void *userptr*/), void *userptr) |
... | ... |
@@ -144,6 +149,8 @@ wk_free(wk *paramweb) |
144 | 149 |
FD_CLR(client->fd,&(web->fdset)); |
145 | 150 |
close(client->fd),client->fd=-1; |
146 | 151 |
} |
152 |
+ if(client->fdtoserve!=-1) |
|
153 |
+ close(client->fdtoserve),client->fdtoserve=-1; |
|
147 | 154 |
} |
148 | 155 |
} |
149 | 156 |
cb->usedclients=0; |
... | ... |
@@ -190,7 +197,7 @@ wk_service(wk *paramweb) |
190 | 197 |
{ |
191 | 198 |
int fds[FDBLOCK]; |
192 | 199 |
int fd; |
193 |
- int n,i,k; |
|
200 |
+ int n,i; |
|
194 | 201 |
sbuf *in; |
195 | 202 |
sbuf *out; |
196 | 203 |
_wk *web=(_wk *)paramweb; |
... | ... |
@@ -221,10 +228,14 @@ wk_service(wk *paramweb) |
221 | 228 |
} |
222 | 229 |
if(sbuf_fill(in,fd,sock_queued(fd))==0) { |
223 | 230 |
/* client has closed connection */ |
224 |
- wk_close((wk *) web, fd); |
|
231 |
+ wk_close((wk *) web, client->connid); |
|
232 |
+ continue; |
|
233 |
+ } |
|
234 |
+ if(wk_clientserviceread(web,client)==-1) { |
|
235 |
+ /* internal error, protocol error or no enough memory */ |
|
236 |
+ wk_close((wk *) web, client->connid); |
|
225 | 237 |
continue; |
226 | 238 |
} |
227 |
- wk_clientserviceread(web,client); |
|
228 | 239 |
} |
229 | 240 |
} |
230 | 241 |
while((n=sselect_getwritefiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) { |
... | ... |
@@ -232,21 +243,30 @@ wk_service(wk *paramweb) |
232 | 243 |
fd=fds[i]; |
233 | 244 |
if((client=(wk_client *)sselect_getuserptr(web->ssel,fd))==NULL || client->web!=(wk *)web) |
234 | 245 |
continue; /* internal error */ |
235 |
- for(out=NULL,k=client->usedoutbufids-1;k>=0;k--) { |
|
236 |
- if((out=wk_sbufget((wk *) web,client->outbufids[k]))==NULL) { |
|
237 |
- k=-1; |
|
238 |
- break; /* internal error */ |
|
239 |
- } |
|
240 |
- } |
|
241 |
- if(k==-1 || out==NULL) { |
|
246 |
+ if((out=wk_sbufget((wk *) web,client->outbufids[0]))==NULL) { |
|
242 | 247 |
wk_close((wk *)web,client->connid); |
243 | 248 |
continue; /* internal error */ |
244 | 249 |
} |
245 | 250 |
sbuf_send(out,fd,sbuf_count(out)); |
251 |
+ /* if we are serving from file, load the next chunk */ |
|
252 |
+ if(client->fdtoserve!=-1 && client->usedoutbufids==1) { |
|
253 |
+ sbuf_discard(out); |
|
254 |
+ if(sbuf_unused(out)>0) { |
|
255 |
+ int n; |
|
256 |
+ n=sbuf_fill(out,client->fdtoserve,sbuf_unused(out)); |
|
257 |
+ if(n<=0) |
|
258 |
+ close(client->fdtoserve),client->fdtoserve=-1; |
|
259 |
+ } |
|
260 |
+ } |
|
261 |
+ /* free unused bufs, detect finished sending */ |
|
246 | 262 |
if(sbuf_count(out)==0) { |
247 |
- if(k>0) { |
|
263 |
+ if(client->usedoutbufids>1) { |
|
264 |
+ int sbufid; |
|
265 |
+ sbufid=client->outbufids[0]; |
|
248 | 266 |
client->usedoutbufids--; |
249 |
- wk_sbufrelease((wk *)web,client->outbufids[k]),client->outbufids[k]=-1; |
|
267 |
+ memmove(client->outbufids,client->outbufids+1,sizeof(int)*(MAXOUTBUF-1)); |
|
268 |
+ client->outbufids[MAXOUTBUF-1]=-1; |
|
269 |
+ wk_sbufrelease((wk *)web,sbufid),sbufid=-1; |
|
250 | 270 |
} else { |
251 | 271 |
sselect_delwrite(web->ssel,client->fd); |
252 | 272 |
if(client->continuationactive && web->callback_continuation!=NULL) { |
... | ... |
@@ -266,29 +286,117 @@ wk_service(wk *paramweb) |
266 | 286 |
int |
267 | 287 |
wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime) |
268 | 288 |
{ |
269 |
- |
|
289 |
+ static const char *strcontenttype={"Content-Type: "}; |
|
290 |
+ _wk *web=(_wk *)paramweb; |
|
291 |
+ wk_client *client; |
|
292 |
+ char buf[256]; |
|
293 |
+ if(web==NULL) |
|
294 |
+ return(-1); |
|
295 |
+ if((client=wk_clientget(web,connid))==NULL) |
|
296 |
+ return(-1); |
|
297 |
+ wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n"); |
|
298 |
+ sprintf(buf,"Content-Length: %i\r\n",datalen); |
|
299 |
+ wk_writestr((wk *)web,connid,buf); |
|
300 |
+ if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
|
301 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,mime); |
|
302 |
+ else |
|
303 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream"); |
|
304 |
+ wk_writestr((wk *)web,connid,buf); |
|
305 |
+ if(client->keepalive) |
|
306 |
+ wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n"); |
|
307 |
+ wk_writestr((wk *)web,connid,"\r\n"); |
|
308 |
+ return(wk_write((wk *)web,connid,data,datalen)); |
|
270 | 309 |
} |
271 | 310 |
|
272 | 311 |
int |
273 | 312 |
wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime) |
274 | 313 |
{ |
275 |
- |
|
314 |
+ static const char *strcontenttype={"Content-Type: "}; |
|
315 |
+ _wk *web=(_wk *)paramweb; |
|
316 |
+ wk_client *client; |
|
317 |
+ char buf[256]; |
|
318 |
+ struct stat st; |
|
319 |
+ if(web==NULL || filename==NULL) |
|
320 |
+ return(-1); |
|
321 |
+ if((client=wk_clientget(web,connid))==NULL) |
|
322 |
+ return(-1); |
|
323 |
+ if(client->fdtoserve!=-1) |
|
324 |
+ close(client->fdtoserve),client->fdtoserve=-1; |
|
325 |
+ if((client->fdtoserve=open(filename,O_RDONLY))==-1) { |
|
326 |
+ wk_serve_error((wk *)web,connid,wkerr_notfound); |
|
327 |
+ return(-1); |
|
328 |
+ } |
|
329 |
+ wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n"); |
|
330 |
+ if(fstat(client->fdtoserve,&st)==0) { |
|
331 |
+ sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size); |
|
332 |
+ wk_writestr((wk *)web,connid,buf); |
|
333 |
+ } else |
|
334 |
+ client->keepalive=0; |
|
335 |
+ if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
|
336 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,mime); |
|
337 |
+ else |
|
338 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream"); |
|
339 |
+ wk_writestr((wk *)web,connid,buf); |
|
340 |
+ if(client->keepalive) |
|
341 |
+ wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n"); |
|
342 |
+ wk_writestr((wk *)web,connid,"\r\n"); |
|
343 |
+ return(0); |
|
276 | 344 |
} |
277 | 345 |
|
278 | 346 |
int |
279 | 347 |
wk_serve_error(wk *paramweb, int connid, wk_error wkerror) |
280 | 348 |
{ |
281 |
- |
|
349 |
+ static const char strnotfound[]={"\ |
|
350 |
+HTTP/1.1 404 Not found\r\n\ |
|
351 |
+Content-Type: text/html\r\n\ |
|
352 |
+Content-Length: 113\r\n\ |
|
353 |
+\r\n\ |
|
354 |
+<title>404 Not Found</title>\r\n\ |
|
355 |
+<h1>404 Not Found</h1>\r\n\ |
|
356 |
+The requested resource could not be found on this server.\r\n\ |
|
357 |
+"}; |
|
358 |
+ static const char strinternal[]={"\ |
|
359 |
+HTTP/1.1 500 Internal Server Error\r\n\ |
|
360 |
+Content-Type: text/html\r\n\ |
|
361 |
+Content-Length: 118\r\n\ |
|
362 |
+\r\n\ |
|
363 |
+<title>500 Internal Server Error</title>\r\n\ |
|
364 |
+<h1>500 Internal Server Error</h1>\r\n\ |
|
365 |
+Internal error processing the request.\r\n\ |
|
366 |
+"}; |
|
367 |
+ static const char strnotimplemented[]={"\ |
|
368 |
+HTTP/1.1 501 Not Implemented\r\n\ |
|
369 |
+Content-Type: text/html\r\n\ |
|
370 |
+Content-Length: 132\r\n\ |
|
371 |
+\r\n\ |
|
372 |
+<title>501 Not Implemented</title>\r\n\ |
|
373 |
+<h1>501 Not Implemented</h1>\r\n\ |
|
374 |
+The request was not understood or is not allowed by this server.\r\n\ |
|
375 |
+"}; |
|
376 |
+ int res; |
|
377 |
+ _wk *web=(_wk *)paramweb; |
|
378 |
+ wk_client *client; |
|
379 |
+ if(web==NULL) |
|
380 |
+ return(-1); |
|
381 |
+ if((client=wk_clientget(web,connid))==NULL) |
|
382 |
+ return(-1); |
|
383 |
+ if(wkerror==wkerr_notfound) |
|
384 |
+ res=wk_write((wk *)web,connid,strnotfound,sizeof(strnotfound)-1); |
|
385 |
+ else if(wkerror==wkerr_notimplemented) |
|
386 |
+ res=wk_write((wk *)web,connid,strnotimplemented,sizeof(strnotimplemented)-1); |
|
387 |
+ else |
|
388 |
+ res=wk_write((wk *)web,connid,strinternal,sizeof(strinternal)-1); |
|
389 |
+ return(res); |
|
282 | 390 |
} |
283 | 391 |
|
284 | 392 |
int |
285 |
-wk_writestr(wk *paramweb, int connid, char *str) |
|
393 |
+wk_writestr(wk *paramweb, int connid, const char *str) |
|
286 | 394 |
{ |
287 | 395 |
return(wk_write(paramweb,connid,str,strlen(str))); |
288 | 396 |
} |
289 | 397 |
|
290 | 398 |
int |
291 |
-wk_write(wk *paramweb, int connid, void *data, int datalen) |
|
399 |
+wk_write(wk *paramweb, int connid, const void *data, int datalen) |
|
292 | 400 |
{ |
293 | 401 |
int k; |
294 | 402 |
_wk *web=(_wk *)paramweb; |
... | ... |
@@ -317,6 +425,8 @@ wk_write(wk *paramweb, int connid, void *data, int datalen) |
317 | 425 |
datalen-=added; |
318 | 426 |
total+=added; |
319 | 427 |
} |
428 |
+ if(total>0) |
|
429 |
+ sselect_addwrite(web->ssel,client->fd,(void *)client); |
|
320 | 430 |
return(total); |
321 | 431 |
} |
322 | 432 |
|
... | ... |
@@ -335,6 +445,8 @@ wk_close(wk *paramweb, int connid) |
335 | 445 |
FD_CLR(client->fd,&(web->fdset)); |
336 | 446 |
close(client->fd),client->fd=-1; |
337 | 447 |
} |
448 |
+ if(client->fdtoserve!=-1) |
|
449 |
+ close(client->fdtoserve),client->fdtoserve=-1; |
|
338 | 450 |
wk_clientrelease(web,connid); |
339 | 451 |
if(web->callback_event!=NULL) |
340 | 452 |
web->callback_event((wk *)web,connid,wke_closed,web->userptr); |
... | ... |
@@ -342,15 +454,32 @@ wk_close(wk *paramweb, int connid) |
342 | 454 |
} |
343 | 455 |
|
344 | 456 |
char * |
345 |
-wk_uri_getheader(wk_uri *wkuri, char *header, char *defaultvalue) |
|
457 |
+wk_uri_getheader(wk_uri *uri, char *header, char *defaultvalue) |
|
346 | 458 |
{ |
347 |
- |
|
459 |
+ int n,len; |
|
460 |
+ char *ptr; |
|
461 |
+ if(uri==NULL || uri->headers==NULL || header==NULL) |
|
462 |
+ return(NULL); |
|
463 |
+ len=strlen(header); |
|
464 |
+ for(n=0,ptr=uri->headers;*ptr!='\0';ptr++,n++) { |
|
465 |
+ if(memcmp(ptr,header,len)==0 && ptr[len]==':' && ptr[len+1]==' ') |
|
466 |
+ return(ptr+len+2); |
|
467 |
+ } |
|
468 |
+ return(defaultvalue); |
|
348 | 469 |
} |
349 | 470 |
|
350 | 471 |
char * |
351 |
-wk_uri_getheaderbynum(wk_uri *wkuri, int num) |
|
472 |
+wk_uri_getheaderbynum(wk_uri *uri, int num) |
|
352 | 473 |
{ |
353 |
- |
|
474 |
+ int n; |
|
475 |
+ char *ptr; |
|
476 |
+ if(uri==NULL || uri->headers==NULL) |
|
477 |
+ return(NULL); |
|
478 |
+ for(n=0,ptr=uri->headers;*ptr!='\0';ptr++,n++) { |
|
479 |
+ if(n==num) |
|
480 |
+ return(ptr); |
|
481 |
+ } |
|
482 |
+ return(NULL); |
|
354 | 483 |
} |
355 | 484 |
|
356 | 485 |
const char * |
... | ... |
@@ -584,6 +713,8 @@ wk_clientacquire(_wk *web) |
584 | 713 |
return(NULL); /* insufficient memory */ |
585 | 714 |
} |
586 | 715 |
client->usedoutbufids=1; |
716 |
+ client->fdtoserve=-1; |
|
717 |
+ client->headerbufid=-1; |
|
587 | 718 |
return(client); |
588 | 719 |
} |
589 | 720 |
|
... | ... |
@@ -604,6 +735,8 @@ wk_clientrelease(_wk *web, int connid) |
604 | 735 |
wk_sbufrelease((wk *)web,client->inbufid),client->inbufid=-1; |
605 | 736 |
for(w=0;w<client->usedoutbufids;w++) |
606 | 737 |
wk_sbufrelease((wk *)web,client->outbufids[w]),client->outbufids[w]=-1; |
738 |
+ if(client->headerbufid!=-1) |
|
739 |
+ wk_sbufrelease((wk *)web,client->headerbufid),client->headerbufid=-1; |
|
607 | 740 |
memset(client,0,sizeof(wk_client)); |
608 | 741 |
return(0); |
609 | 742 |
} |
... | ... |
@@ -624,9 +757,98 @@ wk_clientget(_wk *web, int connid) |
624 | 757 |
return(web->clientblocks[numblock].clients+j); |
625 | 758 |
} |
626 | 759 |
|
627 |
-static void |
|
760 |
+static char * |
|
761 |
+str_findfirstempty(char *ptr, int size) |
|
762 |
+{ |
|
763 |
+ int i; |
|
764 |
+ for(i=0;i<(size-3);i++) { |
|
765 |
+ if(ptr[0]=='\r' && ptr[1]=='\n' && ptr[2]=='\r' && ptr[3]=='\n') |
|
766 |
+ return(ptr); |
|
767 |
+ } |
|
768 |
+ return(NULL); |
|
769 |
+} |
|
770 |
+ |
|
771 |
+static int |
|
628 | 772 |
wk_clientserviceread(_wk *web, wk_client *client) |
629 | 773 |
{ |
630 |
-#warning TODO |
|
774 |
+ sbuf *in,*hbuf; |
|
775 |
+ char *end; |
|
776 |
+ char *ptr; |
|
777 |
+ char *lineend; |
|
778 |
+ char *sep; |
|
779 |
+ wk_uri *uri; |
|
780 |
+ /* check if we have all the headers */ |
|
781 |
+ if((in=wk_sbufget((wk *)web, client->inbufid))==NULL) |
|
782 |
+ return(-1); /* internal error */ |
|
783 |
+ sbuf_discard(in); |
|
784 |
+ if((end=str_findfirstempty(sbuf_ptr(in),sbuf_count(in)))==NULL) { |
|
785 |
+ if(sbuf_unused(in)==0) |
|
786 |
+ return(-1); /* header part too long */ |
|
787 |
+ /* uncomplete headers, have to wait for more data */ |
|
788 |
+ return(0); |
|
789 |
+ } |
|
790 |
+ /* get memory for the uri data */ |
|
791 |
+ if(client->headerbufid!=-1) |
|
792 |
+ wk_sbufrelease((wk *)web,client->headerbufid),client->headerbufid=-1; |
|
793 |
+ if((client->headerbufid=wk_sbufacquire((wk *)web))==-1) |
|
794 |
+ return(-1); /* insufficient memory */ |
|
795 |
+ if((hbuf=wk_sbufget((wk *)web,client->headerbufid))==NULL) |
|
796 |
+ return(-1); /* internal error */ |
|
797 |
+ /* prepare to fill the uri struct */ |
|
798 |
+ uri=&(client->uri); |
|
799 |
+ memset(uri,0,sizeof(wk_uri)); |
|
800 |
+ /* check that the method is supported */ |
|
801 |
+ ptr=sbuf_ptr(in); |
|
802 |
+ if(memcmp(ptr,"GET ",4)!=0 && memcmp(ptr,"PUT ",4)!=0 && memcmp(ptr,"POST ",5)!=0) |
|
803 |
+ return(-1); /* unknown method */ |
|
804 |
+ if((lineend=strchr(ptr,'\r'))!=NULL) |
|
805 |
+ *lineend='\0'; |
|
806 |
+ else |
|
807 |
+ lineend=end; |
|
808 |
+ /* method */ |
|
809 |
+ sep=strchr(ptr,' '); |
|
810 |
+ *sep='\0'; |
|
811 |
+ uri->method=sbuf_ptrunused(hbuf); |
|
812 |
+ sbuf_add(hbuf,ptr,strlen(ptr)+1); |
|
813 |
+ ptr+=strlen(ptr)+1; |
|
814 |
+ /* path */ |
|
815 |
+ if((sep=strchr(ptr,' '))==NULL) |
|
816 |
+ return(-1); /* no separator between path and protocol */ |
|
817 |
+ *sep='\0'; |
|
818 |
+ uri->path=sbuf_ptrunused(hbuf); |
|
819 |
+ sbuf_add(hbuf,ptr,strlen(ptr)+1); |
|
820 |
+ ptr+=strlen(ptr)+1; |
|
821 |
+ /* protocol */ |
|
822 |
+ uri->path=sbuf_ptrunused(hbuf); |
|
823 |
+ sbuf_add(hbuf,ptr,strlen(ptr)+1); |
|
824 |
+ ptr+=strlen(ptr)+1; |
|
825 |
+ /* headers */ |
|
826 |
+ *end='\0'; |
|
827 |
+ uri->headers=sbuf_ptrunused(hbuf); |
|
828 |
+ client->keepalive=0; |
|
829 |
+ while(ptr<end) { |
|
830 |
+ if(*ptr!='\n') |
|
831 |
+ return(-1); /* line is not ended with \r\n */ |
|
832 |
+ ptr++; |
|
833 |
+ if((lineend=strchr(ptr,'\r'))!=NULL) |
|
834 |
+ *lineend='\0'; |
|
835 |
+ else |
|
836 |
+ lineend=end; |
|
837 |
+ if((sep=strchr(ptr,':'))==NULL || sep[1]!=' ') |
|
838 |
+ return(-1); /* header not in format "name: value" */ |
|
839 |
+ /* check for keepalive header */ |
|
840 |
+ if(memcmp(ptr,"Connection: ",12)==0 && |
|
841 |
+ (strcmp(ptr+12,"keep-alive")==0 || strcmp(ptr+12,"Keep-Alive")==0)) |
|
842 |
+ client->keepalive=1; |
|
843 |
+ sbuf_add(hbuf,ptr,strlen(ptr)+1); |
|
844 |
+ ptr+=strlen(ptr)+1; |
|
845 |
+ } |
|
846 |
+ /* add header terminator */ |
|
847 |
+ sbuf_add(hbuf,"",1); |
|
848 |
+ /* call the http method */ |
|
849 |
+ client->serviced=1; |
|
850 |
+ client->continuationactive=0; |
|
851 |
+ client->continuationactive=web->callback_http((wk *)web, client->connid, uri, web->userptr); |
|
852 |
+ return(0); |
|
631 | 853 |
} |
632 | 854 |
|
... | ... |
@@ -53,8 +53,8 @@ int wk_service(wk *web); /* To be called after sselelect_wait() but before ssele |
53 | 53 |
int wk_serve_buffer_as_file(wk *web, int connid, void *data, int datalen, const char *mime); |
54 | 54 |
int wk_serve_file(wk *web, int connid, char *filename, const char *mime); |
55 | 55 |
int wk_serve_error(wk *web, int connid, wk_error wkerror); |
56 |
-int wk_writestr(wk *web, int connid, char *str); |
|
57 |
-int wk_write(wk *web, int connid, void *data, int datalen); |
|
56 |
+int wk_writestr(wk *web, int connid, const char *str); |
|
57 |
+int wk_write(wk *web, int connid, const void *data, int datalen); |
|
58 | 58 |
int wk_close(wk *web, int connid); |
59 | 59 |
|
60 | 60 |
char *wk_uri_getheader(wk_uri *wkuri, char *header, char *defaultvalue); |