同步操作将从 伤神小怪兽/HP-Socket 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/** Copyright: JessMA Open Source (ldcsaa@gmail.com)** Author : Bruce Liang* Website : https://github.com/ldcsaa* Project : https://github.com/ldcsaa/HP-Socket* Blog : http://www.cnblogs.com/ldcsaa* Wiki : http://www.oschina.net/p/hp-socket* QQ Group : 44636872, 75375912** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#pragma once#include "SocketHelper.h"#include "HttpCookie.h"#ifdef _HTTP_SUPPORT#include "./common/http/llhttp.h"#include "./common/http/llhttp_url.h"typedef llhttp_t http_parser;typedef llhttp_settings_t http_parser_settings;#define LLHTTP_MAX_ERROR_NUM 23#define LLHTTP_MAX_METHOD_NUM 45/************************************************************************名称:HTTP 全局常量描述:声明 HTTP 组件的公共全局常量************************************************************************/#define HTTP_DEFAULT_PORT 80#define HTTPS_DEFAULT_PORT 443#define HTTP_SCHEMA "http://"#define HTTPS_SCHEMA "https://"#define HTTP_CRLF "\r\n"#define HTTP_PATH_SEPARATOR_CHAR '/'#define HTTP_PATH_SEPARATOR "/"#define HTTP_HEADER_SEPARATOR ": "#define HTTP_COOKIE_SEPARATOR "; "#define HTTP_1_0_STR "HTTP/1.0"#define HTTP_1_1_STR "HTTP/1.1"#define HTTP_HEADER_HOST "Host"#define HTTP_HEADER_COOKIE "Cookie"#define HTTP_HEADER_SET_COOKIE "Set-Cookie"#define HTTP_HEADER_CONTENT_TYPE "Content-Type"#define HTTP_HEADER_CONTENT_LENGTH "Content-Length"#define HTTP_HEADER_CONTENT_ENCODING "Content-Encoding"#define HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding"#define HTTP_HEADER_CONNECTION "Connection"#define HTTP_HEADER_UPGRADE "Upgrade"#define HTTP_HEADER_VALUE_WEB_SOCKET "WebSocket"#define HTTP_CONNECTION_CLOSE_VALUE "close"#define HTTP_CONNECTION_KEEPALIVE_VALUE "keep-alive"#define HTTP_METHOD_POST "POST"#define HTTP_METHOD_PUT "PUT"#define HTTP_METHOD_PATCH "PATCH"#define HTTP_METHOD_GET "GET"#define HTTP_METHOD_DELETE "DELETE"#define HTTP_METHOD_HEAD "HEAD"#define HTTP_METHOD_TRACE "TRACE"#define HTTP_METHOD_OPTIONS "OPTIONS"#define HTTP_METHOD_CONNECT "CONNECT"#define HTTP_MIN_WS_HEADER_LEN 2#define HTTP_MAX_WS_HEADER_LEN 14#define MIN_HTTP_RELEASE_CHECK_INTERVAL ((DWORD)1000)#define MIN_HTTP_RELEASE_DELAY 100#define MAX_HTTP_RELEASE_DELAY (60 * 1000)#define DEFAULT_HTTP_RELEASE_DELAY (3 * 1000)#define DEFAULT_HTTP_VERSION HV_1_1#define DEFAULT_HTTP_SYNC_CONNECT_TIMEOUT 5000#define DEFAULT_HTTP_SYNC_REQUEST_TIMEOUT 10000// ------------------------------------------------------------------------------------------------------------- //enum EnHttpSyncRequestProgress{HSRP_DONE,HSRP_WAITING,HSRP_ERROR,HSRP_CLOSE};struct TDyingConnection{CONNID connID;DWORD killTime;TDyingConnection(CONNID id, DWORD kt = 0): connID (id), killTime (kt == 0 ? ::TimeGetTime() : kt){}static TDyingConnection* Construct(CONNID id, DWORD kt = 0) {return new TDyingConnection(id, kt);}static void Destruct(TDyingConnection* pObj) {if(pObj) delete pObj;}};typedef unordered_multimap<CStringA, CStringA,cstringa_nc_hash_func::hash, cstringa_nc_hash_func::equal_to> THeaderMap;typedef THeaderMap::const_iterator THeaderMapCI;typedef THeaderMap::iterator THeaderMapI;typedef unordered_map<CStringA, CStringA,cstringa_hash_func::hash, cstringa_hash_func::equal_to> TCookieMap;typedef TCookieMap::const_iterator TCookieMapCI;typedef TCookieMap::iterator TCookieMapI;// ------------------------------------------------------------------------------------------------------------- //struct TBaseWSHeader{public:BOOL fin(){return (data >> 7) & 0x1;}void set_fin(BOOL v){data |= ((v ? 1 : 0) << 7);}BYTE rsv(){return (data >> 4) & 0x7;}void set_rsv(BYTE v){data |= ((v & 0x7) << 4);}BYTE code(){return data & 0xF;}void set_code(BYTE v){data |= (v & 0xF);}BOOL mask(){return (data >> 15) & 0x1;}void set_mask(BOOL v){data |= ((v ? 1 : 0) << 15);}BYTE len(){return (data >> 8) & 0x7F;}void set_len(BYTE v){data |= ((v & 0x7F) << 8);}USHORT extlen(){return ntohs((USHORT)(data >> 16));}void set_extlen(USHORT v){data |= (htons(v) << 16);}TBaseWSHeader(const BYTE* p, BOOL bZero = FALSE): data(*(UINT*)p){if(bZero) data = 0;}private:UINT& data;};template<class T> struct TWSContext{public:EnHandleResult Parse(const BYTE* pData, int iLength){ASSERT(pData != nullptr && iLength > 0);EnHandleResult hr = HR_OK;BYTE* pTemp = (BYTE*)pData;int iRemain = iLength;int iMin = 0;while(iRemain > 0){if(m_bHeader){iMin = MIN(m_iHeaderRemain, iRemain);memcpy(m_szHeader + m_iHeaderLen - m_iHeaderRemain, pTemp, iMin);m_iHeaderRemain -= iMin;if(m_iHeaderRemain == 0){TBaseWSHeader bh(m_szHeader);int iLen = bh.len();int iExtLen = iLen < 126 ? 0 : (iLen == 126 ? 2 : 8);int iMaskLen = bh.mask() ? 4 : 0;int iRealHeaderLen = HTTP_MIN_WS_HEADER_LEN + iExtLen + iMaskLen;if(m_iHeaderLen < iRealHeaderLen){m_iHeaderRemain = iRealHeaderLen - m_iHeaderLen;m_iHeaderLen = iRealHeaderLen;}else{if((m_pHttpObj->IsRequest() && iMaskLen == 0) || (!m_pHttpObj->IsRequest() && iMaskLen > 0)){::SetLastError(ERROR_INVALID_DATA);hr = HR_ERROR;break;}m_ullBodyLen = iExtLen == 0 ? iLen : (iExtLen == 2 ? bh.extlen() : NToH64(*(ULONGLONG*)(m_szHeader + HTTP_MIN_WS_HEADER_LEN)));m_ullBodyRemain = m_ullBodyLen;m_lpszMask = iMaskLen > 0 ? m_szHeader + HTTP_MIN_WS_HEADER_LEN + iExtLen : nullptr;hr = m_pHttpObj->on_ws_message_header(bh.fin(), bh.rsv(), bh.code(), m_lpszMask, m_ullBodyLen);if(hr == HR_ERROR)break;if(m_ullBodyLen > 0)m_bHeader = FALSE;else{hr = CompleteMessage();if(hr == HR_ERROR)break;}}}}else{iMin = (int)MIN(m_ullBodyRemain, (ULONGLONG)iRemain);if(m_lpszMask){int iFactor = (m_ullBodyLen - m_ullBodyRemain) & 0x03;for(int i = 0; i < iMin; i++)pTemp[i] = pTemp[i] ^ m_lpszMask[(i + iFactor) & 0x03];}m_ullBodyRemain -= iMin;hr = m_pHttpObj->on_ws_message_body(pTemp, iMin);if(hr == HR_ERROR)break;if(m_ullBodyRemain == 0){hr = CompleteMessage();if(hr == HR_ERROR)break;}}pTemp += iMin;iRemain -= iMin;}return hr;}BOOL GetMessageState(BOOL* lpbFinal, BYTE* lpiReserved, BYTE* lpiOperationCode, LPCBYTE* lpszMask, ULONGLONG* lpullBodyLen, ULONGLONG* lpullBodyRemain){TBaseWSHeader bh(m_szHeader);if(lpbFinal) *lpbFinal = bh.fin();if(lpiReserved) *lpiReserved = bh.rsv();if(lpiOperationCode) *lpiOperationCode = bh.code();if(lpszMask) *lpszMask = m_lpszMask;if(lpullBodyLen) *lpullBodyLen = m_ullBodyLen;if(lpullBodyRemain) *lpullBodyRemain = m_ullBodyRemain;return TRUE;}BOOL CopyData(const TWSContext& src){if(&src == this)return FALSE;memcpy(m_szHeader, src.m_szHeader, HTTP_MAX_WS_HEADER_LEN);if(src.m_lpszMask)m_lpszMask = m_szHeader + (src.m_lpszMask - src.m_szHeader);elsem_lpszMask = nullptr;m_ullBodyLen = src.m_ullBodyLen;m_ullBodyRemain = src.m_ullBodyRemain;return TRUE;}public:TWSContext(T* pHttpObj) : m_pHttpObj(pHttpObj){Reset();}private:EnHandleResult CompleteMessage(){EnHandleResult hr = m_pHttpObj->on_ws_message_complete();Reset();return hr;}void Reset(){m_bHeader = TRUE;m_lpszMask = nullptr;m_iHeaderLen = HTTP_MIN_WS_HEADER_LEN;m_iHeaderRemain = HTTP_MIN_WS_HEADER_LEN;m_ullBodyLen = 0;m_ullBodyRemain = 0;}private:T* m_pHttpObj;BYTE m_szHeader[HTTP_MAX_WS_HEADER_LEN];const BYTE* m_lpszMask;BOOL m_bHeader;int m_iHeaderLen;int m_iHeaderRemain;ULONGLONG m_ullBodyLen;ULONGLONG m_ullBodyRemain;};// ------------------------------------------------------------------------------------------------------------- ///* Http 上下文结构 */template<class T, class S> struct THttpObjT{public:EnHandleResult Execute(const BYTE* pData, int iLength){ASSERT(pData != nullptr && iLength > 0);if(m_parser.upgrade){if(m_enUpgrade == HUT_WEB_SOCKET){if(m_pwsContext != nullptr)return m_pwsContext->Parse(pData, iLength);}else{return m_pContext->DoFireSuperReceive(m_pSocket, pData, iLength);}}EnHandleResult hr = HR_OK;llhttp_errno rs = ::llhttp_execute(&m_parser, (LPCSTR)pData, iLength);if(rs == HPE_OK)ASSERT(m_parser.error_pos == nullptr);else if(rs == HPE_PAUSED_UPGRADE){int iPased = (m_parser.error_pos == nullptr) ? iLength : (int)((const BYTE*)(m_parser.error_pos) - pData);hr = Upgrade(pData, iLength, iPased);}else{m_pContext->FireParseError(m_pSocket, m_parser.error, ::llhttp_get_error_reason(&m_parser));hr = HR_ERROR;}return hr;}void CheckBodyIdentityEof(){if(!m_parser.upgrade)::llhttp_finish(&m_parser);}static int on_message_begin(http_parser* p){THttpObjT* pSelf = Self(p);pSelf->ResetHeaderState(FALSE, FALSE);return pSelf->m_pContext->FireMessageBegin(pSelf->m_pSocket);}static int on_url(http_parser* p, const char* at, size_t length){Self(p)->AppendBuffer(at, length);return HPR_OK;}static int on_url_complete(llhttp_t* p){THttpObjT* pSelf = Self(p);EnHttpParseResult hpr = pSelf->ParseUrl();if(hpr == HPR_OK)hpr = pSelf->m_pContext->FireRequestLine(pSelf->m_pSocket, ::llhttp_method_name((llhttp_method_t)p->method), pSelf->GetBuffer());pSelf->ResetBuffer();return hpr;}static int on_status(http_parser* p, const char* at, size_t length){Self(p)->AppendBuffer(at, length);return HPR_OK;}static int on_status_complete(llhttp_t* p){THttpObjT* pSelf = Self(p);EnHttpParseResult hpr = pSelf->m_pContext->FireStatusLine(pSelf->m_pSocket, p->status_code, pSelf->GetBuffer());pSelf->ResetBuffer();return hpr;}static int on_header_field(http_parser* p, const char* at, size_t length){Self(p)->AppendBuffer(at, length);return HPR_OK;}static int on_header_field_complete(llhttp_t* p){THttpObjT* pSelf = Self(p);pSelf->m_strCurHeader = pSelf->GetBuffer();pSelf->ResetBuffer();return HPR_OK;}static int on_header_value(http_parser* p, const char* at, size_t length){Self(p)->AppendBuffer(at, length);return HPR_OK;}static int on_header_value_complete(llhttp_t* p){THttpObjT* pSelf = Self(p);pSelf->m_headers.emplace(move(THeaderMap::value_type(pSelf->m_strCurHeader, pSelf->GetBuffer())));EnHttpParseResult hpr = pSelf->m_pContext->FireHeader(pSelf->m_pSocket, pSelf->m_strCurHeader, pSelf->GetBuffer());if(hpr != HPR_ERROR && !pSelf->GetBufferRef().IsEmpty()){if(pSelf->m_bRequest && pSelf->m_strCurHeader.CompareNoCase(HTTP_HEADER_COOKIE) == 0)hpr = pSelf->ParseCookie();else if(!pSelf->m_bRequest && pSelf->m_strCurHeader.CompareNoCase(HTTP_HEADER_SET_COOKIE) == 0)hpr = pSelf->ParseSetCookie();}pSelf->ResetBuffer();return hpr;}static int on_headers_complete(http_parser* p){THttpObjT* pSelf = Self(p);pSelf->CheckUpgrade();pSelf->ResetHeaderBuffer();EnHttpParseResult rs = pSelf->m_pContext->FireHeadersComplete(pSelf->m_pSocket);if(!pSelf->m_bRequest && pSelf->GetMethodInt() == HTTP_HEAD && rs == HPR_OK)rs = HPR_SKIP_BODY;return rs;}static int on_body(http_parser* p, const char* at, size_t length){THttpObjT* pSelf = Self(p);return pSelf->m_pContext->FireBody(pSelf->m_pSocket, (const BYTE*)at, (int)length);}static int on_chunk_header(http_parser* p){THttpObjT* pSelf = Self(p);return pSelf->m_pContext->FireChunkHeader(pSelf->m_pSocket, (int)p->content_length);}static int on_chunk_complete(http_parser* p){THttpObjT* pSelf = Self(p);return pSelf->m_pContext->FireChunkComplete(pSelf->m_pSocket);}static int on_message_complete(http_parser* p){THttpObjT* pSelf = Self(p);return pSelf->m_pContext->FireMessageComplete(pSelf->m_pSocket);}EnHandleResult on_ws_message_header(BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen){return m_pContext->FireWSMessageHeader(m_pSocket, bFinal, iReserved, iOperationCode, lpszMask, ullBodyLen);}EnHandleResult on_ws_message_body(const BYTE* pData, int iLength){return m_pContext->FireWSMessageBody(m_pSocket, pData, iLength);}EnHandleResult on_ws_message_complete(){return m_pContext->FireWSMessageComplete(m_pSocket);}private:EnHandleResult Upgrade(const BYTE* pData, int iLength, int iPased){ASSERT(m_parser.upgrade);if(m_pContext->FireUpgrade(m_pSocket, m_enUpgrade) != HPR_OK)return HR_ERROR;ResetHeaderState();if(m_enUpgrade == HUT_WEB_SOCKET)m_pwsContext = new TWSContext<THttpObjT<T, S>>(this);if(iPased < iLength)return Execute(pData + iPased, iLength - iPased);return HR_OK;}void CheckUpgrade(){if(!m_parser.upgrade)return;if(m_bRequest && m_parser.method == HTTP_CONNECT)m_enUpgrade = HUT_HTTP_TUNNEL;else{LPCSTR lpszValue;if(GetHeader(HTTP_HEADER_UPGRADE, &lpszValue) && stricmp(HTTP_HEADER_VALUE_WEB_SOCKET, lpszValue) == 0)m_enUpgrade = HUT_WEB_SOCKET;elsem_enUpgrade = HUT_UNKNOWN;}}EnHttpParseResult ParseUrl(){http_parser_url url = {0};BOOL isConnect = m_parser.method == HTTP_CONNECT;int rs = ::http_parser_parse_url(m_strBuffer, m_strBuffer.GetLength(), isConnect, &url);if(rs != HPE_OK){/*m_parser.error = HPE_INVALID_URL;m_parser.reason = "Parse url fail";*/return HPR_ERROR;}m_usUrlFieldSet = url.field_set;LPCSTR lpszBuffer = m_strBuffer;for(int i = 0; i < UF_MAX; i++){if((url.field_set & (1 << i)) != 0)m_pstrUrlFileds[i].SetString((lpszBuffer + url.field_data[i].off), url.field_data[i].len);}return HPR_OK;}EnHttpParseResult ParseCookie(){int i = 0;do{CStringA tk = m_strBuffer.Tokenize(COOKIE_FIELD_SEP, i);if(i == -1)break;int j = tk.Trim().Find(COOKIE_KV_SEP_CHAR);if(j <= 0)continue;/*{m_parser.http_errno = HPE_INVALID_HEADER_TOKEN;return HPR_ERROR;}*/AddCookie(tk.Left(j), tk.Mid(j + 1));} while(TRUE);return HPR_OK;}EnHttpParseResult ParseSetCookie(){CCookieMgr* pCookieMgr = m_pContext->GetCookieMgr();if(pCookieMgr == nullptr)return HPR_OK;LPCSTR lpszDomain = GetDomain();LPCSTR lpszPath = GetPath();unique_ptr<CCookie> pCookie(CCookie::FromString(m_strBuffer, lpszDomain, lpszPath));if(pCookie == nullptr)return HPR_ERROR;if(pCookie->Match(lpszDomain, lpszPath, TRUE, m_pContext->IsSecure())){if(pCookie->IsExpired())DeleteCookie(pCookie->name);elseAddCookie(pCookie->name, pCookie->value);}if(pCookieMgr->IsEnableThirdPartyCookie() || pCookie->IsSameDomain(lpszDomain))pCookieMgr->SetCookie(*pCookie);return HPR_OK;}public:int GetCount() const {return 0;}DWORD GetFreeTime() const {return m_dwFreeTime;}void SetFree() {m_dwFreeTime = ::TimeGetTime();}BOOL IsRequest() {return m_bRequest;}BOOL IsUpgrade() {return m_parser.upgrade;}BOOL IsKeepAlive() {return ::llhttp_should_keep_alive(&m_parser);}USHORT GetVersion() {return MAKEWORD(m_parser.http_major, m_parser.http_minor);}ULONGLONG GetContentLength() {return m_parser.content_length;}int GetMethodInt() {return m_bRequest ? m_parser.method : m_sRequestMethod;}USHORT GetUrlFieldSet() {return m_usUrlFieldSet;}USHORT GetStatusCode() {return m_parser.status_code;}EnHttpUpgradeType GetUpgradeType() {return m_enUpgrade;}THeaderMap& GetHeaderMap() {return m_headers;}TCookieMap& GetCookieMap() {return m_cookies;}BOOL HasReleased() {return m_bReleased;}void Release() {m_bReleased = TRUE;}LPCSTR GetMethod(){int iMethod = GetMethodInt();if(iMethod >= 0 && iMethod <= LLHTTP_MAX_METHOD_NUM)return ::llhttp_method_name((llhttp_method)iMethod);return nullptr;}LPCSTR GetContentType(){LPCSTR lpszValue = nullptr;GetHeader(HTTP_HEADER_CONTENT_TYPE, &lpszValue);return lpszValue;}LPCSTR GetContentEncoding(){LPCSTR lpszValue = nullptr;GetHeader(HTTP_HEADER_CONTENT_ENCODING, &lpszValue);return lpszValue;}LPCSTR GetTransferEncoding(){LPCSTR lpszValue = nullptr;GetHeader(HTTP_HEADER_TRANSFER_ENCODING, &lpszValue);return lpszValue;}LPCSTR GetHost(){LPCSTR lpszValue = nullptr;GetHeader(HTTP_HEADER_HOST, &lpszValue);return lpszValue;}USHORT GetParseErrorCode(LPCSTR* lpszErrorDesc = nullptr){USHORT usError = (USHORT)m_parser.error;if(lpszErrorDesc){if(usError == HPE_OK)*lpszErrorDesc = ::llhttp_errno_name((llhttp_errno_t)usError);else{*lpszErrorDesc = ::llhttp_get_error_reason(&m_parser);if(::IsStrEmptyA(*lpszErrorDesc) && usError <= LLHTTP_MAX_ERROR_NUM)*lpszErrorDesc = ::llhttp_errno_name((llhttp_errno_t)usError);}}return usError;}LPCSTR GetUrlField(EnHttpUrlField enField){ASSERT(m_bRequest && enField < HUF_MAX);if(!m_bRequest || enField >= HUF_MAX)return nullptr;return m_pstrUrlFileds[enField];}LPCSTR GetPath(){if(m_bRequest)return GetUrlField(HUF_PATH);elsereturn *m_pstrRequestPath;}LPCSTR GetDomain(){ASSERT(!m_bRequest);return m_pContext->GetRemoteDomain(m_pSocket);}LPCSTR GetRequestPath(){if(m_bRequest)return nullptr;return *m_pstrRequestPath;}void SetRequestPath(LPCSTR lpszMethod, LPCSTR lpszPath){ASSERT(!m_bRequest);if(m_bRequest)return;*m_pstrRequestPath = lpszPath;#define HTTP_METHOD_GEN(NUM, NAME, STRING) else if(stricmp(lpszMethod, #STRING) == 0) m_sRequestMethod = HTTP_##NAME;if(::IsStrEmptyA(lpszMethod)) m_sRequestMethod = -1;HTTP_METHOD_MAP(HTTP_METHOD_GEN)elsem_sRequestMethod = -1;#undef HTTP_METHOD_GEN}BOOL GetHeader(LPCSTR lpszName, LPCSTR* lpszValue){ASSERT(lpszName);BOOL isOK = FALSE;THeaderMapCI it = m_headers.find(lpszName);if(it != m_headers.end()){*lpszValue = it->second;isOK = TRUE;}return isOK;}BOOL GetHeaders(LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount){ASSERT(lpszName);if(lpszValue == nullptr || dwCount == 0){dwCount = (DWORD)m_headers.count(lpszName);return FALSE;}pair<THeaderMapCI, THeaderMapCI> range = m_headers.equal_range(lpszName);THeaderMapCI it = range.first;DWORD dwIndex = 0;while(it != range.second){if(dwIndex < dwCount)lpszValue[dwIndex] = it->second;++dwIndex;++it;}BOOL isOK = (dwIndex > 0 && dwIndex <= dwCount);dwCount = dwIndex;return isOK;}BOOL GetAllHeaders(THeader lpHeaders[], DWORD& dwCount){DWORD dwSize = (DWORD)m_headers.size();if(lpHeaders == nullptr || dwCount == 0 || dwSize == 0 || dwSize > dwCount){dwCount = dwSize;return FALSE;}DWORD dwIndex = 0;for(THeaderMapCI it = m_headers.begin(), end = m_headers.end(); it != end; ++it, ++dwIndex){lpHeaders[dwIndex].name = it->first;lpHeaders[dwIndex].value = it->second;}dwCount = dwSize;return TRUE;}BOOL GetAllHeaderNames(LPCSTR lpszName[], DWORD& dwCount){DWORD dwSize = (DWORD)m_headers.size();if(lpszName == nullptr || dwCount == 0 || dwSize == 0 || dwSize > dwCount){dwCount = dwSize;return FALSE;}DWORD dwIndex = 0;for(THeaderMapCI it = m_headers.begin(), end = m_headers.end(); it != end; ++it, ++dwIndex)lpszName[dwIndex] = it->first;dwCount = dwSize;return TRUE;}BOOL AddCookie(LPCSTR lpszName, LPCSTR lpszValue, BOOL bRelpace = TRUE){ASSERT(lpszName);TCookieMapI it = m_cookies.find(lpszName);if(it == m_cookies.end())return m_cookies.emplace(move(TCookieMap::value_type(lpszName, lpszValue))).second;BOOL isOK = FALSE;if(bRelpace){it->second = lpszValue;isOK = TRUE;}return isOK;}BOOL DeleteCookie(LPCSTR lpszName){ASSERT(lpszName);return m_cookies.erase(lpszName) > 0;}void DeleteAllCookies(){m_cookies.clear();}BOOL GetCookie(LPCSTR lpszName, LPCSTR* lpszValue){ASSERT(lpszName);BOOL isOK = FALSE;TCookieMapCI it = m_cookies.find(lpszName);if(it != m_cookies.end()){*lpszValue = it->second;isOK = TRUE;}return isOK;}BOOL GetAllCookies(TCookie lpCookies[], DWORD& dwCount){DWORD dwSize = (DWORD)m_cookies.size();if(lpCookies == nullptr || dwCount == 0 || dwSize == 0 || dwSize > dwCount){dwCount = dwSize;return FALSE;}DWORD dwIndex = 0;for(TCookieMapCI it = m_cookies.begin(), end = m_cookies.end(); it != end; ++it, ++dwIndex){lpCookies[dwIndex].name = it->first;lpCookies[dwIndex].value = it->second;}dwCount = dwSize;return TRUE;}BOOL ReloadCookies(){CCookieMgr* pCookieMgr = m_pContext->GetCookieMgr();if(pCookieMgr == nullptr)return TRUE;DeleteAllCookies();CCookieSet cookies;if(!pCookieMgr->GetCookies(cookies, GetDomain(), GetPath(), TRUE, m_pContext->IsSecure()))return FALSE;for(CCookieSetCI it = cookies.begin(), end = cookies.end(); it != end; ++it)AddCookie(it->name, it->value);return TRUE;}BOOL GetWSMessageState(BOOL* lpbFinal, BYTE* lpiReserved, BYTE* lpiOperationCode, LPCBYTE* lpszMask, ULONGLONG* lpullBodyLen, ULONGLONG* lpullBodyRemain){if(!m_pwsContext)return FALSE;return m_pwsContext->GetMessageState(lpbFinal, lpiReserved, lpiOperationCode, lpszMask, lpullBodyLen, lpullBodyRemain);}public:THttpObjT (BOOL bRequest, T* pContext, S* pSocket): m_pContext (pContext), m_pSocket (pSocket), m_bRequest (bRequest), m_bValid (FALSE), m_bReleased (FALSE), m_dwFreeTime (0), m_usUrlFieldSet (m_bRequest ? 0 : -1), m_pstrUrlFileds (nullptr), m_enUpgrade (HUT_NONE), m_pwsContext (nullptr){if(m_bRequest)m_pstrUrlFileds = new CStringA[HUF_MAX];elsem_pstrRequestPath = new CStringA;ResetParser();}~THttpObjT(){if(m_bRequest)delete[] m_pstrUrlFileds;elsedelete m_pstrRequestPath;ReleaseWSContext();}static THttpObjT* Construct(BOOL bRequest, T* pContext, S* pSocket){return new THttpObjT(bRequest, pContext, pSocket);}static void Destruct(THttpObjT* pHttpObj){if(pHttpObj) delete pHttpObj;}void Reset(BOOL bValid = FALSE){ResetParser();ResetHeaderState();ReleaseWSContext();m_bValid = bValid;m_bReleased = FALSE;m_enUpgrade = HUT_NONE;m_dwFreeTime = 0;}void Renew(T* pContext, S* pSocket){Reset(TRUE);m_pContext = pContext;m_pSocket = pSocket;}void SetValid(BOOL bValid = TRUE){m_bValid = bValid;}BOOL IsValid(){return m_bValid;}BOOL CopyData(const THttpObjT& src){if(&src == this)return FALSE;if(m_bRequest != src.m_bRequest)return FALSE;void* p = m_parser.data;m_parser = src.m_parser;m_parser.data = p;m_headers = src.m_headers;m_cookies = src.m_cookies;if(m_bRequest){m_usUrlFieldSet = src.m_usUrlFieldSet;for(int i = 0;i < HUF_MAX; i++)m_pstrUrlFileds[i] = src.m_pstrUrlFileds[i];}else{m_sRequestMethod = src.m_sRequestMethod;*m_pstrRequestPath = *src.m_pstrRequestPath;}m_enUpgrade = src.m_enUpgrade;return TRUE;}BOOL CopyWSContext(const THttpObjT& src){if(&src == this)return FALSE;if(m_bRequest != src.m_bRequest)return FALSE;if(!src.m_pwsContext && !m_pwsContext);else if(!src.m_pwsContext && m_pwsContext){delete m_pwsContext;m_pwsContext = nullptr;}else{if(!m_pwsContext)m_pwsContext = new TWSContext<THttpObjT<T, S>>(this);m_pwsContext->CopyData(*src.m_pwsContext);}return TRUE;}private:void ResetParser(){::llhttp_init(&m_parser, m_bRequest ? HTTP_REQUEST : HTTP_RESPONSE, &sm_settings);m_parser.data = this;}void ResetHeaderState(BOOL bClearCookies = TRUE, BOOL bResetRequestData = TRUE){if(m_bRequest){if(m_usUrlFieldSet != 0){m_usUrlFieldSet = 0;for(int i = 0; i < HUF_MAX; i++)m_pstrUrlFileds[i].Empty();}}else{if(bResetRequestData){m_sRequestMethod = -1;m_pstrRequestPath->Empty();}}if(m_bRequest || bClearCookies)DeleteAllCookies();m_headers.clear();ResetHeaderBuffer();}void ResetHeaderBuffer(){ResetBuffer();m_strCurHeader.Empty();}void ReleaseWSContext(){if(m_pwsContext){delete m_pwsContext;m_pwsContext = nullptr;}}void AppendBuffer(const char* at, size_t length) {m_strBuffer.Append(at, (int)length);}void ResetBuffer() {m_strBuffer.Empty();}LPCSTR GetBuffer() {return m_strBuffer;}CStringA& GetBufferRef() {return m_strBuffer;}static THttpObjT* Self(http_parser* p) {return (THttpObjT*)(p->data);}static T* SelfContext(http_parser* p) {return Self(p)->m_pContext;}static S* SelfSocketObj(http_parser* p) {return Self(p)->m_pSocket;}private:BOOL m_bValid;BOOL m_bRequest;BOOL m_bReleased;T* m_pContext;S* m_pSocket;http_parser m_parser;THeaderMap m_headers;TCookieMap m_cookies;CStringA m_strBuffer;CStringA m_strCurHeader;union{USHORT m_usUrlFieldSet;short m_sRequestMethod;};union{CStringA* m_pstrUrlFileds;CStringA* m_pstrRequestPath;};EnHttpUpgradeType m_enUpgrade;DWORD m_dwFreeTime;TWSContext<THttpObjT<T, S>>* m_pwsContext;static http_parser_settings sm_settings;};template<class T, class S> http_parser_settings THttpObjT<T, S>::sm_settings ={on_message_begin,on_url,on_status,nullptr, // on_methodnullptr, // on_versionon_header_field,on_header_value,nullptr, // on_chunk_extension_namenullptr, // on_chunk_extension_valueon_headers_complete,on_body,on_message_complete,on_url_complete,on_status_complete,nullptr, // on_method_completenullptr, // on_version_completeon_header_field_complete,on_header_value_complete,nullptr, // on_chunk_extension_name_completenullptr, // on_chunk_extension_value_completeon_chunk_header,on_chunk_complete,nullptr // on_reset};// ------------------------------------------------------------------------------------------------------------- //template<BOOL is_request, class T, class S> class CHttpObjPoolT{typedef THttpObjT<T, S> THttpObj;typedef CRingPool<THttpObj> TSSLHttpObjList;typedef CCASQueue<THttpObj> TSSLHttpObjQueue;public:THttpObj* PickFreeHttpObj(T* pContext, S* pSocket){DWORD dwIndex;THttpObj* pHttpObj = nullptr;if(m_lsFreeHttpObj.TryLock(&pHttpObj, dwIndex)){if(::GetTimeGap32(pHttpObj->GetFreeTime()) >= m_dwHttpObjLockTime)VERIFY(m_lsFreeHttpObj.ReleaseLock(nullptr, dwIndex));else{VERIFY(m_lsFreeHttpObj.ReleaseLock(pHttpObj, dwIndex));pHttpObj = nullptr;}}if(pHttpObj)pHttpObj->Renew(pContext, pSocket);else{pHttpObj = THttpObj::Construct(is_request, pContext, pSocket);ASSERT(pHttpObj);}return pHttpObj;}void PutFreeHttpObj(THttpObj* pHttpObj){pHttpObj->SetFree();ReleaseGCHttpObj();if(!m_lsFreeHttpObj.TryPut(pHttpObj))m_lsGCHttpObj.PushBack(pHttpObj);}void Prepare(){m_lsFreeHttpObj.Reset(m_dwHttpObjPoolSize);}void Clear(){m_lsFreeHttpObj.Clear();ReleaseGCHttpObj(TRUE);VERIFY(m_lsGCHttpObj.IsEmpty());}private:void ReleaseGCHttpObj(BOOL bForce = FALSE){::ReleaseGCObj(m_lsGCHttpObj, m_dwHttpObjLockTime, bForce);}public:void SetHttpObjLockTime (DWORD dwHttpObjLockTime) {m_dwHttpObjLockTime = dwHttpObjLockTime;}void SetHttpObjPoolSize (DWORD dwHttpObjPoolSize) {m_dwHttpObjPoolSize = dwHttpObjPoolSize;}void SetHttpObjPoolHold (DWORD dwHttpObjPoolHold) {m_dwHttpObjPoolHold = dwHttpObjPoolHold;}DWORD GetHttpObjLockTime() {return m_dwHttpObjLockTime;}DWORD GetHttpObjPoolSize() {return m_dwHttpObjPoolSize;}DWORD GetHttpObjPoolHold() {return m_dwHttpObjPoolHold;}public:CHttpObjPoolT( DWORD dwPoolSize = DEFAULT_HTTPOBJ_POOL_SIZE,DWORD dwPoolHold = DEFAULT_HTTPOBJ_POOL_HOLD,DWORD dwLockTime = DEFAULT_HTTPOBJ_LOCK_TIME): m_dwHttpObjPoolSize(dwPoolSize), m_dwHttpObjPoolHold(dwPoolHold), m_dwHttpObjLockTime(dwLockTime){}~CHttpObjPoolT() {Clear();}DECLARE_NO_COPY_CLASS(CHttpObjPoolT)public:static const DWORD DEFAULT_HTTPOBJ_LOCK_TIME;static const DWORD DEFAULT_HTTPOBJ_POOL_SIZE;static const DWORD DEFAULT_HTTPOBJ_POOL_HOLD;private:DWORD m_dwHttpObjLockTime;DWORD m_dwHttpObjPoolSize;DWORD m_dwHttpObjPoolHold;TSSLHttpObjList m_lsFreeHttpObj;TSSLHttpObjQueue m_lsGCHttpObj;};template<BOOL is_request, class T, class S> const DWORD CHttpObjPoolT<is_request, T, S>::DEFAULT_HTTPOBJ_LOCK_TIME = DEFAULT_OBJECT_CACHE_LOCK_TIME;template<BOOL is_request, class T, class S> const DWORD CHttpObjPoolT<is_request, T, S>::DEFAULT_HTTPOBJ_POOL_SIZE = DEFAULT_OBJECT_CACHE_POOL_SIZE;template<BOOL is_request, class T, class S> const DWORD CHttpObjPoolT<is_request, T, S>::DEFAULT_HTTPOBJ_POOL_HOLD = DEFAULT_OBJECT_CACHE_POOL_HOLD;// ------------------------------------------------------------------------------------------------------------- //extern CStringA& GetHttpVersionStr(EnHttpVersion enVersion, CStringA& strResult);extern CStringA& AdjustRequestPath(BOOL bConnect, LPCSTR lpszPath, CStringA& strPath);extern LPCSTR GetHttpDefaultStatusCodeDesc(EnHttpStatusCode enCode);extern void MakeRequestLine(LPCSTR lpszMethod, LPCSTR lpszPath, EnHttpVersion enVersion, CStringA& strValue);extern void MakeStatusLine(EnHttpVersion enVersion, USHORT usStatusCode, LPCSTR lpszDesc, CStringA& strValue);extern void MakeHeaderLines(const THeader lpHeaders[], int iHeaderCount, const TCookieMap* pCookies, int iBodyLength, BOOL bRequest, int iConnFlag, LPCSTR lpszDefaultHost, USHORT usPort, CStringA& strValue);extern void MakeHttpPacket(const CStringA& strHeader, const BYTE* pBody, int iLength, WSABUF szBuffer[2]);extern int MakeChunkPackage(const BYTE* pData, int iLength, LPCSTR lpszExtensions, char szLen[12], WSABUF bufs[5]);extern BOOL MakeWSPacket(BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], BYTE* pData, int iLength, ULONGLONG ullBodyLen, BYTE szHeader[HTTP_MAX_WS_HEADER_LEN], WSABUF szBuffer[2]);extern BOOL ParseUrl(const CStringA& strUrl, BOOL& bHttps, CStringA& strHost, USHORT& usPort, CStringA& strPath);#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。