casynnet.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:20k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include <windows.h> // For Window-isms
  37. #include "hxcom.h"
  38. #include "hxslist.h"
  39. #include "platform/win/sock.h"
  40. #include "platform/win/hxsock.h"   // For Socket related constants and macros
  41. #include "platform/win/casynnet.h" // Our definition
  42. #include "hxmap.h" // Map object
  43. #include "debugout.h" // DEBUGOUTSTR()
  44. #include "hxassert.h" // HX_ASSERT()
  45. #include "hxstrutl.h"
  46. #include "hxheap.h"
  47. #ifdef _DEBUG
  48. #undef HX_THIS_FILE
  49. static const char HX_THIS_FILE[] = __FILE__;
  50. #endif  
  51. /* Constant Definitions */
  52. #define WND_CLASS_BASE "HX_Internal_Sock_Async"
  53. #define MAX_WND_CLASS_LENGTH 50
  54. #define OFFSET_THIS 0
  55. /* Class Static Definitions */
  56. BOOL CAsyncSockN::zm_bClassRegistered    = FALSE;
  57. CAsyncSockN* CAsyncSockN::zm_pSockNotifiers     = NULL;
  58. SockGlobals sockGlobals;
  59. /* Class Public Methods */
  60. // Either creates a socket notifier, or returns a pointer
  61. // to the socket notifier that should be used for this instance.
  62. CAsyncSockN *CAsyncSockN::GetCAsyncSockNotifier( HINSTANCE hInst , BOOL Create)
  63. {
  64.     CAsyncSockN*    pThis = 0;
  65.     // Does our current session already have a net notifier?
  66.     if (!(pThis = FindSockNotifier()) && Create)
  67.     {
  68. // No, then create one
  69. pThis = new CAsyncSockN(hInst);
  70. if (pThis && !pThis->IsValid())
  71. {
  72.     // If creation failed then delete the pointer
  73.     delete pThis;
  74.     pThis = NULL;
  75. }
  76. if (pThis)
  77. {
  78.     LinkUs(pThis);
  79. }
  80.     }
  81.     // return the results of our labor
  82.     return (pThis);
  83. }
  84. // Our client win_net object calls this method to
  85. // start an async DNS request.
  86. BOOL CAsyncSockN::DoAsyncDNS( win_net *fpSock, LPCSTR lpHostName, LPSTR pBuff, int cbBuffSize )
  87. {
  88.     // Preliminary checks
  89.     HX_ASSERT(this);
  90.     HX_ASSERT(fpSock);
  91.     HX_ASSERT(m_hWnd);
  92.     HX_ASSERT(lpHostName && *lpHostName);
  93.     // Bail on bad input
  94.     if (!this || !fpSock || !lpHostName || !*lpHostName)
  95.     {
  96. return(FALSE);
  97.     }
  98.     DNS_REQUEST* pDNSRequest = new DNS_REQUEST;
  99.     pDNSRequest->fpSock = fpSock;
  100.     if (lpHostName)
  101.     {
  102. pDNSRequest->lpHostName = new CHAR[strlen(lpHostName)+1];
  103. memset(pDNSRequest->lpHostName, 0, strlen(lpHostName)+1);
  104. strcpy(pDNSRequest->lpHostName, lpHostName); /* Flawfinder: ignore */
  105.     }
  106.     
  107.     pDNSRequest->lpBuffer = pBuff;
  108.     pDNSRequest->cbBufferSize = cbBuffSize;
  109.     sockGlobals.m_DNSQueue.AddTail(pDNSRequest);
  110.     
  111.     return ProcessDNSQueue();
  112. }
  113. BOOL CAsyncSockN::ProcessDNSQueue(void)
  114. {
  115.     BOOL     bResult = TRUE;
  116.     DNS_REQUEST*    pDNSRequest = NULL;
  117.     HANDLE     hAsyncHandle = NULL;
  118.     int     nCount = 0;
  119.     if (sockGlobals.m_DNSQueue.GetCount())
  120.     {
  121. if (sockGlobals.m_bWinSock2Suck)
  122. {
  123.     nCount = m_ClientHandlesMap->GetCount();
  124.     if (!nCount)
  125.     {
  126. pDNSRequest = (DNS_REQUEST*)sockGlobals.m_DNSQueue.GetHead();
  127.     }
  128.     else
  129.     {
  130. goto cleanup;
  131.     }
  132. }
  133. else
  134. {
  135.     pDNSRequest = (DNS_REQUEST*)sockGlobals.m_DNSQueue.RemoveHead();
  136. }
  137. // Start the async DNS
  138. hAsyncHandle = sockObj->HXWSAAsyncGetHostByName(m_hWnd, 
  139. PWM_ASYNC_DNS, 
  140. pDNSRequest->lpHostName, 
  141. pDNSRequest->lpBuffer, 
  142. pDNSRequest->cbBufferSize);
  143. // Create a mapping from the async handle to the win_net object pointer
  144. m_ClientHandlesMap->SetAt((void*)hAsyncHandle, pDNSRequest->fpSock);
  145. // You shouldn't already have an async operation active on this socket!
  146. HX_ASSERT(pDNSRequest->fpSock->m_hAsyncHandle == NULL);
  147. // Remember this in case we need to cancel!
  148. pDNSRequest->fpSock->m_hAsyncHandle = hAsyncHandle;
  149. // Bump our client count up
  150. IncrementHandlesClientCount();
  151.     }
  152. cleanup:
  153.     if (!sockGlobals.m_bWinSock2Suck)
  154.     {
  155. HX_DELETE(pDNSRequest);
  156.     }
  157.     return bResult;
  158. }
  159.    
  160. // Our client win_net object calls this method to 
  161. // start receiving async select notifications
  162. // on a socket.
  163. BOOL CAsyncSockN::DoAsyncSelect(win_net* fpSock)
  164. {
  165.     SOCKET theSocket;
  166.     // Preliminary checks
  167.     HX_ASSERT(this);
  168.     HX_ASSERT(fpSock);
  169.     // Bail on bad input
  170.     if (!this || !fpSock)
  171.     {
  172. return(FALSE);
  173.     }
  174.     // Get and verify we have a good socket handle
  175.     theSocket = fpSock->get_sock();
  176.     HX_ASSERT(theSocket != INVALID_SOCKET);
  177.     // Request async Notifications on the socket
  178.     long lEvent = (FD_CONNECT | FD_READ | FD_CLOSE) ;
  179. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  180.     lEvent |= (FD_WRITE | FD_ACCEPT);
  181. #endif
  182.     sockObj->HXWSAAsyncSelect(theSocket, m_hWnd, PWM_ASYNC_SELECT, lEvent);
  183.     // Create a mapping from socket handle to win_net object pointer
  184.     m_ClientSocketsMap->SetAt((void*)theSocket, fpSock);
  185.     // Bump our client count up
  186.     IncrementSocketsClientCount();
  187.     return (TRUE);
  188. }
  189. // Our client win_net object calls this method to 
  190. // stop receiving async select notifications
  191. // on a socket.
  192. BOOL CAsyncSockN::CancelSelect(win_net* fpSock)
  193. {
  194.     SOCKET     theSocket;
  195.     DNS_REQUEST*    pDNSRequest = NULL;
  196.     LISTPOSITION    lPos;
  197.     // Preliminary checks
  198.     HX_ASSERT(this);
  199.     HX_ASSERT(fpSock);
  200.     // Bail on bad input
  201.     if (!this || !fpSock)
  202.     {
  203. return(FALSE);
  204.     }
  205.     m_bInCancelMode = TRUE;
  206.     // If we haven't returned from an Asyn operation like GetHostByName
  207.     // then we need to tell Winsock to cancel the opertation!
  208.     HANDLE hAsyncHandle = fpSock->m_hAsyncHandle;
  209.     if (hAsyncHandle)
  210.     {
  211. sockObj->HXWSACancelAsyncRequest(hAsyncHandle);
  212. fpSock->m_hAsyncHandle = NULL;
  213. // If we've canceled the async DNS is done, 
  214. // then we can forget the Async handle
  215. if (m_ClientHandlesMap->RemoveKey((void*)hAsyncHandle))
  216. {
  217.     DecrementHandlesClientCount();
  218. }
  219.     }
  220.     if (sockGlobals.m_bWinSock2Suck)
  221.     {
  222. lPos = sockGlobals.m_DNSQueue.GetHeadPosition();
  223. while (lPos)
  224. {
  225.     pDNSRequest = (DNS_REQUEST *)sockGlobals.m_DNSQueue.GetAt(lPos);
  226.     if (pDNSRequest->fpSock == fpSock)
  227.     {
  228. sockGlobals.m_DNSQueue.RemoveAt(lPos);
  229. HX_DELETE(pDNSRequest);
  230. break;
  231.     }
  232.     sockGlobals.m_DNSQueue.GetNext(lPos);
  233. }
  234.     }
  235.     // Get and verify we have a good socket handle
  236.     theSocket = fpSock->get_sock();
  237.     
  238. //    HX_ASSERT(theSocket != INVALID_SOCKET);
  239.     /* This may actually happen since we do not check for CONN_CLOSED
  240.      * condition in win_net any more
  241.      */
  242.     if (theSocket == INVALID_SOCKET)
  243.     {
  244. m_bInCancelMode = FALSE;
  245. return FALSE;
  246.     }
  247.     // Turn off async Notifications on the socket
  248.     sockObj->HXWSAAsyncSelect(theSocket, m_hWnd, 0, 0);
  249.     // According to the Winsock help, just cause we cancel
  250.     // the notifications, doesn't mean we still won't get notified
  251.     // of something that has already been posted to our window,
  252.     // so... let's flush our message queue...
  253.     //
  254.     // HACK ATTACK: Notice that both of these message pumps
  255.     // are needed. If you run a debug build or a retail build
  256.     // on some machines without the two message pumps, you
  257.     // won't have any trouble. But on some machines having only
  258.     // this last message pump will cause a GPF.
  259.     MSG msg;
  260.     while (m_hWnd && PeekMessage(&msg, m_hWnd,0,0,PM_REMOVE))
  261.     {
  262. // This will remove any messages!
  263. HX_TRACE("There's a message that would've go you!!rn");
  264. if(msg.message == WM_QUIT) 
  265. {   
  266.     // When peeking WM_QUIT message in the main thread of an application 
  267.     // we have to put it back into message queue to allow the application 
  268.     // to exit correctly. SB
  269.     PostQuitMessage(0);
  270.     break;
  271. }
  272. else
  273. {
  274.     // Even though we want them removed, we also want to act on them.
  275.     DispatchMessage(&msg);
  276. }
  277.     }
  278.     if (m_ClientSocketsMap)
  279.     {
  280. // Delete the mapping from socket handle to win_net object pointer
  281. if (m_ClientSocketsMap->RemoveKey((void*)theSocket))
  282. {
  283.     // Decrement our client count and conditionally
  284.     // delete ourselves.
  285.     DecrementSocketsClientCount();
  286. }
  287.     }
  288.     m_bInCancelMode = FALSE;
  289.     // check to see if we are in use
  290.     CheckClients();
  291.     return (TRUE);
  292. }
  293. /*
  294.  * Private Class Methods
  295.  */
  296. // Static method
  297. // Computes a session id that should be thread unique
  298. // In Win32 we have a thread ID
  299. // In Win16 we have the task (single threaded)
  300. ULONG32 CAsyncSockN::GetSession()
  301. {
  302. #if defined( _WIN32 )
  303. return (GetCurrentThreadId());
  304. #else
  305. return ((ULONG32)(LPSTR)GetCurrentTask());
  306. #endif
  307. }
  308. // Hidden Constructor, called by GetAsyncNotifier() if there
  309. // is no Socket Notifier for the current session
  310. CAsyncSockN::CAsyncSockN(HINSTANCE hInst)
  311.     : m_hWnd(NULL)
  312.     , m_bValid(FALSE)
  313.     , m_hInst(hInst)
  314.     , m_cbNumHandlesClients(0)
  315.     , m_cbNumSocketsClients(0)
  316.     , m_bInCancelMode(FALSE)
  317.     , m_pNextNotifier(0)
  318. {
  319.     // Validate input
  320.     HX_ASSERT(this);
  321.     // assert( hInst );
  322.     if (!this)
  323.     {
  324. return;
  325.     }
  326.     m_ClientHandlesMap = new CHXMapPtrToPtr;
  327.     m_ClientSocketsMap = new CHXMapPtrToPtr;
  328.     m_ulSession = CAsyncSockN::GetSession();
  329.     m_bValid = Create();
  330. }
  331. // Workhorse construction method
  332. BOOL CAsyncSockN::Create()
  333. {
  334.     char szClassName[MAX_WND_CLASS_LENGTH]; /* Flawfinder: ignore */
  335.     SafeSprintf(szClassName, MAX_WND_CLASS_LENGTH, "%s%d", WND_CLASS_BASE, &zm_bClassRegistered);
  336.     if (!zm_bClassRegistered)
  337.     {
  338. WNDCLASS internalClass;
  339.     
  340. // First register our window class                                  
  341. internalClass.style  = 0;
  342. internalClass.lpfnWndProc  = CAsyncSockN::AsyncNotifyProc;
  343. internalClass.cbClsExtra = 0;
  344. internalClass.cbWndExtra = sizeof(this);
  345. internalClass.hInstance = m_hInst; // Use app's instance
  346. internalClass.hIcon = 0;
  347. internalClass.hCursor = 0;
  348. internalClass.hbrBackground = 0;
  349. internalClass.lpszMenuName = NULL;
  350. internalClass.lpszClassName = szClassName;
  351. zm_bClassRegistered = RegisterClass(&internalClass);
  352. if(!zm_bClassRegistered)
  353. {
  354.     UnregisterClass(szClassName, m_hInst);
  355.     zm_bClassRegistered = RegisterClass(&internalClass);
  356. }
  357.     }
  358.     // Now create an instance of the window
  359.     m_hWnd = CreateWindow(szClassName, "RealAudio Internal Messages", 
  360. WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, m_hInst, this);
  361.  
  362.     if (!m_hWnd)
  363.     {
  364. return (FALSE);
  365.     }
  366.     return (TRUE);
  367. }
  368. // Destructor: Destroys the window and unregisters the class if necessary
  369. CAsyncSockN::~CAsyncSockN()
  370. {
  371.     // Validate input
  372.     HX_ASSERT(this);
  373.     if (!this)
  374.     {
  375. return;
  376.     }
  377.     m_bValid = FALSE;
  378.     // UnlinkUs( this );
  379.     m_hWnd = NULL;
  380.     m_hInst = NULL;
  381.     if(m_ClientHandlesMap)
  382.     {
  383. delete m_ClientHandlesMap;
  384. m_ClientHandlesMap = NULL;
  385. m_cbNumHandlesClients = 0;
  386.     }
  387.     if(m_ClientSocketsMap)
  388.     {
  389. delete m_ClientSocketsMap;
  390. m_ClientSocketsMap = NULL;
  391. m_cbNumSocketsClients = 0;
  392.     }
  393. }
  394. // This is the WndProc that handles async notifications on behalf of the client
  395. // win_net objects.
  396. LRESULT HXEXPORT CAsyncSockN::AsyncNotifyProc(HWND hWnd, UINT msg, 
  397.       WPARAM wParam, LPARAM lParam)
  398. {
  399.     CAsyncSockN*    pThis = 0;
  400.     // Make ourselves look like a non-static member function dig the this
  401.     // pointer out of the window.
  402.     if (msg == WM_NCCREATE)
  403.     {
  404. CREATESTRUCT* lpCreate = 0;
  405. // Set our this pointer, so our WndProc can find us again
  406. lpCreate = (CREATESTRUCT FAR*) lParam;
  407. pThis = (CAsyncSockN*) lpCreate->lpCreateParams;
  408. SetWindowLong(hWnd, OFFSET_THIS, (long) pThis);
  409.     }
  410.     else if (msg == WM_NCDESTROY)
  411.     {
  412. // remove our this pointer so if somebody calls this function
  413. // again after the window is gone (and the object is gone
  414. // too) we don't try to call a method from the pointer
  415. SetWindowLong(hWnd, OFFSET_THIS, 0L);
  416.     }
  417.     else
  418.     {
  419. // Note: This MUST be a static function
  420. // However we make it appear to be a member function
  421. // By imbedding a this pointer in the window object
  422. pThis = (CAsyncSockN*) (LPHANDLE)GetWindowLong(hWnd, OFFSET_THIS);
  423.     }
  424.     if (pThis != NULL)
  425.     {
  426. switch (msg)
  427. {
  428.     case PWM_ASYNC_SELECT:
  429. return (pThis->OnAsyncSelect(wParam, lParam));
  430.     case PWM_ASYNC_DNS:
  431. return (pThis->OnAsyncDNS(wParam, lParam));
  432.     default:
  433. break;
  434. }
  435.     }
  436.     return (DefWindowProc(hWnd, msg, wParam, lParam));
  437. }
  438. LRESULT CAsyncSockN::CheckClients()
  439. {
  440.     ProcessDNSQueue();
  441.         
  442.     if (!m_bInCancelMode && !m_cbNumHandlesClients && !m_cbNumSocketsClients)
  443.     {
  444. UnlinkUs(this);
  445. DestroyWindow(m_hWnd);
  446. delete this;
  447.     }
  448.     return(TRUE);
  449. }
  450. // Message handler for PWM_ASYNC_DNS
  451. // Notifies the client win_net object that DNS has completed or
  452. // returned w/ an error.
  453. LRESULT CAsyncSockN::OnAsyncDNS(WPARAM wParam, LPARAM lParam)
  454. {
  455.     void*     handle = (void*) (HANDLE) wParam;
  456.     void*     pVoid = 0;
  457.     win_net*     pClient = 0;
  458.     DNS_REQUEST*    pDNSRequest = NULL;
  459.     // Bail if the client map has been previously deleted, this
  460.     // is a sure sign of us already being cleaned up!
  461.     if(!m_ClientHandlesMap)
  462.     {
  463. return(TRUE);
  464.     }
  465.     DEBUGOUTSTR( "AsyncDNS come backrn" );
  466.     // Based on the handle returned, find our client!
  467.     // Note it might be missing from the map if we canceled
  468.     // the DNS!
  469.     if (m_ClientHandlesMap->Lookup(handle, pVoid))
  470.     {
  471. *((ULONG32 *)&pClient) = (ULONG32)pVoid;
  472. // We should already have an async operation active on this socket!
  473. #ifdef _DEBUG
  474. if ((void *)pClient->m_hAsyncHandle != handle)
  475. {
  476.     char szMessage[256]; /* Flawfinder: ignore */
  477.     sprintf(szMessage,"pClient->m_hAsyncHandle = %#lxnhandle = %#lx", /* Flawfinder: ignore */
  478. pClient->m_hAsyncHandle,
  479. handle
  480.     );
  481.     MessageBox(NULL,szMessage,"Oops!",MB_OK);
  482. }
  483. HX_ASSERT((void *)pClient->m_hAsyncHandle == handle);
  484. #endif
  485. // Tell win_net object to forget the Async handle
  486. pClient->m_hAsyncHandle = NULL;
  487. pClient->CB_DNSComplete(!WSAGETASYNCERROR(lParam));
  488. // If async DNS is done, then we can forget the Async handle
  489. if (m_ClientHandlesMap->RemoveKey(handle))
  490. {
  491.     DecrementHandlesClientCount();
  492. }
  493.     }
  494. #ifdef _DEBUG
  495.     if (m_ClientHandlesMap->GetCount() != m_cbNumHandlesClients)
  496.     {
  497. char szMessage[256]; /* Flawfinder: ignore */
  498. sprintf(szMessage,"m_ClientHandlesMap->GetCount() = %dnm_cbNumHandlesClients = %d", /* Flawfinder: ignore */
  499.     m_ClientHandlesMap->GetCount(),
  500.     m_cbNumHandlesClients
  501. );
  502. MessageBox(NULL,szMessage,"Oops!",MB_OK);
  503.     }
  504.     HX_ASSERT(m_ClientHandlesMap->GetCount() == m_cbNumHandlesClients);
  505. #endif
  506.     if (sockGlobals.m_bWinSock2Suck)
  507.     {
  508. pDNSRequest = (DNS_REQUEST*) sockGlobals.m_DNSQueue.RemoveHead();
  509. HX_DELETE(pDNSRequest);
  510.     }
  511.     // check to see if we are still in use.
  512.     CheckClients();
  513.     return (TRUE);
  514. }
  515. // Message handler for PWM_ASYNC_SELECT
  516. // Notifies the win_net client when the corresponding socket
  517. // is ready to read/write/ or has connected.
  518. LRESULT CAsyncSockN::OnAsyncSelect(WPARAM wParam, LPARAM lParam)
  519. {
  520.     LPVOID pVoid;
  521.     UINT16 theEvent;
  522.     UINT16 theError;
  523.     SOCKET theSocket;
  524.     win_net* pClient = NULL;
  525.     theSocket = (SOCKET) wParam;
  526.     theEvent = WSAGETSELECTEVENT(lParam);
  527.     theError = WSAGETSELECTERROR(lParam);
  528.     // Find out the win_net object we want to talk to
  529.     if(m_ClientSocketsMap->Lookup((void*) theSocket, pVoid))
  530.     {
  531. *((ULONG32 *)&pClient) = (ULONG32) pVoid;
  532.     }
  533.     if (!pClient)
  534.     {
  535. DEBUGOUTSTR( "Error OnAsyncSelect() no win_net object foundrn" );
  536. return(TRUE);
  537.     }
  538.     if (theError)
  539.     {
  540. char acError[100]; /* Flawfinder: ignore */
  541. wsprintf(acError, "Got error %d from Winsockrn", theError);
  542. DEBUGOUTSTR(acError);
  543.     }
  544.     switch (theEvent)
  545.     {
  546.     case FD_WRITE:
  547. DEBUGOUTSTR("Got AsyncWrite notificationrn");
  548. pClient->CB_ReadWriteNotification(theEvent);
  549. break;
  550.     case FD_READ:
  551. #ifndef _DEMPSEY
  552. // Noisy debug output
  553. DEBUGOUTSTR("Got AsyncRead notificationrn");
  554. #endif // _DEMPSEY
  555. pClient->CB_ReadWriteNotification(theEvent);
  556. break;
  557.     case FD_CONNECT:
  558. DEBUGOUTSTR("Got AsyncConnect notificationrn");
  559. pClient->CB_ConnectionComplete(!theError);
  560. break;
  561.     case FD_CLOSE:
  562. DEBUGOUTSTR("Got AsyncClose notificationrn");
  563. pClient->CB_CloseNotification();
  564. break;
  565.     
  566.     case FD_ACCEPT:
  567. DEBUGOUTSTR("Got AsyncAccept notificationrn");
  568. pClient->CB_AcceptNotification();
  569. break;
  570.     }
  571.     return (TRUE);
  572. }
  573. // Static method
  574. // Inserts us at the head of the list
  575. void CAsyncSockN::LinkUs(CAsyncSockN* pUs)
  576. {
  577.     HX_ASSERT(pUs);
  578.     if (!pUs)
  579.     {
  580. return;
  581.     }
  582.     // Tack us on at the head of the list since order doesn't matter
  583.     pUs->m_pNextNotifier = zm_pSockNotifiers;
  584.     zm_pSockNotifiers = pUs;
  585. }
  586. // Static method
  587. // Removes us from the list
  588. void CAsyncSockN::UnlinkUs(CAsyncSockN* pUs)
  589. {
  590.     CAsyncSockN* pWalk = 0;
  591.     HX_ASSERT(pUs);
  592.     // Don't try to remove NULL pointers
  593.     if (!pUs)
  594.     {
  595. return;
  596.     }
  597.     // If the desired node is at the head then it's simple
  598.     if (zm_pSockNotifiers == pUs)
  599.     {
  600. zm_pSockNotifiers = pUs->m_pNextNotifier;
  601. return;
  602.     }
  603.     // Otherwise we have to walk the list till we find our node
  604.     else
  605.     {
  606. // iterate till we find ourselves or reach the end of the list
  607. pWalk = zm_pSockNotifiers;
  608. while (pWalk && (pWalk->m_pNextNotifier != pUs))
  609. {
  610.     pWalk = pWalk->m_pNextNotifier;
  611. }
  612. // Did we find ourselves?
  613. if (pWalk)
  614. {
  615.     // Ok, link to our successor
  616.     pWalk->m_pNextNotifier = pUs->m_pNextNotifier;
  617. }
  618.     }
  619.     return;
  620. }
  621. // Static method
  622. // Returns correct notifier object for our current session (thread/task)
  623. CAsyncSockN *CAsyncSockN::FindSockNotifier()
  624. {
  625.     ULONG32     ulSession;
  626.     CAsyncSockN*    pWalk;
  627.     ulSession = CAsyncSockN::GetSession();
  628.     pWalk = CAsyncSockN::zm_pSockNotifiers;
  629.     while (pWalk && pWalk->m_ulSession != ulSession)
  630.     {
  631. pWalk = pWalk->m_pNextNotifier;
  632.     }
  633.     
  634.     return (pWalk);
  635. }
  636. DNS_REQUEST::DNS_REQUEST()
  637. {
  638.     fpSock = NULL;
  639.     lpHostName = NULL;
  640.     lpBuffer = NULL;
  641.     cbBufferSize = 0;
  642. }
  643. DNS_REQUEST::~DNS_REQUEST()
  644. {
  645.     HX_VECTOR_DELETE(lpHostName);
  646. }
  647. SockGlobals::SockGlobals()
  648. {
  649. }
  650. SockGlobals::~SockGlobals()
  651. {
  652.     while (m_DNSQueue.GetCount())
  653.     {
  654. DNS_REQUEST* pDNSRequest = (DNS_REQUEST*) m_DNSQueue.RemoveHead();
  655. HX_DELETE(pDNSRequest);
  656.     }
  657.     m_DNSQueue.RemoveAll();
  658. }