void core_engine_run(void) { for (; ;) { if (g_termin_service) { break; } web_log(WEB_LOG_DEBUG, "core event dispatch\n"); event_dispatch(); web_log(WEB_LOG_DEBUG, "core events processing\n"); ev_process_all_events(); } }
/* * Add an handler to request data */ int web_server_addhandler(struct web_server *server,const char *mstr,void (*func)(void*),int flag, void* userdata) { _logfile=server->weblog; // xor? flag ^= (server->flags & WS_LOCAL); // global flag to handler flag flag ^= (server->flags & WS_DYNVAR); // global flag to handler flag flag ^= (server->flags & WS_USELEN); // global flag to handler flag web_log("[%s] Adding handler %s <--%s%s%s\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),mstr, ((flag & WS_LOCAL) == WS_LOCAL && !((server->flags & WS_LOCAL) == WS_LOCAL))?"[LOCAL] ":"", ((flag & WS_DYNVAR) == WS_DYNVAR)?"[DYNVAR]":"", ((flag & WS_USELEN) == WS_USELEN)?"[USELEN]":""); return __ILWS_add_handler((struct gethandler *)server->gethandler,mstr,func,NULL,flag,GH_FUNCTION,userdata); }
/* * Add an alias dir (new on 0.5.2) */ int web_server_aliasdir(struct web_server *server, const char *str, char *path,int flag) { char *mstr; int ret; mstr=__ILWS_malloc(strlen(str)+7); if(!strlen(str)) { snprintf(mstr,strlen(str)+7,"* /*"); } else { snprintf(mstr,strlen(str)+7,"* /%s/*",str); }; _logfile=server->weblog; flag ^= (server->flags & WS_LOCAL); // global flag to handler flag flag ^= (server->flags & WS_DYNVAR); // global flag to handler flag flag ^= (server->flags & WS_USELEN); // global flag to handler flag web_log("[%s] Adding directory %s <--%s%s%s\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),mstr, ((flag & WS_LOCAL) == WS_LOCAL && !((server->flags & WS_LOCAL) == WS_LOCAL))?"[LOCAL] ":"", ((flag & WS_DYNVAR) == WS_DYNVAR)?"[DYNVAR]":"", ((flag & WS_USELEN) == WS_USELEN)?"[USELEN]":""); ret=__ILWS_add_handler((struct gethandler *)server->gethandler,mstr,NULL,path,flag,GH_DIRECTORY,NULL); __ILWS_free(mstr); return ret; };
/* * Read what client have to say */ void __ILWS_read_client(struct web_client *node) { int tmp,tmp1; char *tmp2,*tmp3=NULL; char readtemp[READMAX+1]; unsigned long datasize=0; #ifdef HAVE_OPENSSL if(node->ssl!=NULL) { tmp=SSL_read(node->ssl,readtemp,READMAX); } else { tmp=__ILWS_read(node->socket,readtemp,READMAX); }; #else tmp=__ILWS_read(node->socket,readtemp,READMAX); #endif //fprintf(stderr,"readed %d bytes\n",tmp); if(tmp<1) { #ifdef WIN32 if(WSAGetLastError()!=WSAEWOULDBLOCK) { #else if(errno!=EAGAIN) { #endif node->stat=5;return; }; //fprintf(stderr,"try: %d (%s)\n",node->newdata_try,node->rbuf); // check if it is over node->newdata_try++; //fprintf(stderr,"node->newdata_try:%d\n",node->newdata_try); if(node->rbufsize >0) { //&& node->newdata_try>5) { if(node->headersize==0) { // always reachs "\r\n\r\n" if((tmp3=strstr(node->rbuf,"\r\n\r\n"))) { node->headersize=(tmp3-node->rbuf); }; } else { datasize=node->rbufsize-node->headersize; if(node->contentlength==0) { // well if it 0 read all at once __ILWS_init_clientinfo(); // always call this? node->contentlength=atol(ClientInfo->Header("Content-Length")); // range for resuming if((tmp3=strstr(ClientInfo->Header("Range"),"bytes="))) { // if it is in bytes (i hope, always) tmp3+=6; // go to end of "bytes=" node->range=atol(tmp3); //printf("Range is %d - %s - %s\n",node->range,ClientInfo->Header("Range"),tmp3); }; // end range __ILWS_free_clientinfo(); }; if(node->contentlength==datasize-4) { //fprintf(stderr,"client (%d) all readed (%d) (try's)-%d\n",node->socket,node->curcl-node->oldcl,node->newdata_try); node->newdata_try=WEBTIMEOUT; // assume done reading //fprintf(stderr,"Ended naturaly\n"); } }; if((node->newdata_try>=WEBTIMEOUT)) { // All readed node->rbuf[node->rbufsize]='\0'; node->stat=2; // Next state //fprintf(stderr,"%s\n",node->rbuf); //fprintf(stderr,"%d\n",node->rbufsize); } }; }else { tmp1=node->rbufsize; node->rbufsize+=tmp; tmp2=__ILWS_realloc(node->rbuf,node->rbufsize+1); if(tmp2==NULL) { LWSERR(LE_MEMORY); node->stat=5; return; }else { node->rbuf=tmp2; }; memcpy(node->rbuf+tmp1,readtemp,tmp); node->newdata_try=0; }; } /*********************************************************************************************************/ /* * Process headers w/ get handlers */ void __ILWS_process_client(struct web_client *node,struct gethandler *list) { struct gethandler *gettemp=list; time_t secs=time(NULL); // for determining content length #define RTMPMAX 400 struct outstream *tmpstream; // new on 0.5.1 char rtmp[RTMPMAX+1]; int rtmps=0; char *thead=NULL; char *tmpl; /// int tmp=0; int oumask=0; // old usermask char *tmp1=__ILWS_web_client_getreq(); char matchbuf[MATCHMAX]; FILE *nfile; // new file char *fname; // new file name while(gettemp->next!=NULL && tmp==0) { gettemp=gettemp->next; snprintf(matchbuf,MATCHMAX,"%s",gettemp->str); if(!tmp1) { __ILWS_web_client_writef(node,"HTTP/1.1 400 Invalid request\r\n"); __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Invalid request</title><body bgcolor=FFFFFF><font size=6>400 Invalid request</font><BR><BR><small>Yout request doesn't match the requesits to be processed</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 400 (invalid request)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); node->stat=5; return; }; if(strlen(tmp1)>MAXURLSIZE) { __ILWS_web_client_writef(node,"HTTP/1.1 414 URL to large\r\n"); __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>URL to large</title><body bgcolor=FFFFFF><font size=6>414 Requested url to large</font><BR><BR><small>Wonder this... why is that so large?</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 414 (url to large)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); node->stat=5; __ILWS_free(tmp1); return; }; if(!fnmatch(matchbuf,tmp1,5)) { if((gettemp->flag & WS_LOCAL) == WS_LOCAL) { if(node->sa.sin_addr.s_addr!=0x0100007F) { __ILWS_web_client_writef(node,"HTTP/1.1 403 Forbidden\r\n"); __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Forbidden</title><body bgcolor=FFFFFF><font size=6>403 Forbidden</font><BR><BR><small>only local host accepted</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 403 (Forbidden)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); node->stat=5; __ILWS_free(tmp1); return; }; }; tmp=1; // Was found node->outstream->flags=(gettemp->flag & WS_DYNVAR); // pass to outstreams }; }; __ILWS_free(tmp1); if(!tmp) { // Nothing found __ILWS_web_client_writef(node,"HTTP/1.1 404 Not Found\r\n"); __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>not found</title><body bgcolor=FFFFFF><font size=6>404 NOT FOUND</font><BR><BR><small>The requested content wasn't found</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 404 (Not Found)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); node->stat=5; }else { // if cgi do something else, present headers oumask=umask(077); if(!(fname=__ILWS_tmpfname())) { libws_error(LE_FILESYS,": Error giving a temp filename\n"); node->stat=5; return; }; if((nfile=freopen(fname,"wb+",stdout))!=NULL) { flock(fileno(stdout),LOCK_EX); tmp=dup(fileno(stdout)); nfile=fdopen(tmp,"wb+"); if(!__ILWS_add_outstream(node->outstream,fname,nfile,1)) { node->stat=5; // (delete client) return; // ERROR reported by add_outstream }; // THE PROCESS // Setup Clientinfo before running function if(gettemp->type==GH_FUNCTION) { __ILWS_init_clientinfo(); gettemp->hdl.func(gettemp->userdata); // changed (0.5.3) Access by named union (Hilobok Andrew ([email protected]) said that wasn't compile on freeBSD) __ILWS_free_clientinfo(); }; // new on 0.5.2 if(gettemp->type==GH_DIRECTORY) { // as builtin function for directory listing __ILWS_init_clientinfo(); if(strcmp(gettemp->str,"* /*"))ClientInfo->request+=1; // skip '/' if not equal to "* /*" (used by default) __ILWS_lws_list(gettemp->hdl.path); // changed (0.5.3) Access by named union (Hilobok Andrew ([email protected]) said that wasn't compile on freeBSD) __ILWS_free_clientinfo(); }; fflush(stdout); fclose(stdout); // it is a tempfile freopened __ILWS_free(fname); // doesn't need anymore #ifdef WIN32 freopen("con","w",stdout); #else freopen("/dev/tty","w",stdout); #endif if((gettemp->flag & WS_USELEN) == WS_USELEN) { // determine writelength (for content-length: header) (new on 0.5.1) tmpstream=node->outstream; tmp=0; while(tmpstream->next!=NULL) { // end of header probably in the firsts outstream nodes check for that if(tmpstream->next->fname!=NULL) { if(tmpstream->next->fstream==NULL) { nfile=fopen(tmpstream->next->fname,"rb"); tmpstream->next->fstream=nfile; // here (corrected on 0.5.3); } else { fflush(tmpstream->next->fstream); // <- flush tha thing nfile=tmpstream->next->fstream; fseek(nfile,0,SEEK_SET); }; if(nfile!=NULL) { rtmps=0; while((!node->wheadersize) && (!feof(nfile))) { // wheadersize is 0, suposed to be fast, at least if is not malformed if(rtmps>0) {tmp-=4;fseek(nfile,rtmps-4,SEEK_SET);} if((rtmps=fread(rtmp,1,RTMPMAX,nfile))>0) { rtmp[rtmps]=0; if((tmp1=strstr(rtmp,"\r\n\r\n"))) { node->wheadersize=(tmp+((tmp1+4)-rtmp)); rtmps=((tmp1+4)-rtmp); }; if(node->range>0) { tmp1=realloc(thead,tmp+rtmps+1); thead=tmp1; memcpy(thead+tmp,rtmp,rtmps); thead[tmp+rtmps]=0; }; tmp+=rtmps; }; }; fseek(nfile,SEEK_END,SEEK_END); node->writelength+=(ftell(nfile)-2); //fclose(nfile); // <- don't worry they close the file later }; }; tmpstream=tmpstream->next; }; // end writelength } else { node->range=0; // no content-range }; if(node->range>node->writelength-node->wheadersize && node->range>0) { __ILWS_web_client_writef(node,"HTTP/1.1 416 Requested Range Not Satisfiable\r\n"); __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Content-range: bytes */%d\r\n",node->writelength-node->wheadersize); __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Requested Range Not Satisfiable</title><body bgcolor=FFFFFF><font size=6>416 Requested Range Not Satisfiable</font><BR><BR><small>You're trying to resume an content that is smaller than the requested range</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 416 (Requested Range Not Satisfiable)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); node->stat=5; __ILWS_free(thead); umask(oumask); return; }; if(node->range>0 && ((node->outstream->flags & WS_DYNVAR)==WS_DYNVAR)) { // if request range interval and dynvar on than produces not implemented __ILWS_web_client_writef(node,"HTTP/1.1 501 Not Implemented\r\n"); __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Content-type: text/html\r\n\r\n<HTML><title>Not implemented</title><body bgcolor=FFFFFF><font size=6>501 Not implemented</font><BR><BR><small>Your trying to resume an content that is not possible to resume(WS_DYNVAR fault)</small><BR><HR><small><i>%s</i></small></body></html>\n\r",_libwebserver_version); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 501 (Not Implemented)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); node->stat=5; __ILWS_free(thead); umask(oumask); return; }; }else { LWSERR(LE_FILESYS); }; node->stat=4; if(node->HTTPdirective==NULL) { if(node->range>0) { __ILWS_web_client_writef(node,"HTTP/1.1 206 Partial Content\r\n"); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 206 (Partial Content)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); } else { __ILWS_web_client_writef(node,"HTTP/1.1 200 OK\r\n"); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" 200 (OK)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); }; } else { __ILWS_web_client_writef(node,"%s\r\n",node->HTTPdirective); tmpl=__ILWS_web_client_getreqline(); web_log("%s - - [%s] \"%s\" XXX (User defined)\n",inet_ntoa(node->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),tmpl); __ILWS_free(tmpl); }; __ILWS_web_client_writef(node,"Server: %s\r\n",_libwebserver_version); __ILWS_web_client_writef(node,"Date: %s\r\n",__ILWS_date(mktime(gmtime(&secs)),"%a, %d %b %Y %H:%M:%S GMT")); // Date header __ILWS_web_client_writef(node,"Accept-Ranges: bytes\r\n"); if((((node->writelength-node->wheadersize)-node->range)>0) && !((node->outstream->flags & WS_DYNVAR)==WS_DYNVAR))__ILWS_web_client_writef(node,"Content-length: %d\r\n",(node->writelength-node->wheadersize)-node->range); if(node->cookies!=NULL)__ILWS_web_client_writef(node,"%s",node->cookies); // new (0.5.1) if(node->range>0) { __ILWS_web_client_writef(node,"Content-range: bytes %d-%d/%d\r\n",node->range,(node->writelength-node->wheadersize)-1,node->writelength-node->wheadersize); __ILWS_web_client_writef(node,"%s",thead); // the rest of header __ILWS_free(thead); }; umask(oumask); }; } /*********************************************************************************************************/ /* * Process stream output */ void __ILWS_output_client(struct web_client *node) { struct outstream *tstream=node->outstream; char *tmp1,*tmp2,*tmp3; char writetemp[WRITEMAX+1]; int beginsize=0; int endsize=0; int varsize=0; int namesize=0; if(tstream->next!=NULL) { if(tstream->next->fname!=NULL) { if(tstream->next->fstream==NULL) { if((tstream->next->fstream=fopen(tstream->next->fname,"rb"))==NULL) { LWSERR(LE_FILESYS); __ILWS_delete_next_outstream(tstream); //node->outstream->next=tstream->next; return; } }; // read part (must always read) if(tstream->next->rsize==0) { // start from 0 fseek(tstream->next->fstream,0,SEEK_SET); }; memset(writetemp,0,WRITEMAX); tstream->next->rsize=fread(writetemp,1,WRITEMAX,tstream->next->fstream); writetemp[tstream->next->rsize]=0; // if read make var changes on writetemp; // new on 0.5.1 -- UNDERDEV // FIX - if((node->outstream->flags & WS_DYNVAR) == WS_DYNVAR) { tmp1=writetemp; while(((tmp1=strstr(tmp1,"$")+1)!=(char*)1) && beginsize==0) { // check var found for(namesize=0;namesize<50;namesize++) { if(tmp1[namesize]==';') {namesize++;break;} if((tmp1[namesize]<'a' || tmp1[namesize]>'z') && (tmp1[namesize]<'A' || tmp1[namesize]>'Z') && (tmp1[namesize]<'1' || tmp1[namesize]>'0') && tmp1[namesize]!='_') {namesize=0;break;}; }; if(namesize>0) { if(namesize==1) { // this is $; for sure if(!(tmp3=__ILWS_malloc(2))) { LWSERR(LE_MEMORY); node->stat=5; return; }; memcpy(tmp3,"$",namesize); tmp3[namesize]=0; } else { if(!(tmp3=__ILWS_malloc(namesize))) { LWSERR(LE_MEMORY); node->stat=5; return; }; memcpy(tmp3,tmp1,namesize-1); tmp3[namesize-1]=0; }; tmp1-=1; beginsize=tmp1-writetemp; tmp1+=namesize; // get var from whateverwhere (client node probably) endsize=strlen(tmp1); //varsize=2; if((tmp2=__ILWS_malloc(beginsize+1))) { memcpy(tmp2,writetemp,beginsize); tmp2[beginsize]=0; if(namesize==1) { varsize=strlen(tmp3); snprintf(writetemp,WRITEMAX,"%s%s",tmp2,tmp3); } else { varsize=strlen(__ILWS_get_var(node->varlist,tmp3)); snprintf(writetemp,WRITEMAX,"%s%s",tmp2,__ILWS_get_var(node->varlist,tmp3)); }; writetemp[strlen(tmp2)+varsize]=0; __ILWS_free(tmp2); __ILWS_free(tmp3); tstream->next->rsize=(beginsize+varsize); tstream->next->varsize+=(varsize-namesize)-1; } else { LWSERR(LE_MEMORY); __ILWS_free(tmp3); node->stat=5; return; }; }; }; }; // dynvar /* there is nothing more to read here */ if(tstream->next->rsize<1){ // i guess rsize < 1 is eof (make sure that server writed last time) //only change if everything written if(feof(tstream->next->fstream) && (ftell(tstream->next->fstream)==tstream->next->wrotesize)) { //fclose(tstream->next->fstream); __ILWS_delete_next_outstream(tstream); //node->outstream->next=tstream->next; } return; } node->readsize+=tstream->next->rsize; if(!node->skipped && node->range>0) { tstream->next->wsize=tstream->next->rsize; tstream->next->wrotesize+=tstream->next->wsize; if((node->readsize-node->wheadersize)<node->range) { // skip range bytes return; // do nothing }else { node->skipped=1; tstream->next->wrotesize-=(node->readsize-node->wheadersize)-node->range; // the right offset fseek(tstream->next->fstream,tstream->next->wrotesize,SEEK_SET); tstream->next->wsize=tstream->next->rsize; return; }; }; // write part #ifdef HAVE_OPENSSL if(node->ssl!=NULL) { tstream->next->wsize=SSL_write(node->ssl,writetemp,tstream->next->rsize); } else { tstream->next->wsize=send(node->socket,writetemp,tstream->next->rsize,0); }; #else tstream->next->wsize=send(node->socket,writetemp,tstream->next->rsize,0); #endif if(tstream->next->wsize>0) { tstream->next->wrotesize+=tstream->next->wsize; if(tstream->next->rsize!=tstream->next->wsize || beginsize>0) { // FIX fseek(tstream->next->fstream,tstream->next->wrotesize-(tstream->next->varsize),SEEK_SET); // FIX }; }; #ifdef WIN32 if((tstream->next->wsize<=0) && (WSAGetLastError()!=WSAEWOULDBLOCK)) { // WIN32 only #else if(tstream->next->wsize<=0 && errno!=EAGAIN) { // linux only // *nix i guess #endif //fclose(tstream->next->fstream); __ILWS_delete_next_outstream(tstream); //node->outstream->next=tstream->next; return; }else { // broken pipe if(tstream->next->wsize<0) { fseek(tstream->next->fstream,tstream->next->wrotesize-(tstream->next->varsize),SEEK_SET); //didn't read must back to where it was }; }; }else { // filename is null __ILWS_delete_next_outstream(tstream); return; }; }else { // End of streams current_web_client->stat=5; // done }; } /*********************************************************************************************************/ /* * Set http directive */ void web_client_HTTPdirective(char *str) { current_web_client->HTTPdirective=str; } /*********************************************************************************************************/ /* * GET request name */ char *__ILWS_web_client_getreq() { char *ret; char *tmp1=strstr(current_web_client->rbuf,"?"); char *tmp2=strstr(current_web_client->rbuf," HTTP"); char *tmp3=strstr(current_web_client->rbuf,"\r\n"); int size; if(tmp1==NULL || tmp1>tmp2) { tmp1=tmp2; }; if(tmp2>tmp3) { return NULL; }; size=tmp1-current_web_client->rbuf; if(size<1) return NULL; if(!(ret=__ILWS_malloc(size+1))) { LWSERR(LE_MEMORY); return NULL; }; memcpy(ret,current_web_client->rbuf,size); ret[size]=0; return ret; }; /*********************************************************************************************************/ /* * GET request line */ char *__ILWS_web_client_getreqline() { char *ret; char *tmp1=strstr(current_web_client->rbuf,"\r\n"); int size=0; if(tmp1==NULL) return NULL; size=tmp1-current_web_client->rbuf; if(size<1) return NULL; if(!(ret=__ILWS_malloc(size+1))) { LWSERR(LE_MEMORY); return NULL; }; memcpy(ret,current_web_client->rbuf,size); ret[size]=0; return ret; }
/* * Core function, return 2 if no client to process, 1 if some client processed, 0 if error */ int web_server_run(struct web_server *server) { struct web_client *client; int rt; int tsalen=0; int tsocket=0; struct sockaddr_in tsa; _logfile=server->weblog; current_web_server=server; if(server->client->next==NULL) { //if(__ILWS_newdata(server->socket)); // does nothing but act like usleep }; // search for client tsalen=sizeof(client->sa); tsocket=accept(server->socket,(struct sockaddr *)&tsa,&tsalen); if(tsocket==-1) { #ifdef WIN32 if(WSAGetLastError()!=WSAEWOULDBLOCK) { #else if(errno!=EAGAIN) { #endif fprintf(stderr,"What kind of error is this?\n"); // REMOVE // client f****d up? warn somebody? (error or log or something?) return 0; // don't process nothing }; } else { client=__ILWS_malloc(sizeof(struct web_client)); if(client==NULL) { rt=shutdown(tsocket,SHUT_RDWR); #ifdef WIN32 rt=closesocket(tsocket); #else rt=close(tsocket); #endif LWSERR(LE_MEMORY); return 0; }; client->salen=tsalen; client->socket=tsocket; client->sa=tsa; #ifdef HAVE_OPENSSL if((server->flags & WS_USESSL) == WS_USESSL) { client->ssl = SSL_new(server->ctx); SSL_set_fd(client->ssl,client->socket); SSL_accept(client->ssl); //client->cert = SSL_get_peer_certificate (client->ssl); } else { client->ssl=NULL; }; #endif if(!__ILWS_add_client(server->client,client)) { fprintf(stderr,"No client?\n"); // REMOVE return 0; }else { web_log("%s - - [%s] Connected\n",inet_ntoa(client->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z")); //REMOBE }; }; // end search for client client=server->client; // init list if(!client->next) { // think of Rocco Carbone ([email protected]) return 2; // i don't need to process the list (nothing next) returns 2 if there is no client to process }; while(client->next!=NULL) { // Process the client and swap to next; current_web_client=client->next; switch(client->next->stat) { case 1: { __ILWS_read_client(current_web_client); };break; case 2: { __ILWS_process_client(current_web_client,server->gethandler); };break; case 4: { __ILWS_output_client(current_web_client); };break; case 5: { __ILWS_delete_next_client(client); continue; };break; }; client=client->next; }; return 1; // return 1 if something processed }
/* * This function initialize one web_server handler */ int web_server_init(struct web_server *server,int port,const char *logfile,int flags) { #ifdef WIN32 unsigned long t=IOC_INOUT; WSADATA WSAinfo; WSAStartup(2,&WSAinfo); // Damn w32 sockets #endif current_web_server=server; server->port=port; server->conffile=NULL; server->mimefile=NULL; server->weblog=NULL; server->usessl=0; server->flags=flags; server->dataconf=""; if((flags & WS_USEEXTCONF) == WS_USEEXTCONF) { if(!(web_server_setup(server,logfile))) { #ifdef WIN32 WSACleanup(); #endif return 0; }; _logfile=server->weblog; // Set current log stream web_log("%s using config file %s\n",_libwebserver_version,logfile); }; // Create a listen socket port 'port' and listen addr (0) (all interfaces) server->socket=__ILWS_listensocket((short)server->port,0); if(server->socket==-1) { LWSERR(LE_NET); #ifdef WIN32 WSACleanup(); #endif return 0; }; #ifdef WIN32 ioctlsocket(server->socket,FIONBIO,&t); //non blocking sockets for win32 #else fcntl(server->socket,F_SETFL,O_NONBLOCK); #endif // Setup FILE structure of logfile if(logfile!=NULL && !((flags & WS_USEEXTCONF) == WS_USEEXTCONF)) { server->logfile=__ILWS_malloc(strlen(logfile)+1); memcpy(server->logfile,logfile,strlen(logfile)); server->logfile[strlen(logfile)]=0; server->weblog=open_weblog(logfile); // Create File stream for log }; web_log("\n[%s] Server started at port %d (%s)\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),server->port,_libwebserver_version); // Setup Flags // openssl #ifdef HAVE_OPENSSL if((server->flags & WS_USESSL) == WS_USESSL) { web_log("[%s] (FLAG) Using SSL in connections\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z")); web_log(" +-- %s certificate file\n",server->cert_file); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); server->ctx=SSL_CTX_new (SSLv23_server_method()); if (SSL_CTX_use_certificate_file(server->ctx, server->cert_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(3); } if (SSL_CTX_use_PrivateKey_file(server->ctx, server->cert_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(4); } if (SSL_CTX_check_private_key(server->ctx)<= 0) { ERR_print_errors_fp(stderr); exit(4); }; server->usessl=1; }; #endif if((server->flags & WS_LOCAL) == WS_LOCAL) { web_log("[%s] (FLAG) Accepting only local connections\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z")); }; server->client=__ILWS_init_client_list(); // Initializate client list server->gethandler=__ILWS_init_handler_list(); // Initializate handlers list web_server_addhandler(server,"* /libwebserver.gif",_web_server_logo,0,NULL); // Add logo default handler #ifndef WIN32 signal(SIGPIPE,SIG_IGN); #endif return 1; }
/* * Define config file to setup server (new on 0.5.0) */ int web_server_setup(struct web_server *server,const char *conffile) { FILE *tmpf; char *tmp3; //long tmpsize=0; long sizec; struct stat statf; // tested only on win if(!(server->conffile=__ILWS_malloc(strlen(conffile)+1))) { LWSERR(LE_MEMORY); return 0; }; memcpy(server->conffile,conffile,strlen(conffile)); server->conffile[strlen(conffile)]=0; tmpf=fopen(server->conffile,"r"); if(tmpf==NULL) { printf("no config file found\r\n"); server->dataconf=""; return(0); }; fseek(tmpf,SEEK_SET,SEEK_END); sizec=ftell(tmpf); fseek(tmpf,0,SEEK_SET); if(!(server->dataconf=__ILWS_malloc(sizec+1))) { LWSERR(LE_MEMORY); return 0; }; fread(server->dataconf,sizec,1,tmpf); server->dataconf[sizec]=0; // Hilobok Andrew ([email protected]) said to remove the -9 :) fclose(tmpf); stat(server->conffile,&statf); // tested only on win server->conffiletime=statf.st_mtime; // tested only on win if((server->logfile=web_server_getconf(server,"LIBWEBSERVER","LOG"))) { web_log("\nUsing logfile [%s]\n",server->logfile); server->weblog=open_weblog(server->logfile); } else { web_log("\nLOG entry not found\r\n"); server->weblog=NULL; }; if((tmp3=web_server_getconf(server,"LIBWEBSERVER","PORT"))) { web_log("\nListen port [%s]\n",tmp3); server->port=atoi(tmp3); __ILWS_free(tmp3); } else { web_log("PORT entry not found\r\n"); server->port=0; }; #ifdef HAVE_OPENSSL // Fetch SSL if((tmp3=web_server_getconf(server,"LIBWEBSERVER","USESSL"))) { if(tmp3[0]=='1') { server->flags = server->flags | WS_USESSL; }else if(tmp3[0]=='0') { server->flags = server->flags & ~WS_USESSL; } else { fprintf(stderr,"[USESSL=] argument invalid\n"); }; __ILWS_free(tmp3); } // Fetch CERTFILE server->cert_file=web_server_getconf(server,"LIBWEBSERVER","CERTFILE"); server->mimefile=web_server_getconf(server,"LIBWEBSERVER","MIMEFILE"); #endif // Fetch LOCAL if((tmp3=web_server_getconf(server,"LIBWEBSERVER","LOCAL"))) { if(tmp3[0]=='1') { server->flags = server->flags | WS_LOCAL; } else if(tmp3[0]=='0') { server->flags=server->flags & ~WS_LOCAL; }else { fprintf(stderr,"[LOCAL=] argument invalid\n"); }; __ILWS_free(tmp3); } return 1; };