PageRenderTime 65ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/3rdParty/include/nio/AsyncSocketEx.cpp

https://gitlab.com/yoage/TTWinClient
C++ | 1041 lines | 821 code | 123 blank | 97 comment | 118 complexity | 68dd2541b2edd40600add232adce49a9 MD5 | raw file
Possible License(s): LGPL-3.0
  1. /*CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de)
  2. Version 1.2 (2003-03-28)
  3. --------------------------------------------------------
  4. Introduction:
  5. -------------
  6. CAsyncSocketEx is a replacement for the MFC class CAsyncSocket.
  7. This class was written because CAsyncSocket is not the fastest WinSock
  8. wrapper and it's very hard to add new functionality to CAsyncSocket
  9. derived classes. This class offers the same functionality as CAsyncSocket.
  10. Also, CAsyncSocketEx offers some enhancements which were not possible with
  11. CAsyncSocket without some tricks.
  12. How do I use it?
  13. ----------------
  14. Basically exactly like CAsyncSocket.
  15. To use CAsyncSocketEx, just replace all occurrences of CAsyncSocket in your
  16. code with CAsyncSocketEx, if you did not enhance CAsyncSocket yourself in
  17. any way, you won't have to change anything else in your code.
  18. Why is CAsyncSocketEx faster?
  19. -----------------------------
  20. CAsyncSocketEx is slightly faster when dispatching notification event messages.
  21. First have a look at the way CAsyncSocket works. For each thread that uses
  22. CAsyncSocket, a window is created. CAsyncSocket calls WSAAsyncSelect with
  23. the handle of that window. Until here, CAsyncSocketEx works the same way.
  24. But CAsyncSocket uses only one window message (WM_SOCKET_NOTIFY) for all
  25. sockets within one thread. When the window recieve WM_SOCKET_NOTIFY, wParam
  26. contains the socket handle and the window looks up an CAsyncSocket instance
  27. using a map. CAsyncSocketEx works differently. It's helper window uses a
  28. wide range of different window messages (WM_USER through 0xBFFF) and passes
  29. a different message to WSAAsyncSelect for each socket. When a message in
  30. the specified range is received, CAsyncSocketEx looks up the pointer to a
  31. CAsyncSocketEx instance in an Array using the index of message - WM_USER.
  32. As you can see, CAsyncSocketEx uses the helper window in a more efficient
  33. way, as it don't have to use the slow maps to lookup it's own instance.
  34. Still, speed increase is not very much, but it may be noticeable when using
  35. a lot of sockets at the same time.
  36. Please note that the changes do not affect the raw data throughput rate,
  37. CAsyncSocketEx only dispatches the notification messages faster.
  38. What else does CAsyncSocketEx offer?
  39. ------------------------------------
  40. CAsyncSocketEx offers a flexible layer system. One example is the proxy layer.
  41. Just create an instance of the proxy layer, configure it and add it to the layer
  42. chain of your CAsyncSocketEx instance. After that, you can connect through
  43. proxies.
  44. Benefit: You don't have to change much to use the layer system.
  45. Another layer that is currently in development is the SSL layer to establish
  46. SSL encrypted connections.
  47. License
  48. -------
  49. Feel free to use this class, as long as you don't claim that you wrote it
  50. and this copyright notice stays intact in the source files.
  51. If you use this class in commercial applications, please send a short message
  52. to tim.kosse@gmx.de
  53. */
  54. #include "stdafx.h"
  55. #include "AsyncSocketEx.h"
  56. #include "wtypes.h"
  57. #include "oleauto.h"
  58. #include "atlconv.h"
  59. #include "utility/utilCommonAPI.h"
  60. #ifndef NOLAYERS
  61. #include "AsyncSocketExLayer.h"
  62. #endif //NOLAYERS
  63. #ifdef _DEBUG
  64. #undef THIS_FILE
  65. static char THIS_FILE[]=__FILE__;
  66. #endif
  67. #ifndef CCRITICALSECTIONWRAPPERINCLUDED
  68. class CCriticalSectionWrapper
  69. {
  70. public:
  71. CCriticalSectionWrapper()
  72. {
  73. InitializeCriticalSection(&m_criticalSection);
  74. }
  75. ~CCriticalSectionWrapper()
  76. {
  77. DeleteCriticalSection(&m_criticalSection);
  78. }
  79. void Lock()
  80. {
  81. EnterCriticalSection(&m_criticalSection);
  82. }
  83. void Unlock()
  84. {
  85. LeaveCriticalSection(&m_criticalSection);
  86. }
  87. protected:
  88. CRITICAL_SECTION m_criticalSection;
  89. };
  90. #define CCRITICALSECTIONWRAPPERINCLUDED
  91. #endif
  92. CCriticalSectionWrapper CAsyncSocketEx::m_sGlobalCriticalSection;
  93. CAsyncSocketEx::t_AsyncSocketExThreadDataList *CAsyncSocketEx::m_spAsyncSocketExThreadDataList=0;
  94. #ifndef _AFX
  95. #ifndef VERIFY
  96. #define VERIFY(x) (void(x))
  97. #endif //VERIFY
  98. #ifndef ASSERT
  99. #define ASSERT(x)
  100. #endif //ASSERT
  101. #endif //_AFX
  102. /////////////////////////////
  103. //Helper Window class
  104. #define WM_SOCKETEX_NOTIFY (WM_USER+2)
  105. #define MAX_SOCKETS (0xBFFF-WM_SOCKETEX_NOTIFY+1)
  106. class CAsyncSocketExHelperWindow
  107. {
  108. public:
  109. CAsyncSocketExHelperWindow()
  110. {
  111. //Initialize data
  112. m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets
  113. memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));
  114. m_nWindowDataSize=512;
  115. m_nSocketCount=0;
  116. m_nWindowDataPos=0;
  117. //Create window
  118. WNDCLASSEX wndclass;
  119. wndclass.cbSize=sizeof wndclass;
  120. wndclass.style=0;
  121. wndclass.lpfnWndProc=WindowProc;
  122. wndclass.cbClsExtra=0;
  123. wndclass.cbWndExtra=0;
  124. wndclass.hInstance=GetModuleHandle(0);
  125. wndclass.hIcon=0;
  126. wndclass.hCursor=0;
  127. wndclass.hbrBackground=0;
  128. wndclass.lpszMenuName=0;
  129. wndclass.lpszClassName=_T("CAsyncSocketEx Helper Window");
  130. wndclass.hIconSm=0;
  131. RegisterClassEx(&wndclass);
  132. m_hWnd=CreateWindow(_T("CAsyncSocketEx Helper Window"), _T("CAsyncSocketEx Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
  133. ASSERT(m_hWnd);
  134. SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
  135. };
  136. virtual ~CAsyncSocketExHelperWindow()
  137. {
  138. //Clean up socket storage
  139. delete [] m_pAsyncSocketExWindowData;
  140. m_pAsyncSocketExWindowData=0;
  141. m_nWindowDataSize=0;
  142. m_nSocketCount=0;
  143. //Destroy window
  144. if (m_hWnd)
  145. {
  146. DestroyWindow(m_hWnd);
  147. m_hWnd=0;
  148. }
  149. }
  150. //Adds a socket to the list of attached sockets
  151. BOOL AddSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
  152. {
  153. ASSERT(pSocket);
  154. if (!m_nWindowDataSize)
  155. {
  156. ASSERT(!m_nSocketCount);
  157. m_nWindowDataSize=512;
  158. m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets
  159. memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));
  160. }
  161. if (nSocketIndex!=-1)
  162. {
  163. ASSERT(m_pAsyncSocketExWindowData);
  164. ASSERT(m_nWindowDataSize>nSocketIndex);
  165. ASSERT(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket);
  166. ASSERT(m_nSocketCount);
  167. return TRUE;
  168. }
  169. //Increase socket storage if too small
  170. if (m_nSocketCount>=(m_nWindowDataSize-10))
  171. {
  172. int nOldWindowDataSize=m_nWindowDataSize;
  173. ASSERT(m_nWindowDataSize<MAX_SOCKETS);
  174. m_nWindowDataSize+=512;
  175. if (m_nWindowDataSize>MAX_SOCKETS)
  176. m_nWindowDataSize=MAX_SOCKETS;
  177. t_AsyncSocketExWindowData *tmp=m_pAsyncSocketExWindowData;
  178. m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[m_nWindowDataSize];
  179. memcpy(m_pAsyncSocketExWindowData, tmp, nOldWindowDataSize * sizeof(t_AsyncSocketExWindowData));
  180. memset(m_pAsyncSocketExWindowData+nOldWindowDataSize, 0, (m_nWindowDataSize-nOldWindowDataSize)*sizeof(t_AsyncSocketExWindowData));
  181. delete [] tmp;
  182. }
  183. //Search for free slot
  184. for (int i=m_nWindowDataPos;i<(m_nWindowDataSize+m_nWindowDataPos);i++)
  185. {
  186. if (!m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket)
  187. {
  188. m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket=pSocket;
  189. nSocketIndex=i%m_nWindowDataSize;
  190. m_nWindowDataPos=(i+1)%m_nWindowDataSize;
  191. m_nSocketCount++;
  192. return TRUE;
  193. }
  194. }
  195. //No slot found, maybe there are too much sockets!
  196. return FALSE;
  197. }
  198. //Removes a socket from the socket storage
  199. BOOL RemoveSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
  200. {
  201. ASSERT(pSocket);
  202. if (nSocketIndex==-1)
  203. return TRUE;
  204. ASSERT(m_pAsyncSocketExWindowData);
  205. ASSERT(m_nWindowDataSize>0);
  206. ASSERT(m_nSocketCount>0);
  207. ASSERT(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket);
  208. m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket=0;
  209. nSocketIndex=-1;
  210. m_nSocketCount--;
  211. return TRUE;
  212. }
  213. //Processes event notifications sent by the sockets or the layers
  214. static LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
  215. {
  216. if (message>=WM_SOCKETEX_NOTIFY)
  217. {
  218. //Verify parameters
  219. ASSERT(hWnd);
  220. CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLong(hWnd, GWL_USERDATA);
  221. ASSERT(pWnd);
  222. if (message<static_cast<UINT>(WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize)) //Index is within socket storage
  223. {
  224. //Lookup socket and verify if it's valid
  225. CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[message-WM_SOCKETEX_NOTIFY].m_pSocket;
  226. SOCKET hSocket=wParam;
  227. if (!pSocket)
  228. return 0;
  229. if (hSocket==INVALID_SOCKET)
  230. return 0;
  231. if (pSocket->m_SocketData.hSocket!=hSocket)
  232. return 0;
  233. int nEvent=lParam&0xFFFF;
  234. int nErrorCode=lParam>>16;
  235. //Dispatch notification
  236. #ifndef NOLAYERS
  237. if (!pSocket->m_pFirstLayer)
  238. {
  239. #endif //NOLAYERS
  240. //Dispatch to CAsyncSocketEx instance
  241. switch (nEvent)
  242. {
  243. case FD_READ:
  244. {
  245. DWORD nBytes;
  246. if (!pSocket->IOCtl(FIONREAD, &nBytes))
  247. nErrorCode = WSAGetLastError();
  248. if (nBytes != 0 || nErrorCode != 0)
  249. pSocket->onReceive(nErrorCode);
  250. }
  251. break;
  252. case FD_FORCEREAD: //Forceread does not check if there's data waiting
  253. pSocket->onReceive(nErrorCode);
  254. break;
  255. case FD_WRITE:
  256. pSocket->onSend(nErrorCode);
  257. break;
  258. case FD_CONNECT:
  259. pSocket->onConnect(nErrorCode);
  260. break;
  261. case FD_ACCEPT:
  262. pSocket->onAccept(nErrorCode);
  263. break;
  264. case FD_CLOSE:
  265. pSocket->onClose(nErrorCode);
  266. break;
  267. }
  268. }
  269. #ifndef NOLAYERS
  270. else //Dispatch notification to the lowest layer
  271. {
  272. if (nEvent==FD_READ)
  273. {
  274. DWORD nBytes;
  275. if (!pSocket->IOCtl(FIONREAD, &nBytes))
  276. nErrorCode = WSAGetLastError();
  277. if (nBytes != 0 || nErrorCode != 0)
  278. pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
  279. }
  280. else
  281. pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
  282. }
  283. }
  284. #endif //NOLAYERS
  285. return 0;
  286. }
  287. #ifndef NOLAYERS
  288. else if (message==WM_USER) //Notification event sent by a layer
  289. {
  290. //Verify parameters, lookup socket and notification message
  291. if (!wParam)
  292. return 0;
  293. CAsyncSocketEx *pSocket=(CAsyncSocketEx *)wParam;
  294. CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=(CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam;
  295. if (pSocket->m_SocketData.hSocket==INVALID_SOCKET)
  296. {
  297. delete pMsg;
  298. return 0;
  299. }
  300. int nEvent=pMsg->lEvent&0xFFFF;
  301. int nErrorCode=pMsg->lEvent>>16;
  302. //Dispatch to layer
  303. if (pMsg->pLayer)
  304. pMsg->pLayer->CallEvent(nEvent, nErrorCode);
  305. else
  306. {
  307. //Dispatch to socket class
  308. switch (nEvent)
  309. {
  310. case FD_READ:
  311. if (pSocket->m_lEvent&FD_READ)
  312. pSocket->onReceive(nErrorCode);
  313. break;
  314. case FD_FORCEREAD:
  315. if (pSocket->m_lEvent&FD_FORCEREAD)
  316. pSocket->onReceive(nErrorCode);
  317. break;
  318. case FD_WRITE:
  319. if (pSocket->m_lEvent&FD_WRITE)
  320. pSocket->onSend(nErrorCode);
  321. break;
  322. case FD_CONNECT:
  323. if (pSocket->m_lEvent&FD_CONNECT)
  324. pSocket->onConnect(nErrorCode);
  325. break;
  326. case FD_ACCEPT:
  327. if (pSocket->m_lEvent&FD_ACCEPT)
  328. pSocket->onAccept(nErrorCode);
  329. break;
  330. case FD_CLOSE:
  331. if (pSocket->m_lEvent&FD_CLOSE)
  332. pSocket->onClose(nErrorCode);
  333. break;
  334. }
  335. }
  336. delete pMsg;
  337. return 0;
  338. }
  339. #endif //NOLAYERS
  340. else if (message == WM_USER+1)
  341. {
  342. //WSAAsyncGetHostByName reply
  343. //Verify parameters
  344. ASSERT(hWnd);
  345. CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLong(hWnd, GWL_USERDATA);
  346. ASSERT(pWnd);
  347. CAsyncSocketEx *pSocket = nullptr;
  348. int i = 0;
  349. for (i=0; i<pWnd->m_nWindowDataSize; i++)
  350. {
  351. pSocket = pWnd->m_pAsyncSocketExWindowData[i].m_pSocket;
  352. if (pSocket && pSocket->m_hAsyncGetHostByNameHandle &&
  353. pSocket->m_hAsyncGetHostByNameHandle == (HANDLE)wParam)
  354. break;
  355. }
  356. if (i == pWnd->m_nWindowDataSize)
  357. return 0;
  358. int nErrorCode = lParam >> 16;
  359. int len = lParam % 0xFFFF;
  360. if (nErrorCode)
  361. {
  362. pSocket->onConnect(nErrorCode);
  363. return 0;
  364. }
  365. SOCKADDR_IN sockAddr;
  366. memset(&sockAddr,0,sizeof(sockAddr));
  367. sockAddr.sin_family=AF_INET;
  368. sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr;
  369. sockAddr.sin_port = htons(pSocket->m_nAsyncGetHostByNamePort);
  370. BOOL res = pSocket->Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
  371. delete [] pSocket->m_pAsyncGetHostByNameBuffer;
  372. pSocket->m_pAsyncGetHostByNameBuffer=0;
  373. pSocket->m_hAsyncGetHostByNameHandle=0;
  374. if (!res)
  375. if (GetLastError()!=WSAEWOULDBLOCK)
  376. pSocket->onConnect(GetLastError());
  377. return 0;
  378. }
  379. return DefWindowProc(hWnd, message, wParam, lParam);
  380. }
  381. HWND CAsyncSocketExHelperWindow::GetHwnd()
  382. {
  383. return m_hWnd;
  384. }
  385. private:
  386. HWND m_hWnd;
  387. struct t_AsyncSocketExWindowData
  388. {
  389. CAsyncSocketEx *m_pSocket;
  390. } *m_pAsyncSocketExWindowData;
  391. int m_nWindowDataSize;
  392. int m_nWindowDataPos;
  393. int m_nSocketCount;
  394. };
  395. //////////////////////////////////////////////////////////////////////
  396. // Konstruktion/Destruktion
  397. //////////////////////////////////////////////////////////////////////
  398. CAsyncSocketEx::CAsyncSocketEx()
  399. {
  400. m_SocketData.hSocket=INVALID_SOCKET;
  401. m_SocketData.nSocketIndex=-1;
  402. m_pLocalAsyncSocketExThreadData=0;
  403. #ifndef NOLAYERS
  404. m_pFirstLayer=0;
  405. m_pLastLayer=0;
  406. #endif //NOLAYERS
  407. m_pAsyncGetHostByNameBuffer = NULL;
  408. m_hAsyncGetHostByNameHandle = NULL;
  409. }
  410. CAsyncSocketEx::~CAsyncSocketEx()
  411. {
  412. Close();
  413. FreeAsyncSocketExInstance();
  414. }
  415. BOOL CAsyncSocketEx::Create( UINT nSocketPort /*=0*/, int nSocketType /*=SOCK_STREAM*/, long lEvent /*=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/, LPCTSTR lpszSocketAddress /*=NULL*/ )
  416. {
  417. ASSERT(GetSocketHandle()==INVALID_SOCKET);
  418. //Close the socket, although this should not happen
  419. if (GetSocketHandle() != INVALID_SOCKET)
  420. {
  421. WSASetLastError(WSAEALREADY);
  422. return FALSE;
  423. }
  424. BOOL res=InitAsyncSocketExInstance();
  425. ASSERT(res);
  426. if (!res)
  427. {
  428. WSASetLastError(WSANOTINITIALISED);
  429. return FALSE;
  430. }
  431. #ifndef NOLAYERS
  432. if (m_pFirstLayer)
  433. return m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress);
  434. else
  435. #endif //NOLAYERS
  436. {
  437. SOCKET hSocket=socket(AF_INET, nSocketType, 0);
  438. if (hSocket==INVALID_SOCKET)
  439. return FALSE;
  440. m_SocketData.hSocket=hSocket;
  441. AttachHandle(hSocket);
  442. if (!AsyncSelect(lEvent))
  443. {
  444. Close();
  445. return FALSE;
  446. }
  447. #ifndef NOLAYERS
  448. if (m_pFirstLayer)
  449. {
  450. if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle()
  451. , m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY
  452. , FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) )
  453. {
  454. Close();
  455. return FALSE;
  456. }
  457. }
  458. #endif //NOLAYERS
  459. if (!Bind(nSocketPort, lpszSocketAddress))
  460. {
  461. Close();
  462. return FALSE;
  463. }
  464. return TRUE;
  465. }
  466. }
  467. void CAsyncSocketEx::onReceive(int nErrorCode)
  468. {
  469. }
  470. void CAsyncSocketEx::onSend(int nErrorCode)
  471. {
  472. }
  473. void CAsyncSocketEx::onConnect(int nErrorCode)
  474. {
  475. }
  476. void CAsyncSocketEx::onAccept(int nErrorCode)
  477. {
  478. }
  479. void CAsyncSocketEx::onClose(int nErrorCode)
  480. {
  481. }
  482. BOOL CAsyncSocketEx::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress)
  483. {
  484. USES_CONVERSION;
  485. SOCKADDR_IN sockAddr;
  486. memset(&sockAddr,0,sizeof(sockAddr));
  487. LPSTR lpszAscii = T2A((LPTSTR)lpszSocketAddress);
  488. sockAddr.sin_family = AF_INET;
  489. if (lpszAscii == NULL)
  490. sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  491. else
  492. {
  493. DWORD lResult = inet_addr(lpszAscii);
  494. if (lResult == INADDR_NONE)
  495. {
  496. WSASetLastError(WSAEINVAL);
  497. return FALSE;
  498. }
  499. sockAddr.sin_addr.s_addr = lResult;
  500. }
  501. sockAddr.sin_port = htons((u_short)nSocketPort);
  502. return Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr));
  503. }
  504. BOOL CAsyncSocketEx::Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen)
  505. {
  506. if (!bind(m_SocketData.hSocket, lpSockAddr, nSockAddrLen))
  507. return TRUE;
  508. else
  509. return FALSE;
  510. }
  511. void CAsyncSocketEx::AttachHandle(SOCKET hSocket)
  512. {
  513. ASSERT(m_pLocalAsyncSocketExThreadData);
  514. VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->AddSocket(this, m_SocketData.nSocketIndex));
  515. }
  516. void CAsyncSocketEx::DetachHandle(SOCKET hSocket)
  517. {
  518. ASSERT(m_pLocalAsyncSocketExThreadData);
  519. if (!m_pLocalAsyncSocketExThreadData)
  520. return;
  521. ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);
  522. if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)
  523. return;
  524. VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->RemoveSocket(this, m_SocketData.nSocketIndex));
  525. }
  526. void CAsyncSocketEx::Close()
  527. {
  528. #ifndef NOLAYERS
  529. if (m_pFirstLayer)
  530. m_pFirstLayer->Close();
  531. #endif //NOLAYERS
  532. if (m_SocketData.hSocket != INVALID_SOCKET)
  533. {
  534. if(closesocket(m_SocketData.hSocket)==SOCKET_ERROR)
  535. {
  536. APP_LOG(LOG_ERROR,TRUE,_T("close socket error"));
  537. }
  538. DetachHandle(m_SocketData.hSocket);
  539. m_SocketData.hSocket=INVALID_SOCKET;
  540. }
  541. #ifndef NOLAYERS
  542. RemoveAllLayers();
  543. #endif //NOLAYERS
  544. delete [] m_pAsyncGetHostByNameBuffer;
  545. m_pAsyncGetHostByNameBuffer = NULL;
  546. if (m_hAsyncGetHostByNameHandle)
  547. WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle);
  548. m_hAsyncGetHostByNameHandle = NULL;
  549. }
  550. BOOL CAsyncSocketEx::InitAsyncSocketExInstance()
  551. {
  552. //Check if already initialized
  553. if (m_pLocalAsyncSocketExThreadData)
  554. return TRUE;
  555. DWORD id=GetCurrentThreadId();
  556. m_sGlobalCriticalSection.Lock();
  557. //WSADATA wsa_data;
  558. //int r = WSAStartup(MAKEWORD(2,2), &wsa_data);
  559. //Get thread specific data
  560. if (m_spAsyncSocketExThreadDataList)
  561. {
  562. t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;
  563. while (pList)
  564. {
  565. ASSERT(pList->pThreadData);
  566. ASSERT(pList->pThreadData->nInstanceCount>0);
  567. if (pList->pThreadData->nThreadId==id)
  568. {
  569. m_pLocalAsyncSocketExThreadData=pList->pThreadData;
  570. m_pLocalAsyncSocketExThreadData->nInstanceCount++;
  571. break;
  572. }
  573. pList=pList->pNext;
  574. }
  575. //Current thread yet has no sockets
  576. if (!pList)
  577. {
  578. //Initialize data for current thread
  579. pList=new t_AsyncSocketExThreadDataList;
  580. pList->pNext=m_spAsyncSocketExThreadDataList;
  581. m_spAsyncSocketExThreadDataList=pList;
  582. m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;
  583. m_pLocalAsyncSocketExThreadData->nInstanceCount=1;
  584. m_pLocalAsyncSocketExThreadData->nThreadId=id;
  585. m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow;
  586. m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;
  587. }
  588. }
  589. else
  590. { //No thread has instances of CAsyncSocketEx; Initialize data
  591. m_spAsyncSocketExThreadDataList=new t_AsyncSocketExThreadDataList;
  592. m_spAsyncSocketExThreadDataList->pNext=0;
  593. m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;
  594. m_pLocalAsyncSocketExThreadData->nInstanceCount=1;
  595. m_pLocalAsyncSocketExThreadData->nThreadId=id;
  596. m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow;
  597. m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;
  598. }
  599. m_sGlobalCriticalSection.Unlock();
  600. return TRUE;
  601. }
  602. void CAsyncSocketEx::FreeAsyncSocketExInstance()
  603. {
  604. //Check if already freed
  605. if (!m_pLocalAsyncSocketExThreadData)
  606. return;
  607. DWORD id=m_pLocalAsyncSocketExThreadData->nThreadId;
  608. m_sGlobalCriticalSection.Lock();
  609. ASSERT(m_spAsyncSocketExThreadDataList);
  610. t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;
  611. t_AsyncSocketExThreadDataList *pPrev=0;
  612. //Serach for data for current thread and decrease instance count
  613. while (pList)
  614. {
  615. ASSERT(pList->pThreadData);
  616. ASSERT(pList->pThreadData->nInstanceCount>0);
  617. if (pList->pThreadData->nThreadId==id)
  618. {
  619. ASSERT(m_pLocalAsyncSocketExThreadData==pList->pThreadData);
  620. m_pLocalAsyncSocketExThreadData->nInstanceCount--;
  621. //Freeing last instance?
  622. //If so, destroy helper window
  623. if (!m_pLocalAsyncSocketExThreadData->nInstanceCount)
  624. {
  625. delete m_pLocalAsyncSocketExThreadData->m_pHelperWindow;
  626. delete m_pLocalAsyncSocketExThreadData;
  627. if (pPrev)
  628. pPrev->pNext=pList->pNext;
  629. else
  630. m_spAsyncSocketExThreadDataList=pList->pNext;
  631. delete pList;
  632. break;
  633. }
  634. break;
  635. }
  636. pPrev=pList;
  637. pList=pList->pNext;
  638. ASSERT(pList);
  639. }
  640. m_sGlobalCriticalSection.Unlock();
  641. }
  642. int CAsyncSocketEx::Receive(void* lpBuf, int nBufLen, int nFlags /*=0*/)
  643. {
  644. #ifndef NOLAYERS
  645. if (m_pFirstLayer)
  646. return m_pFirstLayer->Receive(lpBuf, nBufLen, nFlags);
  647. else
  648. #endif //NOLAYERS
  649. return recv(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
  650. }
  651. int CAsyncSocketEx::Send(const void* lpBuf, int nBufLen, int nFlags /*=0*/)
  652. {
  653. #ifndef NOLAYERS
  654. if (m_pFirstLayer)
  655. return m_pFirstLayer->Send(lpBuf, nBufLen, nFlags);
  656. else
  657. #endif //NOLAYERS
  658. return send(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
  659. }
  660. BOOL CAsyncSocketEx::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
  661. {
  662. #ifndef NOLAYERS
  663. if (m_pFirstLayer)
  664. return m_pFirstLayer->Connect(lpszHostAddress, nHostPort);
  665. else
  666. #endif //NOLAYERS
  667. {
  668. USES_CONVERSION;
  669. ASSERT(lpszHostAddress != NULL);
  670. SOCKADDR_IN sockAddr;
  671. memset(&sockAddr,0,sizeof(sockAddr));
  672. LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);
  673. sockAddr.sin_family = AF_INET;
  674. sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
  675. if (sockAddr.sin_addr.s_addr == INADDR_NONE)
  676. {
  677. m_pAsyncGetHostByNameBuffer=new char[MAXGETHOSTSTRUCT];
  678. m_nAsyncGetHostByNamePort=nHostPort;
  679. m_hAsyncGetHostByNameHandle=WSAAsyncGetHostByName(GetHelperWindowHandle(), WM_USER+1, lpszAscii, m_pAsyncGetHostByNameBuffer, MAXGETHOSTSTRUCT);
  680. if (!m_hAsyncGetHostByNameHandle)
  681. return FALSE;
  682. WSASetLastError(WSAEWOULDBLOCK);
  683. return TRUE;
  684. }
  685. sockAddr.sin_port = htons((u_short)nHostPort);
  686. return CAsyncSocketEx::Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
  687. }
  688. }
  689. BOOL CAsyncSocketEx::Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen )
  690. {
  691. #ifndef NOLAYERS
  692. if (m_pFirstLayer)
  693. return m_pFirstLayer->Connect(lpSockAddr, nSockAddrLen);
  694. else
  695. #endif //NOLAYERS
  696. return SOCKET_ERROR!=connect(m_SocketData.hSocket, lpSockAddr, nSockAddrLen);
  697. }
  698. #ifdef _AFX
  699. BOOL CAsyncSocketEx::GetPeerName( CString& rPeerAddress, UINT& rPeerPort )
  700. {
  701. #ifndef NOLAYERS
  702. if (m_pFirstLayer)
  703. return m_pFirstLayer->GetPeerName(rPeerAddress, rPeerPort);
  704. #endif NOLAYERS
  705. SOCKADDR_IN sockAddr;
  706. memset(&sockAddr, 0, sizeof(sockAddr));
  707. int nSockAddrLen = sizeof(sockAddr);
  708. BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  709. if (bResult)
  710. {
  711. rPeerPort = ntohs(sockAddr.sin_port);
  712. rPeerAddress = inet_ntoa(sockAddr.sin_addr);
  713. }
  714. return bResult;
  715. }
  716. #endif //AFX
  717. BOOL CAsyncSocketEx::GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
  718. {
  719. #ifndef NOLAYERS
  720. if (m_pFirstLayer)
  721. return m_pFirstLayer->GetPeerName(lpSockAddr, lpSockAddrLen);
  722. #endif //NOLAYERS
  723. if ( !getpeername(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) )
  724. return TRUE;
  725. else
  726. return FALSE;
  727. }
  728. #ifdef _AFX
  729. BOOL CAsyncSocketEx::GetSockName(CString& rSocketAddress, UINT& rSocketPort)
  730. {
  731. SOCKADDR_IN sockAddr;
  732. memset(&sockAddr, 0, sizeof(sockAddr));
  733. int nSockAddrLen = sizeof(sockAddr);
  734. BOOL bResult = GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  735. if (bResult)
  736. {
  737. rSocketPort = ntohs(sockAddr.sin_port);
  738. rSocketAddress = inet_ntoa(sockAddr.sin_addr);
  739. }
  740. return bResult;
  741. }
  742. #endif
  743. BOOL CAsyncSocketEx::GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
  744. {
  745. if ( !getsockname(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) )
  746. return TRUE;
  747. else
  748. return FALSE;
  749. }
  750. BOOL CAsyncSocketEx::ShutDown( int nHow /*=sends*/ )
  751. {
  752. #ifndef NOLAYERS
  753. if (m_pFirstLayer)
  754. {
  755. return m_pFirstLayer->ShutDown();
  756. }
  757. else
  758. #endif
  759. {
  760. if ( !shutdown(m_SocketData.hSocket, nHow) )
  761. return TRUE;
  762. else
  763. return FALSE;
  764. }
  765. }
  766. SOCKET CAsyncSocketEx::Detach( )
  767. {
  768. SOCKET socket=m_SocketData.hSocket;
  769. DetachHandle(socket);
  770. m_SocketData.hSocket=INVALID_SOCKET;
  771. return socket;
  772. }
  773. BOOL CAsyncSocketEx::Attach( SOCKET hSocket, long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ )
  774. {
  775. if (hSocket==INVALID_SOCKET || !hSocket)
  776. return FALSE;
  777. VERIFY(InitAsyncSocketExInstance());
  778. m_SocketData.hSocket=hSocket;
  779. AttachHandle(hSocket);
  780. return AsyncSelect(lEvent);
  781. }
  782. BOOL CAsyncSocketEx::AsyncSelect( long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ )
  783. {
  784. ASSERT(m_pLocalAsyncSocketExThreadData);
  785. m_lEvent=lEvent;
  786. #ifndef NOLAYERS
  787. if (!m_pFirstLayer)
  788. #endif //NOLAYERS
  789. {
  790. if ( !WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, lEvent) )
  791. return TRUE;
  792. else
  793. return FALSE;
  794. }
  795. return TRUE;
  796. }
  797. BOOL CAsyncSocketEx::Listen( int nConnectionBacklog /*=5*/ )
  798. {
  799. #ifndef NOLAYERS
  800. if (m_pFirstLayer)
  801. return m_pFirstLayer->Listen(nConnectionBacklog);
  802. #endif //NOLAYERS
  803. if (!listen(m_SocketData.hSocket, nConnectionBacklog))
  804. return TRUE;
  805. else
  806. return FALSE;
  807. }
  808. BOOL CAsyncSocketEx::Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr /*=NULL*/, int* lpSockAddrLen /*=NULL*/ )
  809. {
  810. ASSERT(rConnectedSocket.m_SocketData.hSocket == INVALID_SOCKET);
  811. #ifndef NOLAYERS
  812. if (m_pFirstLayer)
  813. {
  814. return m_pFirstLayer->Accept(rConnectedSocket, lpSockAddr, lpSockAddrLen);
  815. }
  816. else
  817. #endif //NOLAYERS
  818. {
  819. SOCKET hTemp = accept(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen);
  820. if (hTemp == INVALID_SOCKET)
  821. return FALSE;
  822. VERIFY(rConnectedSocket.InitAsyncSocketExInstance());
  823. rConnectedSocket.m_SocketData.hSocket=hTemp;
  824. rConnectedSocket.AttachHandle(hTemp);
  825. }
  826. return TRUE;
  827. }
  828. BOOL CAsyncSocketEx::IOCtl( long lCommand, DWORD* lpArgument )
  829. {
  830. return ioctlsocket(m_SocketData.hSocket, lCommand, lpArgument) != SOCKET_ERROR;
  831. }
  832. int CAsyncSocketEx::GetLastError()
  833. {
  834. return WSAGetLastError();
  835. }
  836. BOOL CAsyncSocketEx::TriggerEvent(long lEvent)
  837. {
  838. if (m_SocketData.hSocket==INVALID_SOCKET)
  839. return FALSE;
  840. ASSERT(m_pLocalAsyncSocketExThreadData);
  841. ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);
  842. ASSERT(m_SocketData.nSocketIndex!=-1);
  843. #ifndef NOLAYERS
  844. if (m_pFirstLayer)
  845. {
  846. CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=new CAsyncSocketExLayer::t_LayerNotifyMsg;
  847. pMsg->lEvent=lEvent%0xFFFF;
  848. pMsg->pLayer=0;
  849. BOOL res=PostMessage(GetHelperWindowHandle(), WM_USER, (WPARAM)this, (LPARAM)pMsg);
  850. if (!res)
  851. delete pMsg;
  852. return res;
  853. }
  854. else
  855. #endif //NOLAYERS
  856. return PostMessage(GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, m_SocketData.hSocket, lEvent%0xFFFF);
  857. }
  858. SOCKET CAsyncSocketEx::GetSocketHandle()
  859. {
  860. return m_SocketData.hSocket;
  861. }
  862. HWND CAsyncSocketEx::GetHelperWindowHandle()
  863. {
  864. if (!m_pLocalAsyncSocketExThreadData)
  865. return 0;
  866. if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)
  867. return 0;
  868. return m_pLocalAsyncSocketExThreadData->m_pHelperWindow->GetHwnd();
  869. }
  870. #ifndef NOLAYERS
  871. BOOL CAsyncSocketEx::AddLayer(CAsyncSocketExLayer *pLayer)
  872. {
  873. ASSERT(pLayer);
  874. if (m_SocketData.hSocket!=INVALID_SOCKET)
  875. return FALSE;
  876. if (m_pFirstLayer)
  877. {
  878. ASSERT(m_pLastLayer);
  879. m_pLastLayer=m_pLastLayer->AddLayer(pLayer, this);
  880. return m_pLastLayer?TRUE:FALSE;
  881. }
  882. else
  883. {
  884. ASSERT(!m_pLastLayer);
  885. pLayer->Init(0, this);
  886. m_pFirstLayer=pLayer;
  887. m_pLastLayer=m_pFirstLayer;
  888. }
  889. return TRUE;
  890. }
  891. void CAsyncSocketEx::RemoveAllLayers()
  892. {
  893. m_pFirstLayer=0;
  894. m_pLastLayer=0;
  895. }
  896. int CAsyncSocketEx::OnLayerCallback(const CAsyncSocketExLayer *pLayer, int nType, int nParam1, int nParam2)
  897. {
  898. ASSERT(pLayer);
  899. return 1;
  900. }
  901. #endif //NOLAYERS
  902. BOOL CAsyncSocketEx::GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel /*=SOL_SOCKET*/)
  903. {
  904. return (SOCKET_ERROR != getsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen));
  905. }
  906. BOOL CAsyncSocketEx::SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel /*=SOL_SOCKET*/)
  907. {
  908. return (SOCKET_ERROR != setsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, nOptionLen));
  909. }