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