📄 ghttp.cpp
字号:
int n; for(n = 0; (szData[n] < '0' || szData[n] > 'f') && n < nSize; n++) { } int nHexStart = n; for( ; szData[n] >= '0' && szData[n] <= 'f' && n < nSize; n++) { } if(n >= nSize) break; // Convert it from hex to an integer int nPow = 1; int nDig; int i; for(i = n - 1; i >= nHexStart; i--) { if(szData[i] >= '0' && szData[i] <= '9') nDig = szData[i] - '0'; else if(szData[i] >= 'a' && szData[i] <= 'f') nDig = szData[i] - 'a' + 10; else if(szData[i] >= 'A' && szData[i] <= 'F') nDig = szData[i] - 'A' + 10; else { nDig = 0; GAssert(false, "expected a hex digit"); } m_nContentSize += (nDig * nPow); nPow *= 16; } for( ; szData[n] != '\n' && n < nSize; n++) { } if(n < nSize && szData[n] == '\n') n++; szData += n; nSize -= n; } if(m_nContentSize == 0) { m_nContentSize = m_pChunkQueue->GetSize(); delete(m_pData); m_pData = (unsigned char*)m_pChunkQueue->DumpToString(); m_bChunked = false; m_bPastHeader = false; if(m_status == Downloading) m_status = Done; break; } else { int nChunkSize = MIN(m_nContentSize, nSize); m_pChunkQueue->Push(szData, nChunkSize); szData += nChunkSize; nSize -= nChunkSize; m_nContentSize -= nChunkSize; } }}// todo: this is a hack--fix it properlyvoid GHttpClient::GimmeWhatYouGot(){ if(m_bChunked) { m_nContentSize = m_pChunkQueue->GetSize(); if(m_nContentSize > 64) { delete(m_pData); m_pData = (unsigned char*)m_pChunkQueue->DumpToString(); m_bChunked = false; m_bPastHeader = false; if(m_status == Downloading) m_status = Done; } } else if(m_nContentSize > 0) { if(m_nDataPos > 64) { if(m_status == Downloading) m_status = Done; m_pData[m_nDataPos] = '\0'; m_bPastHeader = false; m_nContentSize = m_nDataPos; } } else { if(m_pChunkQueue && m_pChunkQueue->GetSize() > 64) { if(m_status == Downloading) m_status = Done; m_nContentSize = m_pChunkQueue->GetSize(); delete(m_pData); m_pData = (unsigned char*)m_pChunkQueue->DumpToString(); m_bPastHeader = false; } }}unsigned char* GHttpClient::GetData(int* pnSize){ if(m_status != Done) { GimmeWhatYouGot(); if(m_status == Done) { //GAssert(false, "todo: why are we giving it out early?"); } } if(m_status != Done) { // it's really not done, so don't return anything [rdp] *pnSize = 0; return NULL; } *pnSize = m_nContentSize; return m_pData;}unsigned char* GHttpClient::DropData(int* pnSize){ unsigned char* pData = GetData(pnSize); if(!pData) return NULL; m_pData = NULL; return pData;}// -----------------------------------------------------------------------class GHttpServerBuffer{public: enum RequestType { None, Get, Post, }; int m_nPos; char m_szLine[MAX_SERVER_LINE_SIZE]; char m_szUrl[MAX_SERVER_LINE_SIZE]; char m_szParams[MAX_SERVER_LINE_SIZE]; RequestType m_eRequestType; int m_nContentLength; GHttpServerBuffer() { m_eRequestType = None; m_nPos = 0; m_nContentLength = 0; } ~GHttpServerBuffer() { }};GHttpServer::GHttpServer(int nPort){ m_pBuffers = new GPointerArray(16); m_pSocket = GSocketServer::HostTCPSocket(nPort); if(!m_pSocket) throw("failed to open port"); m_pQ = new GQueue(); SetContentType("text/html");}GHttpServer::~GHttpServer(){ int nCount = m_pBuffers->GetSize(); int n; for(n = 0; n < nCount; n++) delete((GHttpServerBuffer*)m_pBuffers->GetPointer(n)); delete(m_pBuffers); delete(m_pSocket); delete(m_pQ);}bool GHttpServer::Process(){ int nMessageSize; int nConnection; unsigned char* pMessage; unsigned char* pIn; char c; GHttpServerBuffer* pBuffer; bool bDidSomething = false; while(m_pSocket->GetMessageCount() > 0) { bDidSomething = true; pMessage = m_pSocket->GetNextMessage(&nMessageSize, &nConnection); pIn = pMessage; while(m_pBuffers->GetSize() <= nConnection) m_pBuffers->AddPointer(new GHttpServerBuffer()); pBuffer = (GHttpServerBuffer*)m_pBuffers->GetPointer(nConnection); while(nMessageSize > 0) { c = *pIn; pBuffer->m_szLine[pBuffer->m_nPos++] = c; pIn++; nMessageSize--; if(c == '\n' || pBuffer->m_nPos >= MAX_SERVER_LINE_SIZE - 1) { pBuffer->m_szLine[pBuffer->m_nPos] = '\0'; ProcessLine(nConnection, pBuffer, pBuffer->m_szLine); pBuffer->m_nPos = 0; } } delete(pMessage); } return bDidSomething;}void GHttpServer::ProcessLine(int nConnection, GHttpServerBuffer* pClient, const char* szLine){ OnProcessLine(nConnection, szLine); while(*szLine > '\0' && *szLine <= ' ') szLine++; if(*szLine == '\0') MakeResponse(nConnection, pClient); else if(strnicmp(szLine, "GET ", 4) == 0) { pClient->m_eRequestType = GHttpServerBuffer::Get; const char* szIn = szLine + 4; char* szOut = pClient->m_szUrl; while(*szIn > ' ' && *szIn != '?') { *szOut = *szIn; szIn++; szOut++; } *szOut = '\0'; if(*szIn == '?') { szIn++; szOut = pClient->m_szParams; while(*szIn > ' ') { *szOut = *szIn; szIn++; szOut++; } *szOut = '\0'; } else pClient->m_szParams[0] = '\0'; } else if(strnicmp(szLine, "POST ", 5) == 0) pClient->m_eRequestType = GHttpServerBuffer::Post; else if(strnicmp(szLine, "Content-Length: ", 16) == 0) pClient->m_nContentLength = atoi(szLine + 16);}void GHttpServer::SetContentType(const char* szContentType){ GString::StrCpy(m_szContentType, szContentType, 64);}void GHttpServer::MakeResponse(int nConnection, GHttpServerBuffer* pClient){ if(pClient->m_eRequestType == GHttpServerBuffer::None) return; else if(pClient->m_eRequestType == GHttpServerBuffer::Get) DoGet(pClient->m_szUrl, pClient->m_szParams, m_pQ); else GAssert(false, "only GET is currently supported"); char szPayloadSize[32]; int nPayloadSize = m_pQ->GetSize(); itoa(nPayloadSize, szPayloadSize, 10); // Send the header GQueue q; q.Push("HTTP/1.1 200 OK\r\nContent-Type: "); q.Push(m_szContentType); q.Push("\r\nContent-Length: "); q.Push(szPayloadSize); q.Push("\r\n\r\n"); int nHeaderSize = q.GetSize(); char* szHeader = q.DumpToString(); ArrayHolder<char*> hHeader(szHeader); m_pSocket->Send(szHeader, nHeaderSize, nConnection); // Send the payload m_pQ->Push("\r\n\r\n"); char* szPayload = m_pQ->DumpToString(); ArrayHolder<char*> hPayload(szPayload); m_pSocket->Send(szPayload, nPayloadSize + 4, nConnection);}/*static*/ void GHttpServer::UnescapeUrl(char* szOut, const char* szIn){ int c1, c2, n1, n2; while(*szIn != '\0') { if(*szIn == '%') { szIn++; n1 = *szIn; szIn++; n2 = *szIn; if(n1 >= '0' && n1 <= '9') c1 = n1 - '0'; else if(n1 >= 'a' && n1 <= 'z') c1 = n1 - 'a' + 10; else if(n1 >= 'A' && n1 <= 'Z') c1 = n1 - 'A' + 10; else c1 = 2; if(n2 >= '0' && n2 <= '9') c2 = n2 - '0'; else if(n2 >= 'a' && n2 <= 'z') c2 = n2 - 'a' + 10; else if(n2 >= 'A' && n2 <= 'Z') c2 = n2 - 'A' + 10; else c2 = 0; *szOut = 16 * c1 + c2; } else if(*szIn == '+') *szOut = ' '; else *szOut = *szIn; szIn++; szOut++; } *szOut = '\0';}/*static*/ void GHttpServer::ParseParams(GStringHeap* pStringHeap, GConstStringHashTable* pTable, const char* szParams){ char szTmp[512]; UnescapeUrl(szTmp, szParams); int nNameStart = 0; int nNameLen, nValueStart, nValueLen; while(true) { for(nNameLen = 0; szTmp[nNameStart + nNameLen] != '=' && szTmp[nNameStart + nNameLen] != '\0'; nNameLen++) { } if(szTmp[nNameStart + nNameLen] == '\0') return; nValueStart = nNameStart + nNameLen + 1; for(nValueLen = 0; szTmp[nValueStart + nValueLen] != '&' && szTmp[nValueStart + nValueLen] != '\0'; nValueLen++) { } const char* szName = pStringHeap->Add(&szTmp[nNameStart], nNameLen); const char* szValue = pStringHeap->Add(&szTmp[nValueStart], nValueLen); pTable->Add(szName, szValue); if(szTmp[nValueStart + nValueLen] == '\0') return; nNameStart = nValueStart + nValueLen + 1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -