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

📄 http.c

📁 MINIWEB 0.75, 可以用于嵌入式系统设计。
💻 C
📖 第 1 页 / 共 3 页
字号:
	// clear state vars	hp->bKillWebserver=FALSE;	hp->bWebserverRunning=FALSE;  	return NULL;} // end of _mwHttpThread////////////////////////////////////////////////////////////////////////////// _mwAcceptSocket// Accept an incoming connection////////////////////////////////////////////////////////////////////////////SOCKET _mwAcceptSocket(HttpParam* hp,struct sockaddr_in *sinaddr){    SOCKET socket;	int namelen=sizeof(struct sockaddr);	socket=accept(hp->listenSocket, (struct sockaddr*)sinaddr,&namelen);    if ((int)socket<=0) {		DEBUG("Error accepting socket\n");		return 0;    }     SYSLOG(LOG_INFO,"[%d] connection accepted @ %s\n",socket,GetTimeString());#ifndef WIN32    // set to non-blocking to stop sends from locking up thread	{        int iRc;        int iSockFlags;        iSockFlags = fcntl(socket, F_GETFL, 0);        iSockFlags |= O_NONBLOCK;        iRc = fcntl(socket, F_SETFL, iSockFlags);	}#endif	if (hp->siSocketRcvBufSize) {		int iSocketBufSize=hp->siSocketRcvBufSize<<10;		setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (const char*)&iSocketBufSize, sizeof(int));	}	return socket;} // end of _mwAcceptSocketint _mwBuildHttpHeader(HttpParam* hp, HttpSocket *phsSocket, time_t contentDateTime, unsigned char* buffer){	char *p=buffer;	p+=sprintf(p,HTTP200_HEADER,		(phsSocket->request.iStartByte==0)?"200 OK":"206 Partial content",		HTTP_KEEPALIVE_TIME,hp->siMaxReqPerConn,		ISFLAGSET(phsSocket,FLAG_CONN_CLOSE)?"close":"Keep-Alive");	p+=mwGetHttpDateTime(contentDateTime, p);	SETWORD(p,DEFWORD('\r','\n'));	p+=2;	p+=sprintf(p,"Content-Type: %s\r\n",contentTypeTable[phsSocket->response.fileType]);	if (phsSocket->response.iContentLength>0) {		p+=sprintf(p,"Content-Length: %d\r\n",phsSocket->response.iContentLength);	}	SETDWORD(p,DEFDWORD('\r','\n',0,0));	return (int)p-(int)buffer+2;}int _mwCheckUrlHandlers(HttpParam* hp, HttpSocket* phsSocket){	UrlHandler* puh;	UrlHandlerParam up;	int ret=0;	up.pxVars=NULL;	up.iVarCount=-1;	for (puh=hp->pxUrlHandler; puh->pchUrlPrefix; puh++) {		int iPrefixLen=strlen(puh->pchUrlPrefix);		if (puh->pfnUrlHandler && !strncmp(phsSocket->request.pucPath,puh->pchUrlPrefix,iPrefixLen)) {			//URL prefix matches			up.hp=hp;			up.iDataBytes=phsSocket->response.iBufferSize;			up.pucRequest=phsSocket->request.pucPath+iPrefixLen;			up.pucHeader=phsSocket->buffer;			up.request=&phsSocket->request;			up.pucBuffer=phsSocket->pucData;			up.pucBuffer[0]=0;			up.iContentBytes=0;			up.iSentBytes=0;			phsSocket->ptr=(void*)puh->pfnUrlHandler;			if (up.iVarCount==-1) {				//parsing variables in URL				char *p,*s=NULL;				up.iVarCount=0;				if (ISFLAGSET(phsSocket,FLAG_REQUEST_GET)) {					s = strchr(up.pucRequest,'?');					if (s) {						*(s++) = 0;					}#ifdef HTTPPOST				} else {					s = phsSocket->request.pucPayload;#endif				}				if (s) {					int i=0;					//get number of variables					for (p = s; *p ; ) {						if (*(p++)=='=') up.iVarCount++;					}					if (up.iVarCount) {						up.pxVars=malloc(up.iVarCount*sizeof(HttpVariables)+sizeof(char*));						//store variable name and value						for (p=s; *p && i<up.iVarCount; p++) {							if (*p=='=') {								*p=0;								(up.pxVars+i)->name=s;								s=p+1;							} else if (*p=='&') {								*p=0;								(up.pxVars+i)->value=s;								s=p+1;								i++;							}						}						(up.pxVars+i)->value=s;						(up.pxVars+up.iVarCount)->name=NULL;					}				}			}			ret=(*(PFNURLCALLBACK)phsSocket->ptr)(&up);			if (ret & (FLAG_DATA_RAW | FLAG_DATA_FILE)) {				phsSocket->flags|=ret;				phsSocket->response.fileType=up.fileType;				hp->stats.urlProcessCount++;				if (ret & FLAG_TO_FREE) {					phsSocket->ptr=up.pucBuffer;	//keep the pointer which will be used to free memory later				}				if (ret & FLAG_DATA_RAW) {					phsSocket->pucData=up.pucBuffer;					phsSocket->iDataLength=up.iDataBytes;					phsSocket->response.iContentLength=up.iContentBytes>0?up.iContentBytes:up.iDataBytes;					DEBUG("URL handler acted (raw data)\n");				} else {					phsSocket->flags|=FLAG_DATA_FILE;					if (up.pucBuffer[0])						phsSocket->request.pucPath=up.pucBuffer;					DEBUG("URL handler acted (file)\n");				}				break;			}		}	}	if (up.pxVars) free(up.pxVars);	return ret;}////////////////////////////////////////////////////////////////////////////// _mwProcessReadSocket// Process a socket (read)////////////////////////////////////////////////////////////////////////////int _mwProcessReadSocket(HttpParam* hp, HttpSocket* phsSocket){	char *p;#ifdef HTTPPOST    if ((HttpMultipart*)phsSocket->ptr != NULL) {      //_mwProcessMultipartPost(phsSocket);      return 0;    }#endif	// check if receive buffer full	if (phsSocket->iDataLength>=MAX_REQUEST_SIZE) {		// close connection		SYSLOG(LOG_INFO,"Invalid request header size (%d bytes)\n",phsSocket->iDataLength);		SETFLAG(phsSocket, FLAG_CONN_CLOSE);		return -1;	}	// read next chunk of data	{		int sLength;		sLength=recv(phsSocket->socket, 						phsSocket->pucData+phsSocket->iDataLength,						phsSocket->response.iBufferSize-phsSocket->iDataLength, 0);		if (sLength <= 0) {			SYSLOG(LOG_INFO,"[%d] socket closed by client\n",phsSocket->socket);			SETFLAG(phsSocket, FLAG_CONN_CLOSE);			return -1;		}		// add in new data received		phsSocket->iDataLength+=sLength;	}	//check request type	switch (GETDWORD(phsSocket->pucData)) {	case HTTP_GET:		SETFLAG(phsSocket,FLAG_REQUEST_GET);		phsSocket->request.pucPath=phsSocket->pucData+5;		break;#ifdef HTTPPOST	case HTTP_POST:		SETFLAG(phsSocket,FLAG_REQUEST_POST);		phsSocket->request.pucPath=phsSocket->pucData+6;		break;#endif	}	// check if end of request	if (phsSocket->request.siHeaderSize==0) {		int i=0;		while (GETDWORD(phsSocket->buffer + i) != HTTP_HEADEREND) {			if (++i > phsSocket->iDataLength - 3) return 0;		}		// reach the end of the header		if (!ISFLAGSET(phsSocket,FLAG_REQUEST_GET|FLAG_REQUEST_POST)) {			SYSLOG(LOG_INFO,"[%d] Unsupported method\n",phsSocket->socket);					SETFLAG(phsSocket,FLAG_CONN_CLOSE);			return -1;		}		phsSocket->request.siHeaderSize = i + 4;		DEBUG("[%d] header size: %d bytes\n",phsSocket->socket,phsSocket->request.siHeaderSize);		if (_mwParseHttpHeader(phsSocket)) {			SYSLOG(LOG_INFO,"Error parsing request\n");			SETFLAG(phsSocket, FLAG_CONN_CLOSE);			return -1;#ifdef HTTPPOST		} else if (ISFLAGSET(phsSocket,FLAG_REQUEST_POST)) {			hp->stats.reqPostCount++;			phsSocket->request.pucPayload=malloc(phsSocket->response.iContentLength+1);			phsSocket->request.pucPayload[phsSocket->response.iContentLength]=0;			phsSocket->iDataLength -= phsSocket->request.siHeaderSize;			memcpy(phsSocket->request.pucPayload, phsSocket->buffer + phsSocket->request.siHeaderSize, phsSocket->iDataLength);			phsSocket->pucData = phsSocket->request.pucPayload;#endif		}		// add header zero terminator		phsSocket->buffer[phsSocket->request.siHeaderSize]=0;		DEBUG("%s",phsSocket->buffer);	}	if ( phsSocket->iDataLength < phsSocket->response.iContentLength ) {		return 0;	}	p=phsSocket->buffer + phsSocket->request.siHeaderSize + 4;	p=(unsigned char*)((unsigned long)p & (-4));	//keep 4-byte aligned	*p=0;	//keep request path	{		char *q;		int iPathLen;		for (q=phsSocket->request.pucPath;*q && *q!=' ';q++);		iPathLen=(int)q-(int)(phsSocket->request.pucPath);		if (iPathLen>=MAX_REQUEST_PATH_LEN) {			DEBUG("Request path too long and is stripped\n");			iPathLen=MAX_REQUEST_PATH_LEN-1;		}		if (iPathLen>0)			memcpy(p,phsSocket->request.pucPath,iPathLen);		*(p+iPathLen)=0;		phsSocket->request.pucPath=p;		p=(unsigned char*)(((unsigned long)(p+iPathLen+4+1))&(-4));	//keep 4-byte aligned	}	phsSocket->pucData=p;	//free buffer space	phsSocket->response.iBufferSize=(HTTP_BUFFER_SIZE-(phsSocket->pucData-phsSocket->buffer)-1)&(-4);	SYSLOG(LOG_INFO,"[%d] request path: /%s\n",phsSocket->socket,phsSocket->request.pucPath);	hp->stats.reqCount++;	if (ISFLAGSET(phsSocket,FLAG_REQUEST_GET|FLAG_REQUEST_POST)) {		if (hp->pxUrlHandler) {			if (!_mwCheckUrlHandlers(hp,phsSocket))				SETFLAG(phsSocket,FLAG_DATA_FILE);		}		// set state to SENDING (actual sending will occur on next select)		CLRFLAG(phsSocket,FLAG_RECEIVING)		SETFLAG(phsSocket,FLAG_SENDING);		hp->stats.reqGetCount++;		if (ISFLAGSET(phsSocket,FLAG_DATA_FILE)) {			// send requested page			return _mwStartSendFile(hp,phsSocket);		} else if (ISFLAGSET(phsSocket,FLAG_DATA_RAW)) {			return _mwStartSendRawData(hp, phsSocket);		}	}	SYSLOG(LOG_INFO,"Error occurred (might be a bug)\n");	return -1;} // end of _mwProcessReadSocket////////////////////////////////////////////////////////////////////////////// _mwProcessWriteSocket// Process a socket (write)////////////////////////////////////////////////////////////////////////////int _mwProcessWriteSocket(HttpParam *hp, HttpSocket* phsSocket){	if (phsSocket->iDataLength<=0) {		SYSLOG(LOG_INFO,"[%d] Data sending completed (%d/%d)\n",phsSocket->socket,phsSocket->response.iSentBytes,phsSocket->response.iContentLength);		return 1;	}	SYSLOG(LOG_INFO,"[%d] sending data\n",phsSocket->socket);	if (ISFLAGSET(phsSocket,FLAG_DATA_RAW|FLAG_DATA_STREAM)) {		return _mwSendRawDataChunk(hp, phsSocket);	} else if (ISFLAGSET(phsSocket,FLAG_DATA_FILE)) {		return _mwSendFileChunk(hp, phsSocket);	} else {		SYSLOG(LOG_INFO,"Invalid content source\n");		return -1;	}} // end of _mwProcessWriteSocket////////////////////////////////////////////////////////////////////////////// _mwCloseSocket// Close an open connection////////////////////////////////////////////////////////////////////////////void _mwCloseSocket(HttpParam* hp, HttpSocket* phsSocket){	if (ISFLAGSET(phsSocket,FLAG_TO_FREE) && phsSocket->ptr) {		free(phsSocket->ptr);		phsSocket->ptr=NULL;	}#ifdef HTTPPOST	if (phsSocket->request.pucPayload) {		free(phsSocket->request.pucPayload);	}#endif	if (!ISFLAGSET(phsSocket,FLAG_CONN_CLOSE) && phsSocket->siRequestCount<hp->siMaxReqPerConn) {		_mwInitSocketData(phsSocket);		//reset flag bits		phsSocket->siRequestCount++;		phsSocket->tmExpirationTime=time(NULL)+HTTP_KEEPALIVE_TIME;		return;	}    if (phsSocket->socket != 0) {		closesocket(phsSocket->socket);	} else {		SYSLOG(LOG_INFO,"[%d] bug: socket=0 (structure: 0x%x \n",phsSocket->socket,phsSocket);	}	hp->stats.clientCount--;	phsSocket->siRequestCount=0;	SYSLOG(LOG_INFO,"[%d] socket closed after responded for %d requests\n",phsSocket->socket,phsSocket->siRequestCount);	SYSLOG(LOG_INFO,"Connected clients: %d\n",hp->stats.clientCount);	phsSocket->socket=0;} // end of _mwCloseSocket__inline int _mwStrCopy(char *dest, char *src){	int i;	for (i=0; src[i]; i++) {		dest[i]=src[i];	}	dest[i]=0;	return i;}int _mwListDirectory(HttpSocket* phsSocket, char* dir){	char cFileName[128];	char cFilePath[MAX_PATH];	char *p=phsSocket->pucData;	int ret;	char *pagebuf=phsSocket->pucData;	int bufsize=phsSocket->response.iBufferSize;		p+=sprintf(p,"<html><head><title>/%s</title></head><body><table border=0 cellpadding=0 cellspacing=0 width=100%%><h2>Directory of /%s</h2><hr>",		phsSocket->request.pucPath,phsSocket->request.pucPath);	if (!*dir) SETWORD(dir,DEFWORD('.',0));	DEBUG("Listing directory: %s\n",dir);	for (ret=ReadDir(dir,cFileName); !ret; ret=ReadDir(NULL,cFileName)) {		struct stat st;		char *s;		int bytes;		if (GETWORD(cFileName)==DEFWORD('.',0)) continue;		DEBUG("Checking %s ...\n",cFileName);		bytes=p-pagebuf;		if (bytes+384>bufsize) {			//need to expand buffer			bufsize+=2048;			if (!ISFLAGSET(phsSocket,FLAG_TO_FREE)) {				//first time expanding				SETFLAG(phsSocket,FLAG_TO_FREE);				pagebuf=malloc(bufsize);				memcpy(pagebuf,phsSocket->pucData,bytes);			} else {				pagebuf=realloc(pagebuf,bufsize);			}			p=pagebuf+bytes;			DEBUG("Buffer expanded to %d bytes\n",bufsize);		}		sprintf(cFilePath,"%s/%s",dir,cFileName);		if (stat(cFilePath,&st)) continue;		if (st.st_mode & S_IFDIR) {			p+=sprintf(p,"<tr><td width=35%%><a href='%s/'>%s</a></td><td width=15%%>&lt;dir&gt;</td><td width=15%%>",				cFileName,cFileName);		} else {			p+=sprintf(p,"<tr><td width=35%%><a href='%s'>%s</a></td><td width=15%%>%d bytes</td><td width=15%%>",				cFileName,cFileName,st.st_size);			s=strrchr(cFileName,'.');			if (s) {				int filetype=_mwGetContentType(++s);				if (filetype!=HTTPFILETYPE_OCTET)					p+=_mwStrCopy(p,contentTypeTable[filetype]);				else					p+=sprintf(p,"%s file",s);			}		}		p+=_mwStrCopy(p,"</td><td>");		p+=mwGetHttpDateTime(st.st_mtime,p);		p+=_mwStrCopy(p,"</td></tr>");	}	p+=sprintf(p,"</table><hr><i>Directory content generated by MiniWeb</i></body></html>");	ReadDir(NULL,NULL);	phsSocket->response.iContentLength=(phsSocket->iDataLength=p-pagebuf);	phsSocket->response.fileType=HTTPFILETYPE_HTML;	if (ISFLAGSET(phsSocket,FLAG_TO_FREE)) {		phsSocket->pucData=pagebuf;		phsSocket->ptr=pagebuf;	}	return 0;}void _mwSend404Page(HttpSocket* phsSocket){	int bytes,offset=0;	char *p=HTTP404_HEADER;	SYSLOG(LOG_INFO,"[%d] Http file not found\n",phsSocket->socket);	// send file not found header	do {		bytes=send(phsSocket->socket, p+offset,sizeof(HTTP404_HEADER)-1-offset,0);		if (bytes<=0) break;		offset+=bytes;	} while (offset<sizeof(HTTP404_HEADER)-1);}#ifdef WIN32#define OPEN_FLAG O_RDONLY|0x8000#else#define OPEN_FLAG O_RDONLY#endif////////////////////////////////////////////////////////////////////////////// _mwStartSendFile// Setup for sending of a file////////////////////////////////////////////////////////////////////////////int _mwStartSendFile(HttpParam* hp, HttpSocket* phsSocket){	struct stat st;	HttpFilePath hfp;#ifdef HTTPAUTH	// check if authenticated	if (FALSE == _mwCheckAuthentication(phsSocket)) {		// Not authenticated		if (phsSocket->response.fileType==HTTPFILETYPE_HTML) {		// send password page only			pchFilename=(char*)g_chPasswordPage;		}	}#endif	hfp.pchRootPath=hp->pchWebPath;	hfp.pchHttpPath=phsSocket->request.pucPath;	// check type of file requested	mwGetLocalFileName(&hfp);	if (stat(hfp.cFilePath,&st)<0) {		// file/dir not found		_mwSend404Page(phsSocket);		return -1;	}	if (st.st_mode & S_IFDIR) {		char *p=hfp.cFilePath;		while (*p) p++;		{

⌨️ 快捷键说明

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