ServerDlg.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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 LPCTSTR CServerDlg::ADDRESS = _T("0.0.0.0");
  9. const USHORT CServerDlg::PORT = 5555;
  10. CServerDlg* CServerDlg::m_spThis = nullptr;
  11. CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
  12. : CDialogEx(CServerDlg::IDD, pParent)
  13. {
  14. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  15. m_spThis = this;
  16. // 初始化 SSL 全局环境参数
  17. ::HP_SSL_Initialize(SSL_SM_SERVER, g_s_iVerifyMode, g_s_lpszPemCertFile, g_s_lpszPemKeyFile, g_s_lpszKeyPasswod, g_s_lpszCAPemCertFileOrPath);
  18. VERIFY(::HP_SSL_IsValid());
  19. // 创建监听器对象
  20. m_pListener = ::Create_HP_TcpPullServerListener();
  21. // 创建 Socket 对象
  22. m_pServer = ::Create_HP_SSLPullServer(m_pListener);
  23. // 设置 Socket 监听器回调函数
  24. ::HP_Set_FN_Server_OnPrepareListen(m_pListener, OnPrepareListen);
  25. ::HP_Set_FN_Server_OnAccept(m_pListener, OnAccept);
  26. ::HP_Set_FN_Server_OnHandShake(m_pListener, OnHandShake);
  27. ::HP_Set_FN_Server_OnSend(m_pListener, OnSend);
  28. ::HP_Set_FN_Server_OnPullReceive(m_pListener, OnReceive);
  29. ::HP_Set_FN_Server_OnClose(m_pListener, OnClose);
  30. ::HP_Set_FN_Server_OnShutdown(m_pListener, OnShutdown);
  31. }
  32. CServerDlg::~CServerDlg()
  33. {
  34. // 销毁 Socket 对象
  35. ::Destroy_HP_SSLPullServer(m_spThis->m_pServer);
  36. // 销毁监听器对象
  37. ::Destroy_HP_TcpPullServerListener(m_pListener);
  38. // 清理 SSL 全局运行环境
  39. ::HP_SSL_Cleanup();
  40. }
  41. void CServerDlg::DoDataExchange(CDataExchange* pDX)
  42. {
  43. CDialogEx::DoDataExchange(pDX);
  44. DDX_Control(pDX, IDC_INFO, m_Info);
  45. DDX_Control(pDX, IDC_START, m_Start);
  46. DDX_Control(pDX, IDC_STOP, m_Stop);
  47. DDX_Control(pDX, IDC_ADDRESS, m_Address);
  48. DDX_Control(pDX, IDC_CONN_ID, m_HP_CONNID);
  49. DDX_Control(pDX, IDC_DISCONNECT, m_DisConn);
  50. }
  51. BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
  52. ON_WM_PAINT()
  53. ON_WM_QUERYDRAGICON()
  54. ON_BN_CLICKED(IDC_START, &CServerDlg::OnBnClickedStart)
  55. ON_BN_CLICKED(IDC_STOP, &CServerDlg::OnBnClickedStop)
  56. ON_MESSAGE(USER_INFO_MSG, OnUserInfoMsg)
  57. ON_BN_CLICKED(IDC_DISCONNECT, &CServerDlg::OnBnClickedDisconnect)
  58. ON_EN_CHANGE(IDC_CONN_ID, &CServerDlg::OnEnChangeHP_CONNID)
  59. ON_WM_VKEYTOITEM()
  60. END_MESSAGE_MAP()
  61. // CServerDlg message handlers
  62. BOOL CServerDlg::OnInitDialog()
  63. {
  64. CDialogEx::OnInitDialog();
  65. // Set the icon for this dialog. The framework does this automatically
  66. // when the application's main window is not a dialog
  67. SetIcon(m_hIcon, TRUE); // Set big icon
  68. SetIcon(m_hIcon, FALSE); // Set small icon
  69. // TODO: Add extra initialization here
  70. CString strTitle;
  71. CString strOriginTitle;
  72. GetWindowText(strOriginTitle);
  73. strTitle.Format(_T("%s - (%s:%d)"), strOriginTitle, ADDRESS, PORT);
  74. SetWindowText(strTitle);
  75. ::SetMainWnd(this);
  76. ::SetInfoList(&m_Info);
  77. SetAppState(ST_STOPPED);
  78. return TRUE; // return TRUE unless you set the focus to a control
  79. }
  80. // If you add a minimize button to your dialog, you will need the code below
  81. // to draw the icon. For MFC applications using the document/view model,
  82. // this is automatically done for you by the framework.
  83. void CServerDlg::OnPaint()
  84. {
  85. if (IsIconic())
  86. {
  87. CPaintDC dc(this); // device context for painting
  88. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  89. // Center icon in client rectangle
  90. int cxIcon = GetSystemMetrics(SM_CXICON);
  91. int cyIcon = GetSystemMetrics(SM_CYICON);
  92. CRect rect;
  93. GetClientRect(&rect);
  94. int x = (rect.Width() - cxIcon + 1) / 2;
  95. int y = (rect.Height() - cyIcon + 1) / 2;
  96. // Draw the icon
  97. dc.DrawIcon(x, y, m_hIcon);
  98. }
  99. else
  100. {
  101. CDialogEx::OnPaint();
  102. }
  103. }
  104. // The system calls this function to obtain the cursor to display while the user drags
  105. // the minimized window.
  106. HCURSOR CServerDlg::OnQueryDragIcon()
  107. {
  108. return static_cast<HCURSOR>(m_hIcon);
  109. }
  110. BOOL CServerDlg::PreTranslateMessage(MSG* pMsg)
  111. {
  112. if (
  113. pMsg->message == WM_KEYDOWN
  114. &&( pMsg->wParam == VK_ESCAPE
  115. || pMsg->wParam == VK_CANCEL
  116. || pMsg->wParam == VK_RETURN
  117. ))
  118. return TRUE;
  119. return CDialog::PreTranslateMessage(pMsg);
  120. }
  121. void CServerDlg::SetAppState(EnAppState state)
  122. {
  123. m_enState = state;
  124. if(this->GetSafeHwnd() == nullptr)
  125. return;
  126. m_Start.EnableWindow(m_enState == ST_STOPPED);
  127. m_Stop.EnableWindow(m_enState == ST_STARTED);
  128. m_Address.EnableWindow(m_enState == ST_STOPPED);
  129. m_DisConn.EnableWindow(m_enState == ST_STARTED && m_HP_CONNID.GetWindowTextLength() > 0);
  130. }
  131. void CServerDlg::OnBnClickedStart()
  132. {
  133. m_Address.GetWindowText(m_strAddress);
  134. m_strAddress.Trim();
  135. SetAppState(ST_STARTING);
  136. //m_Server->SetSocketBufferSize(64);
  137. if(::HP_Server_Start(m_spThis->m_pServer, ADDRESS, PORT))
  138. {
  139. ::LogServerStart(ADDRESS, PORT);
  140. SetAppState(ST_STARTED);
  141. }
  142. else
  143. {
  144. ::LogServerStartFail(::HP_Server_GetLastError(m_spThis->m_pServer), ::HP_Server_GetLastErrorDesc(m_spThis->m_pServer));
  145. SetAppState(ST_STOPPED);
  146. }
  147. }
  148. void CServerDlg::OnBnClickedStop()
  149. {
  150. SetAppState(ST_STOPPING);
  151. if(::HP_Server_Stop(m_spThis->m_pServer))
  152. {
  153. ::LogServerStop();
  154. SetAppState(ST_STOPPED);
  155. }
  156. else
  157. {
  158. ASSERT(FALSE);
  159. }
  160. }
  161. void CServerDlg::OnBnClickedDisconnect()
  162. {
  163. CString strHP_CONNID;
  164. m_HP_CONNID.GetWindowText(strHP_CONNID);
  165. HP_CONNID dwHP_CONNID = (HP_CONNID)_ttoi(strHP_CONNID);
  166. if(::HP_Server_Disconnect(m_spThis->m_pServer, dwHP_CONNID, TRUE))
  167. ::LogDisconnect(dwHP_CONNID);
  168. else
  169. ::LogDisconnectFail(dwHP_CONNID);
  170. }
  171. void CServerDlg::OnEnChangeHP_CONNID()
  172. {
  173. m_DisConn.EnableWindow(m_enState == ST_STARTED && m_HP_CONNID.GetWindowTextLength() > 0);
  174. }
  175. int CServerDlg::OnVKeyToItem(UINT nKey, CListBox* pListBox, UINT nIndex)
  176. {
  177. if(nKey == 'C')
  178. pListBox->ResetContent();
  179. return __super::OnVKeyToItem(nKey, pListBox, nIndex);
  180. }
  181. LRESULT CServerDlg::OnUserInfoMsg(WPARAM wp, LPARAM lp)
  182. {
  183. info_msg* msg = (info_msg*)wp;
  184. ::LogInfoMsg(msg);
  185. return 0;
  186. }
  187. En_HP_HandleResult CServerDlg::OnPrepareListen(SOCKET soListen)
  188. {
  189. TCHAR szAddress[40];
  190. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  191. USHORT usPort;
  192. ::HP_Server_GetListenAddress(m_spThis->m_pServer, szAddress, &iAddressLen, &usPort);
  193. ::PostOnPrepareListen(szAddress, usPort);
  194. return HR_OK;
  195. }
  196. En_HP_HandleResult CServerDlg::OnAccept(HP_CONNID dwHP_CONNID, SOCKET soClient)
  197. {
  198. BOOL bPass = TRUE;
  199. TCHAR szAddress[40];
  200. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  201. USHORT usPort;
  202. ::HP_Server_GetRemoteAddress(m_spThis->m_pServer, dwHP_CONNID, szAddress, &iAddressLen, &usPort);
  203. if(!m_spThis->m_strAddress.IsEmpty())
  204. {
  205. if(m_spThis->m_strAddress.CompareNoCase(szAddress) == 0)
  206. bPass = FALSE;
  207. }
  208. ::PostOnAccept(dwHP_CONNID, szAddress, usPort, bPass);
  209. if(bPass) ::HP_Server_SetConnectionExtra(m_spThis->m_pServer, dwHP_CONNID, new TPkgInfo(true, sizeof(TPkgHeader)));
  210. return bPass ? HR_OK : HR_ERROR;
  211. }
  212. En_HP_HandleResult CServerDlg::OnHandShake(HP_CONNID dwConnID)
  213. {
  214. ::PostOnHandShake(dwConnID);
  215. return HR_OK;
  216. }
  217. En_HP_HandleResult CServerDlg::OnSend(HP_CONNID dwHP_CONNID, const BYTE* pData, int iLength)
  218. {
  219. ::PostOnSend(dwHP_CONNID, pData, iLength);
  220. return HR_OK;
  221. }
  222. En_HP_HandleResult CServerDlg::OnReceive(HP_CONNID dwHP_CONNID, int iLength)
  223. {
  224. TPkgInfo* pInfo = m_spThis->FindPkgInfo(dwHP_CONNID);
  225. if(pInfo != nullptr)
  226. {
  227. int required = pInfo->length;
  228. int remain = iLength;
  229. while(remain >= required)
  230. {
  231. remain -= required;
  232. CBufferPtr buffer(required);
  233. En_HP_FetchResult result = ::HP_TcpPullServer_Fetch(m_spThis->m_pServer, dwHP_CONNID, buffer, (int)buffer.Size());
  234. if(result == FR_OK)
  235. {
  236. if(pInfo->is_header)
  237. {
  238. TPkgHeader* pHeader = (TPkgHeader*)buffer.Ptr();
  239. TRACE("[Server] head -> seq: %d, body_len: %d\n", pHeader->seq, pHeader->body_len);
  240. required = pHeader->body_len;
  241. }
  242. else
  243. {
  244. TPkgBody* pBody = (TPkgBody*)(BYTE*)buffer;
  245. TRACE("[Server] body -> name: %s, age: %d, desc: %s\n", pBody->name, pBody->age, pBody->desc);
  246. required = sizeof(TPkgHeader);
  247. }
  248. pInfo->is_header = !pInfo->is_header;
  249. pInfo->length = required;
  250. ::PostOnReceive(dwHP_CONNID, buffer, (int)buffer.Size());
  251. if(!::HP_Server_Send(m_spThis->m_pServer, dwHP_CONNID, buffer, (int)buffer.Size()))
  252. return HR_ERROR;
  253. }
  254. }
  255. }
  256. return HR_OK;
  257. }
  258. En_HP_HandleResult CServerDlg::OnClose(HP_CONNID dwHP_CONNID, En_HP_SocketOperation enOperation, int iErrorCode)
  259. {
  260. iErrorCode == SE_OK ? ::PostOnClose(dwHP_CONNID):
  261. ::PostOnError(dwHP_CONNID, enOperation, iErrorCode);
  262. m_spThis->RemovePkgInfo(dwHP_CONNID);
  263. return HR_OK;
  264. }
  265. En_HP_HandleResult CServerDlg::OnShutdown()
  266. {
  267. ::PostOnShutdown();
  268. return HR_OK;
  269. }
  270. TPkgInfo* CServerDlg::FindPkgInfo(HP_CONNID dwHP_CONNID)
  271. {
  272. PVOID pInfo = nullptr;
  273. ::HP_Server_GetConnectionExtra(m_spThis->m_pServer, dwHP_CONNID, &pInfo);
  274. return (TPkgInfo*)pInfo;
  275. }
  276. void CServerDlg::RemovePkgInfo(HP_CONNID dwHP_CONNID)
  277. {
  278. //CCriSecLock locallock(m_spThis->m_csPkgInfo);
  279. TPkgInfo* pInfo = FindPkgInfo(dwHP_CONNID);
  280. ASSERT(pInfo != nullptr);
  281. delete pInfo;
  282. }