工具项目

HttpHelper.h 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Author : Bruce Liang
  5. * Website : http://www.jessma.org
  6. * Project : https://github.com/ldcsaa
  7. * Blog : http://www.cnblogs.com/ldcsaa
  8. * Wiki : http://www.oschina.net/p/hp-socket
  9. * QQ Group : 75375912, 44636872
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. */
  23. #pragma once
  24. #include "SocketHelper.h"
  25. #include "HttpCookie.h"
  26. #ifdef _HTTP_SUPPORT
  27. #include "../Common/Src/http/http_parser.h"
  28. #include "../Common/Src/zlib/zutil.h"
  29. /************************************************************************
  30. 名称:HTTP 全局常量
  31. 描述:声明 HTTP 组件的公共全局常量
  32. ************************************************************************/
  33. #define HTTP_DEFAULT_PORT 80
  34. #define HTTPS_DEFAULT_PORT 443
  35. #define HTTP_SCHEMA "http://"
  36. #define HTTPS_SCHEMA "https://"
  37. #define HTTP_CRLF "\r\n"
  38. #define HTTP_PATH_SEPARATOR_CHAR '/'
  39. #define HTTP_PATH_SEPARATOR "/"
  40. #define HTTP_HEADER_SEPARATOR ": "
  41. #define HTTP_COOKIE_SEPARATOR "; "
  42. #define HTTP_1_0_STR "HTTP/1.0"
  43. #define HTTP_1_1_STR "HTTP/1.1"
  44. #define HTTP_HEADER_HOST "Host"
  45. #define HTTP_HEADER_COOKIE "Cookie"
  46. #define HTTP_HEADER_SET_COOKIE "Set-Cookie"
  47. #define HTTP_HEADER_CONTENT_TYPE "Content-Type"
  48. #define HTTP_HEADER_CONTENT_LENGTH "Content-Length"
  49. #define HTTP_HEADER_CONTENT_ENCODING "Content-Encoding"
  50. #define HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding"
  51. #define HTTP_HEADER_CONNECTION "Connection"
  52. #define HTTP_HEADER_UPGRADE "Upgrade"
  53. #define HTTP_HEADER_VALUE_WEB_SOCKET "WebSocket"
  54. #define HTTP_CONNECTION_CLOSE_VALUE "close"
  55. #define HTTP_CONNECTION_KEEPALIVE_VALUE "keep-alive"
  56. #define HTTP_METHOD_POST "POST"
  57. #define HTTP_METHOD_PUT "PUT"
  58. #define HTTP_METHOD_PATCH "PATCH"
  59. #define HTTP_METHOD_GET "GET"
  60. #define HTTP_METHOD_DELETE "DELETE"
  61. #define HTTP_METHOD_HEAD "HEAD"
  62. #define HTTP_METHOD_TRACE "TRACE"
  63. #define HTTP_METHOD_OPTIONS "OPTIONS"
  64. #define HTTP_METHOD_CONNECT "CONNECT"
  65. #define HTTP_MIN_WS_HEADER_LEN 2
  66. #define HTTP_MAX_WS_HEADER_LEN 14
  67. #define MIN_HTTP_RELEASE_CHECK_INTERVAL 1000
  68. #define MIN_HTTP_RELEASE_DELAY 100
  69. #define MAX_HTTP_RELEASE_DELAY (60 * 1000)
  70. #define DEFAULT_HTTP_RELEASE_DELAY (3 * 1000)
  71. #define DEFAULT_HTTP_VERSION HV_1_1
  72. #define DEFAULT_HTTP_SYNC_CONNECT_TIMEOUT 5000
  73. #define DEFAULT_HTTP_SYNC_REQUEST_TIMEOUT 10000
  74. // ------------------------------------------------------------------------------------------------------------- //
  75. enum EnHttpSyncRequestProgress
  76. {
  77. HSRP_DONE,
  78. HSRP_WAITING,
  79. HSRP_ERROR,
  80. HSRP_CLOSE
  81. };
  82. struct TDyingConnection
  83. {
  84. CONNID connID;
  85. DWORD killTime;
  86. TDyingConnection(CONNID id, DWORD kt = 0)
  87. : connID (id)
  88. , killTime (kt == 0 ? ::TimeGetTime() : kt)
  89. {
  90. }
  91. static TDyingConnection* Construct(CONNID id, DWORD kt = 0) {return new TDyingConnection(id, kt);}
  92. static void Destruct(TDyingConnection* pObj) {if(pObj) delete pObj;}
  93. };
  94. typedef unordered_multimap<CStringA, CStringA,
  95. cstringa_nc_hash_func::hash, cstringa_nc_hash_func::equal_to> THeaderMap;
  96. typedef THeaderMap::const_iterator THeaderMapCI;
  97. typedef THeaderMap::iterator THeaderMapI;
  98. typedef unordered_map<CStringA, CStringA,
  99. cstringa_hash_func::hash, cstringa_hash_func::equal_to> TCookieMap;
  100. typedef TCookieMap::const_iterator TCookieMapCI;
  101. typedef TCookieMap::iterator TCookieMapI;
  102. // ------------------------------------------------------------------------------------------------------------- //
  103. struct TBaseWSHeader
  104. {
  105. public:
  106. BOOL fin()
  107. {
  108. return (data >> 7) & 0x1;
  109. }
  110. void set_fin(BOOL v)
  111. {
  112. data |= ((v ? 1 : 0) << 7);
  113. }
  114. BYTE rsv()
  115. {
  116. return (data >> 4) & 0x7;
  117. }
  118. void set_rsv(BYTE v)
  119. {
  120. data |= ((v & 0x7) << 4);
  121. }
  122. BYTE code()
  123. {
  124. return data & 0xF;
  125. }
  126. void set_code(BYTE v)
  127. {
  128. data |= (v & 0xF);
  129. }
  130. BOOL mask()
  131. {
  132. return (data >> 15) & 0x1;
  133. }
  134. void set_mask(BOOL v)
  135. {
  136. data |= ((v ? 1 : 0) << 15);
  137. }
  138. BYTE len()
  139. {
  140. return (data >> 8) & 0x7F;
  141. }
  142. void set_len(BYTE v)
  143. {
  144. data |= ((v & 0x7F) << 8);
  145. }
  146. USHORT extlen()
  147. {
  148. return ntohs(data >> 16);
  149. }
  150. void set_extlen(USHORT v)
  151. {
  152. data |= (htons(v) << 16);
  153. }
  154. TBaseWSHeader(const BYTE* p, BOOL bZero = FALSE)
  155. : data(*(UINT*)p)
  156. {
  157. if(bZero) data = 0;
  158. }
  159. private:
  160. UINT& data;
  161. };
  162. template<class T> struct TWSContext
  163. {
  164. public:
  165. EnHandleResult Parse(const BYTE* pData, int iLength)
  166. {
  167. ASSERT(pData != nullptr && iLength > 0);
  168. EnHandleResult hr = HR_OK;
  169. BYTE* pTemp = (BYTE*)pData;
  170. int iRemain = iLength;
  171. int iMin = 0;
  172. while(iRemain > 0)
  173. {
  174. if(m_bHeader)
  175. {
  176. iMin = min(m_iHeaderRemain, iRemain);
  177. memcpy(m_szHeader + m_iHeaderLen - m_iHeaderRemain, pTemp, iMin);
  178. m_iHeaderRemain -= iMin;
  179. if(m_iHeaderRemain == 0)
  180. {
  181. TBaseWSHeader bh(m_szHeader);
  182. int iLen = bh.len();
  183. int iExtLen = iLen < 126 ? 0 : (iLen == 126 ? 2 : 8);
  184. int iMaskLen = bh.mask() ? 4 : 0;
  185. int iRealHeaderLen = HTTP_MIN_WS_HEADER_LEN + iExtLen + iMaskLen;
  186. if(m_iHeaderLen < iRealHeaderLen)
  187. {
  188. m_iHeaderRemain = iRealHeaderLen - m_iHeaderLen;
  189. m_iHeaderLen = iRealHeaderLen;
  190. }
  191. else
  192. {
  193. m_ullBodyLen = iExtLen == 0 ? iLen : (iExtLen == 2 ? bh.extlen() : NToH64(*(ULONGLONG*)(m_szHeader + HTTP_MIN_WS_HEADER_LEN)));
  194. m_ullBodyRemain = m_ullBodyLen;
  195. m_lpszMask = iMaskLen > 0 ? m_szHeader + HTTP_MIN_WS_HEADER_LEN + iExtLen : nullptr;
  196. hr = m_pHttpObj->on_ws_message_header(bh.fin(), bh.rsv(), bh.code(), m_lpszMask, m_ullBodyLen);
  197. if(hr == HR_ERROR)
  198. break;
  199. if(m_ullBodyLen > 0)
  200. m_bHeader = FALSE;
  201. else
  202. {
  203. hr = CompleteMessage();
  204. if(hr == HR_ERROR)
  205. break;
  206. }
  207. }
  208. }
  209. }
  210. else
  211. {
  212. iMin = (int)min(m_ullBodyRemain, (ULONGLONG)iRemain);
  213. if(m_lpszMask)
  214. {
  215. int iFactor = (m_ullBodyLen - m_ullBodyRemain) & 0x03;
  216. for(int i = 0; i < iMin; i++)
  217. pTemp[i] = pTemp[i] ^ m_lpszMask[(i + iFactor) & 0x03];
  218. }
  219. m_ullBodyRemain -= iMin;
  220. EnHandleResult hr = m_pHttpObj->on_ws_message_body(pTemp, iMin);
  221. if(hr == HR_ERROR)
  222. break;
  223. if(m_ullBodyRemain == 0)
  224. {
  225. hr = CompleteMessage();
  226. if(hr == HR_ERROR)
  227. break;
  228. }
  229. }
  230. pTemp += iMin;
  231. iRemain -= iMin;
  232. }
  233. return HR_OK;
  234. }
  235. BOOL GetMessageState(BOOL* lpbFinal, BYTE* lpiReserved, BYTE* lpiOperationCode, LPCBYTE* lpszMask, ULONGLONG* lpullBodyLen, ULONGLONG* lpullBodyRemain)
  236. {
  237. TBaseWSHeader bh(m_szHeader);
  238. if(lpbFinal) *lpbFinal = bh.fin();
  239. if(lpiReserved) *lpiReserved = bh.rsv();
  240. if(lpiOperationCode) *lpiOperationCode = bh.code();
  241. if(lpszMask) *lpszMask = m_lpszMask;
  242. if(lpullBodyLen) *lpullBodyLen = m_ullBodyLen;
  243. if(lpullBodyRemain) *lpullBodyRemain = m_ullBodyRemain;
  244. return TRUE;
  245. }
  246. BOOL CopyData(const TWSContext& src)
  247. {
  248. if(&src == this)
  249. return FALSE;
  250. memcpy(m_szHeader, src.m_szHeader, HTTP_MAX_WS_HEADER_LEN);
  251. if(src.m_lpszMask)
  252. m_lpszMask = m_szHeader + (src.m_lpszMask - src.m_szHeader);
  253. else
  254. m_lpszMask = nullptr;
  255. m_ullBodyLen = src.m_ullBodyLen;
  256. m_ullBodyRemain = src.m_ullBodyRemain;
  257. return TRUE;
  258. }
  259. public:
  260. TWSContext(T* pHttpObj) : m_pHttpObj(pHttpObj)
  261. {
  262. Reset();
  263. }
  264. private:
  265. EnHandleResult CompleteMessage()
  266. {
  267. EnHandleResult hr = m_pHttpObj->on_ws_message_complete();
  268. Reset();
  269. return hr;
  270. }
  271. void Reset()
  272. {
  273. m_bHeader = TRUE;
  274. m_lpszMask = nullptr;
  275. m_iHeaderLen = HTTP_MIN_WS_HEADER_LEN;
  276. m_iHeaderRemain = HTTP_MIN_WS_HEADER_LEN;
  277. m_ullBodyLen = 0;
  278. m_ullBodyRemain = 0;
  279. }
  280. private:
  281. T* m_pHttpObj;
  282. BYTE m_szHeader[HTTP_MAX_WS_HEADER_LEN];
  283. const BYTE* m_lpszMask;
  284. BOOL m_bHeader;
  285. int m_iHeaderLen;
  286. int m_iHeaderRemain;
  287. ULONGLONG m_ullBodyLen;
  288. ULONGLONG m_ullBodyRemain;
  289. };
  290. // ------------------------------------------------------------------------------------------------------------- //
  291. /* Http 上下文结构 */
  292. template<class T, class S> struct THttpObjT
  293. {
  294. public:
  295. EnHandleResult Execute(const BYTE* pData, int iLength)
  296. {
  297. ASSERT(pData != nullptr && iLength > 0);
  298. if(m_parser.upgrade)
  299. {
  300. if(m_enUpgrade == HUT_WEB_SOCKET)
  301. return m_pwsContext->Parse(pData, iLength);
  302. else
  303. return m_pContext->DoFireSuperReceive(m_pSocket, pData, iLength);
  304. }
  305. EnHandleResult hr = HR_OK;
  306. int iPased = (int)::http_parser_execute(&m_parser, &sm_settings, (LPCSTR)pData, iLength);
  307. if(m_parser.upgrade)
  308. hr = Upgrade(pData, iLength, iPased);
  309. else if(m_parser.http_errno != HPE_OK)
  310. {
  311. m_pContext->FireParseError(m_pSocket, m_parser.http_errno, ::http_errno_description(HTTP_PARSER_ERRNO(&m_parser)));
  312. hr = HR_ERROR;
  313. }
  314. else
  315. ASSERT(iPased == iLength);
  316. return hr;
  317. }
  318. void CheckBodyIdentityEof()
  319. {
  320. if(m_parser.state == s_body_identity_eof && !m_parser.upgrade)
  321. ::http_parser_execute(&m_parser, &sm_settings, nullptr, 0);
  322. }
  323. static int on_message_begin(http_parser* p)
  324. {
  325. THttpObjT* pSelf = Self(p);
  326. pSelf->ResetHeaderState(FALSE, FALSE);
  327. return pSelf->m_pContext->FireMessageBegin(pSelf->m_pSocket);
  328. }
  329. static int on_url(http_parser* p, const char* at, size_t length)
  330. {
  331. EnHttpParseResult hpr = HPR_OK;
  332. THttpObjT* pSelf = Self(p);
  333. pSelf->AppendBuffer(at, length);
  334. if(p->state != s_req_http_start)
  335. return hpr;
  336. hpr = pSelf->ParseUrl();
  337. if(hpr == HPR_OK)
  338. hpr = pSelf->m_pContext->FireRequestLine(pSelf->m_pSocket, ::http_method_str((http_method)p->method), pSelf->GetBuffer());
  339. pSelf->ResetBuffer();
  340. return hpr;
  341. }
  342. static int on_status(http_parser* p, const char* at, size_t length)
  343. {
  344. EnHttpParseResult hpr = HPR_OK;
  345. THttpObjT* pSelf = Self(p);
  346. pSelf->AppendBuffer(at, length);
  347. if(p->state != s_res_line_almost_done)
  348. return hpr;
  349. hpr = pSelf->m_pContext->FireStatusLine(pSelf->m_pSocket, p->status_code, pSelf->GetBuffer());
  350. pSelf->ResetBuffer();
  351. return hpr;
  352. }
  353. static int on_header_field(http_parser* p, const char* at, size_t length)
  354. {
  355. EnHttpParseResult hpr = HPR_OK;
  356. THttpObjT* pSelf = Self(p);
  357. pSelf->AppendBuffer(at, length);
  358. if(p->state != s_header_value_discard_ws)
  359. return hpr;
  360. pSelf->m_strCurHeader = pSelf->GetBuffer();
  361. pSelf->ResetBuffer();
  362. return hpr;
  363. }
  364. static int on_header_value(http_parser* p, const char* at, size_t length)
  365. {
  366. EnHttpParseResult hpr = HPR_OK;
  367. THttpObjT* pSelf = Self(p);
  368. pSelf->AppendBuffer(at, length);
  369. if(p->state != s_header_almost_done && p->state != s_header_field_start)
  370. return hpr;
  371. pSelf->m_headers.emplace(move(THeaderMap::value_type(pSelf->m_strCurHeader, pSelf->GetBuffer())));
  372. hpr = pSelf->m_pContext->FireHeader(pSelf->m_pSocket, pSelf->m_strCurHeader, pSelf->GetBuffer());
  373. if(hpr != HPR_ERROR)
  374. {
  375. if(pSelf->m_bRequest && pSelf->m_strCurHeader == HTTP_HEADER_COOKIE)
  376. hpr = pSelf->ParseCookie();
  377. else if(!pSelf->m_bRequest && pSelf->m_strCurHeader == HTTP_HEADER_SET_COOKIE)
  378. hpr = pSelf->ParseSetCookie();
  379. }
  380. pSelf->ResetBuffer();
  381. return hpr;
  382. }
  383. static int on_headers_complete(http_parser* p)
  384. {
  385. THttpObjT* pSelf = Self(p);
  386. pSelf->CheckUpgrade();
  387. pSelf->ResetHeaderBuffer();
  388. EnHttpParseResult rs = pSelf->m_pContext->FireHeadersComplete(pSelf->m_pSocket);
  389. if(!pSelf->m_bRequest && pSelf->GetMethodInt() == HTTP_HEAD && rs == HPR_OK)
  390. rs = HPR_SKIP_BODY;
  391. return rs;
  392. }
  393. static int on_body(http_parser* p, const char* at, size_t length)
  394. {
  395. THttpObjT* pSelf = Self(p);
  396. return pSelf->m_pContext->FireBody(pSelf->m_pSocket, (const BYTE*)at, (int)length);
  397. }
  398. static int on_chunk_header(http_parser* p)
  399. {
  400. THttpObjT* pSelf = Self(p);
  401. if(p->state == s_chunk_data || p->state == s_header_field_start)
  402. return pSelf->m_pContext->FireChunkHeader(pSelf->m_pSocket, (int)p->content_length);
  403. return HPR_OK;
  404. }
  405. static int on_chunk_complete(http_parser* p)
  406. {
  407. THttpObjT* pSelf = Self(p);
  408. if(p->state == s_headers_done || p->state == s_message_done)
  409. return pSelf->m_pContext->FireChunkComplete(pSelf->m_pSocket);
  410. return HPR_OK;
  411. }
  412. static int on_message_complete(http_parser* p)
  413. {
  414. THttpObjT* pSelf = Self(p);
  415. EnHttpParseResult hpr = pSelf->m_pContext->FireMessageComplete(pSelf->m_pSocket);
  416. return hpr;
  417. }
  418. EnHandleResult on_ws_message_header(BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
  419. {
  420. return m_pContext->FireWSMessageHeader(m_pSocket, bFinal, iReserved, iOperationCode, lpszMask, ullBodyLen);
  421. }
  422. EnHandleResult on_ws_message_body(const BYTE* pData, int iLength)
  423. {
  424. return m_pContext->FireWSMessageBody(m_pSocket, pData, iLength);
  425. }
  426. EnHandleResult on_ws_message_complete()
  427. {
  428. return m_pContext->FireWSMessageComplete(m_pSocket);
  429. }
  430. private:
  431. EnHandleResult Upgrade(const BYTE* pData, int iLength, int iPased)
  432. {
  433. ASSERT(m_parser.upgrade);
  434. if(m_pContext->FireUpgrade(m_pSocket, m_enUpgrade) != HPR_OK)
  435. return HR_ERROR;
  436. ResetHeaderState();
  437. if(m_enUpgrade == HUT_WEB_SOCKET)
  438. m_pwsContext = new TWSContext<THttpObjT<T, S>>(this);
  439. if(iPased < iLength)
  440. return Execute(pData + iPased, iLength - iPased);
  441. return HR_OK;
  442. }
  443. void CheckUpgrade()
  444. {
  445. if(!m_parser.upgrade)
  446. return;
  447. if(m_bRequest && m_parser.method == HTTP_CONNECT)
  448. m_enUpgrade = HUT_HTTP_TUNNEL;
  449. else
  450. {
  451. LPCSTR lpszValue;
  452. if(GetHeader(HTTP_HEADER_UPGRADE, &lpszValue) && _stricmp(HTTP_HEADER_VALUE_WEB_SOCKET, lpszValue) == 0)
  453. m_enUpgrade = HUT_WEB_SOCKET;
  454. else
  455. m_enUpgrade = HUT_UNKNOWN;
  456. }
  457. }
  458. EnHttpParseResult ParseUrl()
  459. {
  460. http_parser_url url = {0};
  461. BOOL isConnect = m_parser.method == HTTP_CONNECT;
  462. int rs = ::http_parser_parse_url(m_strBuffer, m_strBuffer.GetLength(), isConnect, &url);
  463. if(rs != HPE_OK)
  464. {
  465. m_parser.http_errno = HPE_INVALID_URL;
  466. return HPR_ERROR;
  467. }
  468. m_usUrlFieldSet = url.field_set;
  469. LPCSTR lpszBuffer = m_strBuffer;
  470. for(int i = 0; i < UF_MAX; i++)
  471. {
  472. if((url.field_set & (1 << i)) != 0)
  473. m_pstrUrlFileds[i].SetString((lpszBuffer + url.field_data[i].off), url.field_data[i].len);
  474. }
  475. return HPR_OK;
  476. }
  477. EnHttpParseResult ParseCookie()
  478. {
  479. int i = 0;
  480. do
  481. {
  482. CStringA tk = m_strBuffer.Tokenize(COOKIE_FIELD_SEP, i);
  483. if(i == -1)
  484. break;
  485. int j = tk.Trim().Find(COOKIE_KV_SEP_CHAR);
  486. if(j <= 0)
  487. continue;
  488. /*
  489. {
  490. m_parser.http_errno = HPE_INVALID_HEADER_TOKEN;
  491. return HPR_ERROR;
  492. }
  493. */
  494. AddCookie(tk.Left(j), tk.Mid(j + 1));
  495. } while(TRUE);
  496. return HPR_OK;
  497. }
  498. EnHttpParseResult ParseSetCookie()
  499. {
  500. CCookieMgr* pCookieMgr = m_pContext->GetCookieMgr();
  501. if(pCookieMgr == nullptr)
  502. return HPR_OK;
  503. LPCSTR lpszDomain = GetDomain();
  504. LPCSTR lpszPath = GetPath();
  505. unique_ptr<CCookie> pCookie(CCookie::FromString(m_strBuffer, lpszDomain, lpszPath));
  506. if(pCookie == nullptr)
  507. return HPR_ERROR;
  508. if(pCookie->Match(lpszDomain, lpszPath, TRUE, m_pContext->IsSecure()))
  509. {
  510. if(pCookie->IsExpired())
  511. DeleteCookie(pCookie->name);
  512. else
  513. AddCookie(pCookie->name, pCookie->value);
  514. }
  515. if(pCookieMgr->IsEnableThirdPartyCookie() || pCookie->IsSameDomain(lpszDomain))
  516. pCookieMgr->SetCookie(*pCookie);
  517. return HPR_OK;
  518. }
  519. public:
  520. DWORD GetFreeTime() const {return m_dwFreeTime;}
  521. void SetFree() {m_dwFreeTime = ::TimeGetTime();}
  522. BOOL IsUpgrade() {return m_parser.upgrade;}
  523. BOOL IsKeepAlive() {return ::http_should_keep_alive(&m_parser);}
  524. USHORT GetVersion() {return MAKEWORD(m_parser.http_major, m_parser.http_minor);}
  525. ULONGLONG GetContentLength() {return m_parser.content_length;}
  526. int GetMethodInt() {return m_bRequest ? m_parser.method : m_sRequestMethod;}
  527. LPCSTR GetMethod() {return ::http_method_str((http_method)GetMethodInt());}
  528. USHORT GetUrlFieldSet() {return m_usUrlFieldSet;}
  529. USHORT GetStatusCode() {return m_parser.status_code;}
  530. EnHttpUpgradeType GetUpgradeType() {return m_enUpgrade;}
  531. THeaderMap& GetHeaderMap() {return m_headers;}
  532. TCookieMap& GetCookieMap() {return m_cookies;}
  533. BOOL HasReleased() {return m_bReleased;}
  534. void Release() {m_bReleased = TRUE;}
  535. LPCSTR GetContentType()
  536. {
  537. LPCSTR lpszValue = nullptr;
  538. GetHeader(HTTP_HEADER_CONTENT_TYPE, &lpszValue);
  539. return lpszValue;
  540. }
  541. LPCSTR GetContentEncoding()
  542. {
  543. LPCSTR lpszValue = nullptr;
  544. GetHeader(HTTP_HEADER_CONTENT_ENCODING, &lpszValue);
  545. return lpszValue;
  546. }
  547. LPCSTR GetTransferEncoding()
  548. {
  549. LPCSTR lpszValue = nullptr;
  550. GetHeader(HTTP_HEADER_TRANSFER_ENCODING, &lpszValue);
  551. return lpszValue;
  552. }
  553. LPCSTR GetHost()
  554. {
  555. LPCSTR lpszValue = nullptr;
  556. GetHeader(HTTP_HEADER_HOST, &lpszValue);
  557. return lpszValue;
  558. }
  559. USHORT GetParseErrorCode(LPCSTR* lpszErrorDesc = nullptr)
  560. {
  561. if(lpszErrorDesc)
  562. *lpszErrorDesc = ::http_errno_description(HTTP_PARSER_ERRNO(&m_parser));
  563. return m_parser.http_errno;
  564. }
  565. LPCSTR GetUrlField(EnHttpUrlField enField)
  566. {
  567. ASSERT(m_bRequest && enField < HUF_MAX);
  568. if(!m_bRequest || enField >= HUF_MAX)
  569. return nullptr;
  570. return m_pstrUrlFileds[enField];
  571. }
  572. LPCSTR GetPath()
  573. {
  574. if(m_bRequest)
  575. return GetUrlField(HUF_PATH);
  576. else
  577. return *m_pstrRequestPath;
  578. }
  579. LPCSTR GetDomain()
  580. {
  581. ASSERT(!m_bRequest);
  582. return m_pContext->GetRemoteDomain(m_pSocket);
  583. }
  584. LPCSTR GetRequestPath()
  585. {
  586. if(m_bRequest)
  587. return nullptr;
  588. return *m_pstrRequestPath;
  589. }
  590. void SetRequestPath(LPCSTR lpszMethod, LPCSTR lpszPath)
  591. {
  592. ASSERT(!m_bRequest);
  593. if(m_bRequest)
  594. return;
  595. *m_pstrRequestPath = lpszPath;
  596. if(_stricmp(lpszMethod, HTTP_METHOD_GET) == 0)
  597. m_sRequestMethod = HTTP_GET;
  598. else if(_stricmp(lpszMethod, HTTP_METHOD_POST) == 0)
  599. m_sRequestMethod = HTTP_POST;
  600. else if(_stricmp(lpszMethod, HTTP_METHOD_PUT) == 0)
  601. m_sRequestMethod = HTTP_PUT;
  602. else if(_stricmp(lpszMethod, HTTP_METHOD_DELETE) == 0)
  603. m_sRequestMethod = HTTP_DELETE;
  604. else if(_stricmp(lpszMethod, HTTP_METHOD_HEAD) == 0)
  605. m_sRequestMethod = HTTP_HEAD;
  606. else if(_stricmp(lpszMethod, HTTP_METHOD_PATCH) == 0)
  607. m_sRequestMethod = HTTP_PATCH;
  608. else if(_stricmp(lpszMethod, HTTP_METHOD_TRACE) == 0)
  609. m_sRequestMethod = HTTP_TRACE;
  610. else if(_stricmp(lpszMethod, HTTP_METHOD_OPTIONS) == 0)
  611. m_sRequestMethod = HTTP_OPTIONS;
  612. else if(_stricmp(lpszMethod, HTTP_METHOD_CONNECT) == 0)
  613. m_sRequestMethod = HTTP_CONNECT;
  614. else
  615. m_sRequestMethod = -1;
  616. }
  617. BOOL GetHeader(LPCSTR lpszName, LPCSTR* lpszValue)
  618. {
  619. ASSERT(lpszName);
  620. BOOL isOK = FALSE;
  621. THeaderMapCI it = m_headers.find(lpszName);
  622. if(it != m_headers.end())
  623. {
  624. *lpszValue = it->second;
  625. isOK = TRUE;
  626. }
  627. return isOK;
  628. }
  629. BOOL GetHeaders(LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount)
  630. {
  631. ASSERT(lpszName);
  632. if(lpszValue == nullptr || dwCount == 0)
  633. {
  634. dwCount = (DWORD)m_headers.count(lpszName);
  635. return FALSE;
  636. }
  637. pair<THeaderMapCI, THeaderMapCI> range = m_headers.equal_range(lpszName);
  638. THeaderMapCI it = range.first;
  639. DWORD dwIndex = 0;
  640. while(it != range.second)
  641. {
  642. if(dwIndex < dwCount)
  643. lpszValue[dwIndex] = it->second;
  644. ++dwIndex;
  645. ++it;
  646. }
  647. BOOL isOK = (dwIndex > 0 && dwIndex <= dwCount);
  648. dwCount = dwIndex;
  649. return isOK;
  650. }
  651. BOOL GetAllHeaders(THeader lpHeaders[], DWORD& dwCount)
  652. {
  653. DWORD dwSize = (DWORD)m_headers.size();
  654. if(lpHeaders == nullptr || dwCount == 0 || dwSize == 0 || dwSize > dwCount)
  655. {
  656. dwCount = dwSize;
  657. return FALSE;
  658. }
  659. DWORD dwIndex = 0;
  660. for(THeaderMapCI it = m_headers.begin(), end = m_headers.end(); it != end; ++it, ++dwIndex)
  661. {
  662. lpHeaders[dwIndex].name = it->first;
  663. lpHeaders[dwIndex].value = it->second;
  664. }
  665. dwCount = dwSize;
  666. return TRUE;
  667. }
  668. BOOL GetAllHeaderNames(LPCSTR lpszName[], DWORD& dwCount)
  669. {
  670. DWORD dwSize = (DWORD)m_headers.size();
  671. if(lpszName == nullptr || dwCount == 0 || dwSize == 0 || dwSize > dwCount)
  672. {
  673. dwCount = dwSize;
  674. return FALSE;
  675. }
  676. DWORD dwIndex = 0;
  677. for(THeaderMapCI it = m_headers.begin(), end = m_headers.end(); it != end; ++it, ++dwIndex)
  678. lpszName[dwIndex] = it->first;
  679. dwCount = dwSize;
  680. return TRUE;
  681. }
  682. BOOL AddCookie(LPCSTR lpszName, LPCSTR lpszValue, BOOL bRelpace = TRUE)
  683. {
  684. ASSERT(lpszName);
  685. TCookieMapI it = m_cookies.find(lpszName);
  686. if(it == m_cookies.end())
  687. return m_cookies.emplace(move(TCookieMap::value_type(lpszName, lpszValue))).second;
  688. BOOL isOK = FALSE;
  689. if(bRelpace)
  690. {
  691. it->second = lpszValue;
  692. isOK = TRUE;
  693. }
  694. return isOK;
  695. }
  696. BOOL DeleteCookie(LPCSTR lpszName)
  697. {
  698. ASSERT(lpszName);
  699. return m_cookies.erase(lpszName) > 0;
  700. }
  701. void DeleteAllCookies()
  702. {
  703. m_cookies.clear();
  704. }
  705. BOOL GetCookie(LPCSTR lpszName, LPCSTR* lpszValue)
  706. {
  707. ASSERT(lpszName);
  708. BOOL isOK = FALSE;
  709. TCookieMapCI it = m_cookies.find(lpszName);
  710. if(it != m_cookies.end())
  711. {
  712. *lpszValue = it->second;
  713. isOK = TRUE;
  714. }
  715. return isOK;
  716. }
  717. BOOL GetAllCookies(TCookie lpCookies[], DWORD& dwCount)
  718. {
  719. DWORD dwSize = (DWORD)m_cookies.size();
  720. if(lpCookies == nullptr || dwCount == 0 || dwSize == 0 || dwSize > dwCount)
  721. {
  722. dwCount = dwSize;
  723. return FALSE;
  724. }
  725. DWORD dwIndex = 0;
  726. for(TCookieMapCI it = m_cookies.begin(), end = m_cookies.end(); it != end; ++it, ++dwIndex)
  727. {
  728. lpCookies[dwIndex].name = it->first;
  729. lpCookies[dwIndex].value = it->second;
  730. }
  731. dwCount = dwSize;
  732. return TRUE;
  733. }
  734. BOOL ReloadCookies()
  735. {
  736. CCookieMgr* pCookieMgr = m_pContext->GetCookieMgr();
  737. if(pCookieMgr == nullptr)
  738. return TRUE;
  739. DeleteAllCookies();
  740. CCookieSet cookies;
  741. if(!pCookieMgr->GetCookies(cookies, GetDomain(), GetPath(), TRUE, m_pContext->IsSecure()))
  742. return FALSE;
  743. for(CCookieSetCI it = cookies.begin(), end = cookies.end(); it != end; ++it)
  744. AddCookie(it->name, it->value);
  745. return TRUE;
  746. }
  747. BOOL GetWSMessageState(BOOL* lpbFinal, BYTE* lpiReserved, BYTE* lpiOperationCode, LPCBYTE* lpszMask, ULONGLONG* lpullBodyLen, ULONGLONG* lpullBodyRemain)
  748. {
  749. if(!m_pwsContext)
  750. return FALSE;
  751. return m_pwsContext->GetMessageState(lpbFinal, lpiReserved, lpiOperationCode, lpszMask, lpullBodyLen, lpullBodyRemain);
  752. }
  753. public:
  754. THttpObjT (BOOL bRequest, T* pContext, S* pSocket)
  755. : m_pContext (pContext)
  756. , m_pSocket (pSocket)
  757. , m_bRequest (bRequest)
  758. , m_bReleased (FALSE)
  759. , m_dwFreeTime (0)
  760. , m_usUrlFieldSet (m_bRequest ? 0 : -1)
  761. , m_pstrUrlFileds (nullptr)
  762. , m_enUpgrade (HUT_NONE)
  763. , m_pwsContext (nullptr)
  764. {
  765. if(m_bRequest)
  766. m_pstrUrlFileds = new CStringA[HUF_MAX];
  767. else
  768. m_pstrRequestPath = new CStringA;
  769. ResetParser();
  770. }
  771. ~THttpObjT()
  772. {
  773. if(m_bRequest)
  774. delete[] m_pstrUrlFileds;
  775. else
  776. delete m_pstrRequestPath;
  777. ReleaseWSContext();
  778. }
  779. static THttpObjT* Construct(BOOL bRequest, T* pContext, S* pSocket)
  780. {return new THttpObjT(bRequest, pContext, pSocket);}
  781. static void Destruct(THttpObjT* pHttpObj)
  782. {if(pHttpObj) delete pHttpObj;}
  783. void Reset()
  784. {
  785. ResetParser();
  786. ResetHeaderState();
  787. ReleaseWSContext();
  788. m_bReleased = FALSE;
  789. m_enUpgrade = HUT_NONE;
  790. m_dwFreeTime = 0;
  791. }
  792. void Renew(T* pContext, S* pSocket)
  793. {
  794. m_pContext = pContext;
  795. m_pSocket = pSocket;
  796. Reset();
  797. }
  798. BOOL CopyData(const THttpObjT& src)
  799. {
  800. if(&src == this)
  801. return FALSE;
  802. if(m_bRequest != src.m_bRequest)
  803. return FALSE;
  804. void* p = m_parser.data;
  805. m_parser = src.m_parser;
  806. m_parser.data = p;
  807. m_headers = src.m_headers;
  808. m_cookies = src.m_cookies;
  809. if(m_bRequest)
  810. {
  811. m_usUrlFieldSet = src.m_usUrlFieldSet;
  812. for(int i = 0;i < HUF_MAX; i++)
  813. m_pstrUrlFileds[i] = src.m_pstrUrlFileds[i];
  814. }
  815. else
  816. {
  817. m_sRequestMethod = src.m_sRequestMethod;
  818. *m_pstrRequestPath = *src.m_pstrRequestPath;
  819. }
  820. m_enUpgrade = src.m_enUpgrade;
  821. return TRUE;
  822. }
  823. BOOL CopyWSContext(const THttpObjT& src)
  824. {
  825. if(&src == this)
  826. return FALSE;
  827. if(m_bRequest != src.m_bRequest)
  828. return FALSE;
  829. if(!src.m_pwsContext && !m_pwsContext)
  830. ;
  831. else if(!src.m_pwsContext && m_pwsContext)
  832. {
  833. delete m_pwsContext;
  834. m_pwsContext = nullptr;
  835. }
  836. else
  837. {
  838. if(!m_pwsContext)
  839. m_pwsContext = new TWSContext<THttpObjT<T, S>>(this);
  840. m_pwsContext->CopyData(*src.m_pwsContext);
  841. }
  842. return TRUE;
  843. }
  844. private:
  845. void ResetParser()
  846. {
  847. ::http_parser_init(&m_parser, m_bRequest ? HTTP_REQUEST : HTTP_RESPONSE);
  848. m_parser.data = this;
  849. }
  850. void ResetHeaderState(BOOL bClearCookies = TRUE, BOOL bResetRequestData = TRUE)
  851. {
  852. if(m_bRequest)
  853. {
  854. if(m_usUrlFieldSet != 0)
  855. {
  856. m_usUrlFieldSet = 0;
  857. for(int i = 0; i < HUF_MAX; i++)
  858. m_pstrUrlFileds[i].Empty();
  859. }
  860. }
  861. else
  862. {
  863. if(bResetRequestData)
  864. {
  865. m_sRequestMethod = -1;
  866. m_pstrRequestPath->Empty();
  867. }
  868. }
  869. if(m_bRequest || bClearCookies)
  870. DeleteAllCookies();
  871. m_headers.clear();
  872. ResetHeaderBuffer();
  873. }
  874. void ResetHeaderBuffer()
  875. {
  876. ResetBuffer();
  877. m_strCurHeader.Empty();
  878. }
  879. void ReleaseWSContext()
  880. {
  881. if(m_pwsContext)
  882. {
  883. delete m_pwsContext;
  884. m_pwsContext = nullptr;
  885. }
  886. }
  887. void AppendBuffer(const char* at, size_t length) {m_strBuffer.Append(at, (int)length);}
  888. void ResetBuffer() {m_strBuffer.Empty();}
  889. LPCSTR GetBuffer() {return m_strBuffer;}
  890. static THttpObjT* Self(http_parser* p) {return (THttpObjT*)(p->data);}
  891. static T* SelfContext(http_parser* p) {return Self(p)->m_pContext;}
  892. static S* SelfSocketObj(http_parser* p) {return Self(p)->m_pSocket;}
  893. private:
  894. BOOL m_bRequest;
  895. BOOL m_bReleased;
  896. T* m_pContext;
  897. S* m_pSocket;
  898. http_parser m_parser;
  899. THeaderMap m_headers;
  900. TCookieMap m_cookies;
  901. CStringA m_strBuffer;
  902. CStringA m_strCurHeader;
  903. union
  904. {
  905. USHORT m_usUrlFieldSet;
  906. short m_sRequestMethod;
  907. };
  908. union
  909. {
  910. CStringA* m_pstrUrlFileds;
  911. CStringA* m_pstrRequestPath;
  912. };
  913. EnHttpUpgradeType m_enUpgrade;
  914. DWORD m_dwFreeTime;
  915. TWSContext<THttpObjT<T, S>>* m_pwsContext;
  916. static http_parser_settings sm_settings;
  917. };
  918. template<class T, class S> http_parser_settings THttpObjT<T, S>::sm_settings =
  919. {
  920. on_message_begin,
  921. on_url,
  922. on_status,
  923. on_header_field,
  924. on_header_value,
  925. on_headers_complete,
  926. on_body,
  927. on_message_complete,
  928. on_chunk_header,
  929. on_chunk_complete
  930. };
  931. // ------------------------------------------------------------------------------------------------------------- //
  932. template<BOOL is_request, class T, class S> class CHttpObjPoolT
  933. {
  934. typedef THttpObjT<T, S> THttpObj;
  935. typedef CRingPool<THttpObj> TSSLHttpObjList;
  936. typedef CCASQueue<THttpObj> TSSLHttpObjQueue;
  937. public:
  938. THttpObj* PickFreeHttpObj(T* pContext, S* pSocket)
  939. {
  940. DWORD dwIndex;
  941. THttpObj* pHttpObj = nullptr;
  942. if(m_lsFreeHttpObj.TryLock(&pHttpObj, dwIndex))
  943. {
  944. if(::GetTimeGap32(pHttpObj->GetFreeTime()) >= m_dwHttpObjLockTime)
  945. VERIFY(m_lsFreeHttpObj.ReleaseLock(nullptr, dwIndex));
  946. else
  947. {
  948. VERIFY(m_lsFreeHttpObj.ReleaseLock(pHttpObj, dwIndex));
  949. pHttpObj = nullptr;
  950. }
  951. }
  952. if(pHttpObj)
  953. pHttpObj->Renew(pContext, pSocket);
  954. else
  955. {
  956. pHttpObj = THttpObj::Construct(is_request, pContext, pSocket);
  957. ASSERT(pHttpObj);
  958. }
  959. return pHttpObj;
  960. }
  961. void PutFreeHttpObj(THttpObj* pHttpObj)
  962. {
  963. pHttpObj->SetFree();
  964. if(!m_lsFreeHttpObj.TryPut(pHttpObj))
  965. {
  966. m_lsGCHttpObj.PushBack(pHttpObj);
  967. if(m_lsGCHttpObj.Size() > m_dwHttpObjPoolSize)
  968. ReleaseGCHttpObj();
  969. }
  970. }
  971. void Prepare()
  972. {
  973. m_lsFreeHttpObj.Reset(m_dwHttpObjPoolHold);
  974. }
  975. void Clear()
  976. {
  977. THttpObj* pHttpObj = nullptr;
  978. while(m_lsFreeHttpObj.TryGet(&pHttpObj))
  979. delete pHttpObj;
  980. VERIFY(m_lsFreeHttpObj.IsEmpty());
  981. m_lsFreeHttpObj.Reset();
  982. ReleaseGCHttpObj(TRUE);
  983. VERIFY(m_lsGCHttpObj.IsEmpty());
  984. }
  985. private:
  986. void ReleaseGCHttpObj(BOOL bForce = FALSE)
  987. {
  988. THttpObj* pHttpObj = nullptr;
  989. DWORD now = ::TimeGetTime();
  990. while(m_lsGCHttpObj.PopFront(&pHttpObj))
  991. {
  992. if(bForce || (int)(now - pHttpObj->GetFreeTime()) >= (int)m_dwHttpObjLockTime)
  993. delete pHttpObj;
  994. else
  995. {
  996. m_lsGCHttpObj.PushBack(pHttpObj);
  997. break;
  998. }
  999. }
  1000. }
  1001. public:
  1002. void SetHttpObjLockTime (DWORD dwHttpObjLockTime) {m_dwHttpObjLockTime = dwHttpObjLockTime;}
  1003. void SetHttpObjPoolSize (DWORD dwHttpObjPoolSize) {m_dwHttpObjPoolSize = dwHttpObjPoolSize;}
  1004. void SetHttpObjPoolHold (DWORD dwHttpObjPoolHold) {m_dwHttpObjPoolHold = dwHttpObjPoolHold;}
  1005. DWORD GetHttpObjLockTime() {return m_dwHttpObjLockTime;}
  1006. DWORD GetHttpObjPoolSize() {return m_dwHttpObjPoolSize;}
  1007. DWORD GetHttpObjPoolHold() {return m_dwHttpObjPoolHold;}
  1008. public:
  1009. CHttpObjPoolT( DWORD dwPoolSize = DEFAULT_HTTPOBJ_POOL_SIZE,
  1010. DWORD dwPoolHold = DEFAULT_HTTPOBJ_POOL_HOLD,
  1011. DWORD dwLockTime = DEFAULT_HTTPOBJ_LOCK_TIME)
  1012. : m_dwHttpObjPoolSize(dwPoolSize)
  1013. , m_dwHttpObjPoolHold(dwPoolHold)
  1014. , m_dwHttpObjLockTime(dwLockTime)
  1015. {
  1016. }
  1017. ~CHttpObjPoolT() {Clear();}
  1018. DECLARE_NO_COPY_CLASS(CHttpObjPoolT)
  1019. public:
  1020. static const DWORD DEFAULT_HTTPOBJ_LOCK_TIME;
  1021. static const DWORD DEFAULT_HTTPOBJ_POOL_SIZE;
  1022. static const DWORD DEFAULT_HTTPOBJ_POOL_HOLD;
  1023. private:
  1024. DWORD m_dwHttpObjLockTime;
  1025. DWORD m_dwHttpObjPoolSize;
  1026. DWORD m_dwHttpObjPoolHold;
  1027. TSSLHttpObjList m_lsFreeHttpObj;
  1028. TSSLHttpObjQueue m_lsGCHttpObj;
  1029. };
  1030. template<BOOL is_request, class T, class S> const DWORD CHttpObjPoolT<is_request, T, S>::DEFAULT_HTTPOBJ_LOCK_TIME = 10 * 1000;
  1031. template<BOOL is_request, class T, class S> const DWORD CHttpObjPoolT<is_request, T, S>::DEFAULT_HTTPOBJ_POOL_SIZE = 150;
  1032. template<BOOL is_request, class T, class S> const DWORD CHttpObjPoolT<is_request, T, S>::DEFAULT_HTTPOBJ_POOL_HOLD = 600;
  1033. // ------------------------------------------------------------------------------------------------------------- //
  1034. extern CStringA& GetHttpVersionStr(EnHttpVersion enVersion, CStringA& strResult);
  1035. extern CStringA& AdjustRequestPath(BOOL bConnect, LPCSTR lpszPath, CStringA& strPath);
  1036. extern LPCSTR GetHttpDefaultStatusCodeDesc(EnHttpStatusCode enCode);
  1037. extern void MakeRequestLine(LPCSTR lpszMethod, LPCSTR lpszPath, EnHttpVersion enVersion, CStringA& strValue);
  1038. extern void MakeStatusLine(EnHttpVersion enVersion, USHORT usStatusCode, LPCSTR lpszDesc, CStringA& strValue);
  1039. extern void MakeHeaderLines(const THeader lpHeaders[], int iHeaderCount, const TCookieMap* pCookies, int iBodyLength, BOOL bRequest, int iConnFlag, LPCSTR lpszDefaultHost, USHORT usPort, CStringA& strValue);
  1040. extern void MakeHttpPacket(const CStringA& strHeader, const BYTE* pBody, int iLength, WSABUF szBuffer[2]);
  1041. 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]);
  1042. extern BOOL ParseUrl(const CStringA& strUrl, BOOL& bHttps, CStringA& strHost, USHORT& usPort, CStringA& strPath);
  1043. // 普通压缩(返回值:0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
  1044. int Compress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
  1045. // 高级压缩(返回值:0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
  1046. int CompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iLevel = Z_DEFAULT_COMPRESSION, int iMethod = Z_DEFLATED, int iWindowBits = DEF_WBITS, int iMemLevel = DEF_MEM_LEVEL, int iStrategy = Z_DEFAULT_STRATEGY);
  1047. // 普通解压(返回值:0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
  1048. int Uncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
  1049. // 高级解压(返回值:0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
  1050. int UncompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iWindowBits = DEF_WBITS);
  1051. // 推测压缩结果长度
  1052. DWORD GuessCompressBound(DWORD dwSrcLen, BOOL bGZip = FALSE);
  1053. // Gzip 压缩(返回值:0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
  1054. int GZipCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
  1055. // Gzip 解压(返回值:0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
  1056. int GZipUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
  1057. // 推测 Gzip 解压结果长度(如果返回 0 或不合理值则说明输入内容并非有效的 Gzip 格式)
  1058. DWORD GZipGuessUncompressBound(const BYTE* lpszSrc, DWORD dwSrcLen);
  1059. #endif