开源的socket服务端客户端,支持C# C++

ClientDlg.cpp 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. // ClientDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "Client.h"
  5. #include "ClientDlg.h"
  6. #include "afxdialogex.h"
  7. // CClientDlg dialog
  8. #define DEFAULT_PATH _T("req/path?p1=v1&p2=v2")
  9. #define DEFAULT_ADDRESS _T("127.0.0.1")
  10. #define DEFAULT_PORT _T("8080")
  11. CClientDlg* CClientDlg::m_spThis = nullptr;
  12. CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
  13. : CDialogEx(CClientDlg::IDD, pParent)
  14. {
  15. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  16. m_spThis = this;
  17. // 初始化 SSL 全局环境参数
  18. ::HP_SSL_Initialize(SSL_SM_CLIENT, SSL_VM_NONE, g_c_lpszPemCertFile, g_c_lpszPemKeyFile, g_c_lpszKeyPasswod, g_c_lpszCAPemCertFileOrPath, nullptr);
  19. VERIFY(::HP_SSL_IsValid());
  20. // 创建监听器对象
  21. m_HttpClientListener = ::Create_HP_HttpClientListener();
  22. m_HttpClient = nullptr;
  23. // 设置 HTTP 监听器回调函数
  24. ::HP_Set_FN_HttpClient_OnConnect(m_HttpClientListener, OnConnect);
  25. ::HP_Set_FN_HttpClient_OnHandShake(m_HttpClientListener, OnHandShake);
  26. ::HP_Set_FN_HttpClient_OnSend(m_HttpClientListener, OnSend);
  27. ::HP_Set_FN_HttpClient_OnReceive(m_HttpClientListener, OnReceive);
  28. ::HP_Set_FN_HttpClient_OnClose(m_HttpClientListener, OnClose);
  29. ::HP_Set_FN_HttpClient_OnMessageBegin(m_HttpClientListener, OnMessageBegin);
  30. ::HP_Set_FN_HttpClient_OnStatusLine(m_HttpClientListener, OnStatusLine);
  31. ::HP_Set_FN_HttpClient_OnHeader(m_HttpClientListener, OnHeader);
  32. ::HP_Set_FN_HttpClient_OnHeadersComplete(m_HttpClientListener, OnHeadersComplete);
  33. ::HP_Set_FN_HttpClient_OnBody(m_HttpClientListener, OnBody);
  34. ::HP_Set_FN_HttpClient_OnChunkHeader(m_HttpClientListener, OnChunkHeader);
  35. ::HP_Set_FN_HttpClient_OnChunkComplete(m_HttpClientListener, OnChunkComplete);
  36. ::HP_Set_FN_HttpClient_OnMessageComplete(m_HttpClientListener, OnMessageComplete);
  37. ::HP_Set_FN_HttpClient_OnUpgrade(m_HttpClientListener, OnUpgrade);
  38. ::HP_Set_FN_HttpClient_OnParseError(m_HttpClientListener, OnParseError);
  39. ::HP_Set_FN_HttpClient_OnWSMessageHeader(m_HttpClientListener, OnWSMessageHeader);
  40. ::HP_Set_FN_HttpClient_OnWSMessageBody(m_HttpClientListener, OnWSMessageBody);
  41. ::HP_Set_FN_HttpClient_OnWSMessageComplete(m_HttpClientListener, OnWSMessageComplete);
  42. }
  43. CClientDlg::~CClientDlg()
  44. {
  45. // 销毁 HTTP 对象
  46. if(m_HttpClient != nullptr)
  47. ::Destroy_HP_HttpClient(m_HttpClient);
  48. // 销毁监听器对象
  49. ::Destroy_HP_HttpClientListener(m_HttpClientListener);
  50. // 清理 SSL 全局运行环境
  51. ::HP_SSL_Cleanup();
  52. }
  53. void CClientDlg::DoDataExchange(CDataExchange* pDX)
  54. {
  55. CDialogEx::DoDataExchange(pDX);
  56. DDX_Control(pDX, IDC_SEND, m_Send);
  57. DDX_Control(pDX, IDC_INFO, m_Info);
  58. DDX_Control(pDX, IDC_ADDRESS, m_Address);
  59. DDX_Control(pDX, IDC_PORT, m_Port);
  60. DDX_Control(pDX, IDC_ASYNC, m_Async);
  61. DDX_Control(pDX, IDC_START, m_Start);
  62. DDX_Control(pDX, IDC_STOP, m_Stop);
  63. DDX_Control(pDX, IDC_METHOD, m_Method);
  64. DDX_Control(pDX, IDC_SCHEMA, m_Schema);
  65. DDX_Control(pDX, IDC_PATH, m_Path);
  66. DDX_Control(pDX, IDC_HEADER_NAME, m_HeaderName);
  67. DDX_Control(pDX, IDC_HEADER_VALUE, m_HeaderValue);
  68. DDX_Control(pDX, IDC_HEADER_ADD, m_HeaderAdd);
  69. DDX_Control(pDX, IDC_HEADERS, m_Headers);
  70. DDX_Control(pDX, IDC_BODY, m_Body);
  71. }
  72. BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
  73. ON_WM_PAINT()
  74. ON_WM_QUERYDRAGICON()
  75. ON_BN_CLICKED(IDC_SEND, &CClientDlg::OnBnClickedSend)
  76. ON_BN_CLICKED(IDC_START, &CClientDlg::OnBnClickedStart)
  77. ON_BN_CLICKED(IDC_STOP, &CClientDlg::OnBnClickedStop)
  78. ON_BN_CLICKED(IDC_HEADER_ADD, &CClientDlg::OnBnClickedHeaderAdd)
  79. ON_CBN_SELCHANGE(IDC_METHOD, &CClientDlg::OnCbnSelchangeMethod)
  80. ON_MESSAGE(USER_INFO_MSG, OnUserInfoMsg)
  81. ON_WM_VKEYTOITEM()
  82. END_MESSAGE_MAP()
  83. // CClientDlg message handlers
  84. BOOL CClientDlg::OnInitDialog()
  85. {
  86. CDialogEx::OnInitDialog();
  87. // Set the icon for this dialog. The framework does this automatically
  88. // when the application's main window is not a dialog
  89. SetIcon(m_hIcon, TRUE); // Set big icon
  90. SetIcon(m_hIcon, FALSE); // Set small icon
  91. // TODO: Add extra initialization here
  92. m_Method.SetCurSel(3);
  93. m_Schema.SetCurSel(0);
  94. m_Path.SetWindowText(DEFAULT_PATH);
  95. m_Address.SetWindowText(DEFAULT_ADDRESS);
  96. m_Port.SetWindowText(DEFAULT_PORT);
  97. m_Async.SetCheck(BST_CHECKED);
  98. ::SetMainWnd(this);
  99. ::SetInfoList(&m_Info);
  100. SetAppState(ST_STOPPED);
  101. m_bWebSocket = FALSE;
  102. m_bAsyncConn = FALSE;
  103. return TRUE; // return TRUE unless you set the focus to a control
  104. }
  105. // If you add a minimize button to your dialog, you will need the code below
  106. // to draw the icon. For MFC applications using the document/view model,
  107. // this is automatically done for you by the framework.
  108. void CClientDlg::OnPaint()
  109. {
  110. if (IsIconic())
  111. {
  112. CPaintDC dc(this); // device context for painting
  113. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  114. // Center icon in client rectangle
  115. int cxIcon = GetSystemMetrics(SM_CXICON);
  116. int cyIcon = GetSystemMetrics(SM_CYICON);
  117. CRect rect;
  118. GetClientRect(&rect);
  119. int x = (rect.Width() - cxIcon + 1) / 2;
  120. int y = (rect.Height() - cyIcon + 1) / 2;
  121. // Draw the icon
  122. dc.DrawIcon(x, y, m_hIcon);
  123. }
  124. else
  125. {
  126. CDialogEx::OnPaint();
  127. }
  128. }
  129. // The system calls this function to obtain the cursor to display while the user drags
  130. // the minimized window.
  131. HCURSOR CClientDlg::OnQueryDragIcon()
  132. {
  133. return static_cast<HCURSOR>(m_hIcon);
  134. }
  135. BOOL CClientDlg::PreTranslateMessage(MSG* pMsg)
  136. {
  137. if (
  138. pMsg->message == WM_KEYDOWN
  139. &&( pMsg->wParam == VK_ESCAPE
  140. || pMsg->wParam == VK_CANCEL
  141. || (pMsg->wParam == VK_RETURN && pMsg->hwnd == this->GetSafeHwnd())
  142. ))
  143. return TRUE;
  144. return CDialog::PreTranslateMessage(pMsg);
  145. }
  146. void CClientDlg::SetAppState(EnAppState state)
  147. {
  148. m_enState = state;
  149. if(this->GetSafeHwnd() == nullptr)
  150. return;
  151. m_Async.EnableWindow(m_enState == ST_STOPPED);
  152. m_Start.EnableWindow(m_enState == ST_STOPPED);
  153. m_Stop.EnableWindow(m_enState == ST_STARTED);
  154. m_Send.EnableWindow(m_enState == ST_STARTED);
  155. m_Schema.EnableWindow(m_enState == ST_STOPPED);
  156. m_Address.EnableWindow(m_enState == ST_STOPPED);
  157. m_Port.EnableWindow(m_enState == ST_STOPPED);
  158. m_Body.EnableWindow(m_Method.GetCurSel() <= 2 || m_bWebSocket);
  159. m_Path.EnableWindow(m_Method.GetCurSel() != 8);
  160. }
  161. void CClientDlg::OnBnClickedHeaderAdd()
  162. {
  163. CString strName;
  164. CString strValue;
  165. m_HeaderName.GetWindowText(strName);
  166. m_HeaderValue.GetWindowText(strValue);
  167. strName.Trim();
  168. strValue.Trim();
  169. if(!strName.IsEmpty())
  170. {
  171. if(strName == _T("Content-Length"))
  172. {
  173. MessageBox(_T("'Content-Length' header can't be specified!"), _T("Add Header"), MB_OK | MB_ICONINFORMATION);
  174. m_HeaderName.SetFocus();
  175. return;
  176. }
  177. CString strHeader;
  178. strHeader.Format(_T("%s: %s"), strName, strValue);
  179. m_Headers.AddString(strHeader);
  180. m_HeaderName.SetWindowText(_T(""));
  181. m_HeaderValue.SetWindowText(_T(""));
  182. }
  183. }
  184. void CClientDlg::OnBnClickedSend()
  185. {
  186. m_bWebSocket ? SendWebSocket() : SendHttp();
  187. }
  188. void CClientDlg::SendHttp()
  189. {
  190. USES_CONVERSION;
  191. CString strMethod;
  192. CString strSchema;
  193. CString strAddress;
  194. CString strPort;
  195. CString strPath;
  196. m_Method.GetWindowText(strMethod);
  197. m_Schema.GetWindowText(strSchema);
  198. m_Address.GetWindowText(strAddress);
  199. m_Port.GetWindowText(strPort);
  200. if(m_Method.GetCurSel() != 8)
  201. {
  202. m_Path.GetWindowText(strPath);
  203. strPath.Trim();
  204. if(strPath.IsEmpty() || strPath.GetAt(0) != '/')
  205. strPath.Insert(0, '/');
  206. }
  207. THttpHeaderMap headers;
  208. int iCount = m_Headers.GetCount();
  209. for(int i = 0; i < iCount; i++)
  210. {
  211. CString strHeader;
  212. m_Headers.GetText(i, strHeader);
  213. int j = 0;
  214. CString strName = strHeader.Tokenize(_T(": "), j);
  215. CString strValue = strHeader.Mid(j + 1);
  216. headers.emplace(THttpHeaderMap::value_type(T2A(strName), T2A(strValue)));
  217. }
  218. CStringA strBodyA;
  219. CStringA strPathA;
  220. if(m_Method.GetCurSel() <= 2)
  221. {
  222. CString strBody;
  223. m_Body.GetWindowText(strBody);
  224. strBodyA = T2A(strBody);
  225. }
  226. else if(m_Method.GetCurSel() == 8)
  227. {
  228. THttpHeaderMapCI it = headers.find("Host");
  229. if(it != headers.end() && !it->second.IsEmpty())
  230. strPathA = it->second;
  231. else
  232. {
  233. CString strHost;
  234. strHost.Format(_T("%s:%s"), strAddress, strPort);
  235. strPathA = strHost;
  236. }
  237. }
  238. if(strPathA.IsEmpty())
  239. strPathA = T2A(strPath);
  240. DWORD dwIndex = 0;
  241. DWORD dwSize = (DWORD)headers.size();
  242. unique_ptr<THeader[]> szHeaders(new THeader[dwSize]);
  243. for(THttpHeaderMapCI it = headers.begin(), end = headers.end(); it != end; ++it, ++dwIndex)
  244. {
  245. szHeaders[dwIndex].name = it->first;
  246. szHeaders[dwIndex].value = it->second;
  247. }
  248. CString strContent;
  249. strContent.Format(_T("[%s] %s://%s:%s%s"), strMethod, strSchema, strAddress, strPort, strPath);
  250. if(HP_HttpClient_SendRequest(m_HttpClient, T2A(strMethod), strPathA, szHeaders.get(), dwSize, (const BYTE*)(LPCSTR)strBodyA, strBodyA.GetLength()))
  251. ::LogSend(::HP_Client_GetConnectionID(m_HttpClient), strContent);
  252. else
  253. ::LogSendFail(::HP_Client_GetConnectionID(m_HttpClient), ::SYS_GetLastError(), ::HP_GetSocketErrorDesc(SE_DATA_SEND));
  254. }
  255. void CClientDlg::SendWebSocket()
  256. {
  257. static LPCSTR CLOSE_FLAG = "$close";
  258. static const BYTE MASK_KEY[] = {0x1, 0x2, 0x3, 0x4};
  259. USES_CONVERSION;
  260. CString strBody;
  261. m_Body.GetWindowText(strBody);
  262. CStringA strBodyA = T2A(strBody);
  263. if(strBodyA.CompareNoCase(CLOSE_FLAG) != 0)
  264. ::HP_HttpClient_SendWSMessage(m_HttpClient, TRUE, 0, 0x1, MASK_KEY, (BYTE*)(LPCSTR)strBodyA, strBodyA.GetLength(), 0);
  265. else
  266. {
  267. ::HP_HttpClient_SendWSMessage(m_HttpClient, TRUE, 0, 0x8, MASK_KEY, nullptr, 0, 0);
  268. m_Body.SetWindowText(_T(""));
  269. }
  270. }
  271. void CClientDlg::OnBnClickedStart()
  272. {
  273. SetAppState(ST_STARTING);
  274. CString strAddress;
  275. CString strPort;
  276. m_Address.GetWindowText(strAddress);
  277. m_Port.GetWindowText(strPort);
  278. USHORT usPort = (USHORT)_ttoi(strPort);
  279. m_bAsyncConn = m_Async.GetCheck();
  280. BOOL isHttp = m_Schema.GetCurSel() == 0;
  281. if(m_HttpClient != nullptr)
  282. ::Destroy_HP_HttpClient(m_HttpClient);
  283. if(isHttp)
  284. m_HttpClient = ::Create_HP_HttpClient(m_HttpClientListener);
  285. else
  286. m_HttpClient = ::Create_HP_HttpsClient(m_HttpClientListener);
  287. ::LogClientStarting(strAddress, usPort);
  288. if(::HP_Client_Start(m_HttpClient, strAddress, usPort, m_bAsyncConn))
  289. {
  290. }
  291. else
  292. {
  293. ::LogClientStartFail(::HP_Client_GetLastError(m_HttpClient), ::HP_Client_GetLastErrorDesc(m_HttpClient));
  294. SetAppState(ST_STOPPED);
  295. }
  296. }
  297. void CClientDlg::OnBnClickedStop()
  298. {
  299. SetAppState(ST_STOPPING);
  300. if(::HP_Client_Stop(m_HttpClient))
  301. ::LogClientStopping(::HP_Client_GetConnectionID(m_HttpClient));
  302. else
  303. ASSERT(FALSE);
  304. }
  305. void CClientDlg::OnCbnSelchangeMethod()
  306. {
  307. m_Body.EnableWindow(m_Method.GetCurSel() <= 2 || m_bWebSocket);
  308. m_Path.EnableWindow(m_Method.GetCurSel() != 8);
  309. }
  310. int CClientDlg::OnVKeyToItem(UINT nKey, CListBox* pListBox, UINT nIndex)
  311. {
  312. if(nKey == 'C')
  313. pListBox->ResetContent();
  314. else if(nKey == 'D' && pListBox == &m_Headers)
  315. {
  316. int index = pListBox->GetCurSel();
  317. if(index != LB_ERR)
  318. {
  319. pListBox->DeleteString(index);
  320. int count = pListBox->GetCount();
  321. if(index < count)
  322. pListBox->SetCurSel(index);
  323. else if(index > 0)
  324. pListBox->SetCurSel(index - 1);
  325. }
  326. }
  327. return __super::OnVKeyToItem(nKey, pListBox, nIndex);
  328. }
  329. LRESULT CClientDlg::OnUserInfoMsg(WPARAM wp, LPARAM lp)
  330. {
  331. info_msg* msg = (info_msg*)wp;
  332. ::LogInfoMsg(msg);
  333. return 0;
  334. }
  335. EnHandleResult CClientDlg::OnConnect(HP_Client pSender, CONNID dwConnID)
  336. {
  337. TCHAR szAddress[40];
  338. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  339. USHORT usPort;
  340. ::HP_Client_GetLocalAddress(pSender, szAddress, &iAddressLen, &usPort);
  341. ::PostOnConnect(dwConnID, szAddress, usPort);
  342. return HR_OK;
  343. }
  344. EnHandleResult CClientDlg::OnHandShake(HP_Client pSender, CONNID dwConnID)
  345. {
  346. ::PostOnHandShake(dwConnID);
  347. ::HP_HttpClient_AddCookie(pSender, "__reqSequence", "1", TRUE);
  348. m_spThis->SetAppState(ST_STARTED);
  349. return HR_OK;
  350. }
  351. EnHandleResult CClientDlg::OnSend(HP_Client pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  352. {
  353. ::PostOnSend(dwConnID, pData, iLength);
  354. return HR_OK;
  355. }
  356. EnHandleResult CClientDlg::OnReceive(HP_Client pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  357. {
  358. ::PostOnReceive(dwConnID, pData, iLength);
  359. return HR_OK;
  360. }
  361. EnHandleResult CClientDlg::OnClose(HP_Client pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
  362. {
  363. iErrorCode == SE_OK ? ::PostOnClose(dwConnID) :
  364. ::PostOnError(dwConnID, enOperation, iErrorCode) ;
  365. m_spThis->m_bWebSocket = FALSE;
  366. m_spThis->SetAppState(ST_STOPPED);
  367. return HR_OK;
  368. }
  369. // ------------------------------------------------------------------------------------------------------------- //
  370. EnHttpParseResult CClientDlg::OnMessageBegin(HP_HttpClient pSender, CONNID dwConnID)
  371. {
  372. ::PostOnMessageBegin(dwConnID);
  373. return HPR_OK;
  374. }
  375. EnHttpParseResult CClientDlg::OnStatusLine(HP_HttpClient pSender, CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)
  376. {
  377. ::PostOnStatusLine(dwConnID, usStatusCode, lpszDesc);
  378. return HPR_OK;
  379. }
  380. EnHttpParseResult CClientDlg::OnHeader(HP_HttpClient pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
  381. {
  382. ::PostOnHeader(dwConnID, lpszName, lpszValue);
  383. return HPR_OK;
  384. }
  385. EnHttpParseResult CClientDlg::OnHeadersComplete(HP_HttpClient pSender, CONNID dwConnID)
  386. {
  387. CheckSetCookie(pSender);
  388. CStringA strSummary = GetHeaderSummary(pSender, " ", 0, TRUE);
  389. ::PostOnHeadersComplete(dwConnID, strSummary);
  390. return HPR_OK;
  391. }
  392. EnHttpParseResult CClientDlg::OnBody(HP_HttpClient pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  393. {
  394. ::PostOnBody(dwConnID, pData, iLength);
  395. return HPR_OK;
  396. }
  397. EnHttpParseResult CClientDlg::OnChunkHeader(HP_HttpClient pSender, CONNID dwConnID, int iLength)
  398. {
  399. ::PostOnChunkHeader(dwConnID, iLength);
  400. return HPR_OK;
  401. }
  402. EnHttpParseResult CClientDlg::OnChunkComplete(HP_HttpClient pSender, CONNID dwConnID)
  403. {
  404. ::PostOnChunkComplete(dwConnID);
  405. return HPR_OK;
  406. }
  407. EnHttpParseResult CClientDlg::OnMessageComplete(HP_HttpClient pSender, CONNID dwConnID)
  408. {
  409. ::PostOnMessageComplete(dwConnID);
  410. return HPR_OK;
  411. }
  412. EnHttpParseResult CClientDlg::OnUpgrade(HP_HttpClient pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
  413. {
  414. ::PostOnUpgrade(dwConnID, enUpgradeType);
  415. if(enUpgradeType == HUT_WEB_SOCKET)
  416. {
  417. m_spThis->m_bWebSocket = TRUE;
  418. m_spThis->OnCbnSelchangeMethod();
  419. }
  420. return HPR_OK;
  421. }
  422. EnHttpParseResult CClientDlg::OnParseError(HP_HttpClient pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
  423. {
  424. ::PostOnParseError(dwConnID, iErrorCode, lpszErrorDesc);
  425. return HPR_OK;
  426. }
  427. // ------------------------------------------------------------------------------------------------------------- //
  428. EnHandleResult CClientDlg::OnWSMessageHeader(HP_HttpClient pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
  429. {
  430. ::PostOnWSMessageHeader(dwConnID, bFinal, iReserved, iOperationCode, lpszMask, ullBodyLen);
  431. return HR_OK;
  432. }
  433. EnHandleResult CClientDlg::OnWSMessageBody(HP_HttpClient pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  434. {
  435. ::PostOnWSMessageBody(dwConnID, pData, iLength);
  436. return HR_OK;
  437. }
  438. EnHandleResult CClientDlg::OnWSMessageComplete(HP_HttpClient pSender, CONNID dwConnID)
  439. {
  440. ::PostOnWSMessageComplete(dwConnID);
  441. BYTE iOperationCode;
  442. VERIFY(::HP_HttpClient_GetWSMessageState(pSender, nullptr, nullptr, &iOperationCode, nullptr, nullptr, nullptr));
  443. if(iOperationCode == 0x8)
  444. return HR_ERROR;
  445. return HR_OK;
  446. }
  447. // ------------------------------------------------------------------------------------------------------------- //
  448. void CClientDlg::CheckSetCookie(HP_HttpClient pSender)
  449. {
  450. DWORD dwHeaderCount = 0;
  451. ::HP_HttpClient_GetHeaders(pSender, "Set-Cookie", nullptr, &dwHeaderCount);
  452. if(dwHeaderCount == 0)
  453. return;
  454. unique_ptr<LPCSTR[]> values(new LPCSTR[dwHeaderCount]);
  455. VERIFY(::HP_HttpClient_GetHeaders(pSender, "Set-Cookie", values.get(), &dwHeaderCount));
  456. for(DWORD i = 0; i < dwHeaderCount; i++)
  457. {
  458. CStringA strValue = values[i];
  459. int j = 0;
  460. CStringA strItem = strValue.Tokenize("; ", j);
  461. if(j <= 0)
  462. continue;
  463. int k = strItem.Find('=');
  464. if(k <= 0)
  465. continue;
  466. ::HP_HttpClient_AddCookie(pSender, strItem.Left(k), strItem.Mid(k + 1), TRUE);
  467. }
  468. }
  469. CStringA CClientDlg::GetHeaderSummary(HP_HttpClient pSender, LPCSTR lpszSep, int iSepCount, BOOL bWithContentLength)
  470. {
  471. CStringA SEP1;
  472. for(int i = 0; i < iSepCount; i++)
  473. SEP1 += lpszSep;
  474. CStringA SEP2(SEP1);
  475. SEP2 += lpszSep;
  476. CStringA strResult;
  477. strResult.AppendFormat("%s[Status Fields]%s", SEP1, CRLF);
  478. strResult.AppendFormat("%s%13s: %u%s", SEP2, "Status Code", ::HP_HttpClient_GetStatusCode(pSender), CRLF);
  479. DWORD dwHeaderCount = 0;
  480. ::HP_HttpClient_GetAllHeaders(pSender, nullptr, &dwHeaderCount);
  481. strResult.AppendFormat("%s[Response Headers]%s", SEP1, CRLF);
  482. if(dwHeaderCount == 0)
  483. strResult.AppendFormat("%s(no header)%s", SEP2, CRLF);
  484. else
  485. {
  486. unique_ptr<THeader[]> headers(new THeader[dwHeaderCount]);
  487. VERIFY(::HP_HttpClient_GetAllHeaders(pSender, headers.get(), &dwHeaderCount));
  488. for(DWORD i = 0; i < dwHeaderCount; i++)
  489. strResult.AppendFormat("%s%s: %s%s", SEP2, headers[i].name, headers[i].value, CRLF);
  490. }
  491. DWORD dwCookieCount = 0;
  492. ::HP_HttpClient_GetAllCookies(pSender, nullptr, &dwCookieCount);
  493. strResult.AppendFormat("%s[Cookies]%s", SEP1, CRLF);
  494. if(dwCookieCount == 0)
  495. strResult.AppendFormat("%s(no cookie)%s", SEP2, CRLF);
  496. else
  497. {
  498. unique_ptr<TCookie[]> cookies(new TCookie[dwCookieCount]);
  499. VERIFY(::HP_HttpClient_GetAllCookies(pSender, cookies.get(), &dwCookieCount));
  500. for(DWORD i = 0; i < dwCookieCount; i++)
  501. strResult.AppendFormat("%s%s: %s%s", SEP2, cookies[i].name, cookies[i].value, CRLF);
  502. }
  503. CStringA strVersion;
  504. ::HttpVersionToString((EnHttpVersion)::HP_HttpClient_GetVersion(pSender), strVersion);
  505. EnHttpUpgradeType enUpgType = ::HP_HttpClient_GetUpgradeType(pSender);
  506. LPCSTR lpszUpgrade = enUpgType != HUT_NONE ? "true" : "false";
  507. LPCSTR lpszKeepAlive = ::HP_HttpClient_IsKeepAlive(pSender) ? "true" : "false";
  508. strResult.AppendFormat("%s[Basic Info]%s", SEP1, CRLF);
  509. strResult.AppendFormat("%s%13s: %s%s", SEP2, "Version", strVersion, CRLF);
  510. strResult.AppendFormat("%s%13s: %u%s", SEP2, "Status Code", ::HP_HttpClient_GetStatusCode(pSender), CRLF);
  511. strResult.AppendFormat("%s%13s: %s%s", SEP2, "IsUpgrade", lpszUpgrade, CRLF);
  512. if(enUpgType != HUT_NONE)
  513. strResult.AppendFormat("%s%13s: %d%s", SEP2, "UpgradeType", enUpgType, CRLF);
  514. strResult.AppendFormat("%s%13s: %s%s", SEP2, "IsKeepAlive", lpszKeepAlive, CRLF);
  515. if(bWithContentLength)
  516. strResult.AppendFormat("%s%13s: %lld%s", SEP2, "ContentLength", ::HP_HttpClient_GetContentLength(pSender), CRLF);
  517. strResult.AppendFormat("%s%13s: %s%s", SEP2, "ContentType", ::HP_HttpClient_GetContentType(pSender), CRLF);
  518. return strResult;
  519. }