... | ... |
@@ -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 |
} |