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

ServerDlg.cpp 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. // ServerDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "Server.h"
  5. #include "ServerDlg.h"
  6. #include "afxdialogex.h"
  7. // CServerDlg dialog
  8. const CString SPECIAL_SERVER_NAME = _T("hpsocket.org");
  9. int SPECIAL_SERVER_INDEX = -1;
  10. const LPCTSTR CServerDlg::ADDRESS = _T("0.0.0.0");
  11. const USHORT CServerDlg::HTTP_PORT = 8080;
  12. const USHORT CServerDlg::HTTPS_PORT = 8443;
  13. CServerDlg* CServerDlg::m_spThis = nullptr;
  14. CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
  15. : CDialogEx(CServerDlg::IDD, pParent)
  16. {
  17. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  18. m_spThis = this;
  19. // 初始化 SSL 全局环境参数
  20. ::HP_SSL_Initialize(SSL_SM_SERVER, SSL_VM_NONE, g_s_lpszPemCertFile, g_s_lpszPemKeyFile, g_s_lpszKeyPasswod, g_s_lpszCAPemCertFileOrPath, SIN_ServerNameCallback);
  21. VERIFY(::HP_SSL_IsValid());
  22. SPECIAL_SERVER_INDEX = ::HP_SSL_AddServerContext(SSL_VM_NONE, g_s_lpszPemCertFile2, g_s_lpszPemKeyFile2, g_s_lpszKeyPasswod2, g_s_lpszCAPemCertFileOrPath2);
  23. VERIFY(SPECIAL_SERVER_INDEX > 0);
  24. // 创建监听器对象
  25. m_HttpServerListener = ::Create_HP_HttpServerListener();
  26. // 创建 HTTP Server 对象
  27. m_HttpServer = ::Create_HP_HttpServer(m_HttpServerListener);
  28. m_HttpsServer = ::Create_HP_HttpsServer(m_HttpServerListener);
  29. // 设置 HTTP 监听器回调函数
  30. ::HP_Set_FN_HttpServer_OnPrepareListen(m_HttpServerListener, OnPrepareListen);
  31. ::HP_Set_FN_HttpServer_OnAccept(m_HttpServerListener, OnAccept);
  32. ::HP_Set_FN_HttpServer_OnHandShake(m_HttpServerListener, OnHandShake);
  33. ::HP_Set_FN_HttpServer_OnSend(m_HttpServerListener, OnSend);
  34. ::HP_Set_FN_HttpServer_OnReceive(m_HttpServerListener, OnReceive);
  35. ::HP_Set_FN_HttpServer_OnClose(m_HttpServerListener, OnClose);
  36. ::HP_Set_FN_HttpServer_OnShutdown(m_HttpServerListener, OnShutdown);
  37. ::HP_Set_FN_HttpServer_OnMessageBegin(m_HttpServerListener, OnMessageBegin);
  38. ::HP_Set_FN_HttpServer_OnRequestLine(m_HttpServerListener, OnRequestLine);
  39. ::HP_Set_FN_HttpServer_OnHeader(m_HttpServerListener, OnHeader);
  40. ::HP_Set_FN_HttpServer_OnHeadersComplete(m_HttpServerListener, OnHeadersComplete);
  41. ::HP_Set_FN_HttpServer_OnBody(m_HttpServerListener, OnBody);
  42. ::HP_Set_FN_HttpServer_OnChunkHeader(m_HttpServerListener, OnChunkHeader);
  43. ::HP_Set_FN_HttpServer_OnChunkComplete(m_HttpServerListener, OnChunkComplete);
  44. ::HP_Set_FN_HttpServer_OnMessageComplete(m_HttpServerListener, OnMessageComplete);
  45. ::HP_Set_FN_HttpServer_OnUpgrade(m_HttpServerListener, OnUpgrade);
  46. ::HP_Set_FN_HttpServer_OnParseError(m_HttpServerListener, OnParseError);
  47. ::HP_Set_FN_HttpServer_OnWSMessageHeader(m_HttpServerListener, OnWSMessageHeader);
  48. ::HP_Set_FN_HttpServer_OnWSMessageBody(m_HttpServerListener, OnWSMessageBody);
  49. ::HP_Set_FN_HttpServer_OnWSMessageComplete(m_HttpServerListener, OnWSMessageComplete);
  50. }
  51. CServerDlg::~CServerDlg()
  52. {
  53. // 销毁 HTTP 对象
  54. ::Destroy_HP_HttpServer(m_HttpServer);
  55. ::Destroy_HP_HttpsServer(m_HttpsServer);
  56. // 销毁监听器对象
  57. ::Destroy_HP_HttpServerListener(m_HttpServerListener);
  58. // 清理 SSL 全局运行环境
  59. ::HP_SSL_Cleanup();
  60. }
  61. void CServerDlg::DoDataExchange(CDataExchange* pDX)
  62. {
  63. CDialogEx::DoDataExchange(pDX);
  64. DDX_Control(pDX, IDC_INFO, m_Info);
  65. DDX_Control(pDX, IDC_START, m_Start);
  66. DDX_Control(pDX, IDC_STOP, m_Stop);
  67. DDX_Control(pDX, IDC_CONN_ID, m_ConnID);
  68. DDX_Control(pDX, IDC_DISCONNECT, m_DisConn);
  69. DDX_Control(pDX, IDC_RELEASE, m_Release);
  70. DDX_Control(pDX, IDC_HTTP, m_RadioHttp);
  71. DDX_Control(pDX, IDC_HTTPS, m_RadioHttps);
  72. }
  73. BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
  74. ON_WM_PAINT()
  75. ON_WM_VKEYTOITEM()
  76. ON_WM_QUERYDRAGICON()
  77. ON_MESSAGE(USER_INFO_MSG, OnUserInfoMsg)
  78. ON_BN_CLICKED(IDC_START, &CServerDlg::OnBnClickedStart)
  79. ON_BN_CLICKED(IDC_STOP, &CServerDlg::OnBnClickedStop)
  80. ON_BN_CLICKED(IDC_DISCONNECT, &CServerDlg::OnBnClickedDisconnect)
  81. ON_EN_CHANGE(IDC_CONN_ID, &CServerDlg::OnEnChangeConnId)
  82. ON_BN_CLICKED(IDC_RELEASE, &CServerDlg::OnBnClickedRelease)
  83. END_MESSAGE_MAP()
  84. // CServerDlg message handlers
  85. BOOL CServerDlg::OnInitDialog()
  86. {
  87. CDialogEx::OnInitDialog();
  88. // Set the icon for this dialog. The framework does this automatically
  89. // when the application's main window is not a dialog
  90. SetIcon(m_hIcon, TRUE); // Set big icon
  91. SetIcon(m_hIcon, FALSE); // Set small icon
  92. // TODO: Add extra initialization here
  93. CString strTitle;
  94. CString strOriginTitle;
  95. GetWindowText(strOriginTitle);
  96. strTitle.Format(_T("%s - (%s:%d/%d)"), strOriginTitle, ADDRESS, HTTP_PORT, HTTPS_PORT);
  97. SetWindowText(strTitle);
  98. m_RadioHttp.SetCheck(BST_CHECKED);
  99. ::SetMainWnd(this);
  100. ::SetInfoList(&m_Info);
  101. SetAppState(ST_STOPPED);
  102. return TRUE; // return TRUE unless you set the focus to a control
  103. }
  104. // If you add a minimize button to your dialog, you will need the code below
  105. // to draw the icon. For MFC applications using the document/view model,
  106. // this is automatically done for you by the framework.
  107. void CServerDlg::OnPaint()
  108. {
  109. if (IsIconic())
  110. {
  111. CPaintDC dc(this); // device context for painting
  112. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  113. // Center icon in client rectangle
  114. int cxIcon = GetSystemMetrics(SM_CXICON);
  115. int cyIcon = GetSystemMetrics(SM_CYICON);
  116. CRect rect;
  117. GetClientRect(&rect);
  118. int x = (rect.Width() - cxIcon + 1) / 2;
  119. int y = (rect.Height() - cyIcon + 1) / 2;
  120. // Draw the icon
  121. dc.DrawIcon(x, y, m_hIcon);
  122. }
  123. else
  124. {
  125. CDialogEx::OnPaint();
  126. }
  127. }
  128. // The system calls this function to obtain the cursor to display while the user drags
  129. // the minimized window.
  130. HCURSOR CServerDlg::OnQueryDragIcon()
  131. {
  132. return static_cast<HCURSOR>(m_hIcon);
  133. }
  134. BOOL CServerDlg::PreTranslateMessage(MSG* pMsg)
  135. {
  136. if (
  137. pMsg->message == WM_KEYDOWN
  138. &&( pMsg->wParam == VK_ESCAPE
  139. || pMsg->wParam == VK_CANCEL
  140. || pMsg->wParam == VK_RETURN
  141. ))
  142. return TRUE;
  143. return CDialog::PreTranslateMessage(pMsg);
  144. }
  145. void CServerDlg::SetAppState(EnAppState state)
  146. {
  147. m_enState = state;
  148. if(this->GetSafeHwnd() == nullptr)
  149. return;
  150. m_Start.EnableWindow(m_enState == ST_STOPPED);
  151. m_Stop.EnableWindow(m_enState == ST_STARTED);
  152. m_RadioHttp.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  153. m_RadioHttps.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  154. m_DisConn.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  155. m_Release.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  156. }
  157. int CALLBACK CServerDlg::SIN_ServerNameCallback(LPCTSTR lpszServerName)
  158. {
  159. if(::SYS_IsIPAddress(lpszServerName))
  160. return 0;
  161. int len = lstrlen(lpszServerName);
  162. int diff = len - SPECIAL_SERVER_NAME.GetLength();
  163. if(diff < 0)
  164. return 0;
  165. if(SPECIAL_SERVER_NAME.CompareNoCase(lpszServerName + diff) != 0)
  166. return 0;
  167. return SPECIAL_SERVER_INDEX;
  168. }
  169. void CServerDlg::OnBnClickedStart()
  170. {
  171. SetAppState(ST_STARTING);
  172. if(::HP_Server_Start(m_HttpServer, ADDRESS, HTTP_PORT))
  173. {
  174. ::LogServerStart(ADDRESS, HTTP_PORT, HTTP_NAME);
  175. if(::HP_Server_Start(m_HttpsServer, ADDRESS, HTTPS_PORT))
  176. {
  177. ::LogServerStart(ADDRESS, HTTPS_PORT, HTTPS_NAME);
  178. SetAppState(ST_STARTED);
  179. }
  180. else
  181. {
  182. ::HP_Server_Stop(m_HttpServer);
  183. ::LogServerStartFail(::HP_Server_GetLastError(m_HttpsServer), ::HP_Server_GetLastErrorDesc(m_HttpsServer), HTTPS_NAME);
  184. SetAppState(ST_STOPPED);
  185. }
  186. }
  187. else
  188. {
  189. ::LogServerStartFail(::HP_Server_GetLastError(m_HttpServer), ::HP_Server_GetLastErrorDesc(m_HttpServer), HTTP_NAME);
  190. SetAppState(ST_STOPPED);
  191. }
  192. }
  193. void CServerDlg::OnBnClickedStop()
  194. {
  195. SetAppState(ST_STOPPING);
  196. if(!::HP_Server_Stop(m_HttpsServer))
  197. ASSERT(FALSE);
  198. ::LogServerStop(HTTPS_NAME);
  199. if(!::HP_Server_Stop(m_HttpServer))
  200. ASSERT(FALSE);
  201. ::LogServerStop(HTTP_NAME);
  202. SetAppState(ST_STOPPED);
  203. }
  204. void CServerDlg::OnBnClickedDisconnect()
  205. {
  206. CString strConnID;
  207. m_ConnID.GetWindowText(strConnID);
  208. HP_CONNID dwConnID = (HP_CONNID)_ttoi(strConnID);
  209. BOOL bHttp = m_RadioHttp.GetCheck() == BST_CHECKED;
  210. LPCTSTR lpszName = bHttp ? HTTP_NAME : HTTPS_NAME;
  211. HP_HttpServer pServer = bHttp ? m_HttpServer : m_HttpsServer;
  212. if(::HP_Server_Disconnect(pServer, dwConnID, TRUE))
  213. ::LogDisconnect(dwConnID, lpszName);
  214. else
  215. ::LogDisconnectFail(dwConnID, lpszName);
  216. }
  217. void CServerDlg::OnBnClickedRelease()
  218. {
  219. CString strConnID;
  220. m_ConnID.GetWindowText(strConnID);
  221. HP_CONNID dwConnID = (HP_CONNID)_ttoi(strConnID);
  222. BOOL bHttp = m_RadioHttp.GetCheck() == BST_CHECKED;
  223. LPCTSTR lpszName = bHttp ? HTTP_NAME : HTTPS_NAME;
  224. HP_HttpServer pServer = bHttp ? m_HttpServer : m_HttpsServer;
  225. if(::HP_HttpServer_Release(pServer, dwConnID))
  226. ::LogRelease(dwConnID, lpszName);
  227. else
  228. ::LogReleaseFail(dwConnID, lpszName);
  229. }
  230. void CServerDlg::OnEnChangeConnId()
  231. {
  232. m_RadioHttp.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  233. m_RadioHttps.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  234. m_DisConn.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  235. m_Release.EnableWindow(m_enState == ST_STARTED && m_ConnID.GetWindowTextLength() > 0);
  236. }
  237. int CServerDlg::OnVKeyToItem(UINT nKey, CListBox* pListBox, UINT nIndex)
  238. {
  239. if(nKey == 'C')
  240. pListBox->ResetContent();
  241. return __super::OnVKeyToItem(nKey, pListBox, nIndex);
  242. }
  243. LRESULT CServerDlg::OnUserInfoMsg(WPARAM wp, LPARAM lp)
  244. {
  245. info_msg* msg = (info_msg*)wp;
  246. ::LogInfoMsg(msg);
  247. return 0;
  248. }
  249. // ------------------------------------------------------------------------------------------------------------- //
  250. EnHandleResult CServerDlg::OnPrepareListen(HP_Server pSender, SOCKET soListen)
  251. {
  252. TCHAR szAddress[40];
  253. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  254. USHORT usPort;
  255. ::HP_Server_GetListenAddress(pSender, szAddress, &iAddressLen, &usPort);
  256. ::PostOnPrepareListen(szAddress, usPort, m_spThis->GetSenderName(pSender));
  257. return HR_OK;
  258. }
  259. EnHandleResult CServerDlg::OnAccept(HP_Server pSender, HP_CONNID dwConnID, SOCKET soClient)
  260. {
  261. BOOL bPass = TRUE;
  262. TCHAR szAddress[40];
  263. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  264. USHORT usPort;
  265. ::HP_Server_GetRemoteAddress(pSender, dwConnID, szAddress, &iAddressLen, &usPort);
  266. ::PostOnAccept(dwConnID, szAddress, usPort, bPass, m_spThis->GetSenderName(pSender));
  267. return bPass ? HR_OK : HR_ERROR;
  268. }
  269. EnHandleResult CServerDlg::OnHandShake(HP_Server pSender, HP_CONNID dwConnID)
  270. {
  271. ::PostOnHandShake(dwConnID, m_spThis->GetSenderName(pSender));
  272. return HR_OK;
  273. }
  274. EnHandleResult CServerDlg::OnReceive(HP_Server pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
  275. {
  276. ::PostOnReceive(dwConnID, pData, iLength, m_spThis->GetSenderName(pSender));
  277. if(::HP_Server_Send(pSender, dwConnID, pData, iLength))
  278. return HR_OK;
  279. else
  280. return HR_ERROR;
  281. }
  282. EnHandleResult CServerDlg::OnSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
  283. {
  284. ::PostOnSend(dwConnID, pData, iLength, m_spThis->GetSenderName(pSender));
  285. return HR_OK;
  286. }
  287. EnHandleResult CServerDlg::OnClose(HP_Server pSender, HP_CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
  288. {
  289. iErrorCode == SE_OK ? ::PostOnClose(dwConnID, m_spThis->GetSenderName(pSender)) :
  290. ::PostOnError(dwConnID, enOperation, iErrorCode, m_spThis->GetSenderName(pSender)) ;
  291. CBufferPtr* pBuffer = nullptr;
  292. ::HP_Server_GetConnectionExtra(pSender, dwConnID, (PVOID*)&pBuffer);
  293. if(pBuffer) delete pBuffer;
  294. return HR_OK;
  295. }
  296. EnHandleResult CServerDlg::OnShutdown(HP_Server pSender)
  297. {
  298. ::PostOnShutdown(m_spThis->GetSenderName(pSender));
  299. return HR_OK;
  300. }
  301. // ------------------------------------------------------------------------------------------------------------- //
  302. EnHttpParseResult CServerDlg::OnMessageBegin(HP_HttpServer pSender, HP_CONNID dwConnID)
  303. {
  304. ::PostOnMessageBegin(dwConnID, m_spThis->GetSenderName(pSender));
  305. return HPR_OK;
  306. }
  307. EnHttpParseResult CServerDlg::OnRequestLine(HP_HttpServer pSender, HP_CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)
  308. {
  309. ::PostOnRequestLine(dwConnID, lpszMethod, ::HP_HttpServer_GetUrlFieldSet(pSender, dwConnID), lpszUrl, m_spThis->GetSenderName(pSender));
  310. return HPR_OK;
  311. }
  312. EnHttpParseResult CServerDlg::OnHeader(HP_HttpServer pSender, HP_CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
  313. {
  314. ::PostOnHeader(dwConnID, lpszName, lpszValue, m_spThis->GetSenderName(pSender));
  315. return HPR_OK;
  316. }
  317. EnHttpParseResult CServerDlg::OnHeadersComplete(HP_HttpServer pSender, HP_CONNID dwConnID)
  318. {
  319. CStringA strSummary = m_spThis->GetHeaderSummary(pSender, dwConnID, " ", 0, TRUE);
  320. ::PostOnHeadersComplete(dwConnID, strSummary, m_spThis->GetSenderName(pSender));
  321. return HPR_OK;
  322. }
  323. EnHttpParseResult CServerDlg::OnBody(HP_HttpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
  324. {
  325. ::PostOnBody(dwConnID, pData, iLength, m_spThis->GetSenderName(pSender));
  326. return HPR_OK;
  327. }
  328. EnHttpParseResult CServerDlg::OnChunkHeader(HP_HttpServer pSender, HP_CONNID dwConnID, int iLength)
  329. {
  330. ::PostOnChunkHeader(dwConnID, iLength, m_spThis->GetSenderName(pSender));
  331. return HPR_OK;
  332. }
  333. EnHttpParseResult CServerDlg::OnChunkComplete(HP_HttpServer pSender, HP_CONNID dwConnID)
  334. {
  335. ::PostOnChunkComplete(dwConnID, m_spThis->GetSenderName(pSender));
  336. return HPR_OK;
  337. }
  338. EnHttpParseResult CServerDlg::OnMessageComplete(HP_HttpServer pSender, HP_CONNID dwConnID)
  339. {
  340. ::PostOnMessageComplete(dwConnID, m_spThis->GetSenderName(pSender));
  341. if(::HP_HttpServer_IsUpgrade(pSender, dwConnID))
  342. return HPR_OK;
  343. CStringA strBody = m_spThis->GetHeaderSummary(pSender, dwConnID, " ", 0, FALSE);
  344. int iBodyLength = strBody.GetLength();
  345. BOOL bSkipBody = FALSE;
  346. if(strcmp(::HP_HttpServer_GetMethod(pSender, dwConnID), HTTP_METHOD_HEAD) == 0)
  347. bSkipBody = TRUE;
  348. CStringA strContentLength;
  349. strContentLength.Format("%u", iBodyLength);
  350. DWORD dwSeq = 1;
  351. LPCSTR lpszReqSequence = nullptr;
  352. if(::HP_HttpServer_GetCookie(pSender, dwConnID, "__reqSequence", &lpszReqSequence))
  353. dwSeq += atoi(lpszReqSequence);
  354. CStringA strSeqCookie;
  355. strSeqCookie.Format("__reqSequence=%u; path=/", dwSeq);
  356. THeader header[] = {{"Content-Type", "text/plain"}, {"Content-Length", strContentLength}, {"Set-Cookie", strSeqCookie}};
  357. int iHeaderCount = sizeof(header) / sizeof(THeader);
  358. if(bSkipBody)
  359. {
  360. strBody.Empty();
  361. iBodyLength = 0;
  362. }
  363. ::HP_HttpServer_SendResponse(pSender,
  364. dwConnID, HSC_OK,
  365. "HP Http Server OK",
  366. header, iHeaderCount,
  367. (const BYTE*)(LPCSTR)strBody,
  368. iBodyLength);
  369. if(!::HP_HttpServer_IsKeepAlive(pSender, dwConnID))
  370. ::HP_HttpServer_Release(pSender, dwConnID);
  371. return HPR_OK;
  372. }
  373. EnHttpParseResult CServerDlg::OnUpgrade(HP_HttpServer pSender, HP_CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
  374. {
  375. ::PostOnUpgrade(dwConnID, enUpgradeType, m_spThis->GetSenderName(pSender));
  376. if(enUpgradeType == HUT_HTTP_TUNNEL)
  377. {
  378. ::HP_HttpServer_SendResponse(pSender, dwConnID, HSC_OK, "Connection Established", nullptr, 0, nullptr, 0);
  379. }
  380. else if(enUpgradeType == HUT_WEB_SOCKET)
  381. {
  382. THeader header[] = {{"Connection", UPGRADE_HEADER},
  383. {UPGRADE_HEADER, WEB_SOCKET_HEADER_VALUE},
  384. {nullptr, nullptr},
  385. {nullptr, nullptr}};
  386. LPCSTR lpszAccept = nullptr;
  387. if(!::HP_HttpServer_GetHeader(pSender, dwConnID, "Sec-WebSocket-Key", &lpszAccept))
  388. return HPR_ERROR;
  389. CStringA strAccept;
  390. ::MakeSecWebSocketAccept(lpszAccept, strAccept);
  391. header[2].name = "Sec-WebSocket-Accept";
  392. header[2].value = strAccept;
  393. LPCSTR lpszProtocol = nullptr;
  394. if(::HP_HttpServer_GetHeader(pSender, dwConnID, "Sec-WebSocket-Protocol", &lpszProtocol))
  395. {
  396. int i = 0;
  397. CStringA strProtocol(lpszProtocol);
  398. CStringA strFirst = strProtocol.Tokenize(", ", i);
  399. if(!strFirst.IsEmpty())
  400. {
  401. header[3].name = "Sec-WebSocket-Protocol";
  402. header[3].value = strFirst;
  403. }
  404. }
  405. int iHeaderCount = sizeof(header) / sizeof(THeader);
  406. ::HP_HttpServer_SendResponse(pSender, dwConnID, HSC_SWITCHING_PROTOCOLS, nullptr, header, iHeaderCount, nullptr, 0);
  407. ::HP_Server_SetConnectionExtra(pSender, dwConnID, new CBufferPtr);
  408. }
  409. else
  410. ASSERT(FALSE);
  411. return HPR_OK;
  412. }
  413. EnHttpParseResult CServerDlg::OnParseError(HP_HttpServer pSender, HP_CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
  414. {
  415. ::PostOnParseError(dwConnID, iErrorCode, lpszErrorDesc, m_spThis->GetSenderName(pSender));
  416. return HPR_OK;
  417. }
  418. // ------------------------------------------------------------------------------------------------------------- //
  419. En_HP_HandleResult CServerDlg::OnWSMessageHeader(HP_HttpServer pSender, HP_CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
  420. {
  421. ::PostOnWSMessageHeader(dwConnID, bFinal, iReserved, iOperationCode, lpszMask, ullBodyLen, m_spThis->GetSenderName(pSender));
  422. return HR_OK;
  423. }
  424. En_HP_HandleResult CServerDlg::OnWSMessageBody(HP_HttpServer pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
  425. {
  426. ::PostOnWSMessageBody(dwConnID, pData, iLength, m_spThis->GetSenderName(pSender));
  427. CBufferPtr* pBuffer = nullptr;
  428. ::HP_Server_GetConnectionExtra(pSender, dwConnID, (PVOID*)&pBuffer);
  429. VERIFY(pBuffer);
  430. pBuffer->Cat(pData, iLength);
  431. return HR_OK;
  432. }
  433. En_HP_HandleResult CServerDlg::OnWSMessageComplete(HP_HttpServer pSender, HP_CONNID dwConnID)
  434. {
  435. ::PostOnWSMessageComplete(dwConnID, m_spThis->GetSenderName(pSender));
  436. CBufferPtr* pBuffer = nullptr;
  437. ::HP_Server_GetConnectionExtra(pSender, dwConnID, (PVOID*)&pBuffer);
  438. VERIFY(pBuffer);
  439. BOOL bFinal;
  440. BYTE iReserved, iOperationCode;
  441. VERIFY(::HP_HttpServer_GetWSMessageState(pSender, dwConnID, &bFinal, &iReserved, &iOperationCode, nullptr, nullptr, nullptr));
  442. ::HP_HttpServer_SendWSMessage(pSender, dwConnID, bFinal, iReserved, iOperationCode, nullptr, pBuffer->Ptr(), (int)pBuffer->Size(), 0);
  443. pBuffer->Free();
  444. if(iOperationCode == 0x8)
  445. ::HP_Server_Disconnect(pSender, dwConnID, TRUE);
  446. return HR_OK;
  447. }
  448. // ------------------------------------------------------------------------------------------------------------- //
  449. CStringA CServerDlg::GetHeaderSummary(HP_HttpServer pSender, HP_CONNID dwConnID, LPCSTR lpszSep, int iSepCount, BOOL bWithContentLength)
  450. {
  451. CStringA SEP1;
  452. for(int i = 0; i < iSepCount; i++)
  453. SEP1 += lpszSep;
  454. CStringA SEP2(SEP1);
  455. SEP2 += lpszSep;
  456. CStringA strResult;
  457. USHORT usUrlFieldSet = ::HP_HttpServer_GetUrlFieldSet(pSender, dwConnID);
  458. strResult.AppendFormat("%s[URL Fields]%s", SEP1, CRLF);
  459. strResult.AppendFormat("%s%8s: %s%s", SEP2, "SCHEMA", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_SCHEMA), CRLF);
  460. strResult.AppendFormat("%s%8s: %s%s", SEP2, "HOST", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_HOST), CRLF);
  461. strResult.AppendFormat("%s%8s: %s%s", SEP2, "PORT", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_PORT), CRLF);
  462. strResult.AppendFormat("%s%8s: %s%s", SEP2, "PATH", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_PATH), CRLF);
  463. strResult.AppendFormat("%s%8s: %s%s", SEP2, "QUERY", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_QUERY), CRLF);
  464. strResult.AppendFormat("%s%8s: %s%s", SEP2, "FRAGMENT", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_FRAGMENT), CRLF);
  465. strResult.AppendFormat("%s%8s: %s%s", SEP2, "USERINFO", ::HP_HttpServer_GetUrlField(pSender, dwConnID, HUF_USERINFO), CRLF);
  466. DWORD dwHeaderCount = 0;
  467. ::HP_HttpServer_GetAllHeaders(pSender, dwConnID, nullptr, &dwHeaderCount);
  468. strResult.AppendFormat("%s[Request Headers]%s", SEP1, CRLF);
  469. if(dwHeaderCount == 0)
  470. strResult.AppendFormat("%s(no header)%s", SEP2, CRLF);
  471. else
  472. {
  473. unique_ptr<THeader[]> headers(new THeader[dwHeaderCount]);
  474. VERIFY(::HP_HttpServer_GetAllHeaders(pSender, dwConnID, headers.get(), &dwHeaderCount));
  475. for(DWORD i = 0; i < dwHeaderCount; i++)
  476. strResult.AppendFormat("%s%s: %s%s", SEP2, headers[i].name, headers[i].value, CRLF);
  477. }
  478. DWORD dwCookieCount = 0;
  479. ::HP_HttpServer_GetAllCookies(pSender, dwConnID, nullptr, &dwCookieCount);
  480. strResult.AppendFormat("%s[Cookies]%s", SEP1, CRLF);
  481. if(dwCookieCount == 0)
  482. strResult.AppendFormat("%s(no cookie)%s", SEP2, CRLF);
  483. else
  484. {
  485. unique_ptr<TCookie[]> cookies(new TCookie[dwCookieCount]);
  486. VERIFY(::HP_HttpServer_GetAllCookies(pSender, dwConnID, cookies.get(), &dwCookieCount));
  487. for(DWORD i = 0; i < dwCookieCount; i++)
  488. strResult.AppendFormat("%s%s: %s%s", SEP2, cookies[i].name, cookies[i].value, CRLF);
  489. }
  490. CStringA strVersion;
  491. ::HttpVersionToString((EnHttpVersion)::HP_HttpServer_GetVersion(pSender, dwConnID), strVersion);
  492. EnHttpUpgradeType enUpgType = ::HP_HttpServer_GetUpgradeType(pSender, dwConnID);
  493. LPCSTR lpszUpgrade = enUpgType != HUT_NONE ? "true" : "false";
  494. LPCSTR lpszKeepAlive = ::HP_HttpServer_IsKeepAlive(pSender, dwConnID) ? "true" : "false";
  495. strResult.AppendFormat("%s[Basic Info]%s", SEP1, CRLF);
  496. strResult.AppendFormat("%s%13s: %s%s", SEP2, "Version", strVersion, CRLF);
  497. strResult.AppendFormat("%s%13s: %s%s", SEP2, "Method", ::HP_HttpServer_GetMethod(pSender, dwConnID), CRLF);
  498. strResult.AppendFormat("%s%13s: %s%s", SEP2, "IsUpgrade", lpszUpgrade, CRLF);
  499. if(enUpgType != HUT_NONE)
  500. strResult.AppendFormat("%s%13s: %d%s", SEP2, "UpgradeType", enUpgType, CRLF);
  501. strResult.AppendFormat("%s%13s: %s%s", SEP2, "IsKeepAlive", lpszKeepAlive, CRLF);
  502. if(bWithContentLength)
  503. strResult.AppendFormat("%s%13s: %lld%s", SEP2, "ContentLength", ::HP_HttpServer_GetContentLength(pSender, dwConnID), CRLF);
  504. strResult.AppendFormat("%s%13s: %s%s", SEP2, "ContentType", ::HP_HttpServer_GetContentType(pSender, dwConnID), CRLF);
  505. return strResult;
  506. }
  507. LPCTSTR CServerDlg::GetSenderName(HP_HttpServer pSender)
  508. {
  509. return pSender == m_HttpServer ? HTTP_NAME : (pSender == m_HttpsServer ? HTTPS_NAME : nullptr);
  510. }