📄 websocket.cpp
字号:
//// This file is part of the aMule Project.// // Copyright (c) 2004-2008 shakraw ( shakraw@users.sourceforge.net )// Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )// Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )//// Any parts of this program derived from the xMule, lMule or eMule project,// or contributed by third-party developers are copyrighted by their// respective authors.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA//#include "WebSocket.h"#ifdef ENABLE_UPNP# include "UPnPBase.h"#endifCWebSocket::CWebSocket(CWebServerBase *parent){ m_pHead = 0; m_pTail = 0; m_pBuf = new char [4096]; m_dwBufSize = 4096; m_dwRecv = 0; m_dwHttpHeaderLen = 0; m_dwHttpContentLen = 0; m_Cookie = 0; m_IsGet = false; m_IsPost = false; m_pParent = parent; SetEventHandler(*parent, ID_WEBCLIENTSOCKET_ENENT); SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG | wxSOCKET_LOST_FLAG); Notify(true); }void CWebSocket::OnError(){}void CWebSocket::OnLost(){}void CWebSocket::OnInput(){ Read(m_pBuf + m_dwRecv, m_dwBufSize - m_dwRecv); m_dwRecv += LastCount(); while ((m_dwRecv == m_dwBufSize) && (LastCount()!=0) && (!Error())) { // Buffer is too small. Make it bigger. uint32 newsize = m_dwBufSize + (m_dwBufSize >> 1); char* newbuffer = new char[newsize]; char* oldbuffer = m_pBuf; memcpy(newbuffer, oldbuffer, m_dwBufSize); delete[] oldbuffer; m_pBuf = newbuffer; m_dwBufSize = newsize; // And read again Read(m_pBuf + m_dwRecv, m_dwBufSize - m_dwRecv); m_dwRecv += LastCount(); } if (LastCount() == 0) { if (Error()) { if (LastError() != wxSOCKET_WOULDBLOCK) { Close(); return ; } } } m_pBuf[m_dwRecv] = '\0'; // // Check what kind of request is that if ( !m_IsGet && !m_IsPost ) { if ( !strncasecmp(m_pBuf, "GET", 3) ) { m_IsGet = true; } else if ( !strncasecmp(m_pBuf, "POST", 4) ) { m_IsPost = true; } else { // unknown request - close the socket Close(); return ; } } // // RFC1945: // // // "GET" must have last line empty if ( m_IsGet ) { if ( !strncasecmp(m_pBuf + m_dwRecv - 4, "\r\n\r\n", 4) ) { // // Process request OnRequestReceived(m_pBuf, 0, 0); OnOutput(); } } // // "POST" have "Content-Length" if ( m_IsPost ) { char *cont_len = strstr(m_pBuf, "Content-Length"); // do we have received all the line ? if ( cont_len && strstr(cont_len, "\r\n\r\n") ) { cont_len += strlen("Content-Length:"); // can be white space following while ( isspace(*cont_len) ) cont_len++; int len = atoi(cont_len); if ( !len ) { Close(); return ; } // do we have all of data ? char *cont = strstr(m_pBuf, "\r\n\r\n"); cont += 4; if ( cont - m_pBuf + len <= (int)m_dwRecv ) { OnRequestReceived(m_pBuf, cont, len); OnOutput(); } } }}void CWebSocket::OnOutput(){ while (m_pHead && m_pHead->m_pToSend) { Write(m_pHead->m_pToSend, m_pHead->m_dwSize); uint32 nRes = LastCount(); if (nRes >= m_pHead->m_dwSize) { // erase this chunk CChunk* pNext = m_pHead->m_pNext; delete m_pHead; if (!(m_pHead = pNext)) { m_pTail = NULL; } } else { if ((nRes > 0) && (!Error())) { m_pHead->m_pToSend += nRes; m_pHead->m_dwSize -= nRes; } else { if (Error()) { if (LastError() != wxSOCKET_WOULDBLOCK) { Close(); break; } } } } }}void CWebSocket::OnRequestReceived(char* pHeader, char* pData, uint32 dwDataLen){ bool is_post = false; if ( strncmp(pHeader, "GET", 3) == 0 ) { } else if ( strncmp(pHeader, "POST", 4) == 0 ) { is_post = true; } else { // invalid request return ; } char *path = strchr(pHeader, ' '); if ( !path ) { return; } *path++ = 0; pHeader = strchr(path, ' '); if ( !pHeader ) { return; } *pHeader++ = 0; wxString sURL(char2unicode(path)); if ( is_post ) { wxString sData(char2unicode(pData)); sURL += wxT("?") + sData.Left(dwDataLen); } // // Find session cookie. // int sessid = 0; char *current_cookie = strstr(pHeader, "Cookie: "); if ( current_cookie ) { current_cookie = strstr(current_cookie, "amuleweb_session_id"); if ( current_cookie ) { char *value = strchr(current_cookie, '='); if ( value ) { sessid = atoi(++value); } } } ThreadData Data = { CParsedUrl(sURL), sURL, sessid, this }; wxString sFile = Data.parsedURL.File(); if (sFile.Length() > 4 ) { wxString url_ext = sFile.Right( sFile.Length() - sFile.Find('.', true) ).MakeLower(); if ( (url_ext==wxT(".gif")) || (url_ext==wxT(".jpg")) || (url_ext==wxT(".ico")) || (url_ext==wxT(".png")) || (url_ext==wxT(".bmp")) || (url_ext==wxT(".jpeg")) ) { m_pParent->ProcessImgFileReq(Data); } else { m_pParent->ProcessURL(Data); } } else { m_pParent->ProcessURL(Data); } // // Done processing, reset state // m_dwRecv = 0; m_IsGet = 0; m_IsPost = 0;}void CWebSocket::SendContent(const char* szStdResponse, const void* pContent, uint32 dwContentSize) { char szBuf[0x1000]; // 0x1000 is safe because it's just used for the header int nLen = snprintf(szBuf, sizeof(szBuf), "HTTP/1.1 200 OK\r\n%sContent-Length: %d\r\n\r\n", szStdResponse, dwContentSize); SendData(szBuf, nLen); SendData(pContent, dwContentSize);}void CWebSocket::SendHttpHeaders(const char* szType, bool use_gzip, uint32 content_len, int session_id){ char szBuf[0x1000]; char cookie[256]; if ( session_id ) { snprintf(cookie, sizeof(cookie), "Set-Cookie: amuleweb_session_id=%d\r\n", session_id); } else { cookie[0] = 0; } snprintf(szBuf, sizeof(szBuf), "HTTP/1.1 200 OK\r\nServer: aMule\r\nPragma: no-cache\r\nExpires: 0\r\n" "Cache-Control: no-cache, no-store, must-revalidate\r\n" "%s" "Connection: close\r\nContent-Type: %s\r\n" "Content-Length: %d\r\n%s\r\n", cookie, szType, content_len, (use_gzip ? "Content-Encoding: gzip\r\n" : "")); SendData(szBuf, strlen(szBuf));}void CWebSocket::SendData(const void* pData, uint32 dwDataSize) { if (!m_pHead) { // try to send it directly Write((const char*) pData, dwDataSize); uint32 nRes = LastCount(); if ((nRes < dwDataSize) && Error() && (LastError() != wxSOCKET_WOULDBLOCK)) { Close(); } else { ((const char*&) pData) += nRes; dwDataSize -= nRes; } } if (dwDataSize) { // push it to our tails CChunk* pChunk = new CChunk; pChunk->m_pNext = NULL; pChunk->m_dwSize = dwDataSize; pChunk->m_pData = new char[dwDataSize]; memcpy(pChunk->m_pData, pData, dwDataSize); // push it to the end of our queue pChunk->m_pToSend = pChunk->m_pData; if (m_pTail) { m_pTail->m_pNext = pChunk; } else { m_pHead = pChunk; } m_pTail = pChunk; }}// File_checked_for_headers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -