📄 http.c
字号:
default: break; } return; } // ready to read if (bRead && phsSocket->hssState==HTTPSOCKETSTATE_RECEIVING) { int sLength; #ifdef HTTPPOST if (phsSocket->pxMultipartInfo != NULL) { _mwProcessMultipartPost(phsSocket); return; }#endif if (phsSocket->iBufferLength==phsSocket->iDataLength) { phsSocket->iBufferLength=phsSocket->iBufferLength<<1; if (phsSocket->iBufferLength > HTTPMAXRECVBUFFER) { DEBUG("Error! Http max buffer size reached\n"); // close connection _mwCloseSocket(phsSocket); return; } DEBUG("Resizing http receive buffer to %d bytes\n",phsSocket->iBufferLength); phsSocket->pucData=realloc(phsSocket->pucData,phsSocket->iBufferLength); if (!phsSocket->pucData) { DEBUG("Out of memory\n"); _mwCloseSocket(phsSocket); return; } } // read next chunk of data sLength=recv(phsSocket->iSocket, phsSocket->pucData+phsSocket->iDataLength, phsSocket->iBufferLength-phsSocket->iDataLength, 0); if (sLength > 0) { char pchFilename[128]; int ret=0,i,iPrefixLen; // add in new data received phsSocket->iDataLength+=sLength; // check if end of request if (*(DWORD*)(phsSocket->pucData+phsSocket->iDataLength-sizeof(HTTP_HEADEREND))!= HTTP_HEADEREND) { DEBUG("Not end\n"); return; } // add zero terminator *(phsSocket->pucData+sLength)=0; if (!_mwCheckHeader(phsSocket)) { DEBUG("Error! Unknown request type\n"); // close connection _mwCloseSocket(phsSocket); } switch (phsSocket->hrtType) { case HTTPREQTYPE_GET: // get filename DEBUG("Http GET for file %s on socket %d\n",phsSocket->pucRequest, phsSocket->iSocket); if (!_mwCheckAccess(phsSocket)) { DEBUG("Access denied for %s\n",phsSocket->pucRequest); _mwCloseSocket(phsSocket); return; } if (g_urlProcCount>0) { for (i=0;i<g_urlProcCount;i++) { iPrefixLen=strlen((g_urlProcParams+i)->pchUrlPrefix); if (!strncmp(phsSocket->pucRequest,(g_urlProcParams+i)->pchUrlPrefix,iPrefixLen)) { //URL prefix matches ret=(g_urlProcParams+i)->pfnUrlProcCallback(phsSocket,phsSocket->pucRequest+iPrefixLen); if (ret) { DEBUG("URL Preprocessed\n"); break; } } } } if (ret==0) { // check type of file requested phsSocket->hftFileType=_mwGetLocalFilename(phsSocket->pucRequest,pchFilename,128); // mark if substitution needed phsSocket->bSubstitutionNeeded=(g_pfnSubst && (phsSocket->hftFileType==HTTPFILETYPE_HTML ||phsSocket->hftFileType==HTTPFILETYPE_JS)); // send requested page _mwStartSendFile(phsSocket, pchFilename); } else { g_stats.urlProcessCount++; switch(phsSocket->hcsSource){ case HTTPSRC_FILE: // check type of file requested phsSocket->hftFileType=_mwGetLocalFilename(phsSocket->pucData,pchFilename,128); // send specified file _mwStartSendFile(phsSocket, pchFilename); break; case HTTPSRC_MEM: _mwStartSendMemoryData(phsSocket); break; default: _mwCloseSocket(phsSocket); return; } } g_stats.reqGetCount++; break;#ifdef HTTPPOST case HTTPREQTYPE_POST: // http POST .... _mwProcessPost(phsSocket); g_stats.reqPostCount++; break;#endif default: DEBUG("Error! Http unknown request %s\n",phsSocket->pucRequest); // close connection _mwCloseSocket(phsSocket); } } else if (sLength<0) { _mwCloseSocket(phsSocket); return; } }} // end of _mwProcessSocket////////////////////////////////////////////////////////////////////////////// _mwCloseSocket// Close an open connection////////////////////////////////////////////////////////////////////////////void _mwCloseSocket(HttpSocket* phsSocket){ if (phsSocket->hssState != HTTPSOCKETSTATE_NOTINUSE){ if (phsSocket->iSocket != 0) { DEBUG("Http socket %d closed\n\n",phsSocket->iSocket);#ifdef WIN32 closesocket(phsSocket->iSocket);#else close(phsSocket->iSocket);#endif phsSocket->iSocket = -1; } if (phsSocket->pucData != NULL) { free(phsSocket->pucData); phsSocket->pucData=NULL; } if (phsSocket->iFile > 0) { close(phsSocket->iFile); } if (phsSocket->pxMultipartInfo != NULL) { int i; for (i=0;i<phsSocket->pxMultipartInfo->pp.iNumParams;i++) { free(phsSocket->pxMultipartInfo->pp.stParams[i].pchParamName); free(phsSocket->pxMultipartInfo->pp.stParams[i].pchParamValue); } free(phsSocket->pxMultipartInfo); } memset(phsSocket, 0, sizeof(*phsSocket)); phsSocket->hssState=HTTPSOCKETSTATE_NOTINUSE; } else { DEBUG("Warning : closing a http socket (phsSkt=%lx) that is already closed ! \n",(DWORD)phsSocket); }} // end of _mwCloseSocketvoid _mwSendMemoryChunk(HttpSocket* phsSocket){ int iBytesWritten; if (phsSocket->bHeaderSent) { if (phsSocket->iDataLength>0) { iBytesWritten=send(phsSocket->iSocket, phsSocket->pucData, phsSocket->iDataLength, 0); } _mwCloseSocket(phsSocket); } else { _mwSendHttpHeader(phsSocket,phsSocket->iDataLength); }}////////////////////////////////////////////////////////////////////////////// _mwStartSendMemoryData// Send memory content////////////////////////////////////////////////////////////////////////////int _mwStartSendMemoryData(HttpSocket* phsSocket){ phsSocket->hssState=HTTPSOCKETSTATE_SENDING; // and reset expiration timer phsSocket->lExpirationTime=gettime()+HTTPEXPIRATIONTIME; return 1;}////////////////////////////////////////////////////////////////////////////// _mwStartSendFile// Setup for sending of a file////////////////////////////////////////////////////////////////////////////void _mwStartSendFile(HttpSocket* phsSocket, char* pchFilename){#ifdef HTTPAUTH // check if authenticated if (FALSE == _mwCheckAuthentication(phsSocket)) { // Not authenticated if (phsSocket->hftFileType==HTTPFILETYPE_HTML) { // send password page only pchFilename=g_chPasswordPage; } }#endif // open filename phsSocket->iFile=open(pchFilename, phsSocket->bSubstitutionNeeded?O_RDONLY:O_RDONLY|0x8000); // set state to SENDING (actual sending will occur on next select) phsSocket->hssState=HTTPSOCKETSTATE_SENDING; // and reset expiration timer phsSocket->lExpirationTime=gettime()+HTTPEXPIRATIONTIME;} // end of _mwStartSendFileint _mwSendHttpHeader(HttpSocket* phsSocket, int iContentLength){ unsigned char ucHeader[HTTPHEADERSIZE]; ssize_t sBytesWritten; int iHdrSize; // build http header iHdrSize=sprintf(ucHeader,HTTPHEADER_OK,iContentLength,pchFileTypeTable[phsSocket->hftFileType]); if (phsSocket->iDataLength && HTTPHEADERSIZE-iHdrSize>iContentLength) { // embed content in header memcpy(ucHeader+iHdrSize,phsSocket->pucData,phsSocket->iDataLength); iHdrSize+=phsSocket->iDataLength; } // send http header sBytesWritten=send(phsSocket->iSocket, ucHeader, iHdrSize, 0); if (sBytesWritten!=iHdrSize) { // failed to send header (socket may have been closed by peer) DEBUG("Http failed to send header on %d, %d of %d sent\n", phsSocket->iSocket,(int)sBytesWritten, (int)strlen(ucHeader)); _mwCloseSocket(phsSocket); return 0; } phsSocket->bHeaderSent=TRUE; DEBUG("Http header sent on socket %d\n", phsSocket->iSocket); if (phsSocket->iDataLength==0) { DEBUG("Content sent with header\n"); _mwCloseSocket(phsSocket); } return 1;}////////////////////////////////////////////////////////////////////////////// _mwSendFileChunk// Send a chunk of a file////////////////////////////////////////////////////////////////////////////void _mwSendFileChunk(HttpSocket* phsSocket){ // check if file open if (phsSocket->iFile>0) { if (!phsSocket->bHeaderSent) { off_t ofFileSize; // get file length ofFileSize=lseek(phsSocket->iFile,0,SEEK_END); if (ofFileSize<0) { DEBUG("Error! Http could not access file\n"); // close connection _mwCloseSocket(phsSocket); return; } lseek(phsSocket->iFile,0,SEEK_SET); DEBUG("Http file size is %d\n",(int)ofFileSize); // artificially increase file size for substituted files phsSocket->iExpansionLeft= (phsSocket->bSubstitutionNeeded)?HTTPSUBSTEXPANSION:0; ofFileSize+=phsSocket->iExpansionLeft; // load first chunk of file phsSocket->iDataLength=_mwLoadFileChunk(phsSocket, phsSocket->iBufferLength); // build and send header _mwSendHttpHeader(phsSocket,ofFileSize); g_stats.fileSentCount++; g_stats.fileSentBytes+=ofFileSize; } else { int iBytesWritten; if(phsSocket->pucData != NULL){ // send a chunk of data iBytesWritten=send(phsSocket->iSocket, phsSocket->pucData, phsSocket->iDataLength, 0); if (iBytesWritten>0) { DEBUG("Http sent %d bytes of file on socket %d\n", iBytesWritten,phsSocket->iSocket); phsSocket->iDataLength-=iBytesWritten; if (phsSocket->iDataLength<=0) { int iBytesRead; // used all buffered data - load next chunk of file iBytesRead=_mwLoadFileChunk(phsSocket, min(phsSocket->iBufferLength, HTTPMAXFILECHUNK)); if (iBytesRead>0) { phsSocket->iDataLength=iBytesRead; } else { // end of file if (phsSocket->bSubstitutionNeeded) { // finished substituted file. Need to pad with expansion // bytes memset(phsSocket->pucData,0x0d,phsSocket->iBufferLength); if (phsSocket->iExpansionLeft>0) { phsSocket->iDataLength=min(phsSocket->iExpansionLeft, phsSocket->iBufferLength); phsSocket->iExpansionLeft-=phsSocket->iDataLength; DEBUG("Sending %d expansion filler bytes\n", phsSocket->iDataLength); } else { _mwCloseSocket(phsSocket); } } else { // finished regular file _mwCloseSocket(phsSocket); } } } else { // move remaining data to start of buffer memmove(phsSocket->pucData, phsSocket->pucData+iBytesWritten, phsSocket->iDataLength); } } else if (iBytesWritten<=0) { // close connection DEBUG("Connection closed by client for socket %d\n",phsSocket->iSocket); _mwCloseSocket(phsSocket); return; } } } } else { // send file not found header phsSocket->iDataLength=sprintf(phsSocket->pucData,HTTPHEADER_MISSING,VER_MAJOR,VER_MINOR); send(phsSocket->iSocket, phsSocket->pucData, phsSocket->iDataLength, 0); DEBUG("Error! Http file not found\n"); // close connection _mwCloseSocket(phsSocket); }} // end of _mwSendFileChunk////////////////////////////////////////////////////////////////////////////// _mwLoadFileChunk// load and substitute a file chunk////////////////////////////////////////////////////////////////////////////int _mwLoadFileChunk(HttpSocket* phsSocket, int iChunkBufferSize){ int iReturnBytes=0; ssize_t sBytesRead; if (phsSocket->bSubstitutionNeeded) { int iBytesUsed; // substituted file - read smaller chunk sBytesRead=read(phsSocket->iFile,phsSocket->pucData, iChunkBufferSize-HTTPSUBSTEXPANSION); ASSERT((int)sBytesRead<=iChunkBufferSize-HTTPSUBSTEXPANSION); if (sBytesRead>0) { iReturnBytes=_mwSubstVariables(phsSocket->pucData, sBytesRead, iChunkBufferSize, &iBytesUsed); ASSERT(iBytesUsed<=(int)sBytesRead); // update expansion left phsSocket->iExpansionLeft-=(iReturnBytes-iBytesUsed); // update file pointer lseek(phsSocket->iFile,iBytesUsed-sBytesRead,SEEK_CUR); } } else { // normal file sBytesRead=read(phsSocket->iFile,phsSocket->pucData, iChunkBufferSize); ASSERT((int)sBytesRead<=iChunkBufferSize); iReturnBytes=sBytesRead; } return iReturnBytes;}////////////////////////////////////////////////////////////////////////////// _mwFindMultipartBoundary// Searches a memory buffer for a multi-part boundary string////////////////////////////////////////////////////////////////////////////OCTET* _mwFindMultipartBoundary(OCTET *poHaystack, int iHaystackSize, OCTET *poNeedle){ int i; int iNeedleLength = strlen(poNeedle); ASSERT(iNeedleLength > 0); for (i=0; i <= (iHaystackSize-iNeedleLength-2); i++){ if (*(poHaystack+i)==0x0d && *(poHaystack+i+1)==0x0a && memcmp(poHaystack+i+2, poNeedle, iNeedleLength) == 0) { return (poHaystack+i); } } return NULL;}////////////////////////////////////////////////////////////////////////////// _mwSendRawDataChunk// Send a chunk of a raw data block////////////////////////////////////////////////////////////////////////////void _mwSendRawDataChunk(HttpSocket* phsSocket){ ssize_t sBytesWritten; ASSERT(phsSocket->bRawDataSend); ASSERT(phsSocket->pucData!=NULL); if (!phsSocket->bHeaderSent) { // build and send header _mwSendHttpHeader(phsSocket,phsSocket->iDataLength); } else { // send a chunk of data ASSERT(phsSocket->iSocket != 0 ); ASSERT(phsSocket->pucData != NULL); if (phsSocket->iDataLength==0) { _mwCloseSocket(phsSocket); return; } sBytesWritten=send(phsSocket->iSocket, phsSocket->pucData, phsSocket->iDataLength, 0); if (sBytesWritten<0) { // failure - close connection _mwCloseSocket(phsSocket); return; } else { DEBUG("Http sent %d bytes of raw data on socket %d\n", (int)sBytesWritten,phsSocket->iSocket); phsSocket->iDataLength-=sBytesWritten; if (phsSocket->iDataLength<=0) { // used all buffered data - close connection _mwCloseSocket(phsSocket); } else { // move remaining data to start of buffer memmove(phsSocket->pucData, phsSocket->pucData+sBytesWritten, phsSocket->iDataLength); } } }} // end of _mwSendRawDataChunk////////////////////////////////////////////////////////////////////////////// _mwRedirect// Setup for redirect to another file////////////////////////////////////////////////////////////////////////////void _mwRedirect(HttpSocket* phsSocket, char* pchFilename){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -