... | ... |
@@ -111,6 +111,37 @@ static int wk_postset(_wk *web, wk_client *client,char *varname, char *data, int |
111 | 111 |
static char *wk_postget(_wk *web, wk_client *client,char *varname, int *isfile); |
112 | 112 |
static int wk_postfree(_wk *web, wk_client *client); |
113 | 113 |
|
114 |
+#ifdef WK_DEBUG_IO |
|
115 |
+#define DEBUG_IN_PRE { int sbp=sbuf_count(in); |
|
116 |
+#define DEBUG_IN_POST wk_debug_io("READ",fd,sbuf_ptr(in)+sbp,sbuf_count(in)-sbp); } |
|
117 |
+#define DEBUG_OUT_PRE { int sbu=out->got; |
|
118 |
+#define DEBUG_OUT_POST wk_debug_io("WRITTEN",fd,out->buf+sbu,out->got-sbu); } |
|
119 |
+ |
|
120 |
+static void |
|
121 |
+wk_debug_io(char *iotype, int fd, char *ptr, long int size) |
|
122 |
+{ |
|
123 |
+ int n,c; |
|
124 |
+ fprintf(stderr,"%s %li bytes on %i:",iotype,size,fd); |
|
125 |
+ for(n=0;n<size;n++) { |
|
126 |
+ c=((unsigned char *)ptr)[n]; |
|
127 |
+ if(c=='\r' || c=='\n') |
|
128 |
+ fprintf(stderr,"\\%c",(c=='\r')?'r':'n'); |
|
129 |
+ else if(c<' ' || c>'~') |
|
130 |
+ fprintf(stderr,"\\x%02X",c); |
|
131 |
+ else |
|
132 |
+ fprintf(stderr,"%c",c); |
|
133 |
+ } |
|
134 |
+ fprintf(stderr,"\n"); |
|
135 |
+} |
|
136 |
+ |
|
137 |
+#else |
|
138 |
+#define DEBUG_IN_PRE |
|
139 |
+#define DEBUG_IN_POST |
|
140 |
+#define DEBUG_OUT_PRE |
|
141 |
+#define DEBUG_OUT_POST |
|
142 |
+#endif |
|
143 |
+ |
|
144 |
+ |
|
114 | 145 |
wk * |
115 | 146 |
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_post)(/*wk *web,int connid, wk_uri *uri, void *userptr*/), wk_action (*callback_continuation)(/*wk *web,int connid, wk_uri *uri, void *userptr*/), void *userptr) |
116 | 147 |
{ |
... | ... |
@@ -236,13 +267,16 @@ wk_service(wk *paramweb) |
236 | 267 |
for(i=0;i<n;i++) { |
237 | 268 |
fd=fds[i]; |
238 | 269 |
if(fd==web->serverfd) { |
239 |
- /* accept new connection */ |
|
240 |
- if((client=wk_accept(web))!=NULL && web->callback_event!=NULL) |
|
241 |
- web->callback_event((wk *)web,client->connid,wke_connected,web->userptr); |
|
270 |
+ do { |
|
271 |
+ /* accept new connection */ |
|
272 |
+ if((client=wk_accept(web))!=NULL && web->callback_event!=NULL) |
|
273 |
+ web->callback_event((wk *)web,client->connid,wke_connected,web->userptr); |
|
274 |
+ } while(sock_readable(fd)==0); |
|
242 | 275 |
continue; /* all done here */ |
243 | 276 |
} |
244 | 277 |
if((client=(wk_client *)sselect_getuserptr(web->ssel,fd))==NULL || client->web!=(wk *)web) { |
245 |
- wk_close((wk *)web,client->connid); |
|
278 |
+ sselect_delread(web->ssel,fd); |
|
279 |
+ close(fd),fd=-1; |
|
246 | 280 |
continue; /* internal error */ |
247 | 281 |
} |
248 | 282 |
if((in=wk_sbufget((wk *) web,client->inbufid))==NULL) { |
... | ... |
@@ -255,11 +289,13 @@ wk_service(wk *paramweb) |
255 | 289 |
sselect_delread(web->ssel,fd); |
256 | 290 |
continue; |
257 | 291 |
} |
292 |
+ DEBUG_IN_PRE; |
|
258 | 293 |
if(sbuf_fill(in,fd,sock_queued(fd))==0) { |
259 | 294 |
/* client has closed connection */ |
260 | 295 |
wk_close((wk *) web, client->connid); |
261 | 296 |
continue; |
262 | 297 |
} |
298 |
+ DEBUG_IN_POST; |
|
263 | 299 |
if(client->status==wkc_header) { |
264 | 300 |
if(wk_clientservicereadheader(web,client)==-1) { |
265 | 301 |
/* internal error, protocol error or no enough memory */ |
... | ... |
@@ -288,7 +324,9 @@ wk_service(wk *paramweb) |
288 | 324 |
wk_close((wk *)web,client->connid); |
289 | 325 |
continue; /* internal error */ |
290 | 326 |
} |
327 |
+ DEBUG_OUT_PRE; |
|
291 | 328 |
sbuf_send(out,fd,sbuf_count(out)); |
329 |
+ DEBUG_OUT_POST; |
|
292 | 330 |
/* if we are serving from file, load the next chunk */ |
293 | 331 |
if(client->fdtoserve!=-1 && client->usedoutbufids==1) { |
294 | 332 |
sbuf_discard(out); |
... | ... |
@@ -314,8 +352,8 @@ wk_service(wk *paramweb) |
314 | 352 |
client->continuationactive=web->callback_continuation((wk *)web,client->connid,&(client->uri),web->userptr); |
315 | 353 |
} else { |
316 | 354 |
client->uriready=0; /* we have finished servicing this one */ |
317 |
- if(!client->keepalive) |
|
318 |
- wk_close((wk *)web, fd); /* all sent */ |
|
355 |
+ if(client->keepalive==0) |
|
356 |
+ wk_close((wk *)web, client->connid); /* all sent */ |
|
319 | 357 |
} |
320 | 358 |
} |
321 | 359 |
} |
... | ... |
@@ -335,7 +373,7 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const |
335 | 373 |
return(-1); |
336 | 374 |
if((client=wk_clientget(web,connid))==NULL) |
337 | 375 |
return(-1); |
338 |
- wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n"); |
|
376 |
+ wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n"); |
|
339 | 377 |
sprintf(buf,"Content-Length: %i\r\n",datalen); |
340 | 378 |
wk_writestr((wk *)web,connid,buf); |
341 | 379 |
if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
... | ... |
@@ -744,7 +782,7 @@ wk_sbufrelease(wk *paramweb, int sbufid) |
744 | 782 |
return(-1); |
745 | 783 |
numblock=sbufid/BUFBLOCK; |
746 | 784 |
j=sbufid%BUFBLOCK; |
747 |
- bit=0x1<<(j&3); |
|
785 |
+ bit=0x1<<(j&7); |
|
748 | 786 |
if((buf=wk_sbufget(web,sbufid))==NULL) |
749 | 787 |
return(-1); |
750 | 788 |
web->bufblocks[numblock].usedbufs--; |
... | ... |
@@ -763,7 +801,7 @@ wk_sbufget(wk *paramweb, int sbufid) |
763 | 801 |
return(NULL); |
764 | 802 |
numblock=sbufid/BUFBLOCK; |
765 | 803 |
j=sbufid%BUFBLOCK; |
766 |
- bit=0x1<<(j&3); |
|
804 |
+ bit=0x1<<(j&7); |
|
767 | 805 |
if(web==NULL || |
768 | 806 |
web->bufblocks==NULL || |
769 | 807 |
web->sizebufblocks<=numblock || |
... | ... |
@@ -871,7 +909,7 @@ wk_clientrelease(_wk *web, int connid) |
871 | 909 |
int w; |
872 | 910 |
numblock=connid/CLIENTBLOCK; |
873 | 911 |
j=connid%CLIENTBLOCK; |
874 |
- bit=0x1<<(j&3); |
|
912 |
+ bit=0x1<<(j&7); |
|
875 | 913 |
if((client=wk_clientget(web,connid))==NULL) |
876 | 914 |
return(-1); |
877 | 915 |
web->clientblocks[numblock].usedclients--; |
... | ... |
@@ -893,7 +931,7 @@ wk_clientget(_wk *web, int connid) |
893 | 931 |
int numblock,j,bit; |
894 | 932 |
numblock=connid/CLIENTBLOCK; |
895 | 933 |
j=connid%CLIENTBLOCK; |
896 |
- bit=0x1<<(j&3); |
|
934 |
+ bit=0x1<<(j&7); |
|
897 | 935 |
if(web==NULL || |
898 | 936 |
web->clientblocks==NULL || |
899 | 937 |
web->sizeclientblocks<=numblock || |
... | ... |
@@ -974,7 +1012,10 @@ wk_clientservicereadheader(_wk *web, wk_client *client) |
974 | 1012 |
/* headers */ |
975 | 1013 |
*end='\0'; |
976 | 1014 |
uri->headers=sbuf_ptrunused(hbuf); |
977 |
- client->keepalive=0; |
|
1015 |
+ if(strcmp(uri->protocol,"HTTP/0.9")==0 || strcmp(uri->protocol,"HTTP/1.0")==0) |
|
1016 |
+ client->keepalive=0; |
|
1017 |
+ else |
|
1018 |
+ client->keepalive=1; /* default for http/1.1 */ |
|
978 | 1019 |
while(ptr<end) { |
979 | 1020 |
if(*ptr!='\n') |
980 | 1021 |
return(-1); /* line is not ended with \r\n */ |
... | ... |
@@ -994,6 +1035,8 @@ wk_clientservicereadheader(_wk *web, wk_client *client) |
994 | 1035 |
} |
995 | 1036 |
/* add header terminator */ |
996 | 1037 |
sbuf_add(hbuf,"",1); |
1038 |
+ /* mark data as used */ |
|
1039 |
+ sbuf_getbytes(in,end-sbuf_ptr(in)+4); |
|
997 | 1040 |
/* call the http method */ |
998 | 1041 |
client->uriready=1; |
999 | 1042 |
client->continuationactive=0; |
... | ... |
@@ -30,6 +30,7 @@ char *socklib_connect(test_action action); |
30 | 30 |
char *socklib_sselect(test_action action); |
31 | 31 |
char *sbuf_memory(test_action action); |
32 | 32 |
char *webkernel_basic(test_action action); |
33 |
+char *webkernel_dual(test_action action); |
|
33 | 34 |
|
34 | 35 |
|
35 | 36 |
struct { |
... | ... |
@@ -39,6 +40,7 @@ struct { |
39 | 40 |
{socklib_sselect}, |
40 | 41 |
{sbuf_memory}, |
41 | 42 |
{webkernel_basic}, |
43 |
+ {webkernel_dual}, |
|
42 | 44 |
}; |
43 | 45 |
|
44 | 46 |
int |
... | ... |
@@ -48,8 +50,10 @@ main(int argc, char *argv[]) |
48 | 50 |
int flagall; |
49 | 51 |
char *resstr; |
50 | 52 |
int total,totalfail; |
51 |
- if(argc==1 || strcmp(argv[argc-1],"--help")==0 || argc!=2) { |
|
52 |
- printf("Syntax:\n\t%s { --help | --list | test_name | all }\nNOTE: test_name is one of the tests listed in --list\n",argv[0]); |
|
53 |
+ int n; |
|
54 |
+ char *test; |
|
55 |
+ if(argc==1 || strcmp(argv[argc-1],"--help")==0 || argc<2) { |
|
56 |
+ printf("Syntax:\n\t%s { --help | --list | all | test_name [ test_name [...]] }\nNOTE: test_name is one of the tests listed in --list\n",argv[0]); |
|
53 | 57 |
return(0); |
54 | 58 |
} |
55 | 59 |
if(strcmp(argv[argc-1],"--list")==0) { |
... | ... |
@@ -58,8 +62,12 @@ main(int argc, char *argv[]) |
58 | 62 |
return(0); |
59 | 63 |
} |
60 | 64 |
flagall=(strcmp(argv[argc-1],"all")==0)?1:0; |
61 |
- for(total=totalfail=0,i=0;i<(sizeof(tests)/sizeof(tests[0]));i++) { |
|
62 |
- if(!flagall && strcmp(tests[i].test(test_name),argv[argc-1])!=0) |
|
65 |
+ total=totalfail=0; |
|
66 |
+ for(n=(flagall)?0:1;(flagall==0 && n<argc) || (flagall!=0 && n<(sizeof(tests)/sizeof(tests[0])));n++) { |
|
67 |
+ test=(flagall!=0)?tests[n].test(test_name):argv[n]; |
|
68 |
+ for(i=0;i<(sizeof(tests)/sizeof(tests[0])) && strcmp(tests[i].test(test_name),test)!=0;i++) |
|
69 |
+ ; |
|
70 |
+ if(i>=(sizeof(tests)/sizeof(tests[0]))) |
|
63 | 71 |
continue; |
64 | 72 |
printf("%20s...",tests[i].test(test_name)); |
65 | 73 |
fflush(stdout); |
... | ... |
@@ -69,7 +77,7 @@ main(int argc, char *argv[]) |
69 | 77 |
printf("%s\n",resstr); |
70 | 78 |
|
71 | 79 |
} |
72 |
- if(!flagall && i>=(sizeof(tests)/sizeof(tests[0]))) { |
|
80 |
+ if(total==0) { |
|
73 | 81 |
printf("ERROR: test not found\n"); |
74 | 82 |
return(1); |
75 | 83 |
} |
... | ... |
@@ -353,12 +361,17 @@ wk_action |
353 | 361 |
webkernel_basichttp(wk *web, int connid, wk_uri *uri, void *userptr) |
354 | 362 |
{ |
355 | 363 |
|
356 |
- *((int *)userptr)=0; |
|
357 | 364 |
char reply_ok[]={"Ok"}; |
365 |
+#if 1 |
|
366 |
+ printf("CALLBACK! (check is %i, 0x%p), uri->path:%s\n",(*((int *)userptr)),(void *)userptr,uri->path); |
|
367 |
+#endif |
|
358 | 368 |
if(strcmp(uri->path,"/test.cgi")==0) { |
359 |
- *((int *)userptr)=1; |
|
369 |
+ (*((int *)userptr))=(*((int *)userptr))+1; |
|
360 | 370 |
wk_serve_buffer_as_file(web,connid,reply_ok,sizeof(reply_ok)-1,mime_getdefault("test.txt",NULL)); |
361 | 371 |
} |
372 |
+#if 1 |
|
373 |
+ printf("check is now %i\n",(*((int *)userptr))); |
|
374 |
+#endif |
|
362 | 375 |
return(wkact_finished); |
363 | 376 |
} |
364 | 377 |
|
... | ... |
@@ -452,7 +465,7 @@ Connection: keep-alive\r\n\ |
452 | 465 |
/* reply_in_wk -> socket */ |
453 | 466 |
if(sselect_wait(ssel,timeout)!=1) { |
454 | 467 |
webkernel_basicclose(&client,&ssel,&host,&web); |
455 |
- return(STRING_FAIL ": timeout on sselect_wait (after client request)\n"); |
|
468 |
+ return(STRING_FAIL ": (2) timeout on sselect_wait (after client request)\n"); |
|
456 | 469 |
} |
457 | 470 |
wk_service(web); |
458 | 471 |
/* client read availability */ |
... | ... |
@@ -483,3 +496,170 @@ Connection: keep-alive\r\n\ |
483 | 496 |
return(STRING_OK); |
484 | 497 |
} |
485 | 498 |
|
499 |
+void |
|
500 |
+webkernel_dualclose(int *clients,int sizeclients,sselect **ssel, char **host, wk **web) |
|
501 |
+{ |
|
502 |
+ int c; |
|
503 |
+ for(c=0;c<sizeclients;c++) { |
|
504 |
+ if(clients[c]!=-1) |
|
505 |
+ close(clients[c]),clients[c]=-1; |
|
506 |
+ } |
|
507 |
+ if(*host!=NULL) |
|
508 |
+ free(*host),*host=NULL; |
|
509 |
+ if(*web!=NULL) |
|
510 |
+ wk_free(*web),*web=NULL; |
|
511 |
+ if(*ssel!=NULL) |
|
512 |
+ sselect_free(*ssel),*ssel=NULL; |
|
513 |
+} |
|
514 |
+ |
|
515 |
+ |
|
516 |
+char * |
|
517 |
+webkernel_dual(test_action action) |
|
518 |
+{ |
|
519 |
+ wk *web; |
|
520 |
+ int port; |
|
521 |
+ int off; |
|
522 |
+ int check; |
|
523 |
+ sselect *ssel; |
|
524 |
+ int clients[2]; |
|
525 |
+ int c; |
|
526 |
+ char *host; |
|
527 |
+ long hostsize; |
|
528 |
+ int timeout; |
|
529 |
+ int fds[2]; |
|
530 |
+ char buf[128]; |
|
531 |
+ int usedbuf; |
|
532 |
+ char test_request[]={"\ |
|
533 |
+GET /test.cgi HTTP/1.0\r\n\ |
|
534 |
+Host: localhost\r\n\ |
|
535 |
+Connection: keep-alive\r\n\ |
|
536 |
+\r\n\ |
|
537 |
+"}; |
|
538 |
+ if(action==test_name) |
|
539 |
+ return("webkernel_dual"); |
|
540 |
+ else if(action==test_description) |
|
541 |
+ return("webkernel multiple simultaneous connections"); |
|
542 |
+ for(c=0;c<(sizeof(clients)/sizeof(clients[0]));c++) |
|
543 |
+ clients[c]=-1; |
|
544 |
+ ssel=NULL; |
|
545 |
+ host=NULL; |
|
546 |
+ web=NULL; |
|
547 |
+ timeout=100; |
|
548 |
+ check=0; |
|
549 |
+#if 1 |
|
550 |
+printf("\n"); |
|
551 |
+#endif |
|
552 |
+ if((ssel=sselect_init())==NULL) |
|
553 |
+ return(STRING_FAIL ": couln't alloc a sselect structure"); |
|
554 |
+ for(port=19747,off=0;(web=wk_init(port,ssel,NULL,webkernel_basichttp,NULL,NULL,&check))==NULL;off++,port++) |
|
555 |
+ ; |
|
556 |
+ if(web==NULL) { |
|
557 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
558 |
+ return(STRING_FAIL ": couln't find a free port to init webkernel"); |
|
559 |
+ } |
|
560 |
+ if((host=ipv4_genip("localhost",&hostsize))==NULL) { |
|
561 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
562 |
+ return(STRING_FAIL ": couldn't resove localhost"); |
|
563 |
+ } |
|
564 |
+ for(c=0;c<(sizeof(clients)/sizeof(clients[0]));c++) { |
|
565 |
+ if((clients[c]=ipv4_preconnect(host,hostsize,port))==-1) { |
|
566 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
567 |
+ return(STRING_FAIL ": couldn't connect to server\n"); |
|
568 |
+ } |
|
569 |
+ if(ipv4_connect(clients[c],timeout)==-1) { |
|
570 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
571 |
+ return(STRING_FAIL ": timeout on connect\n"); |
|
572 |
+ } |
|
573 |
+ ipv4_postconnect(clients[c]); |
|
574 |
+ } |
|
575 |
+ /* accept the connection */ |
|
576 |
+#if 1 |
|
577 |
+printf("0. fd[0]=%i, fd[1]=%i\n",clients[0],clients[1]); |
|
578 |
+#endif |
|
579 |
+#if 1 |
|
580 |
+printf("1. sselect_wait\n"); |
|
581 |
+#endif |
|
582 |
+ if(sselect_wait(ssel,timeout)!=1) { |
|
583 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
584 |
+ return(STRING_FAIL ": timeout on sselect_wait\n"); |
|
585 |
+ } |
|
586 |
+#if 1 |
|
587 |
+printf("2. wk_service\n"); |
|
588 |
+#endif |
|
589 |
+ wk_service(web); |
|
590 |
+#if 1 |
|
591 |
+printf("3. sselect_getread\n"); |
|
592 |
+#endif |
|
593 |
+ if(sselect_getread(ssel,fds,sizeof(fds)/sizeof(fds[0]))==1) { |
|
594 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
595 |
+ return(STRING_FAIL ": wk_service hasn't serviced the server connection\n"); |
|
596 |
+ } |
|
597 |
+ /* client does request into socket */ |
|
598 |
+#if 1 |
|
599 |
+printf("4. write\n"); |
|
600 |
+#endif |
|
601 |
+ for(c=0;c<(sizeof(clients)/sizeof(clients[0]));c++) |
|
602 |
+ write(clients[c],test_request,sizeof(test_request)-1); |
|
603 |
+ /* socket-> callback_http -> reply_in_wk */ |
|
604 |
+#if 1 |
|
605 |
+printf("5. sselect_wait\n"); |
|
606 |
+#endif |
|
607 |
+ if(sselect_wait(ssel,timeout)!=2) { |
|
608 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
609 |
+ return(STRING_FAIL ": timeout on sselect_wait (after client request)\n"); |
|
610 |
+ } |
|
611 |
+#if 1 |
|
612 |
+printf("6. wk_service\n"); |
|
613 |
+#endif |
|
614 |
+ wk_service(web); |
|
615 |
+#if 1 |
|
616 |
+printf("check is %i\n",check); |
|
617 |
+#endif |
|
618 |
+ if(check!=2) { |
|
619 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
620 |
+ return(STRING_FAIL ": http callback was not called\n"); |
|
621 |
+ } |
|
622 |
+ /* reply_in_wk -> socket */ |
|
623 |
+#if 1 |
|
624 |
+printf("7. sselect_wait\n"); |
|
625 |
+#endif |
|
626 |
+ if(sselect_wait(ssel,timeout)!=2) { |
|
627 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
628 |
+ return(STRING_FAIL ": (2) timeout on sselect_wait (after client request)\n"); |
|
629 |
+ } |
|
630 |
+#if 1 |
|
631 |
+printf("8. wk_service\n"); |
|
632 |
+#endif |
|
633 |
+ wk_service(web); |
|
634 |
+ /* client read availability */ |
|
635 |
+ for(c=0;c<(sizeof(clients)/sizeof(clients[0]));c++) |
|
636 |
+ sselect_addread(ssel,clients[c],NULL); |
|
637 |
+ if(sselect_wait(ssel,timeout)!=2) { |
|
638 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
639 |
+ return(STRING_FAIL ": timeout on sselect_wait (to read client reply)\n"); |
|
640 |
+ } |
|
641 |
+ wk_service(web); |
|
642 |
+ if(sselect_getread(ssel,fds,sizeof(fds)/sizeof(fds[0]))!=2) { |
|
643 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
644 |
+ return(STRING_FAIL ": client read not detected\n"); |
|
645 |
+ } |
|
646 |
+ /* read data */ |
|
647 |
+ for(c=0;c<(sizeof(clients)/sizeof(clients[0]));c++) { |
|
648 |
+ if((usedbuf=read(clients[c],buf,sizeof(buf)-1))<0) { |
|
649 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
650 |
+ return(STRING_FAIL ": couldn't read reply\n"); |
|
651 |
+ } |
|
652 |
+ buf[usedbuf]='\0'; |
|
653 |
+ if(usedbuf<2 || memcmp(buf+usedbuf-2,"Ok",2)!=0) { |
|
654 |
+ webkernel_dualclose(clients,sizeof(clients)/sizeof(clients[0]),&ssel,&host,&web); |
|
655 |
+ return(STRING_FAIL ": corrupted data in read on client\n"); |
|
656 |
+ } |
|
657 |
+ } |
|
658 |
+ for(c=0;c<(sizeof(clients)/sizeof(clients[0]));c++) |
|
659 |
+ close(clients[c]),clients[c]=-1; |
|
660 |
+ wk_free(web),web=NULL; |
|
661 |
+ sselect_free(ssel),ssel=NULL; |
|
662 |
+ free(host),host=NULL; |
|
663 |
+ return(STRING_OK); |
|
664 |
+} |
|
665 |
+ |