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