⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 MINIWEB 0.75, 可以用于嵌入式系统设计。
💻 C
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////////////// http.c//// MiniWeb - mini webserver implementation///////////////////////////////////////////////////////////////////////////////#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <sys/stat.h>#include "httppil.h"#include "httpapi.h"#include "httpint.h"////////////////////////////////////////////////////////////////////////////// global variables////////////////////////////////////////////////////////////////////////////// default pagesconst char g_chPasswordPage[]="password.htm";DWORD fileExtTable[]={	FILEEXT_HTM,FILEEXT_TEXT,FILEEXT_GIF,FILEEXT_JPG,FILEEXT_PNG,FILEEXT_CSS,FILEEXT_SWF,	FILEEXT_MPA,FILEEXT_MPG,FILEEXT_JS,0};char* contentTypeTable[]={	HTTPTYPE_HTML,HTTPTYPE_TEXT,HTTPTYPE_GIF,HTTPTYPE_JPEG,HTTPTYPE_PNG,HTTPTYPE_CSS,HTTPTYPE_SWF,	HTTPTYPE_MPA,HTTPTYPE_MPEG,HTTPTYPE_JS,HTTPTYPE_OCTET,HTTPTYPE_STREAM};char* defaultPages[]={"index.htm","index.html","default.htm",NULL};FILE *fpLog=NULL;#define LOG_INFO fpLog////////////////////////////////////////////////////////////////////////////// API callsc////////////////////////////////////////////////////////////////////////////const char *dayNames="Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";const char *monthNames="Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec";const char *httpDateTimeFormat="%s, %02d %s %02d %02d:%02d:%02d GMT";char* mwGetVarValue(HttpVariables* vars, char *varname){	int i;	if (vars && varname) {		for (i=0; (vars+i)->name; i++) {			if (!strcmp((vars+i)->name,varname))				return (vars+i)->value;		}	}	return NULL;}int mwGetHttpDateTime(time_t timer, char *buf){	struct tm *btm;	btm=gmtime(&timer);	return sprintf(buf,httpDateTimeFormat,		dayNames+(btm->tm_wday<<2),		btm->tm_mday,		monthNames+(btm->tm_mon<<2),		1900+btm->tm_year,		btm->tm_hour,		btm->tm_min,		btm->tm_sec);}////////////////////////////////////////////////////////////////////////////// mwServerStart// Start the webserver////////////////////////////////////////////////////////////////////////////int mwServerStart(HttpParam* hp){	if (hp->bWebserverRunning) {		DEBUG("Error: Webserver thread already running\n");		return -1;	}	if (!fpLog) fpLog=stderr;	if (!InitSocket()) {		DEBUG("Error initializing Winsock\n");		return -1;	}	hp->bKillWebserver=FALSE;	hp->bWebserverRunning=TRUE;	{		int i;		for (i=0;(hp->pxUrlHandler+i)->pchUrlPrefix;i++) {			if ((hp->pxUrlHandler+i)->pfnUrlHandlerInit &&				(hp->pxUrlHandler+i)->pfnUrlHandlerInit(hp,0)) {				//remove the URL handler				(hp->pxUrlHandler+i)->pfnUrlHandler=NULL;			}		}	}/*#ifdef HTTPPOST	if (!hp->pfnPost)		hp->pfnPost=DefaultWebPostCallback;	if (!hp->pfnFileUpload)		hp->pfnFileUpload=DefaultWebFileUploadCallback;#endif*/	if (!(hp->listenSocket=_mwStartListening(hp))) return -1;	hp->stats.startTime=time(NULL);#ifndef NOTHREAD	if (ThreadCreate(&hp->tidHttpThread,_mwHttpThread,(void*)hp)) {		DEBUG("Error creating server thread\n");		return -1;	}#else	_mwHttpThread((void*)hp);#endif	return 0;}////////////////////////////////////////////////////////////////////////////// mwServerShutdown// Shutdown the webserver////////////////////////////////////////////////////////////////////////////int mwServerShutdown(HttpParam* hp){	int i;	DEBUG("Shutting down web server thread\n");	// signal webserver thread to quit	hp->bKillWebserver=TRUE;  	// and wait for thread to exit	for (i=0;hp->bWebserverRunning && i<10;i++) msleep(100);	for (i=0;(hp->pxUrlHandler+i)->pchUrlPrefix;i++) {		if ((hp->pxUrlHandler+i)->pfnUrlHandler && (hp->pxUrlHandler+i)->pfnUrlHandlerInit)			(hp->pxUrlHandler+i)->pfnUrlHandlerInit((void*)hp,1);	}	UninitSocket();	DEBUG("Webserver shutdown complete\n");	return 0;}int mwGetLocalFileName(HttpFilePath* hfp){	char ch;	char *p=hfp->cFilePath,*s=hfp->pchHttpPath,*upLevel=NULL;	hfp->pchExt=NULL;	hfp->fTailSlash=0;	if (hfp->pchRootPath) {		p+=_mwStrCopy(hfp->cFilePath,hfp->pchRootPath);		if (*(p-1)!=SLASH) {			*p=SLASH;			*(++p)=0;		}	}	while ((ch=*s) && ch!='?' && (int)p-(int)hfp->cFilePath<sizeof(hfp->cFilePath)-1) {		if (ch=='%') {			register unsigned char v;			if (*(++s)==0) break;			if (*s>='a' && *s<='f')				v = (*s-('a'-'A'+7)) << 4;			else if (*s>='A' && *s<='F')				v = (*s-7) << 4;			else				v = *s << 4;			if (*(++s)==0) break;			if (*s>='a' && *s<='f')				v |= (*s-('a'-'A'+7)) & 0xf;			else if (*s>='A' && *s<='F')				v |= (*s-7) & 0xf;			else				v |= *s & 0xf;			*(p++)=v;			s++;		} else if (ch=='/') {			*p=SLASH;			upLevel=(++p);			while (*(++s)=='/');			continue;		} else if (ch=='+') {			*(p++)=' ';			s++;		} else if (ch=='.') {			if (upLevel && GETWORD(s+1)==DEFWORD('.','/')) {				s+=2;				p=upLevel;			} else {				*(p++)='.';				hfp->pchExt=p;				while (*(++s)=='.');	//avoid '..' appearing in filename for security issue			}		} else {			*(p++)=*(s++);		}	}	if (*(p-1)==SLASH) {		p--;		hfp->fTailSlash=1;	}	*p=0;	return (int)p-(int)hfp->cFilePath;}////////////////////////////////////////////////////////////////////////////// Internal (private) helper functions////////////////////////////////////////////////////////////////////////////SOCKET _mwStartListening(HttpParam* hp){	SOCKET listenSocket;	int iRc;    // create a new socket    listenSocket=socket(AF_INET,SOCK_STREAM,0);    if (listenSocket<0) return 0;    // allow reuse of port number    {      int iOptVal=1;      iRc=setsockopt(listenSocket,SOL_SOCKET,SO_REUSEADDR,                     (char*)&iOptVal,sizeof(iOptVal));      if (iRc<0) return 0;    }    // bind it to the http port    {      struct sockaddr_in sinAddress;      memset(&sinAddress,0,sizeof(struct sockaddr_in));      sinAddress.sin_family=AF_INET;      sinAddress.sin_addr.s_addr=htonl(INADDR_ANY);      sinAddress.sin_port=htons(hp->siHttpPort); // http port      iRc=bind(listenSocket,(struct sockaddr*)&sinAddress,               sizeof(struct sockaddr_in));	  if (iRc<0) {		DEBUG("Error binding on port %d\n",hp->siHttpPort);		return 0;	  }    }#ifndef WIN32    // set to non-blocking to avoid lockout issue (see Section 15.6    // in Unix network programming book)    {      int iSockFlags;      iSockFlags = fcntl(listenSocket, F_GETFL, 0);      iSockFlags |= O_NONBLOCK;      iRc = fcntl(listenSocket, F_SETFL, iSockFlags);    }#endif    // listen on the socket for incoming calls	if (listen(listenSocket,hp->siMaxClients-1)) {		DEBUG("Unable to listen on socket %d\n",listenSocket);		return 0;	}    DEBUG("Http listen socket %d opened\n",listenSocket);	return listenSocket;}void _mwInitSocketData(HttpSocket *phsSocket){	memset(&phsSocket->response,0,sizeof(HttpResponse));	memset(&phsSocket->request,0,sizeof(HttpRequest));	phsSocket->fd=0;	phsSocket->flags=FLAG_RECEIVING;	phsSocket->pucData=phsSocket->buffer;	phsSocket->iDataLength=0;	phsSocket->response.iBufferSize=HTTP_BUFFER_SIZE;	phsSocket->ptr=NULL;}////////////////////////////////////////////////////////////////////////////// _mwHttpThread// Webserver independant processing thread. Handles all connections////////////////////////////////////////////////////////////////////////////void* _mwHttpThread(HttpParam *hp){ 	HttpSocket *phsSocketCur;	SOCKET socket;	struct sockaddr_in sinaddr;    int iRc;  // main processing loop	while (!hp->bKillWebserver) {		time_t tmCurrentTime;		SOCKET iSelectMaxFds;		fd_set fdsSelectRead;		fd_set fdsSelectWrite;		// clear descriptor sets		FD_ZERO(&fdsSelectRead);		FD_ZERO(&fdsSelectWrite);		FD_SET(hp->listenSocket,&fdsSelectRead);		iSelectMaxFds=hp->listenSocket;		//get current time		tmCurrentTime=time(NULL);  		// build descriptor sets and close timed out sockets		for (phsSocketCur=hp->phsSocketHead; phsSocketCur; phsSocketCur=phsSocketCur->next) {			int iError=0;			int iOptSize=sizeof(int);			// get socket fd			socket=phsSocketCur->socket;			if (!socket) continue;			if (getsockopt(socket,SOL_SOCKET,SO_ERROR,(char*)&iError,&iOptSize)) {				// if a socket contains a error, close it				SYSLOG(LOG_INFO,"[%d] Socket no longer vaild.\n",socket);				phsSocketCur->flags=FLAG_CONN_CLOSE;				_mwCloseSocket(hp, phsSocketCur);				continue;			}			// check expiration timer (for non-listening, in-use sockets)			if (tmCurrentTime > phsSocketCur->tmExpirationTime) {				SYSLOG(LOG_INFO,"[%d] Http socket expired\n",phsSocketCur->socket);				hp->stats.timeOutCount++;				// close connection				phsSocketCur->flags=FLAG_CONN_CLOSE;				_mwCloseSocket(hp, phsSocketCur);			} else {				if (ISFLAGSET(phsSocketCur,FLAG_RECEIVING)) {					// add to read descriptor set					FD_SET(socket,&fdsSelectRead);				}				if (ISFLAGSET(phsSocketCur,FLAG_SENDING)) {					// add to write descriptor set					FD_SET(socket,&fdsSelectWrite);				}				// check if new max socket				if (socket>iSelectMaxFds) {				iSelectMaxFds=socket;				}			}		}		{			struct timeval tvSelectWait;			// initialize select delay			tvSelectWait.tv_sec = 1;			tvSelectWait.tv_usec = 0; // note: using timeval here -> usec not nsec			// and check sockets (may take a while!)			iRc=select(iSelectMaxFds+1, &fdsSelectRead, &fdsSelectWrite,					NULL, &tvSelectWait);		}		if (iRc<0) {			if (hp->bKillWebserver) break;			DEBUG("Select error\n");			msleep(1000);			continue;		}		if (iRc>0) {			HttpSocket *phsSocketNext;			// check which sockets are read/write able			phsSocketCur=hp->phsSocketHead;			while (phsSocketCur) {				BOOL bRead;				BOOL bWrite;				phsSocketNext=phsSocketCur->next;				// get socket fd				socket=phsSocketCur->socket;		          				// get read/write status for socket				bRead=FD_ISSET(socket, &fdsSelectRead);				bWrite=FD_ISSET(socket, &fdsSelectWrite);				if ((bRead|bWrite)!=0) {					//DEBUG("socket %d bWrite=%d, bRead=%d\n",phsSocketCur->socket,bWrite,bRead);					// if readable or writeable then process					if (bWrite && ISFLAGSET(phsSocketCur,FLAG_SENDING)) {						iRc=_mwProcessWriteSocket(hp, phsSocketCur);					} else if (bRead && ISFLAGSET(phsSocketCur,FLAG_RECEIVING)) {						iRc=_mwProcessReadSocket(hp,phsSocketCur);					} else {						iRc=-1;						DEBUG("Invalid socket state (flag: %08x)\n",phsSocketCur->flags);						SETFLAG(phsSocketCur,FLAG_CONN_CLOSE);					}					if (!iRc) {						// and reset expiration timer						phsSocketCur->tmExpirationTime=time(NULL)+HTTP_EXPIRATION_TIME;					} else {						_mwCloseSocket(hp, phsSocketCur);					}				}				phsSocketCur=phsSocketNext;			}			// check if any socket to accept and accept the socket			if (FD_ISSET(hp->listenSocket, &fdsSelectRead) &&					hp->stats.clientCount<hp->siMaxClients &&					(socket=_mwAcceptSocket(hp,&sinaddr))) {				// create a new socket structure and insert it in the linked list				phsSocketCur=(HttpSocket*)malloc(sizeof(HttpSocket));				if (!phsSocketCur) {					DEBUG("Out of memory\n");					break;				}				phsSocketCur->next=hp->phsSocketHead;				hp->phsSocketHead=phsSocketCur;	//set new header of the list				//fill structure with data				_mwInitSocketData(phsSocketCur);				phsSocketCur->tmAcceptTime=time(NULL);				phsSocketCur->socket=socket;				phsSocketCur->tmExpirationTime=time(NULL)+HTTP_EXPIRATION_TIME;				phsSocketCur->siRequestCount=0;				phsSocketCur->request.ipAddr.laddr=ntohl(sinaddr.sin_addr.s_addr);				hp->stats.clientCount++;				//update max client count				if (hp->stats.clientCount>hp->stats.clientCountMax)					hp->stats.clientCountMax=hp->stats.clientCount;				{					IP ip=phsSocketCur->request.ipAddr;					SYSLOG(LOG_INFO,"[%d] IP: %d.%d.%d.%d\n",phsSocketCur->socket,ip.caddr[3],ip.caddr[2],ip.caddr[1],ip.caddr[0]);				}				SYSLOG(LOG_INFO,"Connected clients: %d\n",hp->stats.clientCount);			}		} else {			HttpSocket *phsSocketPrev=NULL;			// select timeout			// clean up the link list			phsSocketCur=hp->phsSocketHead;			while (phsSocketCur) {				if (!phsSocketCur->socket) {					DEBUG("Free up socket structure 0x%08x\n",phsSocketCur);					if (phsSocketPrev) {						phsSocketPrev->next=phsSocketCur->next;						free(phsSocketCur);						phsSocketCur=phsSocketPrev->next;					} else {						hp->phsSocketHead=phsSocketCur->next;						free(phsSocketCur);						phsSocketCur=hp->phsSocketHead;					}				} else {					phsSocketPrev=phsSocketCur;					phsSocketCur=phsSocketCur->next;				}			}		}	}	{		phsSocketCur=hp->phsSocketHead;		while (phsSocketCur) {			HttpSocket *phsSocketNext;			phsSocketCur->flags=FLAG_CONN_CLOSE;			_mwCloseSocket(hp, phsSocketCur);			phsSocketNext=phsSocketCur->next;			free(phsSocketCur);			phsSocketCur=phsSocketNext;	}	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -