sockcore.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <stddef.h>
  12. #ifdef AFX_SOCK_SEG
  13. #pragma code_seg(AFX_SOCK_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. #define new DEBUG_NEW
  20. #define _afxSockThreadState AfxGetModuleThreadState()
  21. #define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
  22. #pragma comment(lib, "wsock32.lib")
  23. /////////////////////////////////////////////////////////////////////////////
  24. // socket state cleanup
  25. _AFX_SOCK_STATE::~_AFX_SOCK_STATE()
  26. {
  27. if (m_pfnSockTerm != NULL)
  28. m_pfnSockTerm();
  29. }
  30. /////////////////////////////////////////////////////////////////////////////
  31. // sockets globals and implementation helpers
  32. void AFXAPI AfxSocketTerm()
  33. {
  34. _AFX_SOCK_STATE* pState = _afxSockState.GetData();
  35. if (pState->m_hInstSOCK != NULL)
  36. {
  37. if (pState->m_pfnSockTerm != NULL)
  38. WSACleanup();
  39. FreeLibrary(pState->m_hInstSOCK);// handle of WSOCK32.DLL
  40. pState->m_hInstSOCK = NULL;
  41. }
  42. }
  43. BOOL AFXAPI AfxSocketInit(WSADATA* lpwsaData)
  44. {
  45. _AFX_SOCK_STATE* pState = _afxSockState.GetData();
  46. if (pState->m_pfnSockTerm == NULL)
  47. {
  48. // initialize Winsock library
  49. WSADATA wsaData;
  50. if (lpwsaData == NULL)
  51. lpwsaData = &wsaData;
  52. WORD wVersionRequested = MAKEWORD(1, 1);
  53. int nResult = WSAStartup(wVersionRequested, lpwsaData);
  54. if (nResult != 0)
  55. return FALSE;
  56. if (LOBYTE(lpwsaData->wVersion) != 1 || HIBYTE(lpwsaData->wVersion) != 1)
  57. {
  58. WSACleanup();
  59. return FALSE;
  60. }
  61. // setup for termination of sockets
  62. pState->m_pfnSockTerm = &AfxSocketTerm;
  63. #ifndef _AFXDLL
  64. // setup maps and lists specific to socket state
  65. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  66. if (pState->m_pmapSocketHandle == NULL)
  67. pState->m_pmapSocketHandle = new CMapPtrToPtr;
  68. if (pState->m_pmapDeadSockets == NULL)
  69. pState->m_pmapDeadSockets = new CMapPtrToPtr;
  70. if (pState->m_plistSocketNotifications == NULL)
  71. pState->m_plistSocketNotifications = new CPtrList;
  72. #endif
  73. }
  74. return TRUE;
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CAsyncSocket Construction
  78. CAsyncSocket::CAsyncSocket()
  79. {
  80. m_hSocket = INVALID_SOCKET;
  81. }
  82. BOOL CAsyncSocket::Create(UINT nSocketPort, int nSocketType,
  83. long lEvent, LPCTSTR lpszSocketAddress)
  84. {
  85. if (Socket(nSocketType, lEvent))
  86. {
  87. if (Bind(nSocketPort,lpszSocketAddress))
  88. return TRUE;
  89. int nResult = GetLastError();
  90. Close();
  91. WSASetLastError(nResult);
  92. }
  93. return FALSE;
  94. }
  95. /////////////////////////////////////////////////////////////////////////////
  96. // CAsyncSocket Attributes
  97. BOOL CAsyncSocket::Attach(SOCKET hSocket, long lEvent)
  98. {
  99. ASSERT(hSocket != INVALID_SOCKET);
  100. m_hSocket = hSocket;
  101. CAsyncSocket::AttachHandle(hSocket, this);
  102. return AsyncSelect(lEvent);
  103. }
  104. SOCKET CAsyncSocket::Detach()
  105. {
  106. SOCKET hSocket = m_hSocket;
  107. if (AsyncSelect(0))
  108. {
  109. CAsyncSocket::KillSocket(hSocket, this);
  110. m_hSocket = INVALID_SOCKET;
  111. return hSocket;
  112. }
  113. return INVALID_SOCKET;
  114. }
  115. BOOL CAsyncSocket::GetPeerName(CString& rPeerAddress, UINT& rPeerPort)
  116. {
  117. SOCKADDR_IN sockAddr;
  118. memset(&sockAddr, 0, sizeof(sockAddr));
  119. int nSockAddrLen = sizeof(sockAddr);
  120. BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  121. if (bResult)
  122. {
  123. rPeerPort = ntohs(sockAddr.sin_port);
  124. rPeerAddress = inet_ntoa(sockAddr.sin_addr);
  125. }
  126. return bResult;
  127. }
  128. BOOL CAsyncSocket::GetSockName(CString& rSocketAddress, UINT& rSocketPort)
  129. {
  130. SOCKADDR_IN sockAddr;
  131. memset(&sockAddr, 0, sizeof(sockAddr));
  132. int nSockAddrLen = sizeof(sockAddr);
  133. BOOL bResult = GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  134. if (bResult)
  135. {
  136. rSocketPort = ntohs(sockAddr.sin_port);
  137. rSocketAddress = inet_ntoa(sockAddr.sin_addr);
  138. }
  139. return bResult;
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. // CAscynSocket Operations
  143. BOOL CAsyncSocket::Accept(CAsyncSocket& rConnectedSocket,
  144. SOCKADDR* lpSockAddr, int* lpSockAddrLen)
  145. {
  146. ASSERT(rConnectedSocket.m_hSocket == INVALID_SOCKET);
  147. ASSERT(CAsyncSocket::FromHandle(INVALID_SOCKET) == NULL);
  148. CAsyncSocket::AttachHandle(INVALID_SOCKET, &rConnectedSocket);
  149. SOCKET hTemp = accept(m_hSocket, lpSockAddr, lpSockAddrLen);
  150. if (hTemp == INVALID_SOCKET)
  151. {
  152. DWORD dwProblem = GetLastError();
  153. CAsyncSocket::DetachHandle(rConnectedSocket.m_hSocket, FALSE);
  154. rConnectedSocket.m_hSocket = INVALID_SOCKET;
  155. SetLastError(dwProblem);
  156. }
  157. else if (CAsyncSocket::FromHandle(INVALID_SOCKET) != NULL)
  158. {
  159. rConnectedSocket.m_hSocket = hTemp;
  160. CAsyncSocket::DetachHandle(INVALID_SOCKET, FALSE);
  161. CAsyncSocket::AttachHandle(hTemp, &rConnectedSocket);
  162. }
  163. return (hTemp != INVALID_SOCKET);
  164. }
  165. BOOL CAsyncSocket::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress)
  166. {
  167. USES_CONVERSION;
  168. SOCKADDR_IN sockAddr;
  169. memset(&sockAddr,0,sizeof(sockAddr));
  170. LPSTR lpszAscii = T2A((LPTSTR)lpszSocketAddress);
  171. sockAddr.sin_family = AF_INET;
  172. if (lpszAscii == NULL)
  173. sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  174. else
  175. {
  176. DWORD lResult = inet_addr(lpszAscii);
  177. if (lResult == INADDR_NONE)
  178. {
  179. WSASetLastError(WSAEINVAL);
  180. return FALSE;
  181. }
  182. sockAddr.sin_addr.s_addr = lResult;
  183. }
  184. sockAddr.sin_port = htons((u_short)nSocketPort);
  185. return Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr));
  186. }
  187. void CAsyncSocket::Close()
  188. {
  189. if (m_hSocket != INVALID_SOCKET)
  190. {
  191. VERIFY(SOCKET_ERROR != closesocket(m_hSocket));
  192. CAsyncSocket::KillSocket(m_hSocket, this);
  193. m_hSocket = INVALID_SOCKET;
  194. }
  195. }
  196. BOOL CAsyncSocket::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
  197. {
  198. USES_CONVERSION;
  199. ASSERT(lpszHostAddress != NULL);
  200. SOCKADDR_IN sockAddr;
  201. memset(&sockAddr,0,sizeof(sockAddr));
  202. LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);
  203. sockAddr.sin_family = AF_INET;
  204. sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
  205. if (sockAddr.sin_addr.s_addr == INADDR_NONE)
  206. {
  207. LPHOSTENT lphost;
  208. lphost = gethostbyname(lpszAscii);
  209. if (lphost != NULL)
  210. sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
  211. else
  212. {
  213. WSASetLastError(WSAEINVAL);
  214. return FALSE;
  215. }
  216. }
  217. sockAddr.sin_port = htons((u_short)nHostPort);
  218. return Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
  219. }
  220. int CAsyncSocket::Receive(void* lpBuf, int nBufLen, int nFlags)
  221. {
  222. return recv(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
  223. }
  224. int CAsyncSocket::ReceiveFrom(void* lpBuf, int nBufLen, CString& rSocketAddress, UINT& rSocketPort, int nFlags)
  225. {
  226. SOCKADDR_IN sockAddr;
  227. memset(&sockAddr, 0, sizeof(sockAddr));
  228. int nSockAddrLen = sizeof(sockAddr);
  229. int nResult = ReceiveFrom(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, &nSockAddrLen, nFlags);
  230. if(nResult != SOCKET_ERROR)
  231. {
  232. rSocketPort = ntohs(sockAddr.sin_port);
  233. rSocketAddress = inet_ntoa(sockAddr.sin_addr);
  234. }
  235. return nResult;
  236. }
  237. int CAsyncSocket::Send(const void* lpBuf, int nBufLen, int nFlags)
  238. {
  239. return send(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
  240. }
  241. int CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags)
  242. {
  243. USES_CONVERSION;
  244. SOCKADDR_IN sockAddr;
  245. memset(&sockAddr,0,sizeof(sockAddr));
  246. LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);
  247. sockAddr.sin_family = AF_INET;
  248. if (lpszAscii == NULL)
  249. sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
  250. else
  251. {
  252. sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
  253. if (sockAddr.sin_addr.s_addr == INADDR_NONE)
  254. {
  255. LPHOSTENT lphost;
  256. lphost = gethostbyname(lpszAscii);
  257. if (lphost != NULL)
  258. sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
  259. else
  260. {
  261. WSASetLastError(WSAEINVAL);
  262. return SOCKET_ERROR;
  263. }
  264. }
  265. }
  266. sockAddr.sin_port = htons((u_short)nHostPort);
  267. return SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags);
  268. }
  269. BOOL CAsyncSocket::AsyncSelect(long lEvent)
  270. {
  271. ASSERT(m_hSocket != INVALID_SOCKET);
  272. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  273. ASSERT(pState->m_hSocketWindow != NULL);
  274. return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow,
  275. WM_SOCKET_NOTIFY, lEvent) != SOCKET_ERROR;
  276. }
  277. /////////////////////////////////////////////////////////////////////////////
  278. // CAsyncSocket Overridable callbacks
  279. void CAsyncSocket::OnReceive(int /*nErrorCode*/)
  280. {
  281. }
  282. void CAsyncSocket::OnSend(int /*nErrorCode*/)
  283. {
  284. }
  285. void CAsyncSocket::OnOutOfBandData(int /*nErrorCode*/)
  286. {
  287. }
  288. void CAsyncSocket::OnAccept(int /*nErrorCode*/)
  289. {
  290. }
  291. void CAsyncSocket::OnConnect(int /*nErrorCode*/)
  292. {
  293. }
  294. void CAsyncSocket::OnClose(int /*nErrorCode*/)
  295. {
  296. }
  297. /////////////////////////////////////////////////////////////////////////////
  298. // CAsyncSocket Implementation
  299. CAsyncSocket::~CAsyncSocket()
  300. {
  301. if (m_hSocket != INVALID_SOCKET)
  302. Close();
  303. }
  304. CAsyncSocket* PASCAL CAsyncSocket::LookupHandle(SOCKET hSocket, BOOL bDead)
  305. {
  306. CAsyncSocket* pSocket;
  307. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  308. if (!bDead)
  309. {
  310. pSocket = (CAsyncSocket*)
  311. pState->m_pmapSocketHandle->GetValueAt((void*)hSocket);
  312. if (pSocket != NULL)
  313. return pSocket;
  314. }
  315. else
  316. {
  317. pSocket = (CAsyncSocket*)
  318. pState->m_pmapDeadSockets->GetValueAt((void*)hSocket);
  319. if (pSocket != NULL)
  320. return pSocket;
  321. }
  322. return NULL;
  323. }
  324. void PASCAL CAsyncSocket::AttachHandle(
  325. SOCKET hSocket, CAsyncSocket* pSocket, BOOL bDead)
  326. {
  327. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  328. BOOL bEnable = AfxEnableMemoryTracking(FALSE);
  329. if (!bDead)
  330. {
  331. ASSERT(CAsyncSocket::LookupHandle(hSocket, bDead) == NULL);
  332. if (pState->m_pmapSocketHandle->IsEmpty())
  333. {
  334. ASSERT(pState->m_pmapDeadSockets->IsEmpty());
  335. ASSERT(pState->m_hSocketWindow == NULL);
  336. CSocketWnd* pWnd = new CSocketWnd;
  337. pWnd->m_hWnd = NULL;
  338. if (!pWnd->CreateEx(0, AfxRegisterWndClass(0),
  339. _T("Socket Notification Sink"),
  340. WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
  341. {
  342. TRACE0("Warning: unable to create socket notify window!\n");
  343. AfxThrowResourceException();
  344. }
  345. ASSERT(pWnd->m_hWnd != NULL);
  346. ASSERT(CWnd::FromHandlePermanent(pWnd->m_hWnd) == pWnd);
  347. pState->m_hSocketWindow = pWnd->m_hWnd;
  348. }
  349. pState->m_pmapSocketHandle->SetAt((void*)hSocket, pSocket);
  350. }
  351. else
  352. {
  353. int nCount;
  354. if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
  355. nCount++;
  356. else
  357. nCount = 1;
  358. pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
  359. }
  360. AfxEnableMemoryTracking(bEnable);
  361. }
  362. void PASCAL CAsyncSocket::DetachHandle(SOCKET hSocket, BOOL bDead)
  363. {
  364. ASSERT(CAsyncSocket::LookupHandle(hSocket, bDead) != NULL);
  365. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  366. if (!bDead)
  367. {
  368. pState->m_pmapSocketHandle->RemoveKey((void*)hSocket);
  369. if (pState->m_pmapSocketHandle->IsEmpty())
  370. {
  371. ASSERT(pState->m_hSocketWindow != NULL);
  372. CWnd* pWnd =
  373. CWnd::FromHandlePermanent(pState->m_hSocketWindow);
  374. ASSERT_VALID(pWnd);
  375. pWnd->DestroyWindow();
  376. delete pWnd;
  377. pState->m_hSocketWindow = NULL;
  378. pState->m_pmapDeadSockets->RemoveAll();
  379. while (!pState->m_plistSocketNotifications->IsEmpty())
  380. delete pState->m_plistSocketNotifications->RemoveHead();
  381. }
  382. }
  383. else
  384. {
  385. int nCount;
  386. if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
  387. {
  388. nCount--;
  389. if (nCount == 0)
  390. pState->m_pmapDeadSockets->RemoveKey((void*)hSocket);
  391. else
  392. pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
  393. }
  394. }
  395. }
  396. void PASCAL CAsyncSocket::KillSocket(SOCKET hSocket, CAsyncSocket* pSocket)
  397. {
  398. ASSERT(CAsyncSocket::LookupHandle(hSocket, FALSE) != NULL);
  399. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  400. CAsyncSocket::DetachHandle(hSocket, FALSE);
  401. if (pState->m_hSocketWindow != NULL)
  402. {
  403. ::PostMessage(pState->m_hSocketWindow, WM_SOCKET_DEAD,
  404. (WPARAM)hSocket, 0L);
  405. CAsyncSocket::AttachHandle(hSocket, pSocket, TRUE);
  406. }
  407. }
  408. void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)
  409. {
  410. if (wParam == 0 && lParam == 0)
  411. return;
  412. // Has the socket be closed?
  413. CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE);
  414. // If yes ignore message
  415. if (pSocket != NULL)
  416. return;
  417. pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE);
  418. if (pSocket == NULL)
  419. {
  420. // Must be in the middle of an Accept call
  421. pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);
  422. ASSERT(pSocket != NULL);
  423. pSocket->m_hSocket = (SOCKET)wParam;
  424. CAsyncSocket::DetachHandle(INVALID_SOCKET, FALSE);
  425. CAsyncSocket::AttachHandle(pSocket->m_hSocket, pSocket, FALSE);
  426. }
  427. int nErrorCode = WSAGETSELECTERROR(lParam);
  428. switch (WSAGETSELECTEVENT(lParam))
  429. {
  430. case FD_READ:
  431. {
  432. DWORD nBytes;
  433. if (!pSocket->IOCtl(FIONREAD, &nBytes))
  434. nErrorCode = WSAGetLastError();
  435. if (nBytes != 0 || nErrorCode != 0)
  436. pSocket->OnReceive(nErrorCode);
  437. }
  438. break;
  439. case FD_WRITE:
  440. pSocket->OnSend(nErrorCode);
  441. break;
  442. case FD_OOB:
  443. pSocket->OnOutOfBandData(nErrorCode);
  444. break;
  445. case FD_ACCEPT:
  446. pSocket->OnAccept(nErrorCode);
  447. break;
  448. case FD_CONNECT:
  449. pSocket->OnConnect(nErrorCode);
  450. break;
  451. case FD_CLOSE:
  452. pSocket->OnClose(nErrorCode);
  453. break;
  454. }
  455. }
  456. BOOL CAsyncSocket::Socket(int nSocketType, long lEvent,
  457. int nProtocolType, int nAddressFormat)
  458. {
  459. ASSERT(m_hSocket == INVALID_SOCKET);
  460. m_hSocket = socket(nAddressFormat,nSocketType,nProtocolType);
  461. if (m_hSocket != INVALID_SOCKET)
  462. {
  463. CAsyncSocket::AttachHandle(m_hSocket, this, FALSE);
  464. return AsyncSelect(lEvent);
  465. }
  466. return FALSE;
  467. }
  468. #ifdef _DEBUG
  469. void CAsyncSocket::AssertValid() const
  470. {
  471. CObject::AssertValid();
  472. ASSERT(m_hSocket == INVALID_SOCKET || CAsyncSocket::FromHandle(m_hSocket) != NULL);
  473. }
  474. void CAsyncSocket::Dump(CDumpContext& dc) const
  475. {
  476. CObject::Dump(dc);
  477. dc << "m_hSocket = ";
  478. if (m_hSocket == INVALID_SOCKET)
  479. dc << "INVALID_SOCKET\n";
  480. else
  481. dc << m_hSocket << "\n";
  482. }
  483. #endif //_DEBUG
  484. int CAsyncSocket::ReceiveFromHelper(void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags)
  485. {
  486. return recvfrom(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags, lpSockAddr, lpSockAddrLen);
  487. }
  488. int CAsyncSocket::SendToHelper(const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags)
  489. {
  490. return sendto(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags, lpSockAddr, nSockAddrLen);
  491. }
  492. BOOL CAsyncSocket::ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen)
  493. {
  494. return connect(m_hSocket, lpSockAddr, nSockAddrLen) != SOCKET_ERROR;
  495. }
  496. /////////////////////////////////////////////////////////////////////////////
  497. // CSocket Construction
  498. CSocket::CSocket()
  499. {
  500. m_pbBlocking = NULL;
  501. m_nConnectError = -1;
  502. m_nTimeOut = 2000;
  503. }
  504. /////////////////////////////////////////////////////////////////////////////
  505. // CSocket Operations
  506. void CSocket::CancelBlockingCall()
  507. {
  508. if (m_pbBlocking != NULL)
  509. {
  510. *m_pbBlocking = FALSE;
  511. m_pbBlocking = NULL;
  512. }
  513. }
  514. /////////////////////////////////////////////////////////////////////////////
  515. // CSocket Overridable callbacks
  516. BOOL CSocket::OnMessagePending()
  517. {
  518. MSG msg;
  519. if (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE))
  520. {
  521. ::DispatchMessage(&msg);
  522. return FALSE; // usually return TRUE, but OnIdle usually causes WM_PAINTs
  523. }
  524. return FALSE;
  525. }
  526. /////////////////////////////////////////////////////////////////////////////
  527. // CSocket Implementation
  528. CSocket::~CSocket()
  529. {
  530. if (m_hSocket != INVALID_SOCKET)
  531. Close();
  532. }
  533. BOOL CSocket::Accept(CAsyncSocket& rConnectedSocket, SOCKADDR* lpSockAddr, int* lpSockAddrLen)
  534. {
  535. if (m_pbBlocking != NULL)
  536. {
  537. WSASetLastError(WSAEINPROGRESS);
  538. return FALSE;
  539. }
  540. while (!CAsyncSocket::Accept(rConnectedSocket, lpSockAddr, lpSockAddrLen))
  541. {
  542. if (GetLastError() == WSAEWOULDBLOCK)
  543. {
  544. if (!PumpMessages(FD_ACCEPT))
  545. return FALSE;
  546. }
  547. else
  548. return FALSE;
  549. }
  550. return TRUE;
  551. }
  552. void CSocket::Close()
  553. {
  554. if (m_hSocket != INVALID_SOCKET)
  555. {
  556. CancelBlockingCall();
  557. VERIFY(AsyncSelect(0));
  558. CAsyncSocket::Close();
  559. m_hSocket = INVALID_SOCKET;
  560. }
  561. }
  562. int CSocket::Receive(void* lpBuf, int nBufLen, int nFlags)
  563. {
  564. if (m_pbBlocking != NULL)
  565. {
  566. WSASetLastError(WSAEINPROGRESS);
  567. return FALSE;
  568. }
  569. int nResult;
  570. while ((nResult = CAsyncSocket::Receive(lpBuf, nBufLen, nFlags)) == SOCKET_ERROR)
  571. {
  572. if (GetLastError() == WSAEWOULDBLOCK)
  573. {
  574. if (!PumpMessages(FD_READ))
  575. return SOCKET_ERROR;
  576. }
  577. else
  578. return SOCKET_ERROR;
  579. }
  580. return nResult;
  581. }
  582. int CSocket::Send(const void* lpBuf, int nBufLen, int nFlags)
  583. {
  584. if (m_pbBlocking != NULL)
  585. {
  586. WSASetLastError(WSAEINPROGRESS);
  587. return FALSE;
  588. }
  589. int nLeft, nWritten;
  590. PBYTE pBuf = (PBYTE)lpBuf;
  591. nLeft = nBufLen;
  592. while (nLeft > 0)
  593. {
  594. nWritten = SendChunk(pBuf, nLeft, nFlags);
  595. if (nWritten == SOCKET_ERROR)
  596. return nWritten;
  597. nLeft -= nWritten;
  598. pBuf += nWritten;
  599. }
  600. return nBufLen - nLeft;
  601. }
  602. int CSocket::SendChunk(const void* lpBuf, int nBufLen, int nFlags)
  603. {
  604. int nResult;
  605. while ((nResult = CAsyncSocket::Send(lpBuf, nBufLen, nFlags)) == SOCKET_ERROR)
  606. {
  607. if (GetLastError() == WSAEWOULDBLOCK)
  608. {
  609. if (!PumpMessages(FD_WRITE))
  610. return SOCKET_ERROR;
  611. }
  612. else
  613. return SOCKET_ERROR;
  614. }
  615. return nResult;
  616. }
  617. BOOL CSocket::ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen)
  618. {
  619. if (m_pbBlocking != NULL)
  620. {
  621. WSASetLastError(WSAEINPROGRESS);
  622. return FALSE;
  623. }
  624. m_nConnectError = -1;
  625. if (!CAsyncSocket::ConnectHelper(lpSockAddr, nSockAddrLen))
  626. {
  627. if (GetLastError() == WSAEWOULDBLOCK)
  628. {
  629. while (PumpMessages(FD_CONNECT))
  630. {
  631. if (m_nConnectError != -1)
  632. {
  633. WSASetLastError(m_nConnectError);
  634. return (m_nConnectError == 0);
  635. }
  636. }
  637. }
  638. return FALSE;
  639. }
  640. return TRUE;
  641. }
  642. int CSocket::ReceiveFromHelper(void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags)
  643. {
  644. if (m_pbBlocking != NULL)
  645. {
  646. WSASetLastError(WSAEINPROGRESS);
  647. return FALSE;
  648. }
  649. int nResult;
  650. while ((nResult = CAsyncSocket::ReceiveFromHelper(lpBuf, nBufLen, lpSockAddr, lpSockAddrLen, nFlags)) == SOCKET_ERROR)
  651. {
  652. if (GetLastError() == WSAEWOULDBLOCK)
  653. {
  654. if (!PumpMessages(FD_READ))
  655. return SOCKET_ERROR;
  656. }
  657. else
  658. return SOCKET_ERROR;
  659. }
  660. return nResult;
  661. }
  662. int CSocket::SendToHelper(const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags)
  663. {
  664. if (m_pbBlocking != NULL)
  665. {
  666. WSASetLastError(WSAEINPROGRESS);
  667. return SOCKET_ERROR;
  668. }
  669. int nResult;
  670. while ((nResult = CAsyncSocket::SendToHelper(lpBuf, nBufLen, lpSockAddr, nSockAddrLen, nFlags)) == SOCKET_ERROR)
  671. {
  672. if (GetLastError() == WSAEWOULDBLOCK)
  673. {
  674. if (!PumpMessages(FD_WRITE))
  675. return SOCKET_ERROR;
  676. }
  677. else
  678. return SOCKET_ERROR;
  679. }
  680. return nResult;
  681. }
  682. int PASCAL CSocket::ProcessAuxQueue()
  683. {
  684. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  685. if (pState->m_plistSocketNotifications->IsEmpty())
  686. return 0;
  687. int nCount = 0;
  688. while(!pState->m_plistSocketNotifications->IsEmpty())
  689. {
  690. nCount++;
  691. MSG* pMsg = (MSG*)pState->m_plistSocketNotifications->RemoveHead();
  692. ASSERT(pMsg != NULL);
  693. if (pMsg->message == WM_SOCKET_NOTIFY)
  694. {
  695. CAsyncSocket::DoCallBack(pMsg->wParam, pMsg->lParam);
  696. }
  697. else
  698. {
  699. ASSERT(CAsyncSocket::LookupHandle((SOCKET)pMsg->wParam, TRUE) != NULL);
  700. CAsyncSocket::DetachHandle((SOCKET)pMsg->wParam, TRUE);
  701. }
  702. delete pMsg;
  703. }
  704. return nCount;
  705. }
  706. void PASCAL CSocket::AuxQueueAdd(UINT message, WPARAM wParam, LPARAM lParam)
  707. {
  708. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  709. MSG* pMsg = new MSG;
  710. pMsg->message = message;
  711. pMsg->wParam = wParam;
  712. pMsg->lParam = lParam;
  713. pState->m_plistSocketNotifications->AddTail(pMsg);
  714. }
  715. BOOL CSocket::PumpMessages(UINT uStopFlag)
  716. {
  717. // The same socket better not be blocking in more than one place.
  718. ASSERT(m_pbBlocking == NULL);
  719. _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
  720. ASSERT(pState->m_hSocketWindow != NULL);
  721. BOOL bBlocking = TRUE;
  722. m_pbBlocking = &bBlocking;
  723. CWinThread* pThread = AfxGetThread();
  724. // This is not a timeout in the WinSock sense, but more
  725. // like a WM_KICKIDLE to keep message pumping alive
  726. UINT nTimerID = ::SetTimer(pState->m_hSocketWindow, 1, m_nTimeOut, NULL);
  727. if (nTimerID == 0)
  728. AfxThrowResourceException();
  729. BOOL bPeek = TRUE;
  730. while (bBlocking)
  731. {
  732. TRY
  733. {
  734. MSG msg;
  735. if (::PeekMessage(&msg, pState->m_hSocketWindow,
  736. WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE))
  737. {
  738. if (msg.message == WM_SOCKET_NOTIFY && (SOCKET)msg.wParam == m_hSocket)
  739. {
  740. if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE)
  741. {
  742. break;
  743. }
  744. if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag)
  745. {
  746. if (uStopFlag == FD_CONNECT)
  747. m_nConnectError = WSAGETSELECTERROR(msg.lParam);
  748. break;
  749. }
  750. }
  751. if (msg.wParam != 0 || msg.lParam != 0)
  752. CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam);
  753. bPeek = TRUE;
  754. }
  755. else if (::PeekMessage(&msg, pState->m_hSocketWindow,
  756. WM_TIMER, WM_TIMER, PM_REMOVE))
  757. {
  758. break;
  759. }
  760. if (bPeek && ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
  761. {
  762. if (OnMessagePending())
  763. {
  764. // allow user-interface updates
  765. pThread->OnIdle(-1);
  766. }
  767. else
  768. {
  769. bPeek = FALSE;
  770. }
  771. }
  772. else
  773. {
  774. // no work to do -- allow CPU to sleep
  775. WaitMessage();
  776. bPeek = TRUE;
  777. }
  778. }
  779. CATCH_ALL(e)
  780. {
  781. TRACE0("Error: caught exception in PumpMessage - continuing.\n");
  782. DELETE_EXCEPTION(e);
  783. bPeek = TRUE;
  784. }
  785. END_CATCH_ALL
  786. }
  787. ::KillTimer(pState->m_hSocketWindow, nTimerID);
  788. if (!bBlocking)
  789. {
  790. WSASetLastError(WSAEINTR);
  791. return FALSE;
  792. }
  793. m_pbBlocking = NULL;
  794. ::PostMessage(pState->m_hSocketWindow, WM_SOCKET_NOTIFY, 0, 0);
  795. return TRUE;
  796. }
  797. #ifdef _DEBUG
  798. void CSocket::AssertValid() const
  799. {
  800. CAsyncSocket::AssertValid();
  801. }
  802. void CSocket::Dump(CDumpContext& dc) const
  803. {
  804. CAsyncSocket::Dump(dc);
  805. dc << "m_pbBlocking = " << m_pbBlocking <<"\n";
  806. dc << "m_nConnectError = " << m_nConnectError <<"\n";
  807. }
  808. #endif //_DEBUG
  809. /////////////////////////////////////////////////////////////////////////////
  810. // CSocketFile Construction
  811. CSocketFile::CSocketFile(CSocket* pSocket, BOOL bArchiveCompatible)
  812. {
  813. m_pSocket = pSocket;
  814. m_bArchiveCompatible = bArchiveCompatible;
  815. #ifdef _DEBUG
  816. ASSERT(m_pSocket != NULL);
  817. ASSERT(m_pSocket->m_hSocket != INVALID_SOCKET);
  818. int nType = 0;
  819. int nTypeLen = sizeof(int);
  820. ASSERT(m_pSocket->GetSockOpt(SO_TYPE,&nType,&nTypeLen));
  821. ASSERT(nType == SOCK_STREAM);
  822. #endif // _DEBUG
  823. }
  824. /////////////////////////////////////////////////////////////////////////////
  825. // CSocketFile Implementation
  826. CSocketFile::~CSocketFile()
  827. {
  828. }
  829. UINT CSocketFile::Read(void* lpBuf, UINT nCount)
  830. {
  831. ASSERT(m_pSocket != NULL);
  832. int nRead;
  833. if (!m_bArchiveCompatible)
  834. {
  835. int nLeft = nCount;
  836. PBYTE pBuf = (PBYTE)lpBuf;
  837. while(nLeft > 0)
  838. {
  839. nRead = m_pSocket->Receive(pBuf, nLeft);
  840. if (nRead == SOCKET_ERROR)
  841. {
  842. int nError = m_pSocket->GetLastError();
  843. AfxThrowFileException(CFileException::generic, nError);
  844. ASSERT(FALSE);
  845. }
  846. else if (nRead == 0)
  847. {
  848. return nCount - nLeft;
  849. }
  850. nLeft -= nRead;
  851. pBuf += nRead;
  852. }
  853. return nCount - nLeft;
  854. }
  855. nRead = m_pSocket->Receive(lpBuf, nCount, 0);
  856. if (nRead == SOCKET_ERROR)
  857. {
  858. int nError = m_pSocket->GetLastError();
  859. AfxThrowFileException(CFileException::generic, nError);
  860. ASSERT(FALSE);
  861. }
  862. return nRead;
  863. }
  864. void CSocketFile::Write(const void* lpBuf, UINT nCount)
  865. {
  866. ASSERT (m_pSocket!=NULL);
  867. int nWritten = m_pSocket->Send(lpBuf, nCount);
  868. if (nWritten == SOCKET_ERROR)
  869. {
  870. int nError = m_pSocket->GetLastError();
  871. AfxThrowFileException(CFileException::generic, nError);
  872. }
  873. }
  874. void CSocketFile::Close()
  875. {
  876. m_pSocket = NULL;
  877. }
  878. BOOL CSocketFile::Open(
  879. LPCTSTR /*lpszFileName*/, UINT /*nOpenFlags*/, CFileException* /*pError*/)
  880. {
  881. AfxThrowNotSupportedException();
  882. return FALSE;
  883. }
  884. CFile* CSocketFile::Duplicate() const
  885. {
  886. AfxThrowNotSupportedException();
  887. return NULL;
  888. }
  889. DWORD CSocketFile::GetPosition() const
  890. {
  891. AfxThrowNotSupportedException();
  892. return 0;
  893. }
  894. LONG CSocketFile::Seek(LONG lOff, UINT nFrom)
  895. {
  896. if (lOff != 0L || nFrom != current)
  897. TRACE0("Warning - Attempt made to seek on a CSocketFile\n");
  898. return 0;
  899. }
  900. void CSocketFile::SetLength(DWORD /*dwNewLen*/)
  901. {
  902. AfxThrowNotSupportedException();
  903. }
  904. DWORD CSocketFile::GetLength() const
  905. {
  906. AfxThrowNotSupportedException();
  907. return 0;
  908. }
  909. void CSocketFile::LockRange(DWORD /*dwPos*/, DWORD /*dwCount*/)
  910. {
  911. AfxThrowNotSupportedException();
  912. }
  913. void CSocketFile::UnlockRange(DWORD /*dwPos*/, DWORD /*dwCount*/)
  914. {
  915. AfxThrowNotSupportedException();
  916. }
  917. void CSocketFile::Flush()
  918. {
  919. }
  920. void CSocketFile::Abort()
  921. {
  922. AfxThrowNotSupportedException();
  923. }
  924. #ifdef _DEBUG
  925. void CSocketFile::AssertValid() const
  926. {
  927. CFile::AssertValid();
  928. if (m_pSocket != NULL)
  929. ASSERT_VALID(m_pSocket);
  930. }
  931. void CSocketFile::Dump(CDumpContext& dc) const
  932. {
  933. CFile::Dump(dc);
  934. if (dc.GetDepth() > 0)
  935. {
  936. if (m_pSocket != NULL)
  937. dc << "with no socket\n";
  938. else
  939. dc << "with socket: " << m_pSocket;
  940. }
  941. }
  942. #endif //_DEBUG
  943. /////////////////////////////////////////////////////////////////////////////
  944. // CSocketWnd implementation
  945. CSocketWnd::CSocketWnd()
  946. {
  947. }
  948. LRESULT CSocketWnd::OnSocketNotify(WPARAM wParam, LPARAM lParam)
  949. {
  950. CSocket::AuxQueueAdd(WM_SOCKET_NOTIFY, wParam, lParam);
  951. CSocket::ProcessAuxQueue();
  952. return 0L;
  953. }
  954. LRESULT CSocketWnd::OnSocketDead(WPARAM wParam, LPARAM lParam)
  955. {
  956. CSocket::AuxQueueAdd(WM_SOCKET_DEAD, wParam, lParam);
  957. CSocket::ProcessAuxQueue();
  958. return 0L;
  959. }
  960. /////////////////////////////////////////////////////////////////////////////
  961. // Message table implementation
  962. BEGIN_MESSAGE_MAP(CSocketWnd, CWnd)
  963. //{{AFX_MSG_MAP(CWnd)
  964. ON_MESSAGE(WM_SOCKET_NOTIFY, OnSocketNotify)
  965. ON_MESSAGE(WM_SOCKET_DEAD, OnSocketDead)
  966. //}}AFX_MSG_MAP
  967. END_MESSAGE_MAP()
  968. //////////////////////////////////////////////////////////////////////////////
  969. // Inline function declarations expanded out-of-line
  970. #ifndef _AFX_ENABLE_INLINES
  971. static char _szAfxSockInl[] = "afxsock.inl";
  972. #undef THIS_FILE
  973. #define THIS_FILE _szAfxSockInl
  974. #define _AFXSOCK_INLINE
  975. #include "afxsock.inl"
  976. #undef _AFXSOCK_INLINE
  977. #endif
  978. #ifdef AFX_INIT_SEG
  979. #pragma code_seg(AFX_INIT_SEG)
  980. #endif
  981. IMPLEMENT_DYNAMIC(CAsyncSocket, CObject)
  982. IMPLEMENT_DYNAMIC(CSocket, CAsyncSocket)
  983. IMPLEMENT_DYNAMIC(CSocketFile, CFile)
  984. #pragma warning(disable: 4074)
  985. #pragma init_seg(lib)
  986. PROCESS_LOCAL(_AFX_SOCK_STATE, _afxSockState)
  987. /////////////////////////////////////////////////////////////////////////////