Browse code

webkernel: when accepting sockets, do a sock_setsafe() on them just in case the server socket is unsafe (if socket is unsafe, that is NOLINGER, the last bytes of a reply would not be sent)

Dario Rodriguez authored on 18/05/2015 19:41:18
Showing 1 changed files
... ...
@@ -1072,6 +1072,7 @@ wk_accept(_wk *web)
1072 1072
                 return(NULL);
1073 1073
         }
1074 1074
         client->fd=newfd;
1075
+        sock_setsafe(client->fd);
1075 1076
         DEBUG_CONN(("WEBK","wk_accept: connid: %i, fd: %i",client->connid,client->fd));
1076 1077
         FD_SET(client->fd,&(web->fdset));
1077 1078
         sselect_addread(web->ssel,client->fd,(void *)client);
Browse code

webkernel: add wk_serve_generic_headers to write only the headers; the data must be written later with wk_write (unless etagnotmodified is true, as that means the reply was 304 Not modified)

Dario Rodriguez authored on 18/05/2015 17:14:13
Showing 1 changed files
... ...
@@ -463,7 +463,7 @@ wk_serve_etagset(wk *paramweb, int connid, char *etag)
463 463
 }
464 464
 
465 465
 int
466
-wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime)
466
+wk_serve_generic_headers(wk *paramweb, int connid, int datalen, const char *mime, int *etagnotmodified)
467 467
 {
468 468
         static const char *strcontenttype={"Content-Type: "};
469 469
         _wk *web=(_wk *)paramweb;
... ...
@@ -476,6 +476,8 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const
476 476
         if((client=wk_clientget(web,connid))==NULL)
477 477
                 return(-1);
478 478
         cachedetag=(wk_etagnotmodified(web,client)==0)?1:0;
479
+        if(etagnotmodified!=NULL)
480
+                *etagnotmodified=cachedetag;
479 481
         if(!cachedetag)
480 482
                 wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n");
481 483
         else
... ...
@@ -505,6 +507,20 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const
505 507
         if(client->keepalive)
506 508
                 wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n");
507 509
         wk_writestr((wk *)web,connid,"\r\n");
510
+        return(0);
511
+}
512
+
513
+int
514
+wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime)
515
+{
516
+        _wk *web=(_wk *)paramweb;
517
+        int cachedetag;
518
+        int res;
519
+        if(web==NULL || datalen<0 || (data==NULL && datalen>0))
520
+                return(-1);
521
+        res=wk_serve_generic_headers((wk *)web,connid,datalen,mime,&cachedetag);
522
+        if(res!=0)
523
+                return(res);
508 524
         if(!cachedetag)
509 525
                 return(wk_write((wk *)web,connid,data,datalen));
510 526
         return(0);
Browse code

Finish POST implementation with application/x-www-form-urlencoded variables

Dario Rodriguez authored on 05/05/2015 19:08:21
Showing 1 changed files
... ...
@@ -1198,6 +1198,7 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
1198 1198
         char *sep;
1199 1199
         wk_uri *uri;
1200 1200
         wk_action action;
1201
+        int flagusepostcallback;
1201 1202
         if((in=wk_sbufget((wk *)web, client->inbufid))==NULL)
1202 1203
                 return(-1); /* internal error */
1203 1204
         /* get memory for the uri data */
... ...
@@ -1276,15 +1277,20 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
1276 1277
         sbuf_add(hbuf,"",1);
1277 1278
         /* mark data as used */
1278 1279
         sbuf_getbytes(in,end-sbuf_ptr(in)+4);
1279
-        /* call the http method */
1280
+        /* call the http method if GET (or not post callback) , or the post method if POST */
1280 1281
         client->uriready=1;
1281 1282
         client->continuationactive=0;
1282
-        action=web->callback_http((wk *)web, client->connid, uri, web->userptr);
1283
+        flagusepostcallback=(strcmp(client->uri.method,"POST")==0 && web->callback_post!=NULL)?1:0;
1284
+        if(flagusepostcallback) {
1285
+                action=web->callback_post((wk *)web, client->connid, uri, web->userptr);
1286
+        } else {
1287
+                action=web->callback_http((wk *)web, client->connid, uri, web->userptr);
1288
+        }
1283 1289
         if(action==wkact_continuation) {
1284 1290
                 client->uriready=1;
1285 1291
                 client->continuationactive=1;
1286 1292
                 client->status=wkc_header;
1287
-        } else if(action==wkact_post && web->callback_post!=NULL) {
1293
+        } else if(flagusepostcallback) {
1288 1294
                 char *lenvar;
1289 1295
                 char *contenttype;
1290 1296
                 if(strcmp(client->uri.method,"POST")!=0 ||
... ...
@@ -1354,7 +1360,7 @@ wk_clientservicereadpost(_wk *web, wk_client *client)
1354 1360
                         sbuf_getbytes(in,end-start);
1355 1361
                         client->pendingpost-=(end-start);
1356 1362
                 }
1357
-                if(*sep=='&') {
1363
+                if(sep!=NULL && *sep=='&') {
1358 1364
                         sbuf_getbytes(in,1);
1359 1365
                         client->pendingpost--;
1360 1366
                         client->inpostvar=-1;
... ...
@@ -1362,14 +1368,14 @@ wk_clientservicereadpost(_wk *web, wk_client *client)
1362 1368
         }
1363 1369
         if(client->pendingpost>0)
1364 1370
                 return(0); /* nothing more to do for now*/
1365
-        /* call the post method */
1371
+        /* call the http method */
1366 1372
         client->uriready=1;
1367 1373
         client->continuationactive=0;
1368
-        action=web->callback_post((wk *)web, client->connid, client->uri, web->userptr);
1374
+        action=web->callback_http((wk *)web, client->connid, &(client->uri), web->userptr);
1369 1375
         if(action==wkact_continuation) {
1370 1376
                 client->uriready=1;
1371 1377
                 client->continuationactive=1;
1372
-                client->status=wkc_header;
1378
+                client->status=wkc_post;
1373 1379
         } else {
1374 1380
                 client->uriready=1;
1375 1381
                 client->continuationactive=0;
... ...
@@ -1407,15 +1413,16 @@ wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile)
1407 1413
                 return(-1); /* varname too long */
1408 1414
         }
1409 1415
         post->name=sbuf_ptrunused(buf);
1410
-        sbuf_addstr(buf,varname);
1416
+        sbuf_add(buf,varname,strlen(varname)+1);
1411 1417
         if(tofile!=NULL) {
1412 1418
                 if((strlen(tofile)+1)>(sbuf_unused(buf))) {
1413 1419
                         wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1;
1414 1420
                         return(-1); /* varname+tofile too long */
1415 1421
                 }
1416 1422
                 post->tofile=sbuf_ptrunused(buf);
1417
-                sbuf_addstr(buf,tofile);
1423
+                sbuf_add(buf,tofile,strlen(tofile)+1);
1418 1424
         }
1425
+        client->usedpost++;
1419 1426
         post->value=NULL;
1420 1427
         post->filewritten=0;
1421 1428
         post->valueterminated=0;
Browse code

webkernel: make uri_urldecode to unescape correctly normal ASCII characters (i.e. %40 to @)

Dario Rodriguez authored on 23/07/2014 20:34:28
Showing 1 changed files
... ...
@@ -930,10 +930,15 @@ uri_urldecode(char *s)
930 930
                         s[o]=' ';
931 931
                 else if(s[i]=='%' && (a=s[i+1])!='\0' && (b=s[i+2])!='\0' && ISHEXNIBBLE(a) && ISHEXNIBBLE(b)) {
932 932
                         n=(HEXNIBBLE2BIN(a)<<4)|HEXNIBBLE2BIN(b);
933
-                        s[o]=128|64|(n>>6);
934
-                        s[o+1]=128|(n&0x3f);
935
-                        i+=2;
936
-                        o++;
933
+                        if(n>=128) {
934
+                                s[o]=128|64|(n>>6);
935
+                                s[o+1]=128|(n&0x3f);
936
+                                i+=2;
937
+                                o++;
938
+                        } else {
939
+                                s[o]=n;
940
+                                i+=2;
941
+                        }
937 942
                 } else
938 943
                         s[o]=s[i];
939 944
         }
Browse code

webkernel: add uri_urldecode (taken from my unreleased vdrsyncts)

Dario Rodriguez authored on 23/07/2014 20:13:42
Showing 1 changed files
... ...
@@ -33,6 +33,10 @@
33 33
 #define ALIVETIMEOUT 15
34 34
 #define MAXETAGSIZE 127
35 35
 
36
+#define HEXNIBBLE2BIN(a) (((a)>='0' && (a)<='9')?(a)-'0':((a)>='a' && (a)<='f')?(a)-'a'+10:((a)>='A' && (a)<='F')?(a)-'A'+10:0)
37
+#define ISHEXNIBBLE(a) ((((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))?1:0)
38
+
39
+
36 40
 typedef struct wk_post {
37 41
         char *name;
38 42
         char *value;
... ...
@@ -916,6 +920,28 @@ mime_getdefault(const char *filename, const char *defaultmime)
916 920
         return(defaultmime);
917 921
 }
918 922
 
923
+int
924
+uri_urldecode(char *s)
925
+{
926
+        int i,o;
927
+        int a,b,n;
928
+        for(i=0,o=0;s[i]!='\0';i++,o++) {
929
+                if(s[i]=='+')
930
+                        s[o]=' ';
931
+                else if(s[i]=='%' && (a=s[i+1])!='\0' && (b=s[i+2])!='\0' && ISHEXNIBBLE(a) && ISHEXNIBBLE(b)) {
932
+                        n=(HEXNIBBLE2BIN(a)<<4)|HEXNIBBLE2BIN(b);
933
+                        s[o]=128|64|(n>>6);
934
+                        s[o+1]=128|(n&0x3f);
935
+                        i+=2;
936
+                        o++;
937
+                } else
938
+                        s[o]=s[i];
939
+        }
940
+        s[o]='\0';
941
+        return(0);
942
+}
943
+
944
+
919 945
 int
920 946
 wk_sbufacquire(wk *paramweb)
921 947
 {
Browse code

webkernel: add etag support (so the the browser can use cached pages)

Dario Rodriguez authored on 16/07/2014 13:27:49
Showing 1 changed files
... ...
@@ -31,6 +31,7 @@
31 31
 #define BUFBLOCKBLOCK 256
32 32
 #define POSTBLOCK 16
33 33
 #define ALIVETIMEOUT 15
34
+#define MAXETAGSIZE 127
34 35
 
35 36
 typedef struct wk_post {
36 37
         char *name;
... ...
@@ -67,6 +68,7 @@ typedef struct wk_client {
67 68
         int pendingpost;
68 69
         int inpostvar;
69 70
         int cookiebufid;
71
+        char etag[MAXETAGSIZE+1];
70 72
         time_t lastio;
71 73
 } wk_client;
72 74
 
... ...
@@ -117,6 +119,7 @@ static int wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile);
117 119
 static int wk_postset(_wk *web, wk_client *client,char *varname, char *data, int datalen);
118 120
 static char *wk_postget(_wk *web, wk_client *client,char *varname, int *isfile);
119 121
 static int wk_postfree(_wk *web, wk_client *client);
122
+static int wk_etagnotmodified(_wk *web, wk_client *client);
120 123
 
121 124
 #ifdef WK_DEBUG_IO
122 125
 #define DEBUG_IN_PRE { int sbp=sbuf_count(in);
... ...
@@ -438,6 +441,22 @@ wk_serve_cookieadd(wk *paramweb, int connid, char *cookiename, char *value, char
438 441
         return(0);
439 442
 }
440 443
 
444
+int
445
+wk_serve_etagset(wk *paramweb, int connid, char *etag)
446
+{
447
+        _wk *web=(_wk *)paramweb;
448
+        wk_client *client;
449
+        if(web==NULL)
450
+                return(-1);
451
+        if((client=wk_clientget(web,connid))==NULL)
452
+                return(-1);
453
+        if(etag!=NULL) {
454
+                strncpy(client->etag,etag,sizeof(client->etag));
455
+                client->etag[sizeof(client->etag)-1]='\0';
456
+        } else
457
+                client->etag[0]='\0';
458
+        return(0);
459
+}
441 460
 
442 461
 int
443 462
 wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime)
... ...
@@ -447,28 +466,44 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const
447 466
         wk_client *client;
448 467
         char buf[256];
449 468
         sbuf *cookiebuf;
469
+        int cachedetag;
450 470
         if(web==NULL)
451 471
                 return(-1);
452 472
         if((client=wk_clientget(web,connid))==NULL)
453 473
                 return(-1);
454
-        wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n");
474
+        cachedetag=(wk_etagnotmodified(web,client)==0)?1:0;
475
+        if(!cachedetag)
476
+                wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n");
477
+        else
478
+                wk_writestr((wk *)web,connid,"HTTP/1.1 304 Not modified\r\n");
455 479
         if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) {
456 480
                 if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 ||
457 481
                   sbuf_count(cookiebuf)!=0)
458 482
                         return(-1); /* insufficient memory */
459 483
                 wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
460 484
         }
461
-        sprintf(buf,"Content-Length: %i\r\n",datalen);
462
-        wk_writestr((wk *)web,connid,buf);
463
-        if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3))
464
-                sprintf(buf,"%s%s\r\n",strcontenttype,mime);
465
-        else
466
-                sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream");
467
-        wk_writestr((wk *)web,connid,buf);
485
+        if(!cachedetag) {
486
+                if(client->etag[0]!='\0') {
487
+                        sprintf(buf,"ETag: \"%s\"\r\n",client->etag);
488
+                        client->etag[0]='\0';
489
+                        wk_writestr((wk *)web,connid,buf);
490
+                }
491
+                sprintf(buf,"Content-Length: %i\r\n",datalen);
492
+                wk_writestr((wk *)web,connid,buf);
493
+                if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3))
494
+                        sprintf(buf,"%s%s\r\n",strcontenttype,mime);
495
+                else
496
+                        sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream");
497
+                wk_writestr((wk *)web,connid,buf);
498
+        } else {
499
+                wk_writestr((wk *)web,connid,"Content-Length: 0\r\n");
500
+        }
468 501
         if(client->keepalive)
469 502
                 wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n");
470 503
         wk_writestr((wk *)web,connid,"\r\n");
471
-        return(wk_write((wk *)web,connid,data,datalen));
504
+        if(!cachedetag)
505
+                return(wk_write((wk *)web,connid,data,datalen));
506
+        return(0);
472 507
 }
473 508
 
474 509
 int
... ...
@@ -480,33 +515,47 @@ wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime)
480 515
         char buf[256];
481 516
         sbuf *cookiebuf;
482 517
         struct stat st;
518
+        int cachedetag;
483 519
         if(web==NULL || filename==NULL)
484 520
                 return(-1);
485 521
         if((client=wk_clientget(web,connid))==NULL)
486 522
                 return(-1);
487 523
         if(client->fdtoserve!=-1)
488 524
                 close(client->fdtoserve),client->fdtoserve=-1;
489
-        if((client->fdtoserve=open(filename,O_RDONLY))==-1) {
490
-                wk_serve_error((wk *)web,connid,wkerr_notfound);
491
-                return(-1);
492
-        }
493
-        wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n");
525
+        cachedetag=(wk_etagnotmodified(web,client)==0)?1:0;
526
+        if(!cachedetag) {
527
+                if((client->fdtoserve=open(filename,O_RDONLY))==-1) {
528
+                        wk_serve_error((wk *)web,connid,wkerr_notfound);
529
+                        return(-1);
530
+                }
531
+                wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n");
532
+        } else
533
+                wk_writestr((wk *)web,connid,"HTTP/1.1 304 Not modified\r\n");
494 534
         if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) {
495 535
                 if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 ||
496 536
                   sbuf_count(cookiebuf)!=0)
497 537
                         return(-1); /* insufficient memory */
498 538
                 wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
499 539
         }
500
-        if(fstat(client->fdtoserve,&st)==0) {
501
-                sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size);
540
+        if(!cachedetag) {
541
+                if(client->etag[0]!='\0') {
542
+                        sprintf(buf,"ETag: \"%s\"\r\n",client->etag);
543
+                        client->etag[0]='\0';
544
+                        wk_writestr((wk *)web,connid,buf);
545
+                }
546
+                if(fstat(client->fdtoserve,&st)==0) {
547
+                        sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size);
548
+                        wk_writestr((wk *)web,connid,buf);
549
+                } else
550
+                        client->keepalive=0;
551
+                if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3))
552
+                        sprintf(buf,"%s%s\r\n",strcontenttype,mime);
553
+                else
554
+                        sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream");
502 555
                 wk_writestr((wk *)web,connid,buf);
503
-        } else
504
-                client->keepalive=0;
505
-        if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3))
506
-                sprintf(buf,"%s%s\r\n",strcontenttype,mime);
507
-        else
508
-                sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream");
509
-        wk_writestr((wk *)web,connid,buf);
556
+        } else {
557
+                wk_writestr((wk *)web,connid,"Content-Length: 0\r\n");
558
+        }
510 559
         if(client->keepalive)
511 560
                 wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n");
512 561
         wk_writestr((wk *)web,connid,"\r\n");
... ...
@@ -1051,6 +1100,7 @@ wk_clientacquire(_wk *web)
1051 1100
         client->fdtoserve=-1;
1052 1101
         client->headerbufid=-1;
1053 1102
         client->cookiebufid=-1;
1103
+        client->etag[0]='\0';
1054 1104
         return(client);
1055 1105
 }
1056 1106
 
... ...
@@ -1225,6 +1275,9 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
1225 1275
                 client->uriready=1;
1226 1276
                 client->continuationactive=0;
1227 1277
                 client->status=wkc_header;
1278
+                if(client->cookiebufid!=-1)
1279
+                        wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
1280
+                client->etag[0]='\0';
1228 1281
         }
1229 1282
         return(0);
1230 1283
 }
... ...
@@ -1431,4 +1484,21 @@ wk_postfree(_wk *web, wk_client *client)
1431 1484
         return(0);
1432 1485
 }
1433 1486
 
1487
+static int
1488
+wk_etagnotmodified(_wk *web, wk_client *client)
1489
+{
1490
+        char *h;
1491
+        int len;
1492
+        int etaglen;
1493
+        if(client->etag[0]=='\0')
1494
+                return(-1);
1495
+        if((h=wk_uri_getheader(&(client->uri),"If-None-Match",NULL))==NULL)
1496
+                return(-1);
1497
+        etaglen=strlen(client->etag);
1498
+        if((len=strlen(h))<2 || h[0]!='\"' || h[len-1]!='\"')
1499
+                return(-1);
1500
+        if((len-2)!=etaglen || memcmp(h+1,client->etag,etaglen)!=0)
1501
+                return(-1);
1502
+        return(0);
1503
+}
1434 1504
 
Browse code

Add WK_DEBUG_CONN define to trace connections. Make BUFSIZE (sbuf size) configurable via Makefile (i.e. CFLAGS=-DBUFSIZE=8192)

Dario Rodriguez authored on 16/07/2014 10:35:50
Showing 1 changed files
... ...
@@ -24,7 +24,9 @@
24 24
 #define CLIENTBLOCK 1024
25 25
 #define CLIENTBLOCKBLOCK 256
26 26
 #define MAXOUTBUF 128
27
+#ifndef BUFSIZE
27 28
 #define BUFSIZE 8192
29
+#endif
28 30
 #define BUFBLOCK 128
29 31
 #define BUFBLOCKBLOCK 256
30 32
 #define POSTBLOCK 16
... ...
@@ -146,6 +148,12 @@ wk_debug_io(char *iotype, int fd, char *ptr, long int size)
146 148
 #define DEBUG_OUT_POST
147 149
 #endif
148 150
 
151
+#ifdef WK_DEBUG_CONN
152
+#include "loglib.h"
153
+#define DEBUG_CONN(a) log_write a
154
+#else
155
+#define DEBUG_CONN(a)
156
+#endif
149 157
 
150 158
 wk *
151 159
 wk_init(int serverfd, 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)
... ...
@@ -386,8 +394,10 @@ wk_service(wk *paramweb)
386 394
                                                 continue;
387 395
                                         if(client->lastio>now)
388 396
                                                 client->lastio=now;
389
-                                        if((now-ALIVETIMEOUT)>client->lastio)
397
+                                        if((now-ALIVETIMEOUT)>client->lastio) {
398
+                                                DEBUG_CONN(("WEBK","TIMEOUT: Closing client connection; now:%li, ALIVETIMEOUT:%li, lastio:%li, diff:%li\n",(long)now,(long)ALIVETIMEOUT,(long)client->lastio,(long)(now-client->lastio)));
390 399
                                                 wk_close((wk *)web, client->connid); /* timeout */
400
+                                        }
391 401
                                 }
392 402
                         }
393 403
                 }
... ...
@@ -637,6 +647,7 @@ wk_close(wk *paramweb, int connid)
637 647
                 return(-1);
638 648
         if((client=wk_clientget(web,connid))==NULL)
639 649
                 return(-1);
650
+        DEBUG_CONN(("WEBK","wk_close: connid: %i, fd: %i",connid,client->fd));
640 651
         if(client->fd!=-1) {
641 652
                 sselect_delread(web->ssel,client->fd);
642 653
                 sselect_delwrite(web->ssel,client->fd);
... ...
@@ -965,6 +976,7 @@ wk_accept(_wk *web)
965 976
                 return(NULL);
966 977
         }
967 978
         client->fd=newfd;
979
+        DEBUG_CONN(("WEBK","wk_accept: connid: %i, fd: %i",client->connid,client->fd));
968 980
         FD_SET(client->fd,&(web->fdset));
969 981
         sselect_addread(web->ssel,client->fd,(void *)client);
970 982
         return(client);
Browse code

webkernel: make wk_init expect a server fd instead of a port number

Dario Rodriguez authored on 15/07/2014 11:03:21
Showing 1 changed files
... ...
@@ -148,15 +148,15 @@ wk_debug_io(char *iotype, int fd, char *ptr, long int size)
148 148
 
149 149
 
150 150
 wk *
151
-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)
151
+wk_init(int serverfd, 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)
152 152
 {
153 153
         _wk *web;
154
-        if(ssel==NULL || callback_http==NULL)
154
+        if(ssel==NULL || callback_http==NULL || serverfd==-1)
155 155
                 return(NULL);
156 156
         if((web=malloc(sizeof(_wk)))==NULL)
157 157
                 return(NULL);
158 158
         memset(web,0,sizeof(_wk));
159
-        web->serverfd=-1;
159
+        web->serverfd=serverfd;
160 160
         web->callback_event=callback_event;
161 161
         web->callback_http=callback_http;
162 162
         web->callback_post=callback_post;
... ...
@@ -164,11 +164,6 @@ wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *web,int connid, wk
164 164
         web->userptr=userptr;
165 165
         web->ssel=ssel;
166 166
         FD_ZERO(&(web->fdset));
167
-        if((web->serverfd=ipv4_server(port))==-1) {
168
-                wk_free((wk *)web),web=NULL;
169
-                return(NULL);
170
-        }
171
-        sock_setunsafe(web->serverfd);
172 167
         FD_SET(web->serverfd,&(web->fdset));
173 168
         sselect_addread(ssel,web->serverfd,NULL);
174 169
         if(web->callback_event!=NULL)
... ...
@@ -188,11 +183,10 @@ wk_free(wk *paramweb)
188 183
                 return;
189 184
         if(web->callback_event!=NULL)
190 185
                 web->callback_event((wk *)web,-1,wke_fini,web->userptr);
191
-        /* release server fds */
186
+        /* unregister the server fd */
192 187
         if(web->serverfd!=-1) {
193 188
                 sselect_delread(web->ssel,web->serverfd);
194 189
                 FD_CLR(web->serverfd,&(web->fdset));
195
-                close(web->serverfd),web->serverfd=-1;
196 190
         }
197 191
         /* release client fds and free clients */
198 192
         for(i=0;i<web->usedclientblocks;i++) {
Browse code

webkernel: fix header and cookies parsing

Dario Rodriguez authored on 13/07/2014 21:39:56
Showing 1 changed files
... ...
@@ -665,7 +665,7 @@ wk_uri_getheader(wk_uri *uri, char *header, char *defaultvalue)
665 665
         if(uri==NULL || uri->headers==NULL || header==NULL)
666 666
                 return(NULL);
667 667
         len=strlen(header);
668
-        for(n=0,ptr=uri->headers;*ptr!='\0';ptr++,n++) {
668
+        for(n=0,ptr=uri->headers;*ptr!='\0';ptr+=strlen(ptr)+1,n++) {
669 669
                 if(memcmp(ptr,header,len)==0 && ptr[len]==':' && ptr[len+1]==' ')
670 670
                         return(ptr+len+2);
671 671
         }
... ...
@@ -679,7 +679,7 @@ wk_uri_getheaderbynum(wk_uri *uri, int num)
679 679
         char *ptr;
680 680
         if(uri==NULL || uri->headers==NULL)
681 681
                 return(NULL);
682
-        for(n=0,ptr=uri->headers;*ptr!='\0';ptr++,n++) {
682
+        for(n=0,ptr=uri->headers;*ptr!='\0';ptr+=strlen(ptr)+1,n++) {
683 683
                 if(n==num)
684 684
                         return(ptr);
685 685
         }
... ...
@@ -736,7 +736,7 @@ wk_uri_getcookie(wk_uri *uri, char *cookiename, int *len)
736 736
         if(uri==NULL || uri->headers==NULL || cookiename==NULL || len==NULL)
737 737
                 return(NULL);
738 738
         namelen=strlen(cookiename);
739
-        for(n=0,header=uri->headers;*header!='\0';header++,n++) {
739
+        for(n=0,header=uri->headers;*header!='\0';header+=strlen(header)+1,n++) {
740 740
                 if(memcmp(header,"Cookie: ",8)!=0 && memcmp(header,"cookie: ",8)!=0)
741 741
                         continue;
742 742
                 for(ptr=header+8;*ptr!='\0';ptr=((*next!='\0')?next+1:next)) {
... ...
@@ -764,7 +764,7 @@ wk_uri_getcookie(wk_uri *uri, char *cookiename, int *len)
764 764
                                 end--;
765 765
                         /* cookie found, return it */
766 766
                         *len=end-sep;
767
-                        return(ptr);
767
+                        return(sep);
768 768
                 }
769 769
         }
770 770
         return(NULL);
Browse code

webkernel: basic cookie support

Dario Rodriguez authored on 13/07/2014 19:55:14
Showing 1 changed files
... ...
@@ -64,6 +64,7 @@ typedef struct wk_client {
64 64
         wk_post *post;
65 65
         int pendingpost;
66 66
         int inpostvar;
67
+        int cookiebufid;
67 68
         time_t lastio;
68 69
 } wk_client;
69 70
 
... ...
@@ -401,6 +402,39 @@ wk_service(wk *paramweb)
401 402
         return(0);
402 403
 }
403 404
 
405
+int
406
+wk_serve_cookieadd(wk *paramweb, int connid, char *cookiename, char *value, char *domain, int maxage, char *attributes)
407
+{
408
+        _wk *web=(_wk *)paramweb;
409
+        wk_client *client;
410
+        sbuf *buf;
411
+        char str[1024];
412
+        if(web==NULL || cookiename==NULL || (value==NULL && maxage>0))
413
+                return(-1);
414
+        if((client=wk_clientget(web,connid))==NULL)
415
+                return(-1);
416
+        if(client->cookiebufid==-1) {
417
+                if((client->cookiebufid=wk_sbufacquire((wk *)web))==-1)
418
+                        return(-1); /* insufficient memory */
419
+        }
420
+        if((buf=wk_sbufget((wk *)web,client->cookiebufid))==NULL)
421
+                return(-1); /* internal error */
422
+        if(sbuf_count(buf)==0) {
423
+                sbuf_addstr(buf,"Cache-control: no-cache=\"set-cookie\"\r\n");
424
+                sbuf_addstr(buf,"Expires: Tue, 01 Jan 1980 1:00:00 GMT\r\n");
425
+        }
426
+        snprintf(str,sizeof(str)-1,"Set-Cookie: %s=%s %s%s%s; Max-Age=%i ; Version=1%s%s\r\n",
427
+                cookiename,(value!=NULL)?value:"",
428
+                (domain!=NULL)?"; Domain = ":"",
429
+                (domain!=NULL && *domain!='.')?".":"",
430
+                (domain!=NULL)?domain:"",
431
+                maxage,
432
+                (attributes!=NULL)?"; ":"",(attributes!=NULL)?attributes:"");
433
+        sbuf_addstr(buf,str);
434
+        return(0);
435
+}
436
+
437
+
404 438
 int
405 439
 wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime)
406 440
 {
... ...
@@ -408,11 +442,18 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const
408 442
         _wk *web=(_wk *)paramweb;
409 443
         wk_client *client;
410 444
         char buf[256];
445
+        sbuf *cookiebuf;
411 446
         if(web==NULL)
412 447
                 return(-1);
413 448
         if((client=wk_clientget(web,connid))==NULL)
414 449
                 return(-1);
415 450
         wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n");
451
+        if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) {
452
+                if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 ||
453
+                  sbuf_count(cookiebuf)!=0)
454
+                        return(-1); /* insufficient memory */
455
+                wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
456
+        }
416 457
         sprintf(buf,"Content-Length: %i\r\n",datalen);
417 458
         wk_writestr((wk *)web,connid,buf);
418 459
         if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3))
... ...
@@ -433,6 +474,7 @@ wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime)
433 474
         _wk *web=(_wk *)paramweb;
434 475
         wk_client *client;
435 476
         char buf[256];
477
+        sbuf *cookiebuf;
436 478
         struct stat st;
437 479
         if(web==NULL || filename==NULL)
438 480
                 return(-1);
... ...
@@ -445,6 +487,12 @@ wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime)
445 487
                 return(-1);
446 488
         }
447 489
         wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n");
490
+        if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) {
491
+                if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 ||
492
+                  sbuf_count(cookiebuf)!=0)
493
+                        return(-1); /* insufficient memory */
494
+                wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
495
+        }
448 496
         if(fstat(client->fdtoserve,&st)==0) {
449 497
                 sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size);
450 498
                 wk_writestr((wk *)web,connid,buf);
... ...
@@ -675,6 +723,65 @@ wk_uri_copyvar(wk_uri *uri, char *varname, char *dest, int destlen)
675 723
         return(dest);
676 724
 }
677 725
 
726
+char *
727
+wk_uri_getcookie(wk_uri *uri, char *cookiename, int *len)
728
+{
729
+        int n;
730
+        char *header;
731
+        int namelen;
732
+        char *ptr;
733
+        char *sep;
734
+        char *end;
735
+        char *next;
736
+        if(uri==NULL || uri->headers==NULL || cookiename==NULL || len==NULL)
737
+                return(NULL);
738
+        namelen=strlen(cookiename);
739
+        for(n=0,header=uri->headers;*header!='\0';header++,n++) {
740
+                if(memcmp(header,"Cookie: ",8)!=0 && memcmp(header,"cookie: ",8)!=0)
741
+                        continue;
742
+                for(ptr=header+8;*ptr!='\0';ptr=((*next!='\0')?next+1:next)) {
743
+                        /* cookies are separated by ',' or ';' */
744
+                        next=strchr(ptr,';');
745
+                        if(next==NULL)
746
+                                next=ptr+strlen(ptr);
747
+                        if((sep=strchr(ptr,','))!=NULL && sep<next)
748
+                                next=sep;
749
+                        /* trim cookie name */
750
+                        while(*ptr==' ')
751
+                                ptr++;
752
+                        /* check for our cookie and search for the value pos */
753
+                        if(memcmp(ptr,cookiename,namelen)!=0)
754
+                                continue; /* not our cookie */
755
+                        for(sep=ptr+namelen;*sep==' ';sep++)
756
+                                ;
757
+                        if(*sep!='=')
758
+                                continue; /* was partial match or unrecognized cookie format */
759
+                        /* skip '=' and trim value */
760
+                        sep++;
761
+                        while(*sep==' ')
762
+                                sep++;
763
+                        for(end=next;end>sep && end[-1]==' ';)
764
+                                end--;
765
+                        /* cookie found, return it */
766
+                        *len=end-sep;
767
+                        return(ptr);
768
+                }
769
+        }
770
+        return(NULL);
771
+}
772
+
773
+char *
774
+wk_uri_copycookie(wk_uri *uri, char *cookiename, char *dest, int destlen)
775
+{
776
+        char *value;
777
+        int len;
778
+        if(dest==NULL || destlen<1 || (value=wk_uri_getcookie(uri,cookiename,&len))==NULL)
779
+                return(NULL);
780
+        memcpy(dest,value,(len<(destlen-1))?len:destlen-1);
781
+        dest[(len<(destlen-1))?len:destlen-1]='\0';
782
+        return(dest);
783
+}
784
+
678 785
 
679 786
 int
680 787
 wk_post_addvalid(wk *paramweb, int connid, char *varname, char *tofile)
... ...
@@ -937,6 +1044,7 @@ wk_clientacquire(_wk *web)
937 1044
         client->usedoutbufids=1;
938 1045
         client->fdtoserve=-1;
939 1046
         client->headerbufid=-1;
1047
+        client->cookiebufid=-1;
940 1048
         return(client);
941 1049
 }
942 1050
 
... ...
@@ -959,6 +1067,8 @@ wk_clientrelease(_wk *web, int connid)
959 1067
                 wk_sbufrelease((wk *)web,client->outbufids[w]),client->outbufids[w]=-1;
960 1068
         if(client->headerbufid!=-1)
961 1069
                 wk_sbufrelease((wk *)web,client->headerbufid),client->headerbufid=-1;
1070
+        if(client->cookiebufid!=-1)
1071
+                wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1;
962 1072
         wk_postfree(web,client);
963 1073
         memset(client,0,sizeof(wk_client));
964 1074
         return(0);
Browse code

Add connection timeouts

Dario Rodriguez authored on 02/07/2014 17:18:07
Showing 1 changed files
... ...
@@ -15,6 +15,7 @@
15 15
 #include <sys/types.h>
16 16
 #include <sys/stat.h>
17 17
 #include <fcntl.h>
18
+#include <time.h>
18 19
 #include "sbuf.h"
19 20
 #include "socklib.h"
20 21
 #include "webkernel.h"
... ...
@@ -27,6 +28,7 @@
27 28
 #define BUFBLOCK 128
28 29
 #define BUFBLOCKBLOCK 256
29 30
 #define POSTBLOCK 16
31
+#define ALIVETIMEOUT 15
30 32
 
31 33
 typedef struct wk_post {
32 34
         char *name;
... ...
@@ -62,6 +64,7 @@ typedef struct wk_client {
62 64
         wk_post *post;
63 65
         int pendingpost;
64 66
         int inpostvar;
67
+        time_t lastio;
65 68
 } wk_client;
66 69
 
67 70
 typedef struct wk_clientblock {
... ...
@@ -98,6 +101,7 @@ typedef struct _wk {
98 101
         wk_action (*callback_post)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
99 102
         wk_action (*callback_continuation)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
100 103
         void *userptr;
104
+        time_t lasttimeoutcheck;
101 105
 } _wk;
102 106
 
103 107
 static wk_client *wk_accept(_wk *web);
... ...
@@ -256,21 +260,27 @@ wk_service(wk *paramweb)
256 260
 {
257 261
         int fds[FDBLOCK];
258 262
         int fd;
259
-        int n,i;
263
+        int n,i,j,k;
260 264
         sbuf *in;
261 265
         sbuf *out;
262 266
         _wk *web=(_wk *)paramweb;
263 267
         wk_client *client;
268
+        wk_clientblock *cb;
269
+        time_t now;
264 270
         if(web==NULL)
265 271
                 return(-1);
272
+        now=time(NULL);
266 273
         while((n=sselect_getreadfiltered(web->ssel,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
267 274
                 for(i=0;i<n;i++) {
268 275
                         fd=fds[i];
269 276
                         if(fd==web->serverfd) {
270 277
                                 do {
271 278
                                         /* 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);
279
+                                        if((client=wk_accept(web))!=NULL) {
280
+                                                if(web->callback_event!=NULL)
281
+                                                        web->callback_event((wk *)web,client->connid,wke_connected,web->userptr);
282
+                                                client->lastio=now;
283
+                                        }
274 284
                                 } while(sock_readable(fd)==0);
275 285
                                 continue; /* all done here */
276 286
                         }
... ...
@@ -296,6 +306,7 @@ wk_service(wk *paramweb)
296 306
                                 continue;
297 307
                         }
298 308
                         DEBUG_IN_POST;
309
+                        client->lastio=now;
299 310
                         if(client->status==wkc_header) {
300 311
                                 if(wk_clientservicereadheader(web,client)==-1) {
301 312
                                         /* internal error, protocol error or no enough memory */
... ...
@@ -325,7 +336,8 @@ wk_service(wk *paramweb)
325 336
                                 continue; /* internal error */
326 337
                         }
327 338
                         DEBUG_OUT_PRE;
328
-                        sbuf_send(out,fd,sbuf_count(out));
339
+                        if(sbuf_send(out,fd,sbuf_count(out))>0)
340
+                                client->lastio=now;
329 341
                         DEBUG_OUT_POST;
330 342
                         /* if we are serving from file, load the next chunk */
331 343
                         if(client->fdtoserve!=-1 && client->usedoutbufids==1) {
... ...
@@ -359,6 +371,33 @@ wk_service(wk *paramweb)
359 371
                         }
360 372
                 }
361 373
         }
374
+        /* timeout check */
375
+        if(web->lasttimeoutcheck>now)
376
+                web->lasttimeoutcheck=now; /* fix time warp */
377
+        if((now-(ALIVETIMEOUT/2))>web->lasttimeoutcheck) {
378
+                web->lasttimeoutcheck=now;
379
+                for(i=0;i<web->usedclientblocks;i++) {
380
+                        cb=web->clientblocks+i;
381
+                        if(cb->clients==NULL)
382
+                                continue;
383
+                        for(j=0;j<cb->sizeclients;j+=8) {
384
+                                if(cb->acquired[j>>3]==0)
385
+                                        continue;
386
+                                for(k=0x1,n=0;n<8;n++,k<<=1) {
387
+                                        if(!(cb->acquired[j>>3]&k))
388
+                                                continue;
389
+                                        client=cb->clients+j+n;
390
+                                        if(client->fd==-1)
391
+                                                continue;
392
+                                        if(client->lastio>now)
393
+                                                client->lastio=now;
394
+                                        if((now-ALIVETIMEOUT)>client->lastio)
395
+                                                wk_close((wk *)web, client->connid); /* timeout */
396
+                                }
397
+                        }
398
+                }
399
+
400
+        }
362 401
         return(0);
363 402
 }
364 403
 
... ...
@@ -1028,11 +1067,11 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
1028 1067
                         return(-1); /* header not in format "name: value" */
1029 1068
                 /* check for keepalive header */
1030 1069
                 if(memcmp(ptr,"Connection: ",12)==0) {
1031
-		  if(strcmp(ptr+12,"keep-alive")==0 || strcmp(ptr+12,"Keep-Alive")==0)
1070
+                  if(strcmp(ptr+12,"keep-alive")==0 || strcmp(ptr+12,"Keep-Alive")==0)
1032 1071
                         client->keepalive=1;
1033 1072
                   else if(strcmp(ptr+12,"close")==0 || strcmp(ptr+12,"Close")==0)
1034 1073
                         client->keepalive=0;
1035
-		}
1074
+                }
1036 1075
                 sbuf_add(hbuf,ptr,strlen(ptr)+1);
1037 1076
                 ptr+=strlen(ptr)+1;
1038 1077
         }
Browse code

Honor 'Connection: close' header

Dario Rodriguez authored on 02/07/2014 12:27:46
Showing 1 changed files
... ...
@@ -1027,9 +1027,12 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
1027 1027
                 if((sep=strchr(ptr,':'))==NULL || sep[1]!=' ')
1028 1028
                         return(-1); /* header not in format "name: value" */
1029 1029
                 /* check for keepalive header */
1030
-                if(memcmp(ptr,"Connection: ",12)==0 &&
1031
-                  (strcmp(ptr+12,"keep-alive")==0 || strcmp(ptr+12,"Keep-Alive")==0))
1030
+                if(memcmp(ptr,"Connection: ",12)==0) {
1031
+		  if(strcmp(ptr+12,"keep-alive")==0 || strcmp(ptr+12,"Keep-Alive")==0)
1032 1032
                         client->keepalive=1;
1033
+                  else if(strcmp(ptr+12,"close")==0 || strcmp(ptr+12,"Close")==0)
1034
+                        client->keepalive=0;
1035
+		}
1033 1036
                 sbuf_add(hbuf,ptr,strlen(ptr)+1);
1034 1037
                 ptr+=strlen(ptr)+1;
1035 1038
         }
Browse code

Fix clientblock and bufblock management. Fix wk_clientservicereadheader to consume input. Set keep-alive as default for HTTP/1.1 or greater connections

Dario Rodriguez authored on 02/07/2014 12:12:46
Showing 1 changed files
... ...
@@ -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;
Browse code

webkernel: fix definition of (clientblock).acquired, fix freeing of clients' fd.

Dario Rodriguez authored on 30/06/2014 21:02:36
Showing 1 changed files
... ...
@@ -67,7 +67,7 @@ typedef struct wk_client {
67 67
 typedef struct wk_clientblock {
68 68
         int sizeclients;
69 69
         int usedclients;
70
-        unsigned char acquired[CLIENTBLOCKBLOCK/8];
70
+        unsigned char acquired[CLIENTBLOCK/8];
71 71
         wk_client *clients;
72 72
 } wk_clientblock;
73 73
 
... ...
@@ -169,7 +169,7 @@ wk_free(wk *paramweb)
169 169
                         for(k=0x1,n=0;n<8;n++,k<<=1) {
170 170
                                 if(!(cb->acquired[j>>3]&k))
171 171
                                         continue;
172
-                                client=cb->clients+j+k;
172
+                                client=cb->clients+j+n;
173 173
                                 if(client->fd!=-1) {
174 174
                                         sselect_delread(web->ssel,client->fd);
175 175
                                         sselect_delwrite(web->ssel,client->fd);
... ...
@@ -821,6 +821,7 @@ wk_clientacquire(_wk *web)
821 821
                 if((cb->clients=malloc(sizeof(wk_client)*CLIENTBLOCK))==NULL)
822 822
                         return(NULL); /* insufficient memory */
823 823
                 memset(cb->clients,0,sizeof(wk_client)*CLIENTBLOCK);
824
+                memset(cb->acquired,0,sizeof(cb->acquired));
824 825
                 cb->sizeclients=CLIENTBLOCK;
825 826
                 cb->usedclients=0;
826 827
                 web->usedclientblocks++;
Browse code

make the redirect reply similar to that of the other server messages

Dario Rodriguez authored on 26/06/2014 17:42:39
Showing 1 changed files
... ...
@@ -433,6 +433,19 @@ The request was not understood or is not allowed by this server.\r\n\
433 433
 int
434 434
 wk_serve_redirect(wk *paramweb, int connid, char *newlocation)
435 435
 {
436
+        static const char strredirect1[]={"\
437
+HTTP/1.1 307 Temporary Redirect\r\n\
438
+Content-Type: text/html\r\n\
439
+Content-Length: 114\r\n\
440
+Location: "
441
+};
442
+        static const char strredirect2[]={"\
443
+\r\n\
444
+\r\n\
445
+<title>307 Temporary Redirect</title>\r\n\
446
+<h1>307 Temporary Redirect</h1>\r\n\
447
+The requsted page was moved temporarily.\r\n\
448
+"};
436 449
         int res;
437 450
         int total;
438 451
         _wk *web=(_wk *)paramweb;
... ...
@@ -442,13 +455,13 @@ wk_serve_redirect(wk *paramweb, int connid, char *newlocation)
442 455
         if((client=wk_clientget(web,connid))==NULL || newlocation==NULL || newlocation[0]=='\0')
443 456
                 return(-1);
444 457
         total=0;
445
-        if((res=wk_writestr((wk *)web,connid,"HTTP/1.1 302 Found\r\nLocation: "))<0)
458
+        if((res=wk_writestr((wk *)web,connid,strredirect1))<0)
446 459
                 return(-1);
447 460
         total+=res;
448 461
         if((res=wk_writestr((wk *)web,connid,newlocation))<0)
449 462
                 return(-1);
450 463
         total+=res;
451
-        if((res=wk_writestr((wk *)web,connid,"\r\n\r\n\r\n"))<0)
464
+        if((res=wk_writestr((wk *)web,connid,strredirect2))<0)
452 465
                 return(-1);
453 466
         total+=res;
454 467
         return(total);
Browse code

fix redirects

Dario Rodriguez authored on 26/06/2014 17:19:59
Showing 1 changed files
... ...
@@ -448,7 +448,7 @@ wk_serve_redirect(wk *paramweb, int connid, char *newlocation)
448 448
         if((res=wk_writestr((wk *)web,connid,newlocation))<0)
449 449
                 return(-1);
450 450
         total+=res;
451
-        if((res=wk_writestr((wk *)web,connid,"\r\n\r\n"))<0)
451
+        if((res=wk_writestr((wk *)web,connid,"\r\n\r\n\r\n"))<0)
452 452
                 return(-1);
453 453
         total+=res;
454 454
         return(total);
Browse code

add wk_serve_Redirect()

Dario Rodriguez authored on 26/06/2014 16:55:55
Showing 1 changed files
... ...
@@ -430,6 +430,31 @@ The request was not understood or is not allowed by this server.\r\n\
430 430
         return(res);
431 431
 }
432 432
 
433
+int
434
+wk_serve_redirect(wk *paramweb, int connid, char *newlocation)
435
+{
436
+        int res;
437
+        int total;
438
+        _wk *web=(_wk *)paramweb;
439
+        wk_client *client;
440
+        if(web==NULL)
441
+                return(-1);
442
+        if((client=wk_clientget(web,connid))==NULL || newlocation==NULL || newlocation[0]=='\0')
443
+                return(-1);
444
+        total=0;
445
+        if((res=wk_writestr((wk *)web,connid,"HTTP/1.1 302 Found\r\nLocation: "))<0)
446
+                return(-1);
447
+        total+=res;
448
+        if((res=wk_writestr((wk *)web,connid,newlocation))<0)
449
+                return(-1);
450
+        total+=res;
451
+        if((res=wk_writestr((wk *)web,connid,"\r\n\r\n"))<0)
452
+                return(-1);
453
+        total+=res;
454
+        return(total);
455
+}
456
+
457
+
433 458
 int
434 459
 wk_writestr(wk *paramweb, int connid, const char *str)
435 460
 {
Browse code

webkernel: fix connection state machine

Dario Rodriguez authored on 24/06/2014 20:35:11
Showing 1 changed files
... ...
@@ -40,7 +40,6 @@ typedef struct wk_post {
40 40
 typedef enum wkc_status {
41 41
         wkc_header=0,
42 42
         wkc_post,
43
-        wkc_none,
44 43
 } wkc_status;
45 44
 
46 45
 typedef struct wk_client {
... ...
@@ -51,13 +50,13 @@ typedef struct wk_client {
51 50
         int sizeoutbufids;
52 51
         int usedoutbufids;
53 52
         int outbufids[MAXOUTBUF];
54
-        wkc_status status;
55
-        int serviced;
56
-        int continuationactive;
57
-        int fdtoserve;
53
+        int uriready;
58 54
         wk_uri uri;
59 55
         int headerbufid;
56
+        wkc_status status;
60 57
         int keepalive;
58
+        int continuationactive;
59
+        int fdtoserve;
61 60
         int sizepost;
62 61
         int usedpost;
63 62
         wk_post *post;
... ...
@@ -216,7 +215,7 @@ wk_geturi(wk *paramweb, int connid)
216 215
                 return(NULL);
217 216
         if((client=wk_clientget(web,connid))==NULL)
218 217
                 return(NULL);
219
-        if(client->serviced==0)
218
+        if(client->uriready==0)
220 219
                 return(NULL);
221 220
         return(&(client->uri));
222 221
 }
... ...
@@ -314,7 +313,7 @@ wk_service(wk *paramweb)
314 313
                                         if(client->continuationactive && web->callback_continuation!=NULL) {
315 314
                                                 client->continuationactive=web->callback_continuation((wk *)web,client->connid,&(client->uri),web->userptr);
316 315
                                         } else {
317
-                                                client->serviced=0; /* we have finished servicing this one */
316
+                                                client->uriready=0; /* we have finished servicing this one */
318 317
                                                 if(!client->keepalive)
319 318
                                                         wk_close((wk *)web, fd); /* all sent */
320 319
                                         }
... ...
@@ -886,16 +885,8 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
886 885
         char *sep;
887 886
         wk_uri *uri;
888 887
         wk_action action;
889
-        /* check if we have all the headers */
890 888
         if((in=wk_sbufget((wk *)web, client->inbufid))==NULL)
891 889
                 return(-1); /* internal error */
892
-        if((end=str_findfirstempty(sbuf_ptr(in),sbuf_count(in)))==NULL) {
893
-                sbuf_discard(in);
894
-                if(sbuf_unused(in)==0)
895
-                        return(-1); /* header part too long */
896
-                /* incomplete headers, have to wait for more data */
897
-                return(0);
898
-        }
899 890
         /* get memory for the uri data */
900 891
         if(client->headerbufid!=-1)
901 892
                 wk_sbufrelease((wk *)web,client->headerbufid),client->headerbufid=-1;
... ...
@@ -903,7 +894,17 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
903 894
                 return(-1); /* insufficient memory */
904 895
         if((hbuf=wk_sbufget((wk *)web,client->headerbufid))==NULL)
905 896
                 return(-1); /* internal error */
897
+        /* check if we have all the headers */
898
+        if((end=str_findfirstempty(sbuf_ptr(in),sbuf_count(in)))==NULL) {
899
+                sbuf_discard(in);
900
+                if(sbuf_unused(in)==0)
901
+                        return(-1); /* header part too long */
902
+                /* incomplete headers, have to wait for more data */
903
+                return(0);
904
+        }
906 905
         /* prepare to fill the uri struct */
906
+        client->uriready=0;
907
+        sbuf_wipe(hbuf);
907 908
         uri=&(client->uri);
908 909
         memset(uri,0,sizeof(wk_uri));
909 910
         /* check that the method is supported */
... ...
@@ -955,13 +956,13 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
955 956
         /* add header terminator */
956 957
         sbuf_add(hbuf,"",1);
957 958
         /* call the http method */
958
-        client->serviced=1;
959
+        client->uriready=1;
959 960
         client->continuationactive=0;
960 961
         action=web->callback_http((wk *)web, client->connid, uri, web->userptr);
961 962
         if(action==wkact_continuation) {
962
-                client->serviced=1;
963
+                client->uriready=1;
963 964
                 client->continuationactive=1;
964
-                client->status=wkc_none;
965
+                client->status=wkc_header;
965 966
         } else if(action==wkact_post && web->callback_post!=NULL) {
966 967
                 char *lenvar;
967 968
                 char *contenttype;
... ...
@@ -975,15 +976,15 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
975 976
                 }
976 977
                 while(*lenvar==' ' || *lenvar=='\t')
977 978
                         lenvar++;
978
-                client->serviced=1;
979
+                client->uriready=1;
979 980
                 client->continuationactive=0;
980 981
                 client->status=wkc_post;
981 982
                 client->pendingpost=atoi(lenvar);
982 983
                 client->inpostvar=-1;
983 984
         } else {
984
-                client->serviced=1;
985
+                client->uriready=1;
985 986
                 client->continuationactive=0;
986
-                client->status=wkc_none;
987
+                client->status=wkc_header;
987 988
         }
988 989
         return(0);
989 990
 }
... ...
@@ -1038,17 +1039,17 @@ wk_clientservicereadpost(_wk *web, wk_client *client)
1038 1039
         if(client->pendingpost>0)
1039 1040
                 return(0); /* nothing more to do for now*/
1040 1041
         /* call the post method */
1041
-        client->serviced=1;
1042
+        client->uriready=1;
1042 1043
         client->continuationactive=0;
1043 1044
         action=web->callback_post((wk *)web, client->connid, client->uri, web->userptr);
1044 1045
         if(action==wkact_continuation) {
1045
-                client->serviced=1;
1046
+                client->uriready=1;
1046 1047
                 client->continuationactive=1;
1047
-                client->status=wkc_none;
1048
+                client->status=wkc_header;
1048 1049
         } else {
1049
-                client->serviced=1;
1050
+                client->uriready=1;
1050 1051
                 client->continuationactive=0;
1051
-                client->status=wkc_none;
1052
+                client->status=wkc_header;
1052 1053
         }
1053 1054
         return(0);
1054 1055
 }
Browse code

webkernel: post callback

Dario Rodriguez authored on 24/06/2014 20:25:38
Showing 1 changed files
... ...
@@ -275,6 +275,9 @@ wk_service(wk *paramweb)
275 275
                                         continue;
276 276
                                 }
277 277
                         }
278
+                        sbuf_discard(in);
279
+                        if(sbuf_unused(in)>0)
280
+                                sselect_addread(web->ssel,client->fd,(void *)client);
278 281
                 }
279 282
         }
280 283
         while((n=sselect_getwritefiltered(web->ssel,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
... ...
@@ -959,7 +962,7 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
959 962
                 client->serviced=1;
960 963
                 client->continuationactive=1;
961 964
                 client->status=wkc_none;
962
-        } else if(action==wkact_post) {
965
+        } else if(action==wkact_post && web->callback_post!=NULL) {
963 966
                 char *lenvar;
964 967
                 char *contenttype;
965 968
                 if(strcmp(client->uri.method,"POST")!=0 ||
... ...
@@ -994,9 +997,10 @@ wk_clientservicereadpost(_wk *web, wk_client *client)
994 997
         char *sep;
995 998
         char *start;
996 999
         char *end;
1000
+        wk_action action;
997 1001
         if((in=wk_sbufget((wk *)web, client->inbufid))==NULL)
998 1002
                 return(-1); /* internal error */
999
-        while(sbuf_count(in)>0) {
1003
+        while(sbuf_count(in)>0 && client->pendingpost>0) {
1000 1004
                 if(client->inpostvar==-1) {
1001 1005
                         sbuf_discard(in);
1002 1006
                         buf=sbuf_ptr(in);
... ...
@@ -1031,6 +1035,21 @@ wk_clientservicereadpost(_wk *web, wk_client *client)
1031 1035
                         client->inpostvar=-1;
1032 1036
                 }
1033 1037
         }
1038
+        if(client->pendingpost>0)
1039
+                return(0); /* nothing more to do for now*/
1040
+        /* call the post method */
1041
+        client->serviced=1;
1042
+        client->continuationactive=0;
1043
+        action=web->callback_post((wk *)web, client->connid, client->uri, web->userptr);
1044
+        if(action==wkact_continuation) {
1045
+                client->serviced=1;
1046
+                client->continuationactive=1;
1047
+                client->status=wkc_none;
1048
+        } else {
1049
+                client->serviced=1;
1050
+                client->continuationactive=0;
1051
+                client->status=wkc_none;
1052
+        }
1034 1053
         return(0);
1035 1054
 }
1036 1055
 
Browse code

webkernel: finished POST variables for application/x-www-form-urlencoded

Dario Rodriguez authored on 24/06/2014 12:02:23
Showing 1 changed files
... ...
@@ -31,8 +31,10 @@
31 31
 typedef struct wk_post {
32 32
         char *name;
33 33
         char *value;
34
-        int isfile;
34
+        char *tofile;
35
+        int bufid;
35 36
         int filewritten;
37
+        int valueterminated;
36 38
 } wk_post;
37 39
 
38 40
 typedef enum wkc_status {
... ...
@@ -59,6 +61,8 @@ typedef struct wk_client {
59 61
         int sizepost;
60 62
         int usedpost;
61 63
         wk_post *post;
64
+        int pendingpost;
65
+        int inpostvar;
62 66
 } wk_client;
63 67
 
64 68
 typedef struct wk_clientblock {
... ...
@@ -102,8 +106,9 @@ static wk_client *wk_clientacquire(_wk *web);
102 106
 static int wk_clientrelease(_wk *web, int connid);
103 107
 static wk_client *wk_clientget(_wk *web, int connid);
104 108
 static int wk_clientservicereadheader(_wk *web, wk_client *client);
109
+static int wk_clientservicereadpost(_wk *web, wk_client *client);
105 110
 static int wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile);
106
-static int wk_postset(_wk *web, wk_client *client,char *varname, char *value);
111
+static int wk_postset(_wk *web, wk_client *client,char *varname, char *data, int datalen);
107 112
 static char *wk_postget(_wk *web, wk_client *client,char *varname, int *isfile);
108 113
 static int wk_postfree(_wk *web, wk_client *client);
109 114
 
... ...
@@ -245,6 +250,7 @@ wk_service(wk *paramweb)
245 250
                                 wk_close((wk *)web,client->connid);
246 251
                                 continue; /* internal error */
247 252
                         }
253
+                        sbuf_discard(in);
248 254
                         if(sbuf_unused(in)<=0) {
249 255
                                 /* no room for the new data */
250 256
                                 sselect_delread(web->ssel,fd);
... ...
@@ -261,8 +267,13 @@ wk_service(wk *paramweb)
261 267
                                         wk_close((wk *) web, client->connid);
262 268
                                         continue;
263 269
                                 }
264
-                        } else if(client->status==wkc_post) {
265
-#warning TODO
270
+                        }
271
+                        if(client->status==wkc_post) {
272
+                                if(wk_clientservicereadpost(web,client)==-1) {
273
+                                        /* internal error, protocol error or no enough memory */
274
+                                        wk_close((wk *) web, client->connid);
275
+                                        continue;
276
+                                }
266 277
                         }
267 278
                 }
268 279
         }
... ...
@@ -871,14 +882,15 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
871 882
         char *lineend;
872 883
         char *sep;
873 884
         wk_uri *uri;
885
+        wk_action action;
874 886
         /* check if we have all the headers */
875 887
         if((in=wk_sbufget((wk *)web, client->inbufid))==NULL)
876 888
                 return(-1); /* internal error */
877
-        sbuf_discard(in);
878 889
         if((end=str_findfirstempty(sbuf_ptr(in),sbuf_count(in)))==NULL) {
890
+                sbuf_discard(in);
879 891
                 if(sbuf_unused(in)==0)
880 892
                         return(-1); /* header part too long */
881
-                /* uncomplete headers, have to wait for more data */
893
+                /* incomplete headers, have to wait for more data */
882 894
                 return(0);
883 895
         }
884 896
         /* get memory for the uri data */
... ...
@@ -942,44 +954,138 @@ wk_clientservicereadheader(_wk *web, wk_client *client)
942 954
         /* call the http method */
943 955
         client->serviced=1;
944 956
         client->continuationactive=0;
945
-#warning TODO: wkc_post
946
-        client->continuationactive=web->callback_http((wk *)web, client->connid, uri, web->userptr);
957
+        action=web->callback_http((wk *)web, client->connid, uri, web->userptr);
958
+        if(action==wkact_continuation) {
959
+                client->serviced=1;
960
+                client->continuationactive=1;
961
+                client->status=wkc_none;
962
+        } else if(action==wkact_post) {
963
+                char *lenvar;
964
+                char *contenttype;
965
+                if(strcmp(client->uri.method,"POST")!=0 ||
966
+                  (lenvar=wk_uri_getheader(&(client->uri),"Content-Length",NULL))==NULL) {
967
+                        return(-1); /* malformed post */
968
+                }
969
+                if((contenttype=wk_uri_getheader(&(client->uri),"Content-Type",NULL))==NULL ||
970
+                  strcmp(contenttype,"application/x-www-form-urlencoded")!=0) {
971
+                        return(-1); /* unsupported encoding */
972
+                }
973
+                while(*lenvar==' ' || *lenvar=='\t')
974
+                        lenvar++;
975
+                client->serviced=1;
976
+                client->continuationactive=0;
977
+                client->status=wkc_post;
978
+                client->pendingpost=atoi(lenvar);
979
+                client->inpostvar=-1;
980
+        } else {
981
+                client->serviced=1;
982
+                client->continuationactive=0;
983
+                client->status=wkc_none;
984
+        }
985
+        return(0);
986
+}
987
+
988
+static int
989
+wk_clientservicereadpost(_wk *web, wk_client *client)
990
+{
991
+        sbuf *in;
992
+        char *buf;
993
+        int buflen;
994
+        char *sep;
995
+        char *start;
996
+        char *end;
997
+        if((in=wk_sbufget((wk *)web, client->inbufid))==NULL)
998
+                return(-1); /* internal error */
999
+        while(sbuf_count(in)>0) {
1000
+                if(client->inpostvar==-1) {
1001
+                        sbuf_discard(in);
1002
+                        buf=sbuf_ptr(in);
1003
+                        buflen=sbuf_count(in);
1004
+                        if(buflen>client->pendingpost)
1005
+                                buflen=client->pendingpost;
1006
+                        if((sep=memchr(buf,'=',buflen))==NULL)
1007
+                                return(0); /* varname not found */
1008
+                        *sep='\0';
1009
+                        for(client->inpostvar=0;client->inpostvar<client->usedpost;client->inpostvar++) {
1010
+                                if(strcmp(client->post[client->inpostvar].name,buf)==0)
1011
+                                        break;
1012
+                        }
1013
+                        sbuf_getbytes(in,(sep+1)-buf);
1014
+                        client->pendingpost-=((sep+1)-buf);
1015
+                }
1016
+                start=sbuf_ptr(in);
1017
+                end=start+sbuf_count(in);
1018
+                if((end-start)>client->pendingpost)
1019
+                        end=start+client->pendingpost;
1020
+                if((sep=memchr(start,'&',end-start))!=NULL)
1021
+                        end=sep;
1022
+                if(client->inpostvar>=0) {
1023
+                        if(client->inpostvar<client->usedpost)
1024
+                                wk_postset(web,client,client->post[client->inpostvar].name,start,end-start);
1025
+                        sbuf_getbytes(in,end-start);
1026
+                        client->pendingpost-=(end-start);
1027
+                }
1028
+                if(*sep=='&') {
1029
+                        sbuf_getbytes(in,1);
1030
+                        client->pendingpost--;
1031
+                        client->inpostvar=-1;
1032
+                }
1033
+        }
947 1034
         return(0);
948 1035
 }
949 1036
 
1037
+
950 1038
 static int
951 1039
 wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile)
952 1040
 {
953 1041
         wk_post *post;
1042
+        sbuf *buf;
1043
+        int i;
954 1044
         if(client->post==NULL || client->sizepost==client->usedpost) {
955 1045
                 wk_post *newpost;
956 1046
                 if((newpost=(wk_post *)realloc(client->post,(client->sizepost+POSTBLOCK)*sizeof(wk_post)))==NULL)
957 1047
                         return(-1); /* insufficient memory */
958 1048
                 client->post=newpost;
959 1049
                 memset(client->post+client->sizepost,0,POSTBLOCK*sizeof(wk_post));
1050
+                for(i=0;i<POSTBLOCK;i++)
1051
+                        client->post[client->sizepost+i].bufid=-1;
960 1052
                 client->sizepost+=POSTBLOCK;
961 1053
         }
962 1054
         post=client->post+client->usedpost;
963
-        if((post->name=strdup(varname))==NULL)
1055
+        if((post->bufid=wk_sbufacquire((wk *)web))==-1)
964 1056
                 return(-1); /* insufficient memory */
1057
+        if((buf=wk_sbufget((wk *)web,post->bufid))==NULL) {
1058
+                post->bufid=-1;
1059
+                return(-1); /* internal error */
1060
+        }
1061
+        if((strlen(varname)+1)>(sbuf_unused(buf)-2)) {
1062
+                wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1;
1063
+                return(-1); /* varname too long */
1064
+        }
1065
+        post->name=sbuf_ptrunused(buf);
1066
+        sbuf_addstr(buf,varname);
965 1067
         if(tofile!=NULL) {
966
-                if((post->value=strdup(tofile))==NULL) {
967
-                        free(post->name),post->name=NULL;
968
-                        return(-1); /* insufficient memory */
1068
+                if((strlen(tofile)+1)>(sbuf_unused(buf))) {
1069
+                        wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1;
1070
+                        return(-1); /* varname+tofile too long */
969 1071
                 }
970
-        } else
971
-                post->isfile=0;
1072
+                post->tofile=sbuf_ptrunused(buf);
1073
+                sbuf_addstr(buf,tofile);
1074
+        }
1075
+        post->value=NULL;
1076
+        post->filewritten=0;
1077
+        post->valueterminated=0;
972 1078
         return(0);
973 1079
 }
974 1080
 
975 1081
 static int
976
-wk_postset(_wk *web, wk_client *client,char *varname, char *value)
1082
+wk_postset(_wk *web, wk_client *client,char *varname, char *data, int datalen)
977 1083
 {
978 1084
         int i;
979 1085
         wk_post *post;
980 1086
         int fd;
981
-        int len;
982
-        if(varname==NULL || value==NULL)
1087
+        sbuf *buf;
1088
+        if(varname==NULL || data==NULL || datalen==0)
983 1089
                 return(-1);
984 1090
         for(i=0;i<client->usedpost;i++) {
985 1091
                 if(strcmp(client->post[i].name,varname)==0)
... ...
@@ -988,21 +1094,26 @@ wk_postset(_wk *web, wk_client *client,char *varname, char *value)
988 1094
         if(i>=client->usedpost)
989 1095
                 return(-1); /* var not found */
990 1096
         post=client->post+i;
991
-        if(post->isfile) {
992
-                if((fd=open(post->value,O_CREAT|O_APPEND,0600))==-1)
1097
+        if(post->tofile!=NULL) {
1098
+                if((fd=open(post->tofile,O_CREAT|O_APPEND,0600))==-1)
993 1099
                         return(-1); /* couldn't open file */
994
-                len=strlen(value);
995
-                if(write(fd,value,len)!=len) {
1100
+                if(write(fd,data,datalen)!=datalen) {
996 1101
                         close(fd),fd=-1;
997
-                        return(-1); /* couldn't open file */
1102
+                        return(-1); /* couldn't write all data */
998 1103
                 }
999 1104
                 close(fd),fd=-1;
1000 1105
                 post->filewritten=1;
1001 1106
         } else {
1002
-                if(post->value!=NULL)
1003
-                        free(post->value),post->value=NULL;
1004
-                if((post->value=strdup(value))==NULL)
1005
-                        return(-1);
1107
+                if((buf=wk_sbufget((wk *)web,post->bufid))==NULL) {
1108
+                        post->bufid=-1;
1109
+                        return(-1); /* internal error */
1110
+                }
1111
+                if(post->value==NULL)
1112
+                        post->value=sbuf_ptrunused(buf);
1113
+                if(datalen>(sbuf_unused(buf)-1))
1114
+                        datalen=sbuf_unused(buf)-1;
1115
+                sbuf_add(buf,data,datalen);
1116
+                post->valueterminated=0;
1006 1117
         }
1007 1118
         return(0);
1008 1119
 }
... ...
@@ -1012,6 +1123,7 @@ wk_postget(_wk *web, wk_client *client,char *varname, int *isfile)
1012 1123
 {
1013 1124
         int i;
1014 1125
         wk_post *post;
1126
+        sbuf *buf;
1015 1127
         if(varname==NULL)
1016 1128
                 return(NULL);
1017 1129
         for(i=0;i<client->usedpost;i++) {
... ...
@@ -1021,10 +1133,23 @@ wk_postget(_wk *web, wk_client *client,char *varname, int *isfile)
1021 1133
         if(i>=client->usedpost)
1022 1134
                 return(NULL); /* var not found */
1023 1135
         post=client->post+i;
1136
+        /* file post */
1024 1137
         if(isfile!=NULL)
1025
-                *isfile=post->isfile;
1026
-        if(post->isfile && !post->filewritten)
1027
-                return(NULL);
1138
+                *isfile=(post->tofile!=NULL)?1:0;
1139
+        if(post->tofile) {
1140
+                if(!post->filewritten)
1141
+                        return(NULL);
1142
+                return(post->tofile);
1143
+        }
1144
+        /* buffer post */
1145
+        if((buf=wk_sbufget((wk *)web,post->bufid))==NULL)
1146
+                return(NULL); /* internal error */
1147
+        if(!post->valueterminated) {
1148
+                if(sbuf_unused(buf)<1)
1149
+                        return(NULL); /* internal error */
1150
+                *(sbuf_ptrunused(buf))='\0';
1151
+                post->valueterminated=1;
1152
+        }
1028 1153
         return(post->value);
1029 1154
 }
1030 1155
 
... ...
@@ -1032,12 +1157,11 @@ static int
1032 1157
 wk_postfree(_wk *web, wk_client *client)
1033 1158
 {
1034 1159
         int i;
1160
+        wk_post *post;
1035 1161
         for(i=0;i<client->usedpost;i++) {
1036
-                if(client->post[i].name!=NULL)
1037
-                        free(client->post[i].name),client->post[i].name=NULL;
1038
-                if(client->post[i].value!=NULL)
1039
-                        free(client->post[i].value),client->post[i].value=NULL;
1040
-                client->post[i].isfile=0;
1162
+                post=client->post+i;
1163
+                if(post->bufid!=-1)
1164
+                        wk_sbufrelease((wk *)web,post->bufid),post->bufid=-1;
1041 1165
         }
1042 1166
         if(client->post!=NULL) {
1043 1167
                 client->usedpost=0;
Browse code

webkernel: add wk_uri_copyvar()

Dario Rodriguez authored on 23/06/2014 20:51:11
Showing 1 changed files
... ...
@@ -535,6 +535,18 @@ wk_uri_getvar(wk_uri *uri, char *varname, int *len)
535 535
         return(NULL);
536 536
 }
537 537
 
538
+char *
539
+wk_uri_copyvar(wk_uri *uri, char *varname, char *dest, int destlen)
540
+{
541
+        char *value;
542
+        int len;
543
+        if(dest==NULL || destlen<1 || (value=wk_uri_getvar(uri,varname,&len))==NULL)
544
+                return(NULL);
545
+        memcpy(dest,value,(len<(destlen-1))?len:destlen-1);
546
+        dest[(len<(destlen-1))?len:destlen-1]='\0';
547
+        return(dest);
548
+}
549
+
538 550
 
539 551
 int
540 552
 wk_post_addvalid(wk *paramweb, int connid, char *varname, char *tofile)
Browse code

webkernel: get vars from GET request, partial implementation of vars for POST request.

Dario Rodriguez authored on 23/06/2014 20:31:46
Showing 1 changed files
... ...
@@ -26,7 +26,20 @@
26 26
 #define BUFSIZE 8192
27 27
 #define BUFBLOCK 128
28 28
 #define BUFBLOCKBLOCK 256
29
+#define POSTBLOCK 16
29 30
 
31
+typedef struct wk_post {
32
+        char *name;
33
+        char *value;
34
+        int isfile;
35
+        int filewritten;
36
+} wk_post;
37
+
38
+typedef enum wkc_status {
39
+        wkc_header=0,
40
+        wkc_post,
41
+        wkc_none,
42
+} wkc_status;
30 43
 
31 44
 typedef struct wk_client {
32 45
         wk *web;
... ...
@@ -36,12 +49,16 @@ typedef struct wk_client {
36 49
         int sizeoutbufids;
37 50
         int usedoutbufids;
38 51
         int outbufids[MAXOUTBUF];
52
+        wkc_status status;
39 53
         int serviced;
40 54
         int continuationactive;
41 55
         int fdtoserve;
42 56
         wk_uri uri;
43 57
         int headerbufid;
44 58
         int keepalive;
59
+        int sizepost;
60
+        int usedpost;
61
+        wk_post *post;
45 62
 } wk_client;
46 63
 
47 64
 typedef struct wk_clientblock {
... ...
@@ -75,6 +92,7 @@ typedef struct _wk {
75 92
         wk_bufblock *bufblocks;
76 93
         void (*callback_event)(/*wk *web,int connid, wk_event event, void *userptr*/);
77 94
         wk_action (*callback_http)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
95
+        wk_action (*callback_post)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
78 96
         wk_action (*callback_continuation)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
79 97
         void *userptr;
80 98
 } _wk;
... ...
@@ -83,10 +101,14 @@ static wk_client *wk_accept(_wk *web);
83 101
 static wk_client *wk_clientacquire(_wk *web);
84 102
 static int wk_clientrelease(_wk *web, int connid);
85 103
 static wk_client *wk_clientget(_wk *web, int connid);
86
-static int wk_clientserviceread(_wk *web, wk_client *client);
104
+static int wk_clientservicereadheader(_wk *web, wk_client *client);
105
+static int wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile);
106
+static int wk_postset(_wk *web, wk_client *client,char *varname, char *value);
107
+static char *wk_postget(_wk *web, wk_client *client,char *varname, int *isfile);
108
+static int wk_postfree(_wk *web, wk_client *client);
87 109
 
88 110
 wk *
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)
111
+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)
90 112
 {
91 113
         _wk *web;
92 114
         if(ssel==NULL || callback_http==NULL)
... ...
@@ -97,6 +119,7 @@ wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *web,int connid, wk
97 119
         web->serverfd=-1;
98 120
         web->callback_event=callback_event;
99 121
         web->callback_http=callback_http;
122
+        web->callback_post=callback_post;
100 123
         web->callback_continuation=callback_continuation;
101 124
         web->userptr=userptr;
102 125
         web->ssel=ssel;
... ...
@@ -151,6 +174,7 @@ wk_free(wk *paramweb)
151 174
                                 }
152 175
                                 if(client->fdtoserve!=-1)
153 176
                                         close(client->fdtoserve),client->fdtoserve=-1;
177
+                                wk_postfree(web,client);
154 178
                         }
155 179
                 }
156 180
                 cb->usedclients=0;
... ...
@@ -231,10 +255,14 @@ wk_service(wk *paramweb)
231 255
                                 wk_close((wk *) web, client->connid);
232 256
                                 continue;
233 257
                         }
234
-                        if(wk_clientserviceread(web,client)==-1) {
235
-                                /* internal error, protocol error or no enough memory */
236
-                                wk_close((wk *) web, client->connid);
237
-                                continue;
258
+                        if(client->status==wkc_header) {
259
+                                if(wk_clientservicereadheader(web,client)==-1) {
260
+                                        /* internal error, protocol error or no enough memory */
261
+                                        wk_close((wk *) web, client->connid);
262
+                                        continue;
263
+                                }
264
+                        } else if(client->status==wkc_post) {
265
+#warning TODO
238 266
                         }
239 267
                 }
240 268
         }
... ...
@@ -482,6 +510,57 @@ wk_uri_getheaderbynum(wk_uri *uri, int num)
482 510
         return(NULL);
483 511
 }
484 512
 
513
+char *
514
+wk_uri_getvar(wk_uri *uri, char *varname, int *len)
515
+{
516
+        char *ptr,*end;
517
+        int varlen;
518
+        if(uri==NULL || uri->path==NULL || (ptr=strchr(uri->path,'?'))==NULL)
519
+                return(NULL);
520
+        varlen=strlen(varname);
521
+        ptr++;
522
+        while(*ptr!='\0' && ptr!=NULL) {
523
+                if(memcmp(ptr,varname,varlen)==0 && ptr[varlen]=='=') {
524
+                        ptr+=varlen+1;
525
+                        if((end=strchr(ptr,'&'))==NULL)
526
+                                end=ptr+strlen(ptr);
527
+                        if(len!=NULL)
528
+                                *len=end-ptr;
529
+                        return(ptr);
530
+                }
531
+                if((end=strchr(ptr,'&'))==NULL)
532
+                        break;
533
+                ptr=end+1;
534
+        }
535
+        return(NULL);
536
+}
537
+
538
+
539
+int
540
+wk_post_addvalid(wk *paramweb, int connid, char *varname, char *tofile)
541
+{
542
+        _wk *web=(_wk *)paramweb;
543
+        wk_client *client;
544
+        if(web==NULL || varname==NULL)
545
+                return(-1);
546
+        if((client=wk_clientget(web,connid))==NULL)
547
+                return(-1);
548
+        return(wk_postadd(web,client,varname,tofile));
549
+}
550
+
551
+char *
552
+wk_post_get(wk *paramweb, int connid, char *varname, int *isfile)
553
+{
554
+        _wk *web=(_wk *)paramweb;
555
+        wk_client *client;
556
+        if(web==NULL || varname==NULL)
557
+                return(NULL);
558
+        if((client=wk_clientget(web,connid))==NULL)
559
+                return(NULL);
560
+        return(wk_postget(web,client,varname,isfile));
561
+}
562
+
563
+
485 564
 const char *
486 565
 mime_getdefault(const char *filename, const char *defaultmime)
487 566
 {
... ...
@@ -739,6 +818,7 @@ wk_clientrelease(_wk *web, int connid)
739 818
                 wk_sbufrelease((wk *)web,client->outbufids[w]),client->outbufids[w]=-1;
740 819
         if(client->headerbufid!=-1)
741 820
                 wk_sbufrelease((wk *)web,client->headerbufid),client->headerbufid=-1;
821
+        wk_postfree(web,client);
742 822
         memset(client,0,sizeof(wk_client));
743 823
         return(0);
744 824
 }
... ...
@@ -771,7 +851,7 @@ str_findfirstempty(char *ptr, int size)
771 851
 }
772 852
 
773 853
 static int
774
-wk_clientserviceread(_wk *web, wk_client *client)
854
+wk_clientservicereadheader(_wk *web, wk_client *client)
775 855
 {
776 856
         sbuf *in,*hbuf;
777 857
         char *end;
... ...
@@ -850,7 +930,109 @@ wk_clientserviceread(_wk *web, wk_client *client)
850 930
         /* call the http method */
851 931
         client->serviced=1;
852 932
         client->continuationactive=0;
933
+#warning TODO: wkc_post
853 934
         client->continuationactive=web->callback_http((wk *)web, client->connid, uri, web->userptr);
854 935
         return(0);
855 936
 }
856 937
 
938
+static int
939
+wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile)
940
+{
941
+        wk_post *post;
942
+        if(client->post==NULL || client->sizepost==client->usedpost) {
943
+                wk_post *newpost;
944
+                if((newpost=(wk_post *)realloc(client->post,(client->sizepost+POSTBLOCK)*sizeof(wk_post)))==NULL)
945
+                        return(-1); /* insufficient memory */
946
+                client->post=newpost;
947
+                memset(client->post+client->sizepost,0,POSTBLOCK*sizeof(wk_post));
948
+                client->sizepost+=POSTBLOCK;
949
+        }
950
+        post=client->post+client->usedpost;
951
+        if((post->name=strdup(varname))==NULL)
952
+                return(-1); /* insufficient memory */
953
+        if(tofile!=NULL) {
954
+                if((post->value=strdup(tofile))==NULL) {
955
+                        free(post->name),post->name=NULL;
956
+                        return(-1); /* insufficient memory */
957
+                }
958
+        } else
959
+                post->isfile=0;
960
+        return(0);
961
+}
962
+
963
+static int
964
+wk_postset(_wk *web, wk_client *client,char *varname, char *value)
965
+{
966
+        int i;
967
+        wk_post *post;
968
+        int fd;
969
+        int len;
970
+        if(varname==NULL || value==NULL)
971
+                return(-1);
972
+        for(i=0;i<client->usedpost;i++) {
973
+                if(strcmp(client->post[i].name,varname)==0)
974
+                        break;
975
+        }
976
+        if(i>=client->usedpost)
977
+                return(-1); /* var not found */
978
+        post=client->post+i;
979
+        if(post->isfile) {
980
+                if((fd=open(post->value,O_CREAT|O_APPEND,0600))==-1)
981
+                        return(-1); /* couldn't open file */
982
+                len=strlen(value);
983
+                if(write(fd,value,len)!=len) {
984
+                        close(fd),fd=-1;
985
+                        return(-1); /* couldn't open file */
986
+                }
987
+                close(fd),fd=-1;
988
+                post->filewritten=1;
989
+        } else {
990
+                if(post->value!=NULL)
991
+                        free(post->value),post->value=NULL;
992
+                if((post->value=strdup(value))==NULL)
993
+                        return(-1);
994
+        }
995
+        return(0);
996
+}
997
+
998
+static char *
999
+wk_postget(_wk *web, wk_client *client,char *varname, int *isfile)
1000
+{
1001
+        int i;
1002
+        wk_post *post;
1003
+        if(varname==NULL)
1004
+                return(NULL);
1005
+        for(i=0;i<client->usedpost;i++) {
1006
+                if(strcmp(client->post[i].name,varname)==0)
1007
+                        break;
1008
+        }
1009
+        if(i>=client->usedpost)
1010
+                return(NULL); /* var not found */
1011
+        post=client->post+i;
1012
+        if(isfile!=NULL)
1013
+                *isfile=post->isfile;
1014
+        if(post->isfile && !post->filewritten)
1015
+                return(NULL);
1016
+        return(post->value);
1017
+}
1018
+
1019
+static int
1020
+wk_postfree(_wk *web, wk_client *client)
1021
+{
1022
+        int i;
1023
+        for(i=0;i<client->usedpost;i++) {
1024
+                if(client->post[i].name!=NULL)
1025
+                        free(client->post[i].name),client->post[i].name=NULL;
1026
+                if(client->post[i].value!=NULL)
1027
+                        free(client->post[i].value),client->post[i].value=NULL;
1028
+                client->post[i].isfile=0;
1029
+        }
1030
+        if(client->post!=NULL) {
1031
+                client->usedpost=0;
1032
+                client->sizepost=0;
1033
+                free(client->post),client->post=NULL;
1034
+        }
1035
+        return(0);
1036
+}
1037
+
1038
+
Browse code

webkernel: fix str_findfirstempty, wk_service, sbuf and client allocation, wk_clientserviceread

Dario Rodriguez authored on 21/06/2014 09:41:14
Showing 1 changed files
... ...
@@ -204,7 +204,7 @@ wk_service(wk *paramweb)
204 204
         wk_client *client;
205 205
         if(web==NULL)
206 206
                 return(-1);
207
-        while((n=sselect_getreadfiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
207
+        while((n=sselect_getreadfiltered(web->ssel,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
208 208
                 for(i=0;i<n;i++) {
209 209
                         fd=fds[i];
210 210
                         if(fd==web->serverfd) {
... ...
@@ -238,7 +238,7 @@ wk_service(wk *paramweb)
238 238
                         }
239 239
                 }
240 240
         }
241
-        while((n=sselect_getwritefiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
241
+        while((n=sselect_getwritefiltered(web->ssel,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
242 242
                 for(i=0;i<n;i++) {
243 243
                         fd=fds[i];
244 244
                         if((client=(wk_client *)sselect_getuserptr(web->ssel,fd))==NULL || client->web!=(wk *)web)
... ...
@@ -548,7 +548,7 @@ wk_sbufacquire(wk *paramweb)
548 548
         /* make sure there are free bufblocks */
549 549
         if(web->usedbufblocks==web->sizebufblocks) {
550 550
                 wk_bufblock *newbb;
551
-                if((newbb=(wk_bufblock *)realloc(web->bufblocks,web->sizebufblocks+BUFBLOCKBLOCK))==NULL)
551
+                if((newbb=(wk_bufblock *)realloc(web->bufblocks,(web->sizebufblocks+BUFBLOCKBLOCK)*sizeof(wk_bufblock)))==NULL)
552 552
                         return(-1); /* insufficient memory */
553 553
                 web->bufblocks=newbb;
554 554
                 memset(web->bufblocks+web->sizebufblocks,0,BUFBLOCKBLOCK*sizeof(wk_bufblock));
... ...
@@ -569,6 +569,7 @@ wk_sbufacquire(wk *paramweb)
569 569
                 memset(bb->bufs,0,sizeof(wk_buf)*BUFBLOCK);
570 570
                 bb->sizebufs=BUFBLOCK;
571 571
                 bb->usedbufs=0;
572
+                web->usedbufblocks++;
572 573
         }
573 574
         /* get first unused sbuf */
574 575
         for(j=0;j<bb->sizebufs;j+=8) {
... ...
@@ -659,7 +660,7 @@ wk_clientacquire(_wk *web)
659 660
         /* make sure there are free clientblocks */
660 661
         if(web->usedclientblocks==web->sizeclientblocks) {
661 662
                 wk_clientblock *newcb;
662
-                if((newcb=(wk_clientblock *)realloc(web->clientblocks,web->sizeclientblocks+CLIENTBLOCKBLOCK))==NULL)
663
+                if((newcb=(wk_clientblock *)realloc(web->clientblocks,(web->sizeclientblocks+CLIENTBLOCKBLOCK)*sizeof(wk_clientblock)))==NULL)
663 664
                         return(NULL); /* insufficient memory */
664 665
                 web->clientblocks=newcb;
665 666
                 memset(web->clientblocks+web->sizeclientblocks,0,CLIENTBLOCKBLOCK*sizeof(wk_clientblock));
... ...
@@ -680,6 +681,7 @@ wk_clientacquire(_wk *web)
680 681
                 memset(cb->clients,0,sizeof(wk_client)*CLIENTBLOCK);
681 682
                 cb->sizeclients=CLIENTBLOCK;
682 683
                 cb->usedclients=0;
684
+                web->usedclientblocks++;
683 685
         }
684 686
         /* get first unused client */
685 687
         for(j=0;j<cb->sizeclients;j+=8) {
... ...
@@ -762,8 +764,8 @@ str_findfirstempty(char *ptr, int size)
762 764
 {
763 765
         int i;
764 766
         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
+                if(ptr[i+0]=='\r' && ptr[i+1]=='\n' && ptr[i+2]=='\r' && ptr[i+3]=='\n')
768
+                        return(ptr+i);
767 769
         }
768 770
         return(NULL);
769 771
 }
... ...
@@ -819,7 +821,7 @@ wk_clientserviceread(_wk *web, wk_client *client)
819 821
         sbuf_add(hbuf,ptr,strlen(ptr)+1);
820 822
         ptr+=strlen(ptr)+1;
821 823
         /* protocol */
822
-        uri->path=sbuf_ptrunused(hbuf);
824
+        uri->protocol=sbuf_ptrunused(hbuf);
823 825
         sbuf_add(hbuf,ptr,strlen(ptr)+1);
824 826
         ptr+=strlen(ptr)+1;
825 827
         /* headers */
Browse code

webkernel_test: initial implementation of the testing framework

Dario Rodriguez authored on 18/06/2014 11:18:10
Showing 1 changed files
... ...
@@ -592,7 +592,7 @@ wk_sbufacquire(wk *paramweb)
592 592
 }
593 593
 
594 594
 int
595
-wk_bufrelease(wk *paramweb, int sbufid)
595
+wk_sbufrelease(wk *paramweb, int sbufid)
596 596
 {
597 597
         sbuf *buf;
598 598
         int numblock,j,bit;
... ...
@@ -612,7 +612,7 @@ wk_bufrelease(wk *paramweb, int sbufid)
612 612
 }
613 613
 
614 614
 sbuf *
615
-wk_bufget(wk *paramweb, int sbufid)
615
+wk_sbufget(wk *paramweb, int sbufid)
616 616
 {
617 617
         int numblock,j,bit;
618 618
         _wk *web=(_wk *)paramweb;
Browse code

webkernel: completed initial implementation

Dario Rodriguez authored on 17/06/2014 20:32:33
Showing 1 changed files
... ...
@@ -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
 
Browse code

webkernel: wk_write

Dario Rodriguez authored on 17/06/2014 13:37:13
Showing 1 changed files
... ...
@@ -255,7 +255,6 @@ wk_service(wk *paramweb)
255 255
                                                 client->serviced=0; /* we have finished servicing this one */
256 256
                                                 if(!client->keepalive)
257 257
                                                         wk_close((wk *)web, fd); /* all sent */
258
-
259 258
                                         }
260 259
                                 }
261 260
                         }
... ...
@@ -285,13 +284,40 @@ wk_serve_error(wk *paramweb, int connid, wk_error wkerror)
285 284
 int
286 285
 wk_writestr(wk *paramweb, int connid, char *str)
287 286
 {
288
-
287
+        return(wk_write(paramweb,connid,str,strlen(str)));
289 288
 }
290 289
 
291 290
 int
292 291
 wk_write(wk *paramweb, int connid, void *data, int datalen)
293 292
 {
294
-
293
+        int k;
294
+        _wk *web=(_wk *)paramweb;
295
+        wk_client *client;
296
+        sbuf *out;
297
+        long added;
298
+        long total;
299
+        if(web==NULL)
300
+                return(-1);
301
+        if((client=wk_clientget(web,connid))==NULL)
302
+                return(-1);
303
+        total=0;
304
+        for(k=(client->usedoutbufids>0)?client->usedoutbufids-1:0;
305
+          datalen>0 && k<MAXOUTBUF;k++) {
306
+                if(client->outbufids[k]==-1) {
307
+                        if((client->outbufids[k]=wk_sbufacquire((wk *)web))==-1)
308
+                                return(-1); /* insufficient memory */
309
+                        client->usedoutbufids++;
310
+                }
311
+                if((out=wk_sbufget((wk *)web,client->outbufids[k]))==NULL)
312
+                        return(-1); /* internal error */
313
+                if(sbuf_unused(out)==0)
314
+                        continue;
315
+                added=sbuf_add(out,data,datalen);
316
+                data+=added;
317
+                datalen-=added;
318
+                total+=added;
319
+        }
320
+        return(total);
295 321
 }
296 322
 
297 323
 int
Browse code

webkernel: service (withoy read processing and without write-from-fd functionality)

Dario Rodriguez authored on 17/06/2014 11:12:59
Showing 1 changed files
... ...
@@ -33,6 +33,10 @@ typedef struct wk_client {
33 33
         int sizeoutbufids;
34 34
         int usedoutbufids;
35 35
         int outbufids[MAXOUTBUF];
36
+        int serviced;
37
+        wk_uri uri;
38
+        int continuationactive;
39
+        int keepalive;
36 40
 } wk_client;
37 41
 
38 42
 typedef struct wk_clientblock {
... ...
@@ -64,15 +68,20 @@ typedef struct _wk {
64 68
         int sizebufblocks;
65 69
         int usedbufblocks;
66 70
         wk_bufblock *bufblocks;
71
+        void (*callback_event)(/*wk *web,int connid, wk_event event, void *userptr*/);
72
+        wk_action (*callback_http)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
73
+        wk_action (*callback_continuation)(/*wk *web,int connid, wk_uri *uri, void *userptr*/);
74
+        void *userptr;
67 75
 } _wk;
68 76
 
69
-static int wk_accept(_wk *web);
77
+static wk_client *wk_accept(_wk *web);
70 78
 static wk_client *wk_clientacquire(_wk *web);
71 79
 static int wk_clientrelease(_wk *web, int connid);
72 80
 static wk_client *wk_clientget(_wk *web, int connid);
81
+static void wk_clientserviceread(_wk *web, wk_client *client);
73 82
 
74 83
 wk *
75
-wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int connid, wk_event event, void *userptr*/), void (*callback_http)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void (*callback_continuation)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void *userptr)
84
+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)
76 85
 {
77 86
         _wk *web;
78 87
         if(ssel==NULL || callback_http==NULL)
... ...
@@ -81,6 +90,10 @@ wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int conni
81 90
                 return(NULL);
82 91
         memset(web,0,sizeof(_wk));
83 92
         web->serverfd=-1;
93
+        web->callback_event=callback_event;
94
+        web->callback_http=callback_http;
95
+        web->callback_continuation=callback_continuation;
96
+        web->userptr=userptr;
84 97
         web->ssel=ssel;
85 98
         FD_ZERO(&(web->fdset));
86 99
         if((web->serverfd=ipv4_server(port))==-1) {
... ...
@@ -90,6 +103,8 @@ wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int conni
90 103
         sock_setunsafe(web->serverfd);
91 104
         FD_SET(web->serverfd,&(web->fdset));
92 105
         sselect_addread(ssel,web->serverfd,NULL);
106
+        if(web->callback_event!=NULL)
107
+                web->callback_event((wk *)web,-1,wke_init,web->userptr);
93 108
         return((wk *)web);
94 109
 }
95 110
 
... ...
@@ -103,6 +118,8 @@ wk_free(wk *paramweb)
103 118
         wk_bufblock *bb;
104 119
         if(web==NULL)
105 120
                 return;
121
+        if(web->callback_event!=NULL)
122
+                web->callback_event((wk *)web,-1,wke_fini,web->userptr);
106 123
         /* release server fds */
107 124
         if(web->serverfd!=-1) {
108 125
                 sselect_delread(web->ssel,web->serverfd);
... ...
@@ -137,7 +154,7 @@ wk_free(wk *paramweb)
137 154
         web->sizeclientblocks=0;
138 155
         if(web->clientblocks!=NULL)
139 156
                 free(web->clientblocks),web->clientblocks=NULL;
140
-	/* release the used sbuf */
157
+        /* release the used sbuf */
141 158
         for(i=0;i<web->usedbufblocks;i++) {
142 159
                 bb=web->bufblocks+i;
143 160
                 if(bb->bufs==NULL)
... ...
@@ -157,7 +174,15 @@ wk_free(wk *paramweb)
157 174
 wk_uri *
158 175
 wk_geturi(wk *paramweb, int connid)
159 176
 {
160
-
177
+        _wk *web=(_wk *)paramweb;
178
+        wk_client *client;
179
+        if(web==NULL)
180
+                return(NULL);
181
+        if((client=wk_clientget(web,connid))==NULL)
182
+                return(NULL);
183
+        if(client->serviced==0)
184
+                return(NULL);
185
+        return(&(client->uri));
161 186
 }
162 187
 
163 188
 int
... ...
@@ -165,8 +190,9 @@ wk_service(wk *paramweb)
165 190
 {
166 191
         int fds[FDBLOCK];
167 192
         int fd;
168
-        int n;
169
-        int i;
193
+        int n,i,k;
194
+        sbuf *in;
195
+        sbuf *out;
170 196
         _wk *web=(_wk *)paramweb;
171 197
         wk_client *client;
172 198
         if(web==NULL)
... ...
@@ -176,14 +202,66 @@ wk_service(wk *paramweb)
176 202
                         fd=fds[i];
177 203
                         if(fd==web->serverfd) {
178 204
                                 /* accept new connection */
179
-                                wk_accept(web);
205
+                                if((client=wk_accept(web))!=NULL && web->callback_event!=NULL)
206
+                                        web->callback_event((wk *)web,client->connid,wke_connected,web->userptr);
207
+                                continue; /* all done here */
208
+                        }
209
+                        if((client=(wk_client *)sselect_getuserptr(web->ssel,fd))==NULL || client->web!=(wk *)web) {
210
+                                wk_close((wk *)web,client->connid);
211
+                                continue; /* internal error */
212
+                        }
213
+                        if((in=wk_sbufget((wk *) web,client->inbufid))==NULL) {
214
+                                wk_close((wk *)web,client->connid);
215
+                                continue; /* internal error */
216
+                        }
217
+                        if(sbuf_unused(in)<=0) {
218
+                                /* no room for the new data */
219
+                                sselect_delread(web->ssel,fd);
220
+                                continue;
221
+                        }
222
+                        if(sbuf_fill(in,fd,sock_queued(fd))==0) {
223
+                                /* client has closed connection */
224
+                                wk_close((wk *) web, fd);
180 225
                                 continue;
181 226
                         }
227
+                        wk_clientserviceread(web,client);
228
+                }
229
+        }
230
+        while((n=sselect_getwritefiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
231
+                for(i=0;i<n;i++) {
232
+                        fd=fds[i];
182 233
                         if((client=(wk_client *)sselect_getuserptr(web->ssel,fd))==NULL || client->web!=(wk *)web)
183 234
                                 continue; /* internal error */
184
-
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) {
242
+                                wk_close((wk *)web,client->connid);
243
+                                continue; /* internal error */
244
+                        }
245
+                        sbuf_send(out,fd,sbuf_count(out));
246
+                        if(sbuf_count(out)==0) {
247
+                                if(k>0) {
248
+                                        client->usedoutbufids--;
249
+                                        wk_sbufrelease((wk *)web,client->outbufids[k]),client->outbufids[k]=-1;
250
+                                } else {
251
+                                        sselect_delwrite(web->ssel,client->fd);
252
+                                        if(client->continuationactive && web->callback_continuation!=NULL) {
253
+                                                client->continuationactive=web->callback_continuation((wk *)web,client->connid,&(client->uri),web->userptr);
254
+                                        } else {
255
+                                                client->serviced=0; /* we have finished servicing this one */
256
+                                                if(!client->keepalive)
257
+                                                        wk_close((wk *)web, fd); /* all sent */
258
+
259
+                                        }
260
+                                }
261
+                        }
185 262
                 }
186 263
         }
264
+        return(0);
187 265
 }
188 266
 
189 267
 int
... ...
@@ -219,7 +297,22 @@ wk_write(wk *paramweb, int connid, void *data, int datalen)
219 297
 int
220 298
 wk_close(wk *paramweb, int connid)
221 299
 {
222
-
300
+        _wk *web=(_wk *)paramweb;
301
+        wk_client *client;
302
+        if(web==NULL)
303
+                return(-1);
304
+        if((client=wk_clientget(web,connid))==NULL)
305
+                return(-1);
306
+        if(client->fd!=-1) {
307
+                sselect_delread(web->ssel,client->fd);
308
+                sselect_delwrite(web->ssel,client->fd);
309
+                FD_CLR(client->fd,&(web->fdset));
310
+                close(client->fd),client->fd=-1;
311
+        }
312
+        wk_clientrelease(web,connid);
313
+        if(web->callback_event!=NULL)
314
+                web->callback_event((wk *)web,connid,wke_closed,web->userptr);
315
+        return(0);
223 316
 }
224 317
 
225 318
 char *
... ...
@@ -384,21 +477,21 @@ wk_bufget(wk *paramweb, int sbufid)
384 477
 
385 478
 
386 479
 /* local functions */
387
-static int
480
+static wk_client *
388 481
 wk_accept(_wk *web)
389 482
 {
390 483
         int newfd;
391 484
         wk_client *client;
392 485
         if((newfd=sock_accept(web->serverfd))==-1)
393
-                return(-1);
486
+                return(NULL);
394 487
         if((client=wk_clientacquire(web))==NULL) {
395 488
                 close(newfd),newfd=-1;
396
-                return(-1);
489
+                return(NULL);
397 490
         }
398 491
         client->fd=newfd;
399 492
         FD_SET(client->fd,&(web->fdset));
400 493
         sselect_addread(web->ssel,client->fd,(void *)client);
401
-        return(0);
494
+        return(client);
402 495
 }
403 496
 
404 497
 static wk_client *
... ...
@@ -483,7 +576,7 @@ wk_clientrelease(_wk *web, int connid)
483 576
         web->clientblocks[numblock].acquired[j>>3]&=(~bit);
484 577
         if(client->inbufid!=-1)
485 578
                 wk_sbufrelease((wk *)web,client->inbufid),client->inbufid=-1;
486
-        for(w=0;w<client->usedoutbufids;w++) 
579
+        for(w=0;w<client->usedoutbufids;w++)
487 580
                 wk_sbufrelease((wk *)web,client->outbufids[w]),client->outbufids[w]=-1;
488 581
         memset(client,0,sizeof(wk_client));
489 582
         return(0);
... ...
@@ -505,4 +598,9 @@ wk_clientget(_wk *web, int connid)
505 598
         return(web->clientblocks[numblock].clients+j);
506 599
 }
507 600
 
601
+static void
602
+wk_clientserviceread(_wk *web, wk_client *client)
603
+{
604
+#warning TODO
605
+}
508 606
 
Browse code

webkernel: integrate the in/out bufs into the client structures

Dario Rodriguez authored on 15/06/2014 15:13:14
Showing 1 changed files
... ...
@@ -100,6 +100,7 @@ wk_free(wk *paramweb)
100 100
         _wk *web=(_wk *)paramweb;
101 101
         wk_clientblock *cb;
102 102
         wk_client *client;
103
+        wk_bufblock *bb;
103 104
         if(web==NULL)
104 105
                 return;
105 106
         /* release server fds */
... ...
@@ -136,6 +137,19 @@ wk_free(wk *paramweb)
136 137
         web->sizeclientblocks=0;
137 138
         if(web->clientblocks!=NULL)
138 139
                 free(web->clientblocks),web->clientblocks=NULL;
140
+	/* release the used sbuf */
141
+        for(i=0;i<web->usedbufblocks;i++) {
142
+                bb=web->bufblocks+i;
143
+                if(bb->bufs==NULL)
144
+                        continue;
145
+                bb->usedbufs=0;
146
+                bb->sizebufs=0;
147
+                free(bb->bufs),bb->bufs=NULL;
148
+        }
149
+        web->usedbufblocks=0;
150
+        web->sizebufblocks=0;
151
+        if(web->bufblocks!=NULL)
152
+                free(web->bufblocks),web->bufblocks=NULL;
139 153
         /* free the main struct */
140 154
         free(web),web=NULL;
141 155
 }
... ...
@@ -335,7 +349,7 @@ wk_bufrelease(wk *paramweb, int sbufid)
335 349
         sbuf *buf;
336 350
         int numblock,j,bit;
337 351
         _wk *web=(_wk *)paramweb;
338
-        if(web==NULL)
352
+        if(web==NULL || sbufid<0)
339 353
                 return(-1);
340 354
         numblock=sbufid/BUFBLOCK;
341 355
         j=sbufid%BUFBLOCK;
... ...
@@ -393,6 +407,7 @@ wk_clientacquire(_wk *web)
393 407
         int i,j,k;
394 408
         wk_clientblock *cb;
395 409
         wk_client *client;
410
+        int w;
396 411
         /* make sure there are free clientblocks */
397 412
         if(web->usedclientblocks==web->sizeclientblocks) {
398 413
                 wk_clientblock *newcb;
... ...
@@ -439,6 +454,17 @@ wk_clientacquire(_wk *web)
439 454
         client->web=(wk *)web;
440 455
         client->connid=i*CLIENTBLOCK+j;
441 456
         client->fd=-1;
457
+        if((client->inbufid=wk_sbufacquire((wk *)web))==-1) {
458
+                wk_clientrelease(web,client->connid);
459
+                return(NULL); /* insufficient memory */
460
+        }
461
+        for(w=0;w<MAXOUTBUF;w++)
462
+                client->outbufids[w]=-1;
463
+        if((client->outbufids[0]=wk_sbufacquire((wk *)web))==-1) {
464
+                wk_clientrelease(web,client->connid);
465
+                return(NULL); /* insufficient memory */
466
+        }
467
+        client->usedoutbufids=1;
442 468
         return(client);
443 469
 }
444 470
 
... ...
@@ -447,6 +473,7 @@ wk_clientrelease(_wk *web, int connid)
447 473
 {
448 474
         wk_client *client;
449 475
         int numblock,j,bit;
476
+        int w;
450 477
         numblock=connid/CLIENTBLOCK;
451 478
         j=connid%CLIENTBLOCK;
452 479
         bit=0x1<<(j&3);
... ...
@@ -454,6 +481,10 @@ wk_clientrelease(_wk *web, int connid)
454 481
                 return(-1);
455 482
         web->clientblocks[numblock].usedclients--;
456 483
         web->clientblocks[numblock].acquired[j>>3]&=(~bit);
484
+        if(client->inbufid!=-1)
485
+                wk_sbufrelease((wk *)web,client->inbufid),client->inbufid=-1;
486
+        for(w=0;w<client->usedoutbufids;w++) 
487
+                wk_sbufrelease((wk *)web,client->outbufids[w]),client->outbufids[w]=-1;
457 488
         memset(client,0,sizeof(wk_client));
458 489
         return(0);
459 490
 }
Browse code

webkernel: sbuf acquire/release

Dario Rodriguez authored on 15/06/2014 14:41:12
Showing 1 changed files
... ...
@@ -12,18 +12,27 @@
12 12
 #include <stdlib.h>
13 13
 #include <unistd.h>
14 14
 #include <string.h>
15
+#include "sbuf.h"
15 16
 #include "socklib.h"
16 17
 #include "webkernel.h"
17 18
 
18 19
 #define FDBLOCK 256
19 20
 #define CLIENTBLOCK 1024
20 21
 #define CLIENTBLOCKBLOCK 256
22
+#define MAXOUTBUF 128
23
+#define BUFSIZE 8192
24
+#define BUFBLOCK 128
25
+#define BUFBLOCKBLOCK 256
21 26
 
22 27
 
23 28
 typedef struct wk_client {
24 29
         wk *web;
25
-        int connid; /* it is numblock*CLIENTBLOCK+offset_in_block */
30
+        int connid; /* this is numblock*CLIENTBLOCK+offset_in_block */
26 31
         int fd;
32
+        int inbufid;
33
+        int sizeoutbufids;
34
+        int usedoutbufids;
35
+        int outbufids[MAXOUTBUF];
27 36
 } wk_client;
28 37
 
29 38
 typedef struct wk_clientblock {
... ...
@@ -33,6 +42,18 @@ typedef struct wk_clientblock {
33 42
         wk_client *clients;
34 43
 } wk_clientblock;
35 44
 
45
+typedef struct wk_buf {
46
+        sbuf buf;
47
+        char bufdata[BUFSIZE];
48
+} wk_buf;
49
+
50
+typedef struct wk_bufblock {
51
+        int sizebufs;
52
+        int usedbufs;
53
+        unsigned char acquired[BUFBLOCK/8];
54
+        wk_buf *bufs;
55
+} wk_bufblock;
56
+
36 57
 typedef struct _wk {
37 58
         int serverfd;
38 59
         fd_set fdset;
... ...
@@ -40,6 +61,9 @@ typedef struct _wk {
40 61
         int sizeclientblocks;
41 62
         int usedclientblocks;
42 63
         wk_clientblock *clientblocks;
64
+        int sizebufblocks;
65
+        int usedbufblocks;
66
+        wk_bufblock *bufblocks;
43 67
 } _wk;
44 68
 
45 69
 static int wk_accept(_wk *web);
... ...
@@ -63,6 +87,7 @@ wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int conni
63 87
                 wk_free((wk *)web),web=NULL;
64 88
                 return(NULL);
65 89
         }
90
+        sock_setunsafe(web->serverfd);
66 91
         FD_SET(web->serverfd,&(web->fdset));
67 92
         sselect_addread(ssel,web->serverfd,NULL);
68 93
         return((wk *)web);
... ...
@@ -129,6 +154,7 @@ wk_service(wk *paramweb)
129 154
         int n;
130 155
         int i;
131 156
         _wk *web=(_wk *)paramweb;
157
+        wk_client *client;
132 158
         if(web==NULL)
133 159
                 return(-1);
134 160
         while((n=sselect_getreadfiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
... ...
@@ -139,6 +165,9 @@ wk_service(wk *paramweb)
139 165
                                 wk_accept(web);
140 166
                                 continue;
141 167
                         }
168
+                        if((client=(wk_client *)sselect_getuserptr(web->ssel,fd))==NULL || client->web!=(wk *)web)
169
+                                continue; /* internal error */
170
+
142 171
                 }
143 172
         }
144 173
 }
... ...
@@ -245,18 +274,101 @@ mime_getdefault(const char *filename, const char *defaultmime)
245 274
         return(defaultmime);
246 275
 }
247 276
 
248
-siobuf *
249
-wk_iobufget(wk *paramweb)
277
+int
278
+wk_sbufacquire(wk *paramweb)
250 279
 {
251
-
280
+        int i,j,k;
281
+        wk_bufblock *bb;
282
+        sbuf *buf;
283
+        _wk *web=(_wk *)paramweb;
284
+        if(web==NULL)
285
+                return(-1);
286
+        /* make sure there are free bufblocks */
287
+        if(web->usedbufblocks==web->sizebufblocks) {
288
+                wk_bufblock *newbb;
289
+                if((newbb=(wk_bufblock *)realloc(web->bufblocks,web->sizebufblocks+BUFBLOCKBLOCK))==NULL)
290
+                        return(-1); /* insufficient memory */
291
+                web->bufblocks=newbb;
292
+                memset(web->bufblocks+web->sizebufblocks,0,BUFBLOCKBLOCK*sizeof(wk_bufblock));
293
+                web->sizebufblocks+=BUFBLOCKBLOCK;
294
+        }
295
+        /* search for a block with unused sbufs (or the first unalloc'd block) */
296
+        for(i=0;i<web->sizebufblocks;i++) {
297
+                bb=web->bufblocks+i;
298
+                if(bb->bufs==NULL || bb->usedbufs<bb->sizebufs)
299
+                        break;
300
+        }
301
+        if(i>=web->sizebufblocks)
302
+                return(-1); /* internal error */
303
+        /* alloc block if not alloc'd */
304
+        if(bb->bufs==NULL) {
305
+                if((bb->bufs=malloc(sizeof(wk_buf)*BUFBLOCK))==NULL)
306
+                        return(-1); /* insufficient memory */
307
+                memset(bb->bufs,0,sizeof(wk_buf)*BUFBLOCK);
308
+                bb->sizebufs=BUFBLOCK;
309
+                bb->usedbufs=0;
310
+        }
311
+        /* get first unused sbuf */
312
+        for(j=0;j<bb->sizebufs;j+=8) {
313
+                if(bb->acquired[j>>3]!=0xff)
314
+                        break;
315
+        }
316
+        if(j>=bb->sizebufs)
317
+                return(-1); /* internal error */
318
+        for(k=0x01;k<0x100;k<<=1,j++) {
319
+                if((bb->acquired[j>>3]&k)==0)
320
+                        break;
321
+        }
322
+        if(k>=0x100)
323
+                return(-1); /* internal error */
324
+        bb->acquired[j>>3]|=k;
325
+        bb->usedbufs++;
326
+        /* initialize sbuf and return it */
327
+        buf=&(bb->bufs[j].buf);
328
+        sbuf_staticinit(buf,BUFSIZE,bb->bufs[j].bufdata);
329
+        return(i*BUFBLOCK+j);
252 330
 }
253 331
 
254
-void
255
-wk_iobuffree(wk *paramweb, int iobufnum)
332
+int
333
+wk_bufrelease(wk *paramweb, int sbufid)
256 334
 {
335
+        sbuf *buf;
336
+        int numblock,j,bit;
337
+        _wk *web=(_wk *)paramweb;
338
+        if(web==NULL)
339
+                return(-1);
340
+        numblock=sbufid/BUFBLOCK;
341
+        j=sbufid%BUFBLOCK;
342
+        bit=0x1<<(j&3);
343
+        if((buf=wk_sbufget(web,sbufid))==NULL)
344
+                return(-1);
345
+        web->bufblocks[numblock].usedbufs--;
346
+        web->bufblocks[numblock].acquired[j>>3]&=(~bit);
347
+        sbuf_staticfree(buf);
348
+        memset(web->bufblocks[numblock].bufs[j].bufdata,0,sizeof(BUFSIZE));
349
+        return(0);
350
+}
257 351
 
352
+sbuf *
353
+wk_bufget(wk *paramweb, int sbufid)
354
+{
355
+        int numblock,j,bit;
356
+        _wk *web=(_wk *)paramweb;
357
+        if(web==NULL)
358
+                return(NULL);
359
+        numblock=sbufid/BUFBLOCK;
360
+        j=sbufid%BUFBLOCK;
361
+        bit=0x1<<(j&3);
362
+        if(web==NULL ||
363
+          web->bufblocks==NULL ||
364
+          web->sizebufblocks<=numblock ||
365
+          web->bufblocks[numblock].bufs==NULL ||
366
+          (web->bufblocks[numblock].acquired[j>>3]&bit)!=bit)
367
+                return(NULL);
368
+        return(&(web->bufblocks[numblock].bufs[j].buf));
258 369
 }
259 370
 
371
+
260 372
 /* local functions */
261 373
 static int
262 374
 wk_accept(_wk *web)
... ...
@@ -304,6 +416,7 @@ wk_clientacquire(_wk *web)
304 416
                         return(NULL); /* insufficient memory */
305 417
                 memset(cb->clients,0,sizeof(wk_client)*CLIENTBLOCK);
306 418
                 cb->sizeclients=CLIENTBLOCK;
419
+                cb->usedclients=0;
307 420
         }
308 421
         /* get first unused client */
309 422
         for(j=0;j<cb->sizeclients;j+=8) {
... ...
@@ -361,3 +474,4 @@ wk_clientget(_wk *web, int connid)
361 474
         return(web->clientblocks[numblock].clients+j);
362 475
 }
363 476
 
477
+
Browse code

webkernel: implement clientacquire/clientrelease

Dario Rodriguez authored on 14/06/2014 15:47:03
Showing 1 changed files
... ...
@@ -29,6 +29,7 @@ typedef struct wk_client {
29 29
 typedef struct wk_clientblock {
30 30
         int sizeclients;
31 31
         int usedclients;
32
+        unsigned char acquired[CLIENTBLOCKBLOCK/8];
32 33
         wk_client *clients;
33 34
 } wk_clientblock;
34 35
 
... ...
@@ -44,7 +45,7 @@ typedef struct _wk {
44 45
 static int wk_accept(_wk *web);
45 46
 static wk_client *wk_clientacquire(_wk *web);
46 47
 static int wk_clientrelease(_wk *web, int connid);
47
-wk_client *wk_clientget(_wk *web, int connid);
48
+static wk_client *wk_clientget(_wk *web, int connid);
48 49
 
49 50
 wk *
50 51
 wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int connid, wk_event event, void *userptr*/), void (*callback_http)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void (*callback_continuation)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void *userptr)
... ...
@@ -70,14 +71,47 @@ wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int conni
70 71
 void
71 72
 wk_free(wk *paramweb)
72 73
 {
74
+        int i,j,k,n;
73 75
         _wk *web=(_wk *)paramweb;
76
+        wk_clientblock *cb;
77
+        wk_client *client;
74 78
         if(web==NULL)
75 79
                 return;
80
+        /* release server fds */
76 81
         if(web->serverfd!=-1) {
77 82
                 sselect_delread(web->ssel,web->serverfd);
78 83
                 FD_CLR(web->serverfd,&(web->fdset));
79 84
                 close(web->serverfd),web->serverfd=-1;
80 85
         }
86
+        /* release client fds and free clients */
87
+        for(i=0;i<web->usedclientblocks;i++) {
88
+                cb=web->clientblocks+i;
89
+                if(cb->clients==NULL)
90
+                        continue;
91
+                for(j=0;j<cb->sizeclients;j+=8) {
92
+                        if(cb->acquired[j>>3]==0)
93
+                                continue;
94
+                        for(k=0x1,n=0;n<8;n++,k<<=1) {
95
+                                if(!(cb->acquired[j>>3]&k))
96
+                                        continue;
97
+                                client=cb->clients+j+k;
98
+                                if(client->fd!=-1) {
99
+                                        sselect_delread(web->ssel,client->fd);
100
+                                        sselect_delwrite(web->ssel,client->fd);
101
+                                        FD_CLR(client->fd,&(web->fdset));
102
+                                        close(client->fd),client->fd=-1;
103
+                                }
104
+                        }
105
+                }
106
+                cb->usedclients=0;
107
+                cb->sizeclients=0;
108
+                free(cb->clients),cb->clients=NULL;
109
+        }
110
+        web->usedclientblocks=0;
111
+        web->sizeclientblocks=0;
112
+        if(web->clientblocks!=NULL)
113
+                free(web->clientblocks),web->clientblocks=NULL;
114
+        /* free the main struct */
81 115
         free(web),web=NULL;
82 116
 }
83 117
 
... ...
@@ -244,24 +278,86 @@ wk_accept(_wk *web)
244 278
 static wk_client *
245 279
 wk_clientacquire(_wk *web)
246 280
 {
247
-#warning TODO
281
+        int i,j,k;
282
+        wk_clientblock *cb;
283
+        wk_client *client;
284
+        /* make sure there are free clientblocks */
285
+        if(web->usedclientblocks==web->sizeclientblocks) {
286
+                wk_clientblock *newcb;
287
+                if((newcb=(wk_clientblock *)realloc(web->clientblocks,web->sizeclientblocks+CLIENTBLOCKBLOCK))==NULL)
288
+                        return(NULL); /* insufficient memory */
289
+                web->clientblocks=newcb;
290
+                memset(web->clientblocks+web->sizeclientblocks,0,CLIENTBLOCKBLOCK*sizeof(wk_clientblock));
291
+                web->sizeclientblocks+=CLIENTBLOCKBLOCK;
292
+        }
293
+        /* search for a block with unused clients (or the first unalloc'd block) */
294
+        for(i=0;i<web->sizeclientblocks;i++) {
295
+                cb=web->clientblocks+i;
296
+                if(cb->clients==NULL || cb->usedclients<cb->sizeclients)
297
+                        break;
298
+        }
299
+        if(i>=web->sizeclientblocks)
300
+                return(NULL); /* internal error */
301
+        /* alloc block if not alloc'd */
302
+        if(cb->clients==NULL) {
303
+                if((cb->clients=malloc(sizeof(wk_client)*CLIENTBLOCK))==NULL)
304
+                        return(NULL); /* insufficient memory */
305
+                memset(cb->clients,0,sizeof(wk_client)*CLIENTBLOCK);
306
+                cb->sizeclients=CLIENTBLOCK;
307
+        }
308
+        /* get first unused client */
309
+        for(j=0;j<cb->sizeclients;j+=8) {
310
+                if(cb->acquired[j>>3]!=0xff)
311
+                        break;
312
+        }
313
+        if(j>=cb->sizeclients)
314
+                return(NULL); /* internal error */
315
+        for(k=0x01;k<0x100;k<<=1,j++) {
316
+                if((cb->acquired[j>>3]&k)==0)
317
+                        break;
318
+        }
319
+        if(k>=0x100)
320
+                return(NULL); /* internal error */
321
+        cb->acquired[j>>3]|=k;
322
+        cb->usedclients++;
323
+        /* initialize client and return it */
324
+        client=cb->clients+j;
325
+        memset(client,0,sizeof(wk_client));
326
+        client->web=(wk *)web;
327
+        client->connid=i*CLIENTBLOCK+j;
328
+        client->fd=-1;
329
+        return(client);
248 330
 }
249 331
 
250 332
 static int
251 333
 wk_clientrelease(_wk *web, int connid)
252 334
 {
335
+        wk_client *client;
336
+        int numblock,j,bit;
337
+        numblock=connid/CLIENTBLOCK;
338
+        j=connid%CLIENTBLOCK;
339
+        bit=0x1<<(j&3);
340
+        if((client=wk_clientget(web,connid))==NULL)
341
+                return(-1);
342
+        web->clientblocks[numblock].usedclients--;
343
+        web->clientblocks[numblock].acquired[j>>3]&=(~bit);
344
+        memset(client,0,sizeof(wk_client));
345
+        return(0);
253 346
 }
254 347
 
255
-wk_client *
348
+static wk_client *
256 349
 wk_clientget(_wk *web, int connid)
257 350
 {
258
-        int numblock;
351
+        int numblock,j,bit;
259 352
         numblock=connid/CLIENTBLOCK;
353
+        j=connid%CLIENTBLOCK;
354
+        bit=0x1<<(j&3);
260 355
         if(web==NULL ||
261 356
           web->clientblocks==NULL ||
262 357
           web->sizeclientblocks<=numblock ||
263
-          web->clientblocks[numblock].clients==NULL)
358
+          web->clientblocks[numblock].clients==NULL ||
359
+          (web->clientblocks[numblock].acquired[j>>3]&bit)!=bit)
264 360
                 return(NULL);
265
-        return(web->clientblocks[numblock].clients+(connid%CLIENTBLOCK));
361
+        return(web->clientblocks[numblock].clients+j);
266 362
 }
267 363
 
Browse code

webkernel: init, free, start of service and structures of clients

Dario Rodriguez authored on 13/06/2014 11:16:28
Showing 1 changed files
... ...
@@ -12,19 +12,58 @@
12 12
 #include <stdlib.h>
13 13
 #include <unistd.h>
14 14
 #include <string.h>
15
+#include "socklib.h"
15 16
 #include "webkernel.h"
16 17
 
18
+#define FDBLOCK 256
19
+#define CLIENTBLOCK 1024
20
+#define CLIENTBLOCKBLOCK 256
21
+
22
+
23
+typedef struct wk_client {
24
+        wk *web;
25
+        int connid; /* it is numblock*CLIENTBLOCK+offset_in_block */
26
+        int fd;
27
+} wk_client;
28
+
29
+typedef struct wk_clientblock {
30
+        int sizeclients;
31
+        int usedclients;
32
+        wk_client *clients;
33
+} wk_clientblock;
34
+
17 35
 typedef struct _wk {
18
-        int dummy;
36
+        int serverfd;
37
+        fd_set fdset;
38
+        sselect *ssel;
39
+        int sizeclientblocks;
40
+        int usedclientblocks;
41
+        wk_clientblock *clientblocks;
19 42
 } _wk;
20 43
 
44
+static int wk_accept(_wk *web);
45
+static wk_client *wk_clientacquire(_wk *web);
46
+static int wk_clientrelease(_wk *web, int connid);
47
+wk_client *wk_clientget(_wk *web, int connid);
48
+
21 49
 wk *
22 50
 wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int connid, wk_event event, void *userptr*/), void (*callback_http)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void (*callback_continuation)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void *userptr)
23 51
 {
24 52
         _wk *web;
53
+        if(ssel==NULL || callback_http==NULL)
54
+                return(NULL);
25 55
         if((web=malloc(sizeof(_wk)))==NULL)
26 56
                 return(NULL);
27 57
         memset(web,0,sizeof(_wk));
58
+        web->serverfd=-1;
59
+        web->ssel=ssel;
60
+        FD_ZERO(&(web->fdset));
61
+        if((web->serverfd=ipv4_server(port))==-1) {
62
+                wk_free((wk *)web),web=NULL;
63
+                return(NULL);
64
+        }
65
+        FD_SET(web->serverfd,&(web->fdset));
66
+        sselect_addread(ssel,web->serverfd,NULL);
28 67
         return((wk *)web);
29 68
 }
30 69
 
... ...
@@ -34,6 +73,11 @@ wk_free(wk *paramweb)
34 73
         _wk *web=(_wk *)paramweb;
35 74
         if(web==NULL)
36 75
                 return;
76
+        if(web->serverfd!=-1) {
77
+                sselect_delread(web->ssel,web->serverfd);
78
+                FD_CLR(web->serverfd,&(web->fdset));
79
+                close(web->serverfd),web->serverfd=-1;
80
+        }
37 81
         free(web),web=NULL;
38 82
 }
39 83
 
... ...
@@ -46,7 +90,23 @@ wk_geturi(wk *paramweb, int connid)
46 90
 int
47 91
 wk_service(wk *paramweb)
48 92
 {
49
-
93
+        int fds[FDBLOCK];
94
+        int fd;
95
+        int n;
96
+        int i;
97
+        _wk *web=(_wk *)paramweb;
98
+        if(web==NULL)
99
+                return(-1);
100
+        while((n=sselect_getreadfiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) {
101
+                for(i=0;i<n;i++) {
102
+                        fd=fds[i];
103
+                        if(fd==web->serverfd) {
104
+                                /* accept new connection */
105
+                                wk_accept(web);
106
+                                continue;
107
+                        }
108
+                }
109
+        }
50 110
 }
51 111
 
52 112
 int
... ...
@@ -98,12 +158,14 @@ wk_uri_getheaderbynum(wk_uri *wkuri, int num)
98 158
 }
99 159
 
100 160
 const char *
101
-mime_getdefault(char *filename)
161
+mime_getdefault(const char *filename, const char *defaultmime)
102 162
 {
163
+        const char *dotptr,*dotdotptr;
164
+        int i;
103 165
         struct {
104
-                char *ext;
105
-                char *mime;
106
-        } dotdot[]={{".tar.gz","application/x-tgz"}},
166
+                const char *ext;
167
+                const char *mime;
168
+        } dotdot[]={{"tar.gz","application/x-tgz"}},
107 169
           dot[]={
108 170
                 {"html","text/html"},
109 171
                 {"htm","text/html"},
... ...
@@ -130,7 +192,23 @@ mime_getdefault(char *filename)
130 192
                 {"mp4","video/mp4"},
131 193
                 {"webm","video/webm"},
132 194
                 {"avi","video/x-msvideo"}};
133
-#warning TODO
195
+        if(filename==NULL || (dotptr=strrchr(filename,'.'))==NULL)
196
+                return(defaultmime);
197
+        if(dotptr>filename) {
198
+                for(dotdotptr=(dotptr-1);dotdotptr>filename && *dotdotptr!='.';dotdotptr--)
199
+                        ;
200
+                if(*dotdotptr=='.') {
201
+                        for(i=0;i<(sizeof(dotdot)/sizeof(dotdot[0]));i++) {
202
+                                if(strcmp(dotdotptr+1,dotdot[i].ext)==0)
203
+                                        return(dotdot[i].mime);
204
+                        }
205
+                }
206
+        }
207
+        for(i=0;i<(sizeof(dot)/sizeof(dot[0]));i++) {
208
+                if(strcmp(dotptr+1,dot[i].ext)==0)
209
+                        return(dot[i].mime);
210
+        }
211
+        return(defaultmime);
134 212
 }
135 213
 
136 214
 siobuf *
... ...
@@ -145,3 +223,45 @@ wk_iobuffree(wk *paramweb, int iobufnum)
145 223
 
146 224
 }
147 225
 
226
+/* local functions */
227
+static int
228
+wk_accept(_wk *web)
229
+{
230
+        int newfd;
231
+        wk_client *client;
232
+        if((newfd=sock_accept(web->serverfd))==-1)
233
+                return(-1);
234
+        if((client=wk_clientacquire(web))==NULL) {
235
+                close(newfd),newfd=-1;
236
+                return(-1);
237
+        }
238
+        client->fd=newfd;
239
+        FD_SET(client->fd,&(web->fdset));
240
+        sselect_addread(web->ssel,client->fd,(void *)client);
241
+        return(0);
242
+}
243
+
244
+static wk_client *
245
+wk_clientacquire(_wk *web)
246
+{
247
+#warning TODO
248
+}
249
+
250
+static int
251
+wk_clientrelease(_wk *web, int connid)
252
+{
253
+}
254
+
255
+wk_client *
256
+wk_clientget(_wk *web, int connid)
257
+{
258
+        int numblock;
259
+        numblock=connid/CLIENTBLOCK;
260
+        if(web==NULL ||
261
+          web->clientblocks==NULL ||
262
+          web->sizeclientblocks<=numblock ||
263
+          web->clientblocks[numblock].clients==NULL)
264
+                return(NULL);
265
+        return(web->clientblocks[numblock].clients+(connid%CLIENTBLOCK));
266
+}
267
+
Browse code

webkernel: rework API

Dario Rodriguez authored on 11/06/2014 11:10:24
Showing 1 changed files
... ...
@@ -1,36 +1,147 @@
1 1
 /*
2
- * webkernel.v
2
+ * webkernel.c
3 3
  *
4 4
  * A small embeddable web server.
5 5
  *
6
- *      21/01/2014 Creation.
7
- *
8 6
  * Author: Dario Rodriguez dario@softhome.net
9 7
  * This library is licensed on the terms of the GNU LGPL v2+
10 8
  */
11 9
 
12 10
 
13
-typedef struct {
11
+#include <stdio.h>
12
+#include <stdlib.h>
13
+#include <unistd.h>
14
+#include <string.h>
15
+#include "webkernel.h"
16
+
17
+typedef struct _wk {
14 18
         int dummy;
15
-} swk;
19
+} _wk;
16 20
 
17 21
 wk *
18
-wk_init(int port)
22
+wk_init(int port, sselect *ssel, void (*callback_event)(/*wk *paramweb,int connid, wk_event event, void *userptr*/), void (*callback_http)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void (*callback_continuation)(/*wk *paramweb,int connid, wk_uri *uri, void *userptr*/), void *userptr)
19 23
 {
24
+        _wk *web;
25
+        if((web=malloc(sizeof(_wk)))==NULL)
26
+                return(NULL);
27
+        memset(web,0,sizeof(_wk));
28
+        return((wk *)web);
20 29
 }
21 30
 
22 31
 void
23
-wk_free(wk *web)
32
+wk_free(wk *paramweb)
33
+{
34
+        _wk *web=(_wk *)paramweb;
35
+        if(web==NULL)
36
+                return;
37
+        free(web),web=NULL;
38
+}
39
+
40
+wk_uri *
41
+wk_geturi(wk *paramweb, int connid)
42
+{
43
+
44
+}
45
+
46
+int
47
+wk_service(wk *paramweb)
48
+{
49
+
50
+}
51
+
52
+int
53
+wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime)
54
+{
55
+
56
+}
57
+
58
+int
59
+wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime)
60
+{
61
+
62
+}
63
+
64
+int
65
+wk_serve_error(wk *paramweb, int connid, wk_error wkerror)
66
+{
67
+
68
+}
69
+
70
+int
71
+wk_writestr(wk *paramweb, int connid, char *str)
72
+{
73
+
74
+}
75
+
76
+int
77
+wk_write(wk *paramweb, int connid, void *data, int datalen)
78
+{
79
+
80
+}
81
+
82
+int
83
+wk_close(wk *paramweb, int connid)
84
+{
85
+
86
+}
87
+
88
+char *
89
+wk_uri_getheader(wk_uri *wkuri, char *header, char *defaultvalue)
90
+{
91
+
92
+}
93
+
94
+char *
95
+wk_uri_getheaderbynum(wk_uri *wkuri, int num)
24 96
 {
25 97
 
26 98
 }
27 99
 
28
-int wk_select(wk *web, int timemoutms,...);
29
-int wk_httpaccept(wk *web, int *httpnum);
30
-int wk_httpisrequest(char *line);
31
-int wk_httpfromdisk(wk *web, int httpnum,char *firstline);
32
-int wk_httpreset(wk *web, int httpnum);
33
-int wk_httpclose(wk *web, int httpnum);
34
-int wk_iobufget(wk *web);
35
-int wk_iobuffree(wk *web, int iobufnum);
100
+const char *
101
+mime_getdefault(char *filename)
102
+{
103
+        struct {
104
+                char *ext;
105
+                char *mime;
106
+        } dotdot[]={{".tar.gz","application/x-tgz"}},
107
+          dot[]={
108
+                {"html","text/html"},
109
+                {"htm","text/html"},
110
+                {"shtml","text/html"},
111
+                {"css","text/css"},
112
+                {"gif","image/gif"},
113
+                {"jpeg","image/jpeg"},
114
+                {"jpg","image/jpeg"},
115
+                {"png","image/png"},
116
+                {"tiff","image/tiff"},
117
+                {"tif","image/tiff"},
118
+                {"bmp","image/x-ms-bmp"},
119
+                {"svg","image/svg+xml"},
120
+                {"svgz","image/svg+xml"},
121
+                {"js","application/x-javascript"},
122
+                {"atom","application/atom+xml"},
123
+                {"txt","text/plain"},
124
+                {"json","application/json"},
125
+                {"pdf","application/pdf"},
126
+                {"zip","application/zip"},
127
+                {"mp3","audio/mpeg"},
128
+                {"wav","audio/x-wav"},
129
+                {"ogg","audio/ogg"},
130
+                {"mp4","video/mp4"},
131
+                {"webm","video/webm"},
132
+                {"avi","video/x-msvideo"}};
133
+#warning TODO
134
+}
135
+
136
+siobuf *
137
+wk_iobufget(wk *paramweb)
138
+{
139
+
140
+}
141
+
142
+void
143
+wk_iobuffree(wk *paramweb, int iobufnum)
144
+{
145
+
146
+}
36 147
 
Browse code

Added current unfinished sources

Dario Rodriguez authored on 12/03/2014 11:38:34
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,36 @@
1
+/*
2
+ * webkernel.v
3
+ *
4
+ * A small embeddable web server.
5
+ *
6
+ *      21/01/2014 Creation.
7
+ *
8
+ * Author: Dario Rodriguez dario@softhome.net
9
+ * This library is licensed on the terms of the GNU LGPL v2+
10
+ */
11
+
12
+
13
+typedef struct {
14
+        int dummy;
15
+} swk;
16
+
17
+wk *
18
+wk_init(int port)
19
+{
20
+}
21
+
22
+void
23
+wk_free(wk *web)
24
+{
25
+
26
+}
27
+
28
+int wk_select(wk *web, int timemoutms,...);
29
+int wk_httpaccept(wk *web, int *httpnum);
30
+int wk_httpisrequest(char *line);
31
+int wk_httpfromdisk(wk *web, int httpnum,char *firstline);
32
+int wk_httpreset(wk *web, int httpnum);
33
+int wk_httpclose(wk *web, int httpnum);
34
+int wk_iobufget(wk *web);
35
+int wk_iobuffree(wk *web, int iobufnum);
36
+