/* * webkernel.c * * A small embeddable web server. * * Author: Dario Rodriguez dario@softhome.net * This library is licensed on the terms of the GNU LGPL v2+ */ #include #include #include #include #include "socklib.h" #include "webkernel.h" #define FDBLOCK 256 #define CLIENTBLOCK 1024 #define CLIENTBLOCKBLOCK 256 typedef struct wk_client { wk *web; int connid; /* it is numblock*CLIENTBLOCK+offset_in_block */ int fd; } wk_client; typedef struct wk_clientblock { int sizeclients; int usedclients; wk_client *clients; } wk_clientblock; typedef struct _wk { int serverfd; fd_set fdset; sselect *ssel; int sizeclientblocks; int usedclientblocks; wk_clientblock *clientblocks; } _wk; static int wk_accept(_wk *web); static wk_client *wk_clientacquire(_wk *web); static int wk_clientrelease(_wk *web, int connid); wk_client *wk_clientget(_wk *web, int connid); wk * 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) { _wk *web; if(ssel==NULL || callback_http==NULL) return(NULL); if((web=malloc(sizeof(_wk)))==NULL) return(NULL); memset(web,0,sizeof(_wk)); web->serverfd=-1; web->ssel=ssel; FD_ZERO(&(web->fdset)); if((web->serverfd=ipv4_server(port))==-1) { wk_free((wk *)web),web=NULL; return(NULL); } FD_SET(web->serverfd,&(web->fdset)); sselect_addread(ssel,web->serverfd,NULL); return((wk *)web); } void wk_free(wk *paramweb) { _wk *web=(_wk *)paramweb; if(web==NULL) return; if(web->serverfd!=-1) { sselect_delread(web->ssel,web->serverfd); FD_CLR(web->serverfd,&(web->fdset)); close(web->serverfd),web->serverfd=-1; } free(web),web=NULL; } wk_uri * wk_geturi(wk *paramweb, int connid) { } int wk_service(wk *paramweb) { int fds[FDBLOCK]; int fd; int n; int i; _wk *web=(_wk *)paramweb; if(web==NULL) return(-1); while((n=sselect_getreadfiltered(web,&(web->fdset),fds,sizeof(fds)/sizeof(fds[0])))>0) { for(i=0;iserverfd) { /* accept new connection */ wk_accept(web); continue; } } } } int wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime) { } int wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime) { } int wk_serve_error(wk *paramweb, int connid, wk_error wkerror) { } int wk_writestr(wk *paramweb, int connid, char *str) { } int wk_write(wk *paramweb, int connid, void *data, int datalen) { } int wk_close(wk *paramweb, int connid) { } char * wk_uri_getheader(wk_uri *wkuri, char *header, char *defaultvalue) { } char * wk_uri_getheaderbynum(wk_uri *wkuri, int num) { } const char * mime_getdefault(const char *filename, const char *defaultmime) { const char *dotptr,*dotdotptr; int i; struct { const char *ext; const char *mime; } dotdot[]={{"tar.gz","application/x-tgz"}}, dot[]={ {"html","text/html"}, {"htm","text/html"}, {"shtml","text/html"}, {"css","text/css"}, {"gif","image/gif"}, {"jpeg","image/jpeg"}, {"jpg","image/jpeg"}, {"png","image/png"}, {"tiff","image/tiff"}, {"tif","image/tiff"}, {"bmp","image/x-ms-bmp"}, {"svg","image/svg+xml"}, {"svgz","image/svg+xml"}, {"js","application/x-javascript"}, {"atom","application/atom+xml"}, {"txt","text/plain"}, {"json","application/json"}, {"pdf","application/pdf"}, {"zip","application/zip"}, {"mp3","audio/mpeg"}, {"wav","audio/x-wav"}, {"ogg","audio/ogg"}, {"mp4","video/mp4"}, {"webm","video/webm"}, {"avi","video/x-msvideo"}}; if(filename==NULL || (dotptr=strrchr(filename,'.'))==NULL) return(defaultmime); if(dotptr>filename) { for(dotdotptr=(dotptr-1);dotdotptr>filename && *dotdotptr!='.';dotdotptr--) ; if(*dotdotptr=='.') { for(i=0;i<(sizeof(dotdot)/sizeof(dotdot[0]));i++) { if(strcmp(dotdotptr+1,dotdot[i].ext)==0) return(dotdot[i].mime); } } } for(i=0;i<(sizeof(dot)/sizeof(dot[0]));i++) { if(strcmp(dotptr+1,dot[i].ext)==0) return(dot[i].mime); } return(defaultmime); } siobuf * wk_iobufget(wk *paramweb) { } void wk_iobuffree(wk *paramweb, int iobufnum) { } /* local functions */ static int wk_accept(_wk *web) { int newfd; wk_client *client; if((newfd=sock_accept(web->serverfd))==-1) return(-1); if((client=wk_clientacquire(web))==NULL) { close(newfd),newfd=-1; return(-1); } client->fd=newfd; FD_SET(client->fd,&(web->fdset)); sselect_addread(web->ssel,client->fd,(void *)client); return(0); } static wk_client * wk_clientacquire(_wk *web) { #warning TODO } static int wk_clientrelease(_wk *web, int connid) { } wk_client * wk_clientget(_wk *web, int connid) { int numblock; numblock=connid/CLIENTBLOCK; if(web==NULL || web->clientblocks==NULL || web->sizeclientblocks<=numblock || web->clientblocks[numblock].clients==NULL) return(NULL); return(web->clientblocks[numblock].clients+(connid%CLIENTBLOCK)); }