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
         }