ServerService.cpp
上传用户:hysujiao87
上传日期:2007-12-02
资源大小:156k
文件大小:13k
源码类别:

ICQ/即时通讯

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "serverservice.h"
  3. #include "MainFrm.h"
  4. #include "xmlparser.h"
  5. #include "QQSocket.h"
  6. CServerService::CServerService(void)
  7. {
  8. _listenThread = NULL;
  9. _list = NULL;
  10. }
  11. CServerService::~CServerService(void)
  12. {
  13. }
  14. HRESULT CServerService::dealLogOnRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
  15. {
  16. DEAL_REQUEST_BEGIN()
  17. CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
  18. if (userData != NULL)
  19. {
  20. if (requestRoot->getChildContent(_T("password")) != userData->_password)
  21. userData = NULL;
  22. }
  23. if (userData == NULL)
  24. {
  25. responseRoot->AddChild(_T("message"), _T("用户名或密码错误."));
  26. responseRoot->AddChild(_T("result"), _T("1"));
  27. return S_OK;
  28. }
  29. responseRoot->AddChild(_T("result"), _T("0"));
  30. responseRoot->AddChild(_T("nickname"), userData->_nickname);
  31. return S_OK;
  32. }
  33. HRESULT CServerService::dealLogOffRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
  34. {
  35. DEAL_REQUEST_BEGIN()
  36. CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
  37. if (userData != NULL)
  38. {
  39. userData->_online = FALSE;
  40. userData->_lastReport = 0;
  41. ::ZeroMemory(&userData->_sockAddr, sizeof(sockaddr_in));
  42. }
  43. return S_OK;
  44. }
  45. HRESULT CServerService::dealRegisterRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
  46. {
  47. DEAL_REQUEST_BEGIN()
  48. CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
  49. if (userData != NULL)
  50. {
  51. responseRoot->AddChild(_T("result"), _T("1"));
  52. responseRoot->AddChild(_T("message"), _T("这个ID已经有人使用了."));
  53. return S_OK;
  54. }
  55. CUserData newUser;
  56. newUser._clientID = requestRoot->getChildContent(_T("userID"));
  57. newUser._password = requestRoot->getChildContent(_T("password"));
  58. newUser._nickname = requestRoot->getChildContent(_T("nickname"));
  59. list.addUser(&newUser);
  60. responseRoot->AddChild(_T("result"), _T("0"));
  61. return S_OK;
  62. }
  63. HRESULT CServerService::dealQueryUserRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
  64. {
  65. DEAL_REQUEST_BEGIN()
  66. CString userID = requestRoot->getChildContent(_T("userID"));
  67. CUserData *userData = list.getUserByID(userID);
  68. if (userData == NULL)
  69. {
  70. responseRoot->AddChild(_T("result"), _T("1"));
  71. }
  72. else
  73. {
  74. responseRoot->AddChild(_T("result"), _T("0"));
  75. responseRoot->AddChild(_T("userID"), userData->_clientID);
  76. responseRoot->AddChild(_T("nickname"), userData->_nickname);
  77. if (userData->_online)
  78. {
  79. responseRoot->AddChild(_T("online"), _T("true"));
  80. responseRoot->AddChild(_T("ipAddr"), CQQSocket::IPAddrToString(userData->_sockAddr));
  81. CString port;
  82. port.Format("%d", userData->_sockAddr.sin_port);
  83. responseRoot->AddChild(_T("port"), port);
  84. }
  85. else
  86. responseRoot->AddChild(_T("online"), _T("false"));
  87. }
  88. return S_OK;
  89. }
  90. HRESULT CServerService::dealAddFriendRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
  91. {
  92. DEAL_REQUEST_BEGIN()
  93. CUserData *friendData = list.getUserByID(requestRoot->getChildContent(_T("friendID")));
  94. if (friendData != NULL)
  95. {
  96. CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
  97. HRESULT ret = userData->addFriend(friendData->_clientID);
  98. if (ret == S_OK)
  99. {
  100. responseRoot->AddChild(_T("result"), _T("0"));
  101. return S_OK;
  102. }
  103. if (ret == S_FALSE)
  104. {
  105. responseRoot->AddChild(_T("result"), _T("1"));
  106. responseRoot->AddChild(_T("message"), _T("该用户已经在好友列表中."));
  107. return S_OK;
  108. }
  109. responseRoot->AddChild(_T("result"), _T("500"));
  110. responseRoot->AddChild(_T("message"), _T("服务器内部错误."));
  111. return S_OK;
  112. }
  113. responseRoot->AddChild(_T("result"), _T("2"));
  114. responseRoot->AddChild(_T("message"), _T("该用户不存在."));
  115. return S_OK;
  116. }
  117. HRESULT CServerService::dealDownloadFriendsRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
  118. {
  119. DEAL_REQUEST_BEGIN()
  120. CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
  121. if (userData != NULL)
  122. {
  123. responseRoot->AddChild(_T("result"), _T("0"));
  124. for (int i = 0; i < userData->getFriendCount(); i++)
  125. {
  126. responseRoot->AddChild(_T("friend"), userData->getFriendID(i));
  127. }
  128. }
  129. else
  130. {
  131. responseRoot->AddChild(_T("result"), _T("1"));
  132. responseRoot->AddChild(_T("message"), _T("要查询好友的用户不存在."));
  133. }
  134. return S_OK;
  135. }
  136. HRESULT CServerService::dealOnlineRequest(CXMLParser *request, CElement *responseRoot, const sockaddr_in& addrFrom, CUserList &list)
  137. {
  138. DEAL_REQUEST_BEGIN()
  139. CUserData *friendData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
  140. if (friendData != NULL)
  141. {
  142. CString csPort = requestRoot->getChildContent(_T("port"));
  143. short port = _ttoi(csPort);
  144. memcpy(&friendData->_sockAddr, &addrFrom, sizeof(sockaddr_in));
  145. friendData->_sockAddr.sin_port = port;
  146. friendData->_lastReport = ::GetTickCount();
  147. friendData->_online = TRUE;
  148. }
  149. return S_OK;
  150. }
  151. HRESULT CServerService::dealRequest(BYTE *data, 
  152. int dataLen, 
  153. const SOCKET &sock, 
  154. const sockaddr_in &addrFrom, 
  155. CUserList* list)
  156. {
  157. _ASSERTE(data != NULL);
  158. if (data == NULL)
  159. return E_INVALIDARG;
  160. CXMLParser request;
  161. if (request.LoadXML(data, dataLen) != 0)
  162. return E_FAIL;
  163. CElement *requestRoot = request.get_root();
  164. _ASSERTE(requestRoot->get_tag() == _T("REQUEST"));
  165. CElement *type = requestRoot->GetFirstChildByTag(_T("type"));
  166. _ASSERTE(type != NULL);
  167. if (type == NULL)
  168. return E_FAIL;
  169. if (type->get_content() != _T("ONLINE"))
  170. {
  171. CString log = logMessage(&request, addrFrom);
  172. TCHAR *msg = new TCHAR[log.GetLength() + 1];
  173. _tcscpy(msg, log);
  174. AfxGetMainWnd()->PostMessage(WM_SERVICE_NOTIFY, (WPARAM)msg, 0);
  175. }
  176. CXMLParser response;
  177. CElement *responseRoot = response.createElement(_T("RESPONSE"), _T(""));
  178. // Add the new request deal code here.
  179. if (type->get_content() == _T("LOGON"))
  180. {
  181. HRESULT ret = dealLogOnRequest(&request, responseRoot, *list);
  182. if (ret != S_OK)
  183. {
  184. delete responseRoot;
  185. return ret;
  186. }
  187. }
  188. if (type->get_content() == _T("REGISTER"))
  189. {
  190. HRESULT ret = dealRegisterRequest(&request, responseRoot, *list);
  191. if (ret != S_OK)
  192. {
  193. delete responseRoot;
  194. return ret;
  195. }
  196. }
  197. if (type->get_content() == _T("ADDFRIEND"))
  198. {
  199. HRESULT ret = dealAddFriendRequest(&request, responseRoot, *list);
  200. if (ret != S_OK)
  201. {
  202. delete responseRoot;
  203. return ret;
  204. }
  205. }
  206. if (type->get_content() == _T("DOWNLOADFRIENDS"))
  207. {
  208. HRESULT ret = dealDownloadFriendsRequest(&request, responseRoot, *list);
  209. if (ret != S_OK)
  210. {
  211. delete responseRoot;
  212. return ret;
  213. }
  214. }
  215. if (type->get_content() == _T("QUERYUSER"))
  216. {
  217. HRESULT ret = dealQueryUserRequest(&request, responseRoot, *list);
  218. if (ret != S_OK)
  219. {
  220. delete responseRoot;
  221. return ret;
  222. }
  223. }
  224. if (type->get_content() == _T("ONLINE"))
  225. {
  226. dealOnlineRequest(&request, responseRoot, addrFrom, *list);
  227. delete responseRoot;
  228. return S_OK;
  229. }
  230. if (type->get_content() == _T("LOGOFF"))
  231. {
  232. dealLogOffRequest(&request, responseRoot, *list);
  233. delete responseRoot;
  234. return S_OK;
  235. }
  236. // End of adding request deal code.
  237. response.set_root(responseRoot);
  238. if (response.BuildXML() != 0)
  239. {
  240. TRACE("ERROR: Failed to build the response xml.n");
  241. return E_FAIL;
  242. }
  243. CString xml = response.get_xml();
  244. int ret = send(sock, ((LPCTSTR)xml), xml.GetLength() * sizeof(TCHAR), 0);
  245. if (ret == SOCKET_ERROR)
  246. return E_FAIL;
  247. return S_OK;
  248. }
  249. UINT CServerService::serviceProc(LPVOID wParam)
  250. {
  251. auto_ptr<LISTEN_PARAM> param((LISTEN_PARAM*)wParam);
  252. SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
  253. sockaddr_in addrListen;
  254. addrListen.sin_family = AF_INET;
  255. addrListen.sin_addr.S_un.S_addr = INADDR_ANY;
  256. addrListen.sin_port = htons(6000);
  257. int ret = bind(sock, (SOCKADDR*)&addrListen, sizeof(sockaddr_in));
  258. if (ret != 0)
  259. {
  260. ::closesocket(sock);
  261. int error = ::WSAGetLastError();
  262. TRACE("ERROR: Failed to bind the server listen socket (%d).n", error);
  263. return -1;
  264. }
  265. ret = listen(sock, 5);
  266. if (ret != 0)
  267. {
  268. ::closesocket(sock);
  269. int error = ::WSAGetLastError();
  270. TRACE("ERROR: Failed to listen the server listen socket (%d).n", error);
  271. return -1;
  272. }
  273. u_long arg = TRUE;
  274. ret = ioctlsocket(sock, FIONBIO, &arg);
  275. if (ret != 0)
  276. {
  277. ::closesocket(sock);
  278. int error = ::WSAGetLastError();
  279. TRACE("ERROR: Failed to ioctlsocket the socket to non-blocking mode (%d).n", error);
  280. return -1;
  281. }
  282. while(TRUE)
  283. {
  284. while(TRUE)
  285. {
  286. if (::WaitForSingleObject(*(param->finishEvent), 0) == WAIT_OBJECT_0)
  287. {
  288. ::closesocket(sock);
  289. TRACE("NOTIFY: The server's listening thread is finished.n");
  290. return 0;
  291. }
  292. fd_set readset;
  293. FD_ZERO(&readset);
  294. FD_SET(sock, &readset);
  295. TIMEVAL time;
  296. time.tv_sec = 0;
  297. time.tv_usec = 1;
  298. int ret = select(0, &readset, NULL, NULL, &time);
  299. if (ret == SOCKET_ERROR)
  300. {
  301. ::closesocket(sock);
  302. int error = ::WSAGetLastError();
  303. TRACE("ERROR: Failed to select the socket states (%d).n", error);
  304. return -1;
  305. }
  306. if (ret != 0)
  307. break ;
  308. }
  309. sockaddr_in addrFrom;
  310. ::ZeroMemory(&addrFrom, sizeof(sockaddr_in));
  311. int addrLen = sizeof(sockaddr_in);
  312. SOCKET acceptedSock = accept(sock, (SOCKADDR*)&addrFrom, &addrLen);
  313. _ASSERTE(acceptedSock != INVALID_SOCKET);
  314. if (acceptedSock == INVALID_SOCKET)
  315. {
  316. ::closesocket(sock);
  317. int error = ::WSAGetLastError();
  318. TRACE("ERROR: Failed to accept a connect (%d).n", error);
  319. return -1;
  320. }
  321. u_long arg = FALSE;
  322. ret = ioctlsocket(acceptedSock, FIONBIO, &arg);
  323. if (ret != 0)
  324. {
  325. ::closesocket(acceptedSock);
  326. ::closesocket(sock);
  327. int error = ::WSAGetLastError();
  328. TRACE("ERROR: Failed to ioctlsocket the socket to non-blocking mode (%d).n", error);
  329. return -1;
  330. }
  331. while(TRUE)
  332. {
  333. if (::WaitForSingleObject(*(param->finishEvent), 0) == WAIT_OBJECT_0)
  334. {
  335. ::closesocket(acceptedSock);
  336. ::closesocket(sock);
  337. TRACE("NOTIFY: The server's listening thread is finished.n");
  338. return 0;
  339. }
  340. DWORD dataLen = 0;
  341. ret = ::ioctlsocket(acceptedSock, FIONREAD, &dataLen);
  342. if (ret != 0)
  343. {
  344. ::closesocket(acceptedSock);
  345. ::closesocket(sock);
  346. int error = ::WSAGetLastError();
  347. TRACE("ERROR: Failed to ioctlsocket() on the accepted socket (%d).n", error);
  348. return -1;
  349. }
  350. if (dataLen <= 0)
  351. {
  352. Sleep(50);
  353. continue ;
  354. }
  355. auto_ptr<BYTE> data(new BYTE[dataLen]);
  356. dataLen = recv(acceptedSock, (char*)(data.get()), dataLen, 0);
  357. if (dataLen == SOCKET_ERROR)
  358. {
  359. ::closesocket(acceptedSock);
  360. ::closesocket(sock);
  361. int error = ::WSAGetLastError();
  362. TRACE("ERROR: Failed to receive the request (%d).n", error);
  363. return -1;
  364. }
  365.             dealRequest(data.get(), dataLen, acceptedSock, addrFrom, param->list);
  366. break ;
  367. }
  368. closesocket(acceptedSock);
  369. }
  370. return -1;
  371. }
  372. HRESULT CServerService::startListen(CUserList *list)
  373. {
  374. _ASSERTE(_listenThread == NULL);
  375. if (_listenThread != NULL)
  376. return E_UNEXPECTED;
  377. _list = list;
  378. LISTEN_PARAM *param = new LISTEN_PARAM;
  379. param->finishEvent = &_finishEvent;
  380. param->list = list;
  381. CWinThread *pThread = AfxBeginThread(CServerService::serviceProc, (LPVOID)param, 0, 0, CREATE_SUSPENDED);
  382. _ASSERTE(pThread != NULL);
  383. if (pThread == NULL)
  384. return E_FAIL;
  385. HANDLE hProcess = ::GetCurrentProcess();
  386. BOOL ret = ::DuplicateHandle(hProcess, 
  387. pThread->m_hThread, 
  388. hProcess, 
  389. &_listenThread, 
  390. 0, 
  391. TRUE, 
  392. DUPLICATE_SAME_ACCESS);
  393. _ASSERTE(ret != FALSE);
  394. if (ret == FALSE)
  395. return E_FAIL;
  396. pThread->ResumeThread();
  397. return S_OK;
  398. }
  399. HRESULT CServerService::stopListen()
  400. {
  401. if(_listenThread == NULL)
  402. return S_OK;
  403. _finishEvent.SetEvent();
  404. DWORD ret = ::WaitForSingleObject(_listenThread, 5000);
  405. _ASSERTE(ret == WAIT_OBJECT_0);
  406. if (ret != WAIT_OBJECT_0)
  407. return E_FAIL;
  408. ::CloseHandle(_listenThread);
  409. _listenThread = NULL;
  410. return S_OK;
  411. }
  412. CString CServerService::logMessage(CXMLParser *msg, const sockaddr_in &addrFrom)
  413. {
  414. CString notifyMsg = _T("Received a request from ");
  415. notifyMsg += CQQSocket::IPAddrToString(addrFrom);
  416. CElementList list;
  417. msg->get_root()->GetChildrenByTag(NULL, list);
  418. POSITION pos = list.GetHeadPosition();
  419. while(pos != NULL)
  420. {
  421. CElement *element = list.GetNext(pos);
  422. _ASSERTE(element != NULL);
  423. if (element == NULL)
  424. return _T("");
  425. CString csElement;
  426. csElement.Format(" %s=%s", element->get_tag(), element->get_content());
  427. notifyMsg += csElement;
  428. }
  429. return notifyMsg;
  430. }