ServerDlg.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. // ServerDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "Server.h"
  5. #include "ServerDlg.h"
  6. #include "afxdialogex.h"
  7. #include "../../../../Common/Src/WaitFor.h"
  8. #ifdef _WIN64
  9. #ifdef _DEBUG
  10. #pragma comment(lib, "../../../Bin/HPSocket/x64/HPSocket_UD.lib")
  11. #else
  12. #pragma comment(lib, "../../../Bin/HPSocket/x64/HPSocket_U.lib")
  13. #endif
  14. #else
  15. #ifdef _DEBUG
  16. #pragma comment(lib, "../../../Bin/HPSocket/x86/HPSocket_UD.lib")
  17. #else
  18. #pragma comment(lib, "../../../Bin/HPSocket/x86/HPSocket_U.lib")
  19. #endif
  20. #endif
  21. // CServerDlg dialog
  22. #define DEFAULT_ADDRESS _T("0.0.0.0")
  23. #define DEFAULT_PORT _T("5555")
  24. #ifdef _DEBUG
  25. #define DEF_SHOW_LOG BST_CHECKED
  26. #else
  27. #define DEF_SHOW_LOG BST_UNCHECKED
  28. #endif
  29. #define DEF_HTTP_PORT 80
  30. #define DEF_HTTPS_PORT 443
  31. #define HTTPS_FLAG "CONNECT"
  32. #define HTTP_SCHEME "http://"
  33. #define HTTP_1_1 "HTTP/1.1"
  34. #define HEAD_CONN "Connection:"
  35. #define HEAD_PROXY_CONN "Proxy-Connection:"
  36. #define HTTPS_RESP "HTTP/1.1 200 Connection Established\r\n\r\n"
  37. #define IE_OPT_DIALOG "rundll32.exe shell32.dll, Control_RunDLL inetcpl.cpl, , 4"
  38. static int HTTP_SCHEME_LEN = (int)strlen(HTTP_SCHEME);
  39. static int HEAD_CONN_LEN = (int)strlen(HEAD_CONN);
  40. static int HEAD_PROXY_CONN_LEN = (int)strlen(HEAD_PROXY_CONN);
  41. static int HTTPS_RESP_LEN = (int)strlen(HTTPS_RESP);
  42. CServerDlg::CServerDlg(CWnd* pParent /*=nullptr*/)
  43. : CDialogEx(CServerDlg::IDD, pParent)
  44. , m_pServerListener(new CTcpServerListenerImpl(this))
  45. , m_pAgentListener(new CTcpAgentListenerImpl(this))
  46. , m_Server(m_pServerListener)
  47. , m_Agent(m_pAgentListener)
  48. {
  49. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  50. }
  51. void CServerDlg::DoDataExchange(CDataExchange* pDX)
  52. {
  53. CDialogEx::DoDataExchange(pDX);
  54. DDX_Control(pDX, IDC_INFO, m_Info);
  55. DDX_Control(pDX, IDC_START, m_Start);
  56. DDX_Control(pDX, IDC_STOP, m_Stop);
  57. DDX_Control(pDX, IDC_PORT, m_Port);
  58. DDX_Control(pDX, IDC_OPTIONS, m_Options);
  59. DDX_Control(pDX, IDC_SHOWLOG, m_ShowLog);
  60. }
  61. BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
  62. ON_WM_PAINT()
  63. ON_WM_QUERYDRAGICON()
  64. ON_BN_CLICKED(IDC_START, &CServerDlg::OnBnClickedStart)
  65. ON_BN_CLICKED(IDC_STOP, &CServerDlg::OnBnClickedStop)
  66. ON_MESSAGE(USER_INFO_MSG, OnUserInfoMsg)
  67. ON_WM_VKEYTOITEM()
  68. ON_WM_CLOSE()
  69. ON_BN_CLICKED(IDC_OPTIONS, &CServerDlg::OnBnClickedOptions)
  70. END_MESSAGE_MAP()
  71. // CServerDlg message handlers
  72. BOOL CServerDlg::OnInitDialog()
  73. {
  74. CDialogEx::OnInitDialog();
  75. // Set the icon for this dialog. The framework does this automatically
  76. // when the application's main window is not a dialog
  77. SetIcon(m_hIcon, TRUE); // Set big icon
  78. SetIcon(m_hIcon, FALSE); // Set small icon
  79. // TODO: Add extra initialization here
  80. CString strTitle;
  81. CString strOriginTitle;
  82. m_Port.SetWindowText(DEFAULT_PORT);
  83. m_ShowLog.SetCheck(DEF_SHOW_LOG);
  84. ::SetMainWnd(this);
  85. ::SetInfoList(&m_Info);
  86. SetAppState(ST_STOPPED);
  87. return TRUE; // return TRUE unless you set the focus to a control
  88. }
  89. void CServerDlg::OnClose()
  90. {
  91. /*
  92. if(m_Server->GetState() != SS_STOPED)
  93. {
  94. this->MessageBox(_T("stop IOCP Server first, pls !"), _T("forbiddden"));
  95. return;
  96. }
  97. */
  98. ::SetMainWnd(nullptr);
  99. __super::OnClose();
  100. if(m_Server->HasStarted())
  101. m_Server->Stop();
  102. if(m_Agent->HasStarted())
  103. m_Agent->Stop();
  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 CServerDlg::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 CServerDlg::OnQueryDragIcon()
  132. {
  133. return static_cast<HCURSOR>(m_hIcon);
  134. }
  135. BOOL CServerDlg::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
  142. ))
  143. return TRUE;
  144. return CDialog::PreTranslateMessage(pMsg);
  145. }
  146. void CServerDlg::SetAppState(EnAppState state)
  147. {
  148. if(m_enState == state)
  149. return;
  150. m_enState = state;
  151. if(this->GetSafeHwnd() == nullptr)
  152. return;
  153. m_Start.EnableWindow(m_enState == ST_STOPPED);
  154. m_Stop.EnableWindow(m_enState == ST_STARTED);
  155. m_Port.EnableWindow(m_enState == ST_STOPPED);
  156. //m_Options.EnableWindow(m_enState == ST_STOPPED);
  157. m_ShowLog.EnableWindow(m_enState == ST_STOPPED);
  158. }
  159. void CServerDlg::OnBnClickedStart()
  160. {
  161. CString strPort;
  162. m_Port.GetWindowText(strPort);
  163. USHORT usPort = (USHORT)_ttoi(strPort);
  164. if(usPort == 0)
  165. {
  166. MessageBox(_T("Listen Port invalid, pls check!"), _T("Params Error"), MB_OK);
  167. m_Port.SetFocus();
  168. return;
  169. }
  170. m_bLog = (m_ShowLog.GetCheck() == BST_CHECKED);
  171. SetAppState(ST_STARTING);
  172. //m_Server->SetFreeSocketObjPool(500);
  173. //m_Server->SetFreeSocketObjHold(1500);
  174. //m_Server->SetFreeBufferObjPool(2000);
  175. //m_Server->SetFreeBufferObjHold(6000);
  176. //m_Server->SetAcceptSocketCount(50);
  177. m_Server->SetSendPolicy(SP_DIRECT);
  178. m_Agent->SetSendPolicy(SP_DIRECT);
  179. if(m_Server->Start(DEFAULT_ADDRESS, usPort))
  180. {
  181. VERIFY(m_Agent->Start(nullptr, FALSE));
  182. ::LogServerStart(DEFAULT_ADDRESS, usPort);
  183. SetAppState(ST_STARTED);
  184. }
  185. else
  186. {
  187. ::LogServerStartFail(m_Server->GetLastError(), m_Server->GetLastErrorDesc());
  188. SetAppState(ST_STOPPED);
  189. }
  190. }
  191. void CServerDlg::OnBnClickedStop()
  192. {
  193. SetAppState(ST_STOPPING);
  194. VERIFY(m_Server->Stop());
  195. VERIFY(m_Agent->Stop());
  196. ::LogServerStop();
  197. SetAppState(ST_STOPPED);
  198. }
  199. void CServerDlg::OnBnClickedOptions()
  200. {
  201. ::WinExec(IE_OPT_DIALOG, 0);
  202. }
  203. int CServerDlg::OnVKeyToItem(UINT nKey, CListBox* pListBox, UINT nIndex)
  204. {
  205. if(nKey == 'C')
  206. pListBox->ResetContent();
  207. return __super::OnVKeyToItem(nKey, pListBox, nIndex);
  208. }
  209. LRESULT CServerDlg::OnUserInfoMsg(WPARAM wp, LPARAM lp)
  210. {
  211. info_msg* msg = (info_msg*)wp;
  212. ::LogInfoMsg(msg);
  213. return 0;
  214. }
  215. EnHandleResult CTcpServerListenerImpl::OnPrepareListen(SOCKET soListen)
  216. {
  217. TCHAR szAddress[40];
  218. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  219. USHORT usPort;
  220. m_pDlg->m_Server->GetListenAddress(szAddress, iAddressLen, usPort);
  221. ::PostOnPrepareListen(szAddress, usPort);
  222. return HR_OK;
  223. }
  224. EnHandleResult CTcpServerListenerImpl::OnAccept(CONNID dwConnID, SOCKET soClient)
  225. {
  226. //if(m_pDlg->m_bLog) ::PostOnAccept2(dwConnID);
  227. return HR_OK;
  228. }
  229. EnHandleResult CTcpServerListenerImpl::OnSend(CONNID dwConnID, const BYTE* pData, int iLength)
  230. {
  231. //if(m_pDlg->m_bLog) ::PostOnSend(dwConnID, pData, iLength);
  232. return HR_OK;
  233. }
  234. EnHandleResult CTcpServerListenerImpl::OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)
  235. {
  236. //if(m_pDlg->m_bLog) ::PostOnReceive(dwConnID, pData, iLength);
  237. CONNID dwAgentID = 0;
  238. if(!m_pDlg->m_Server->GetConnectionExtra(dwConnID, (PVOID*)&dwAgentID))
  239. return HR_IGNORE;
  240. EnHandleResult rs = HR_ERROR;
  241. BYTE* pData2 = (BYTE*)pData;
  242. int iLength2 = iLength;
  243. BOOL isHttps;
  244. CString strAddr;
  245. USHORT usPort;
  246. if(dwAgentID == 0)
  247. {
  248. if(ParseRequestHeader(pData2, iLength2, isHttps, strAddr, usPort))
  249. {
  250. if(m_pDlg->m_Agent->Connect(strAddr, usPort, &dwAgentID))
  251. {
  252. m_pDlg->m_Agent->SetConnectionExtra(dwAgentID, (PVOID)dwConnID);
  253. m_pDlg->m_Server->SetConnectionExtra(dwConnID, (PVOID)dwAgentID);
  254. if(isHttps)
  255. {
  256. if(m_pDlg->m_Server->Send(dwConnID, (BYTE*)HTTPS_RESP, HTTPS_RESP_LEN))
  257. rs = HR_OK;
  258. }
  259. else
  260. {
  261. if(m_pDlg->m_Agent->Send(dwAgentID, pData2, iLength2))
  262. rs = HR_OK;
  263. }
  264. }
  265. }
  266. }
  267. else
  268. {
  269. BOOL isOK = TRUE;
  270. if(CheckIfHttp(pData2, iLength2))
  271. isOK = ParseRequestHeader(pData2, iLength2, isHttps, strAddr, usPort);
  272. if(isOK && m_pDlg->m_Agent->Send(dwAgentID, pData2, iLength2))
  273. rs = HR_OK;
  274. }
  275. return rs;
  276. }
  277. EnHandleResult CTcpServerListenerImpl::OnClose(CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
  278. {
  279. /*
  280. if(m_pDlg->m_bLog)
  281. {
  282. iErrorCode == SE_OK ? ::PostOnClose(dwConnID) :
  283. ::PostOnError(dwConnID, enOperation, iErrorCode);
  284. }
  285. */
  286. DetachConnInfo(dwConnID);
  287. return HR_OK;
  288. }
  289. EnHandleResult CTcpServerListenerImpl::OnShutdown()
  290. {
  291. return HR_OK;
  292. }
  293. void CTcpServerListenerImpl::DetachConnInfo(CONNID dwConnID)
  294. {
  295. CONNID dwAgentID = 0;
  296. BOOL bExist = m_pDlg->m_Server->GetConnectionExtra(dwConnID, (PVOID*)&dwAgentID);
  297. if(bExist && dwAgentID != 0)
  298. {
  299. m_pDlg->m_Agent->SetConnectionExtra(dwAgentID, (PVOID)0);
  300. m_pDlg->m_Agent->Disconnect(dwAgentID);
  301. }
  302. }
  303. BOOL CTcpServerListenerImpl::ParseRequestHeader(BYTE*& pData, int& iLength, BOOL& isHttps, CString& strAddr, USHORT& usPort)
  304. {
  305. usPort = 0;
  306. isHttps = FALSE;
  307. strAddr.Empty();
  308. BYTE* pTemp = pData;
  309. int i = 0;
  310. for(; i < iLength; ++i, ++pTemp)
  311. {
  312. if(*pTemp == '\r')
  313. break;
  314. }
  315. if(i == iLength)
  316. return FALSE;
  317. CStringA strContent;
  318. int iBufferLen = (int)(pTemp - pData);
  319. LPSTR lpstr = strContent.GetBufferSetLength(iBufferLen);
  320. memcpy(lpstr, pData, iBufferLen);
  321. int iPos = 0;
  322. int iPos1 = 0;
  323. int iSchemePos = 0;
  324. BOOL bHttp11 = FALSE;
  325. CStringA strHost;
  326. CStringA strToken = strContent.Tokenize(" ", iPos);
  327. for(int i = 0; !strToken.IsEmpty() && i < 3; i++)
  328. {
  329. if(i == 0)
  330. {
  331. if(strToken.CompareNoCase(HTTPS_FLAG) == 0)
  332. isHttps = TRUE;
  333. else
  334. iPos1 = iPos;
  335. strToken = strContent.Tokenize(" ", iPos);
  336. }
  337. else if(i == 1)
  338. {
  339. if(isHttps)
  340. strHost = strToken;
  341. else
  342. {
  343. if(strToken.Find(HTTP_SCHEME) != 0)
  344. return FALSE;
  345. int iPos2 = 0;
  346. iSchemePos = iPos1;
  347. strToken.Replace(HTTP_SCHEME, "");
  348. strHost = strToken.Tokenize("/", iPos2);
  349. }
  350. strToken = strContent.Tokenize(" ", iPos);
  351. }
  352. else if(i == 2)
  353. {
  354. if(strToken.CompareNoCase(HTTP_1_1) == 0)
  355. bHttp11 = TRUE;
  356. }
  357. }
  358. if(strHost.IsEmpty())
  359. return FALSE;
  360. iPos = 0;
  361. strToken = strHost.Tokenize(":", iPos);
  362. for(int i = 0; !strToken.IsEmpty() && i < 2; i++)
  363. {
  364. if(i == 0)
  365. {
  366. strAddr = strToken;
  367. strToken = strHost.Tokenize(":", iPos);
  368. }
  369. else if(i == 1)
  370. {
  371. usPort = atoi(strToken);
  372. }
  373. }
  374. if(usPort == 0)
  375. usPort = isHttps ? DEF_HTTPS_PORT : DEF_HTTP_PORT;
  376. if(!isHttps && bHttp11)
  377. {
  378. int iMoveLen = strHost.GetLength() + HTTP_SCHEME_LEN;
  379. memcpy(pData + iMoveLen, pData, iSchemePos);
  380. pData += iMoveLen;
  381. iLength -= iMoveLen;
  382. }
  383. ++pTemp;
  384. BYTE* pHead = pTemp;
  385. int iRange = iLength - (int)(pHead - pData);
  386. for(i = 0; i < iRange; ++i, ++pTemp)
  387. {
  388. if(*pTemp == '\r')
  389. {
  390. if(_strnicmp((char*)pHead, HEAD_PROXY_CONN, HEAD_PROXY_CONN_LEN) == 0)
  391. {
  392. int iMoveLen = HEAD_PROXY_CONN_LEN - HEAD_CONN_LEN;
  393. memcpy(pHead + iMoveLen, HEAD_CONN, HEAD_CONN_LEN);
  394. int iCopyLen = (int)(pHead - pData);
  395. memcpy(pData + iMoveLen, pData, iCopyLen);
  396. pData += iMoveLen;
  397. iLength -= iMoveLen;
  398. break;
  399. }
  400. else if(*(pTemp - 1) == '\r' || *(pTemp - 2) == '\r')
  401. break;
  402. }
  403. else if(*pTemp == '\n')
  404. {
  405. ++pTemp;
  406. pHead = pTemp;
  407. }
  408. }
  409. return TRUE;
  410. }
  411. BOOL CTcpServerListenerImpl::CheckIfHttp(const BYTE* pData, int iLength)
  412. {
  413. BYTE c = *pData;
  414. if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z')
  415. return FALSE;
  416. LPCSTR lpszData = (LPCSTR)pData;
  417. if(_strnicmp(lpszData, "GET " , 4) == 0)
  418. return TRUE;
  419. if(_strnicmp(lpszData, "POST " , 5) == 0)
  420. return TRUE;
  421. if(_strnicmp(lpszData, "HEAD " , 5) == 0)
  422. return TRUE;
  423. if(_strnicmp(lpszData, "PUT " , 4) == 0)
  424. return TRUE;
  425. if(_strnicmp(lpszData, "DELETE " , 7) == 0)
  426. return TRUE;
  427. if(_strnicmp(lpszData, "TRACE " , 6) == 0)
  428. return TRUE;
  429. if(_strnicmp(lpszData, "OPTIONS " , 8) == 0)
  430. return TRUE;
  431. return FALSE;
  432. }
  433. EnHandleResult CTcpAgentListenerImpl::OnConnect(CONNID dwConnID)
  434. {
  435. if(m_pDlg->m_bLog)
  436. {
  437. TCHAR szAddress[40];
  438. int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
  439. USHORT usPort;
  440. m_pDlg->m_Agent->GetRemoteAddress(dwConnID, szAddress, iAddressLen, usPort);
  441. ::PostOnConnect2(dwConnID, szAddress, usPort);
  442. }
  443. return HR_OK;
  444. }
  445. EnHandleResult CTcpAgentListenerImpl::OnSend(CONNID dwConnID, const BYTE* pData, int iLength)
  446. {
  447. if(m_pDlg->m_bLog) ::PostOnSend(dwConnID, pData, iLength);
  448. return HR_OK;
  449. }
  450. EnHandleResult CTcpAgentListenerImpl::OnReceive(CONNID dwConnID, const BYTE* pData, int iLength)
  451. {
  452. if(m_pDlg->m_bLog) ::PostOnReceive(dwConnID, pData, iLength);
  453. CONNID dwServerID = 0;
  454. BOOL bExist = TRUE;
  455. while(TRUE)
  456. {
  457. bExist = m_pDlg->m_Agent->GetConnectionExtra(dwConnID, (PVOID*)&dwServerID);
  458. if(bExist && dwServerID == 0)
  459. ::WaitWithMessageLoop(10);
  460. else
  461. break;
  462. }
  463. if(!bExist)
  464. return HR_IGNORE;
  465. if(!m_pDlg->m_Server->Send(dwServerID, pData, iLength))
  466. return HR_ERROR;
  467. return HR_OK;
  468. }
  469. EnHandleResult CTcpAgentListenerImpl::OnClose(CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
  470. {
  471. if(m_pDlg->m_bLog)
  472. {
  473. iErrorCode == SE_OK ? ::PostOnClose(dwConnID) :
  474. ::PostOnError(dwConnID, enOperation, iErrorCode);
  475. }
  476. DetachConnInfo(dwConnID);
  477. return HR_OK;
  478. }
  479. EnHandleResult CTcpAgentListenerImpl::OnShutdown()
  480. {
  481. ::PostOnShutdown();
  482. return HR_OK;
  483. }
  484. void CTcpAgentListenerImpl::DetachConnInfo(CONNID dwConnID)
  485. {
  486. CONNID dwServerID = 0;
  487. BOOL bExist = m_pDlg->m_Agent->GetConnectionExtra(dwConnID, (PVOID*)&dwServerID);
  488. if(bExist && dwServerID != 0)
  489. {
  490. m_pDlg->m_Server->SetConnectionExtra(dwServerID, (PVOID)0);
  491. m_pDlg->m_Server->Disconnect(dwServerID);
  492. }
  493. }