home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / sockcore.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  28KB  |  1,174 lines

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