thrdconn.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:52k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: thrdconn.cpp,v 1.11.2.4 2004/07/09 01:47:02 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hlxclib/time.h"
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include "hxcom.h"
  53. #include "conn.h"
  54. #if defined (_WIN32) || defined (WIN32)
  55. #include "platform/win/win_net.h"
  56. #include "platform/win/casynthr.h"
  57. #endif
  58. #if defined(_UNIX) && (defined( _UNIX_THREADED_NETWORK_IO ) || defined(THREADS_SUPPORTED))
  59. #include "platform/unix/UnixThreads.h"
  60. #endif /* _UNIX_THREADED_NETWORK_IO */
  61. #ifdef _CARBON
  62. #include "carbthrd.h"
  63. #endif
  64. #include "hxslist.h"
  65. #include "growingq.h"
  66. #include "hxengin.h"
  67. #include "ihxpckts.h"
  68. #include "hxbuffer.h"
  69. #include "timebuff.h"
  70. #include "hxtick.h"
  71. #include "hxthread.h"
  72. #include "threngin.h"
  73. #include "conn.h"
  74. #include "thrdconn.h"
  75. #include "hxheap.h"
  76. #ifdef _DEBUG
  77. #undef HX_THIS_FILE
  78. static const char HX_THIS_FILE[] = __FILE__;
  79. #endif
  80. #define QUEUE_START_SIZE    512
  81. ThreadedConn*
  82. ThreadedConn::new_socket(UINT16 type)
  83. {
  84.     return new ThreadedConn(type);
  85. }
  86. #ifdef THREADS_SUPPORTED
  87. #ifdef HELIX_FEATURE_ADD_NETWORK_THREAD_SLEEP
  88. #define DEFAULT_NETWORK_THREAD_SLEEP 50
  89. #endif //HELIX_FEATURE_ADD_NETWORK_THREAD_SLEEP
  90. #endif //THREADS_SUPPORTED
  91. /*
  92. HXThread*
  93. ThreadedConn::GetNetworkThread(void)
  94. {
  95. #if defined (_WIN32)
  96.     return win_net::GetNetworkThread();
  97. #else
  98.     HX_ASSERT(FALSE);
  99.     return HXR_UNEXXPECTED;
  100. #endif
  101. }
  102. void
  103. ThreadedConn::DestroyNetworkThread(void)
  104. {
  105. #if defined (_WIN32)
  106.     win_net::DestroyNetworkThread();
  107. #else
  108.     HX_ASSERT(FALSE);
  109.     return P NR_UNEXXPECTED;
  110. #endif
  111. }
  112. */
  113. ThreadedConn::ThreadedConn(UINT16 type)
  114.     : m_lRefCount(0)
  115.     , m_pActualConn(NULL)
  116.     , m_uSocketType(type)
  117.     , m_pNetworkThread(NULL)
  118.     , m_pMainAppThread(NULL)
  119.     , m_pNetCallback(0)
  120.     , m_pSendTCP (0)
  121.     , m_pReceiveTCP (0)
  122.     , m_pTempBuffer (0)
  123.     , m_ulUserHandle(0)
  124.     , m_pInternalWindowHandle(NULL)
  125.     , m_bConnected(FALSE)
  126.     , m_bIsDone(FALSE)
  127.     , m_bDetachPending(TRUE)
  128.     , m_pInitEvent(0)
  129.     , m_pQuitEvent(0)
  130.     , m_pListenEvent(NULL)
  131.     , m_pDetachEvent(0)
  132.     , m_bInitialized(FALSE)
  133.     , m_bOutstandingReadNotification(FALSE)
  134.     , m_bOutstandingWriteNotification(FALSE)
  135.     , m_bWriteFlushPending(FALSE)
  136.     , m_bNetworkIOPending(FALSE)
  137.     , m_bReadNowPending(FALSE)
  138.     , m_bReadPostPendingWouldBlock(FALSE)
  139.     , m_pIncommingConnections(NULL)
  140.     , m_bIgnoreWSAECONNRESET(FALSE)
  141. #if defined (_WIN32) || defined (WIN32)
  142.     , m_pNotifier(NULL)
  143. #endif
  144. #ifdef THREADS_SUPPORTED
  145. #ifdef HELIX_FEATURE_ADD_NETWORK_THREAD_SLEEP
  146.     , m_ulNetworkThreadSleep(DEFAULT_NETWORK_THREAD_SLEEP)
  147. #endif //HELIX_FEATURE_ADD_NETWORK_THREAD_SLEEP
  148. #endif //THREADS_SUPPORTED
  149. {
  150.     m_pActualConn = conn::actual_new_socket(type);
  151.     m_pActualConn->AddRef();
  152.     conn::add_connection_to_list (m_pActualConn);
  153.     ThreadEngine* pEngine = ThreadEngine::GetThreadEngine();
  154.     // NOTE: pEngine allocation is not checked for success.
  155.     pEngine->AttachSocket(this);
  156.     m_pNetworkThread    = pEngine->GetNetworkThread();
  157.     m_pMainAppThread    = pEngine->GetMainAppThread();
  158.     m_pNetCallback      = new ThrConnSocketCallback(this);
  159. #if defined(THREADS_SUPPORTED) || defined(_UNIX_THREADED_NETWORK_IO)
  160.     HXMutex::MakeMutex(m_pMutex);
  161.     HXEvent::MakeEvent(m_pInitEvent, NULL, FALSE);
  162.     HXEvent::MakeEvent(m_pQuitEvent, NULL);
  163.     HXEvent::MakeEvent(m_pDetachEvent, NULL);
  164.     HXEvent::MakeEvent(m_pListenEvent, NULL, FALSE);
  165. #else
  166.     HXMutex::MakeStubMutex(m_pMutex);
  167.     HXEvent::MakeStubEvent(m_pInitEvent, NULL, FALSE);
  168.     HXEvent::MakeStubEvent(m_pQuitEvent, NULL);
  169.     HXEvent::MakeStubEvent(m_pDetachEvent, NULL);
  170.     HXEvent::MakeStubEvent(m_pListenEvent, NULL, FALSE);
  171. #endif
  172.     m_pTempBuffer = new char[TCP_BUF_SIZE];
  173.     /* Allocate byte queues ONLY if it is a TCP socket */
  174.     if (m_uSocketType == HX_TCP_SOCKET)
  175.     {
  176.         // allocate TCP send and receive queue
  177.         m_pSendTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  178.         if (!m_pSendTCP || !m_pSendTCP->IsQueueValid())
  179.         {
  180.             mLastError = HXR_OUTOFMEMORY;
  181.         }
  182.         m_pSendTCP->SetMaxSize(TCP_BUF_SIZE);
  183.         m_pReceiveTCP = new CByteGrowingQueue(QUEUE_START_SIZE,1);
  184.         if (!m_pReceiveTCP || !m_pReceiveTCP->IsQueueValid())
  185.         {
  186.             mLastError = HXR_OUTOFMEMORY;
  187.         }
  188.         m_pReceiveTCP->SetMaxSize(TCP_BUF_SIZE);
  189.     }
  190. }
  191. ThreadedConn::~ThreadedConn()
  192. {
  193.     if (m_pNetCallback)
  194.     {
  195.         m_pNetCallback->m_pContext = 0;
  196.     }
  197.     if (m_pActualConn)
  198.     {
  199.         m_pActualConn->done();
  200.         m_pActualConn->Release();
  201.         m_pActualConn = 0;
  202.     }
  203.     HX_DELETE(m_pNetCallback);
  204.     HX_VECTOR_DELETE(m_pTempBuffer);
  205.     HX_DELETE(m_pSendTCP);
  206.     HX_DELETE(m_pReceiveTCP);
  207.     while (m_WriteUDPBuffers.GetCount() > 0)
  208.     {
  209.         UDPPacketInfo* pPacket = (UDPPacketInfo*) m_WriteUDPBuffers.RemoveHead();
  210.         pPacket->m_pBuffer->Release();
  211.         delete pPacket;
  212.     }
  213.     while (m_ReadUDPBuffers.GetCount() > 0)
  214.     {
  215.         UDP_PACKET* pPacket = (UDP_PACKET*) m_ReadUDPBuffers.RemoveHead();
  216.         HX_RELEASE(pPacket->pBuffer);
  217.         HX_DELETE(pPacket);
  218.     }
  219.     HX_DELETE(m_pMutex);
  220.     HX_DELETE(m_pInitEvent);
  221.     HX_DELETE(m_pQuitEvent);
  222.     HX_DELETE(m_pDetachEvent);
  223.     HX_DELETE(m_pListenEvent);
  224.     HX_DELETE(m_pIncommingConnections);
  225.     mCallBack = NULL;
  226. #ifdef _UNIX_THREADED_NETWORK_IO
  227.     if( m_bNetworkThreading )
  228.     {
  229.         //Remove any messages from the main app thread for us.
  230.         HX_ASSERT( m_pMainAppThread );
  231.         HXThreadMessage msgBack;
  232.         HXThreadMessage msgMatch(0, (void*)this, NULL, NULL);
  233.         while(((HXUnixThread*)m_pMainAppThread)->PeekMessageMatching(&msgBack, &msgMatch, TRUE )==HXR_OK)
  234.         {
  235.         }
  236.     }
  237.     m_pMainAppThread=NULL;
  238. #elif defined(_CARBON) && defined(THREADS_SUPPORTED)
  239.     // remove any messages from the main app thread for us.
  240.     HX_ASSERT(m_pMainAppThread);
  241.     HXThreadMessage msgBack;
  242.     HXThreadMessage msgMatch(0, (void*)this, NULL, NULL);
  243.     while (((HXCarbonThread*)m_pMainAppThread)->PeekMessageMatching(&msgBack, &msgMatch, TRUE) == HXR_OK)
  244.     {
  245.     }
  246.     m_pMainAppThread = NULL;
  247. #endif
  248. }
  249. ULONG32 ThreadedConn::AddRef()
  250. {
  251.     return InterlockedIncrement(&m_lRefCount);
  252. }
  253. ULONG32 ThreadedConn::Release()
  254. {
  255.     if (InterlockedDecrement(&m_lRefCount) > 0)
  256.     {
  257.         return m_lRefCount;
  258.     }
  259.     delete this;
  260.     return 0;
  261. }
  262. HX_RESULT
  263. ThreadedConn::dns_find_ip_addr(const char* host, UINT16 blocking)
  264. {
  265.     ThrdConnGenericCallback* pCallback  = new ThrdConnGenericCallback(this, DNS_CALLBACK_TYPE);
  266.     pCallback->m_HostName   = host;
  267.     pCallback->m_bBlocking  = (BOOL) blocking;
  268.     /* Will be released by the thread engine */
  269.     pCallback->AddRef();
  270.     HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  271.     return m_pNetworkThread->PostMessage(&msg);
  272. }
  273. HX_RESULT
  274. ThreadedConn::ActualDnsFindIpAddr(const char* host, UINT16 blocking)
  275. {
  276.     HX_RESULT theErr = HXR_UNEXPECTED;
  277.     HX_ASSERT(m_pActualConn);
  278.     if (m_pActualConn)
  279.     {
  280.         m_pMutex->Lock();
  281.         theErr = m_pActualConn->dns_find_ip_addr(host, blocking);
  282.         m_pMutex->Unlock();
  283.     }
  284.     return theErr;
  285. }
  286. BOOL
  287. ThreadedConn::dns_ip_addr_found(BOOL* valid, ULONG32* addr)
  288. {
  289.     BOOL bResult = FALSE;
  290.     HX_ASSERT(m_pActualConn);
  291.     if (m_pActualConn)
  292.     {
  293.         m_pMutex->Lock();
  294.         bResult = m_pActualConn->dns_ip_addr_found(valid, addr);
  295.         m_pMutex->Unlock();
  296.     }
  297.     return bResult;
  298. }
  299. void
  300. ThreadedConn::finaldone (void)
  301. {
  302.     if (!m_bIsDone)
  303.     {
  304.         done();
  305.     }
  306.     /* final attempt to cleanup */
  307.     PostDoneAndDetach();
  308.     if (m_pQuitEvent)
  309.     {
  310.         m_pQuitEvent->Wait(ALLFS);
  311.     }
  312.     if (m_pDetachEvent)
  313.     {
  314.         m_pDetachEvent->Wait(ALLFS);
  315.     }
  316. }
  317. void
  318. ThreadedConn::Detached (void)
  319. {
  320.     if (m_pDetachEvent)
  321.     {
  322.         m_pDetachEvent->SignalEvent();
  323.     }
  324. }
  325. void
  326. ThreadedConn::done (void)
  327. {
  328.     /* Do not pass any more callbacks to the client above */
  329.     mCallBack   = NULL;
  330.     m_bIsDone   = TRUE;
  331.     /* Actual message to release the socket will be posted in DoWrite() */
  332. #if (defined (_WIN32) || defined (WIN32)) && !defined(WIN32_PLATFORM_PSPC)
  333.     if (!m_pNotifier)
  334.     {
  335.         m_pNotifier =
  336.             CAsyncNetThread::GetCAsyncNetThreadNotifier((HINSTANCE)m_ulUserHandle,
  337.                                                         FALSE);
  338.     }
  339.     if (m_pNotifier)
  340.     {
  341.         m_pNotifier->DetachSocket(this);
  342.         m_pNotifier = NULL;
  343.     }
  344. #endif /*defined (_WINDOWS) || defined (_WIN32)*/
  345.     if (!m_bConnected)
  346.     {
  347.         PostDoneAndDetach();
  348.     }
  349. }
  350. void
  351. ThreadedConn::PostDoneAndDetach()
  352. {
  353.     // If we are out of memory, let's just get out of here. Ideally, we should
  354.     // not ever get to this point, but lots of functions here have void return
  355.     // types, so it is possible.
  356.     if( mLastError == HXR_OUTOFMEMORY )
  357.     {
  358.         return;
  359.     }
  360.     m_pMutex->Lock();
  361.     if (m_bDetachPending)
  362.     {
  363.         m_bDetachPending = FALSE;
  364.         ThrdConnGenericCallback* pCallback      = new ThrdConnGenericCallback(this, DONE_CALLBACK_TYPE);
  365.         /* Will be released by the thread engine */
  366.         pCallback->AddRef();
  367.         HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  368.         m_pNetworkThread->PostMessage(&msg);
  369.         HXThreadMessage msg1(HXMSG_ASYNC_DETACH, this, NULL);
  370.         m_pNetworkThread->PostMessage(&msg1);
  371.     }
  372.     m_pMutex->Unlock();
  373. }
  374. void
  375. ThreadedConn::ActualDone (void)
  376. {
  377.     HX_ASSERT(m_pActualConn);
  378.     if (m_pActualConn)
  379.     {
  380.         m_pMutex->Lock();
  381.         m_bConnected = FALSE;
  382.         m_pActualConn->done();
  383.         m_pActualConn->Release();
  384.         m_pActualConn = 0;
  385.         m_pMutex->Unlock();
  386.     }
  387.     if (m_pQuitEvent)
  388.     {
  389.         m_pQuitEvent->SignalEvent();
  390.     }
  391. }
  392. HX_RESULT
  393. ThreadedConn::init  (UINT32 local_addr,UINT16 port, UINT16 blocking)
  394. {
  395.     ThrdConnGenericCallback* pCallback  = new ThrdConnGenericCallback(this, INIT_CALLBACK_TYPE);
  396.     pCallback->m_ulLocalAddr    = local_addr;
  397.     pCallback->m_uPort          = port;
  398.     pCallback->m_bBlocking      = (BOOL) blocking;
  399.     /* Will be released by the thread engine */
  400.     pCallback->AddRef();
  401.     HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  402.     m_pNetworkThread->PostMessage(&msg);
  403.     /* Wait for the actual Initialization to complete. This is the only
  404.        function we wait for the networking thread to complete before passing
  405.        the result to the user since there is no async interface to pass the result
  406.        back and it very much possible that socket binding may fail during
  407.        initialization
  408.      */
  409.     m_pInitEvent->Wait();
  410.     if (m_bInitialized)
  411.     {
  412.         return HXR_OK;
  413.     }
  414.     else
  415.     {
  416.         return HXR_FAIL;
  417.     }
  418. }
  419. HX_RESULT
  420. ThreadedConn::ActualInit(UINT32 local_addr,UINT16 port, UINT16 blocking)
  421. {
  422.     HX_RESULT theErr = HXR_UNEXPECTED;
  423.     HX_ASSERT(m_pActualConn);
  424.     if (m_pActualConn)
  425.     {
  426.         m_pMutex->Lock();
  427.         theErr = m_pActualConn->init(local_addr, port, blocking);
  428.         if (!theErr && m_uSocketType == HX_UDP_SOCKET)
  429.         {
  430.             m_bConnected = TRUE;
  431.         }
  432.         if (!theErr)
  433.         {
  434.             m_bInitialized = TRUE;
  435.         }
  436.         /* Signal the main thread that intialization is complete */
  437.         m_pInitEvent->SignalEvent();
  438.         m_pMutex->Unlock();
  439.     }
  440.     return theErr;
  441. }
  442. HX_RESULT
  443. ThreadedConn::listen(ULONG32 ulAddr,  UINT16 port, UINT16 backlog,
  444.                      UINT16 blocking, ULONG32 ulPlatform)
  445. {
  446.     HX_RESULT theErr = HXR_OK;
  447. #if (defined (_WIN32) || defined (WIN32)) && !defined(WIN32_PLATFORM_PSPC)
  448.     m_ulUserHandle  = ulPlatform;
  449.     if (!m_pNotifier)
  450.     {
  451.         m_pNotifier =
  452.             CAsyncNetThread::GetCAsyncNetThreadNotifier((HINSTANCE)ulPlatform,
  453.                                                         TRUE);
  454.     }
  455.     if (m_pNotifier)
  456.     {
  457.         m_pInternalWindowHandle = (void*) m_pNotifier->GetWindowHandle();
  458.         m_pNotifier->AttachSocket(this);
  459.     }
  460.     else
  461.     {
  462.         theErr = HXR_OUTOFMEMORY;
  463.     }
  464. #endif /*defined (_WIN32) || defined (WIN32)*/
  465.     HX_DELETE(m_pIncommingConnections);
  466.     m_pIncommingConnections = new CHXSimpleList();
  467.     if (!theErr)
  468.     {
  469.         ThrdConnGenericCallback* pCallback      =
  470.                 new ThrdConnGenericCallback(this, LISTEN_CALLBACK_TYPE);
  471.         pCallback->m_ulLocalAddr = ulAddr;
  472.         pCallback->m_uPort      = port;
  473.         pCallback->m_uBacklog   = backlog;
  474.         pCallback->m_bBlocking  = (BOOL) blocking;
  475.         pCallback->m_ulHandle   = ulPlatform;
  476.         /* Will be released by the thread engine */
  477.         pCallback->AddRef();
  478.         HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  479.         theErr = m_pNetworkThread->PostMessage(&msg);
  480.         if ( SUCCEEDED(theErr) )
  481.         {
  482.             /*
  483.              * Wait for the actual Listen to complete.
  484.              */
  485.     // listen is called from the network thread, so this will wait forever
  486. #ifdef HELIX_FEATURE_NETWORK_USE_SELECT
  487.     m_bListenning = TRUE;
  488. #else
  489.             m_pListenEvent->Wait();
  490. #endif
  491.             if ( m_bListenning )
  492.             {
  493.                 theErr = HXR_OK;
  494.             }
  495.             else
  496.             {
  497.                 theErr = HXR_FAIL;
  498.             }
  499.         }
  500.     }
  501. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  502.     set_callback(m_pNetCallback); // for accept msg
  503. #endif //HELIX_FEATURE_NETWORK_USE_SELECT
  504.     return theErr;
  505. }
  506. HX_RESULT
  507. ThreadedConn::ActualListen( ULONG32     ulAddr,
  508.                             UINT16      port,
  509.                             UINT16      backlog,
  510.                             UINT16      blocking,
  511.                             ULONG32     ulPlatform)
  512. {
  513.     HX_RESULT err = HXR_UNEXPECTED;
  514.     HX_ASSERT(m_pActualConn);
  515.     if ( m_pActualConn )
  516.     {
  517.         m_pMutex->Lock();
  518.         err = m_pActualConn->listen(ulAddr, port, backlog, blocking, ulPlatform);
  519.         if ( SUCCEEDED(err) )
  520.         {
  521.             m_bListenning = TRUE;
  522.         }
  523.         else
  524.         {
  525.             m_bListenning = FALSE;
  526.         }
  527.         m_pListenEvent->SignalEvent();
  528.         m_pMutex->Unlock();
  529.     }
  530.     return err;
  531. }
  532. #if     defined (_WINDOWS) || defined (_WIN32)
  533. // we need it for dns_find_ip_addr since async stuff needs a window handle...
  534. HX_RESULT
  535. ThreadedConn::SetWindowHandle(ULONG32 handle)
  536. {
  537.     HX_RESULT theErr = HXR_OK;
  538.     m_pMutex->Lock();
  539.     m_ulUserHandle  = handle;
  540. #if (defined (_WIN32) || defined (WIN32)) && !defined(WIN32_PLATFORM_PSPC)
  541.     if (!m_pNotifier)
  542.     {
  543.         m_pNotifier =
  544.             CAsyncNetThread::GetCAsyncNetThreadNotifier((HINSTANCE)handle,
  545.                                                         TRUE);
  546.     }
  547.     if (m_pNotifier)
  548.     {
  549.         m_pInternalWindowHandle = (void*)m_pNotifier->GetWindowHandle();
  550.         m_pNotifier->AttachSocket(this);
  551.     }
  552.     else
  553.     {
  554.         theErr = HXR_OUTOFMEMORY;
  555.     }
  556. #endif /*defined (_WIN32) || defined (WIN32)*/
  557.     if (!theErr)
  558.     {
  559.         ThrdConnGenericCallback* pCallback      =
  560.                 new ThrdConnGenericCallback(this, SETWINDOWHANDLE_CALLBACK_TYPE);
  561.         pCallback->m_ulHandle   = handle;
  562.         /* Will be released by the thread engine */
  563.         pCallback->AddRef();
  564.         HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  565.         theErr = m_pNetworkThread->PostMessage(&msg);
  566.     }
  567.     m_pMutex->Unlock();
  568.     return theErr;
  569. }
  570. HX_RESULT
  571. ThreadedConn::ActuallSetWindowHandle(ULONG32 handle)
  572. {
  573.     HX_RESULT theErr = HXR_UNEXPECTED;
  574.     HX_ASSERT(m_pActualConn);
  575.     if (m_pActualConn)
  576.     {
  577.         m_pMutex->Lock();
  578.         theErr = m_pActualConn->SetWindowHandle(handle);
  579.         if (!theErr)
  580.         {
  581.         }
  582.         m_pMutex->Unlock();
  583.     }
  584.     return theErr;
  585. }
  586. #endif /* defined (_WINDOWS) || defined (_WIN32)*/
  587. HX_RESULT
  588. ThreadedConn::connect(const char*   host,
  589.                      UINT16         port,
  590.                      UINT16         blocking,
  591.                      ULONG32        ulPlatform)
  592. {
  593.     HX_RESULT theErr = HXR_OK;
  594. #if (defined (_WIN32) || defined (WIN32)) && !defined(WIN32_PLATFORM_PSPC)
  595.     m_ulUserHandle  = ulPlatform;
  596.     if (!m_pNotifier)
  597.     {
  598.         m_pNotifier =
  599.             CAsyncNetThread::GetCAsyncNetThreadNotifier((HINSTANCE)ulPlatform,
  600.                                                         TRUE);
  601.     }
  602.     if (m_pNotifier)
  603.     {
  604.         m_pInternalWindowHandle = (void*) m_pNotifier->GetWindowHandle();
  605.         m_pNotifier->AttachSocket(this);
  606.     }
  607.     else
  608.     {
  609.         theErr = HXR_OUTOFMEMORY;
  610.     }
  611. #endif /*defined (_WIN32) || defined (WIN32)*/
  612.     if (!theErr)
  613.     {
  614.         ThrdConnGenericCallback* pCallback      =
  615.                 new ThrdConnGenericCallback(this, CONNECT_CALLBACK_TYPE);
  616.         pCallback->m_HostName   = host;
  617.         pCallback->m_uPort              = port;
  618. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  619. blocking = 1; // we don't get fd_connect when doing loopback
  620. #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  621.         pCallback->m_bBlocking  = (BOOL) blocking;
  622.         pCallback->m_ulHandle   = ulPlatform;
  623.         /* Will be released by the thread engine */
  624.         pCallback->AddRef();
  625.         HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  626.         theErr = m_pNetworkThread->PostMessage(&msg);
  627.     }
  628.     return theErr;
  629. }
  630. HX_RESULT
  631. ThreadedConn::ActualConnect(const char* host,
  632.                             UINT16      port,
  633.                             UINT16      blocking,
  634.                             ULONG32     ulPlatform)
  635. {
  636.     HX_RESULT theErr = HXR_UNEXPECTED;
  637.     HX_ASSERT(m_pActualConn);
  638.     if (m_pActualConn)
  639.     {
  640.         m_pMutex->Lock();
  641.         theErr = m_pActualConn->connect(host, port, blocking, ulPlatform);
  642.         m_pMutex->Unlock();
  643.     }
  644.     return theErr;
  645. }
  646. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  647. HX_RESULT
  648. ThreadedConn::accept (ULONG32 ulAddr)
  649. {
  650.     HX_RESULT theErr = HXR_OK;
  651. #if (defined (_WIN32) || defined (WIN32)) && !defined(WIN32_PLATFORM_PSPC)
  652.     m_ulUserHandle  = NULL; //ulPlatform;
  653.     if (!m_pNotifier)
  654.     {
  655.         m_pNotifier =
  656.             CAsyncNetThread::GetCAsyncNetThreadNotifier((HINSTANCE)m_ulUserHandle,
  657.                                                         TRUE);
  658.     }
  659.     if (m_pNotifier)
  660.     {
  661.         m_pInternalWindowHandle = (void*) m_pNotifier->GetWindowHandle();
  662.         m_pNotifier->AttachSocket(this);
  663.     }
  664.     else
  665.     {
  666.         theErr = HXR_OUTOFMEMORY;
  667.     }
  668. #endif /*defined (_WIN32) || defined (WIN32)*/
  669.     if (!theErr)
  670.     {
  671.         ThrdConnGenericCallback* pCallback      =
  672.                 new ThrdConnGenericCallback(this, ACCEPT_CALLBACK_TYPE);
  673.         pCallback->m_ulHandle   = m_ulUserHandle;
  674. pCallback->m_ulLocalAddr = ulAddr;
  675.         /* Will be released by the thread engine */
  676.         pCallback->AddRef();
  677.         HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  678.         theErr = m_pNetworkThread->PostMessage(&msg);
  679.     }
  680.     return theErr;
  681. }
  682. HX_RESULT
  683. ThreadedConn::ActualAccept(ULONG32 ulAddr,
  684.                             ULONG32     ulPlatform)
  685. {
  686.     HX_RESULT theErr = HXR_UNEXPECTED;
  687.     HX_ASSERT(m_pActualConn);
  688.     if (m_pActualConn)
  689.     {
  690.         m_pMutex->Lock();
  691.         theErr = m_pActualConn->CheckForConnection();
  692.         m_pMutex->Unlock();
  693. if (theErr == HXR_WOULD_BLOCK)
  694. {
  695.     ThrdConnGenericCallback* pCallback      =
  696.     new ThrdConnGenericCallback(this, ACCEPT_CALLBACK_TYPE);
  697.     pCallback->m_ulHandle   = ulPlatform;
  698.     pCallback->m_ulLocalAddr = ulAddr;
  699.     /* Will be released by the thread engine */
  700.     pCallback->AddRef();
  701.     HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  702.     theErr = m_pNetworkThread->PostMessage(&msg);
  703. }
  704.     }
  705.     return theErr;
  706. }
  707. #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  708. HX_RESULT
  709. ThreadedConn::blocking(void)
  710. {
  711.     ThrdConnGenericCallback* pCallback  = new ThrdConnGenericCallback(this, BLOCKING_CALLBACK_TYPE);
  712.     /* Will be released by the thread engine */
  713.     pCallback->AddRef();
  714.     HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  715.     return m_pNetworkThread->PostMessage(&msg);
  716. }
  717. HX_RESULT
  718. ThreadedConn::ActualBlocking(void)
  719. {
  720.     HX_RESULT theErr = HXR_UNEXPECTED;
  721.     HX_ASSERT(m_pActualConn);
  722.     if (m_pActualConn)
  723.     {
  724.         m_pMutex->Lock();
  725.         theErr = m_pActualConn->blocking();
  726.         m_pMutex->Unlock();
  727.     }
  728.     return theErr;
  729. }
  730. HX_RESULT
  731. ThreadedConn::nonblocking(void)
  732. {
  733.     ThrdConnGenericCallback* pCallback  = new ThrdConnGenericCallback(this, NONBLOCKING_CALLBACK_TYPE);
  734.     /* Will be released by the thread engine */
  735.     pCallback->AddRef();
  736.     HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  737.     return m_pNetworkThread->PostMessage(&msg);
  738. }
  739. HX_RESULT
  740. ThreadedConn::ActualNonBlocking(void)
  741. {
  742.     HX_RESULT theErr = HXR_UNEXPECTED;
  743.     HX_ASSERT(m_pActualConn);
  744.     if (m_pActualConn)
  745.     {
  746.         m_pMutex->Lock();
  747.         theErr = m_pActualConn->nonblocking();
  748.         m_pMutex->Unlock();
  749.     }
  750.     return theErr;
  751. }
  752. HX_RESULT
  753. ThreadedConn::read (void* buf, UINT16* size)
  754. {
  755.     HX_RESULT theErr = HXR_OK;
  756.     UINT16 uCount = 0;
  757.     m_pMutex->Lock();
  758.     m_bOutstandingReadNotification = FALSE;
  759.     if (m_uSocketType != HX_TCP_SOCKET)
  760.     {
  761.         theErr = HXR_NET_SOCKET_INVALID;
  762.         goto cleanup;
  763.     }
  764.     uCount = m_pReceiveTCP->GetQueuedItemCount();
  765.     if (uCount > 0)
  766.     {
  767.         uCount = (uCount <= *size ? uCount : *size);
  768.         m_pReceiveTCP->DeQueue(buf, uCount);
  769.         *size = uCount;
  770.     }
  771.     else
  772.     {
  773.         *size = 0;
  774.         if (!mLastError && m_pActualConn)
  775.         {
  776.             theErr = HXR_WOULD_BLOCK;
  777.         }
  778.         else
  779.         {
  780.             theErr = mLastError;
  781.         }
  782.     }
  783. cleanup:
  784.     if (!mLastError && !m_bNetworkIOPending)
  785.     {
  786.         theErr = PostIOMessage();
  787.     }
  788.     m_pMutex->Unlock();
  789.     return theErr;
  790. }
  791. HX_RESULT
  792. ThreadedConn::readfrom (REF(IHXBuffer*)    pBuffer,
  793.                         REF(UINT32)         ulAddress,
  794.                         REF(UINT16)         ulPort)
  795. {
  796.     HX_RESULT theErr = HXR_OK;
  797.     UDP_PACKET* pPacket = NULL;
  798.     m_pMutex->Lock();
  799.     m_bOutstandingReadNotification = FALSE;
  800.     pBuffer = NULL;
  801.     ulAddress = 0;
  802.     ulPort = 0;
  803.     if (m_uSocketType != HX_UDP_SOCKET)
  804.     {
  805.         theErr = HXR_NET_SOCKET_INVALID;
  806.         goto cleanup;
  807.     }
  808.     if (m_ReadUDPBuffers.GetCount() > 0)
  809.     {
  810.         pPacket = (UDP_PACKET*)m_ReadUDPBuffers.RemoveHead();;
  811.         pBuffer = pPacket->pBuffer;
  812.         ulAddress = pPacket->ulAddress;
  813.         ulPort = pPacket->ulPort;
  814.         HX_DELETE(pPacket);
  815.     }
  816.     else
  817.     {
  818.         if (!mLastError)
  819.         {
  820.             theErr = HXR_WOULD_BLOCK;
  821.         }
  822.         else
  823.         {
  824.             theErr = mLastError;
  825.         }
  826.     }
  827. cleanup:
  828.     if (!m_bReadPostPendingWouldBlock && !mLastError && !m_bNetworkIOPending)
  829.     {
  830.         theErr = PostIOMessage();
  831.     }
  832.     m_pMutex->Unlock();
  833.     if( mLastError == HXR_OUTOFMEMORY )
  834.     {
  835.         theErr = mLastError;
  836.     }
  837.     return theErr;
  838. }
  839. HX_RESULT
  840. ThreadedConn::write (void* buf, UINT16* size)
  841. {
  842.     HX_RESULT theErr = HXR_OK;
  843.     HX_ASSERT(m_pActualConn && m_uSocketType == HX_TCP_SOCKET);
  844.     m_pMutex->Lock();
  845.     m_bOutstandingWriteNotification = FALSE;
  846.     UINT16 uCount = m_pSendTCP->GetMaxAvailableElements();
  847.     if (uCount > 0)
  848.     {
  849.         uCount = (uCount <= *size ? uCount : *size);
  850.         m_pSendTCP->EnQueue(buf, uCount);
  851.         *size = uCount;
  852.     }
  853.     else
  854.     {
  855.         *size = 0;
  856.         if (!mLastError)
  857.         {
  858.             theErr = HXR_WOULD_BLOCK;
  859.         }
  860.         else
  861.         {
  862.             theErr = mLastError;
  863.         }
  864.     }
  865.     if (!m_bWriteFlushPending && m_pSendTCP->GetQueuedItemCount() > 0 && m_bConnected)
  866.     {
  867.         m_bWriteFlushPending    = TRUE;
  868.         AddRef();
  869.     }
  870.     if (!mLastError && !m_bNetworkIOPending)
  871.     {
  872.         theErr = PostIOMessage();
  873.     }
  874.     m_pMutex->Unlock();
  875.     return theErr;
  876. }
  877. HX_RESULT
  878. ThreadedConn::writeto(void* buf,UINT16* len, ULONG32 addr, UINT16 port)
  879. {
  880.     HX_RESULT theErr = HXR_OK;
  881.     HX_ASSERT(m_pActualConn && m_uSocketType == HX_UDP_SOCKET);
  882.     m_pMutex->Lock();
  883.     m_bOutstandingWriteNotification = FALSE;
  884.     if (!mLastError)
  885.     {
  886.         UDPPacketInfo* pPacket  = new UDPPacketInfo;
  887.         pPacket->m_pBuffer  = new CHXBuffer;
  888.         pPacket->m_pBuffer->AddRef();
  889.         pPacket->m_pBuffer->Set((UCHAR*) buf, (ULONG32) *len);
  890.         pPacket->m_ulAddr   = addr;
  891.         pPacket->m_uPort    = port;
  892.         m_WriteUDPBuffers.AddTail((void*) pPacket);
  893.     }
  894.     else
  895.     {
  896.         theErr = mLastError;
  897.     }
  898.     if (!theErr && !m_bWriteFlushPending && m_WriteUDPBuffers.GetCount() > 0 && m_bConnected)
  899.     {
  900.         m_bWriteFlushPending    = TRUE;
  901.         AddRef();
  902.     }
  903.     if (!mLastError && !m_bNetworkIOPending)
  904.     {
  905.         theErr = PostIOMessage();
  906.     }
  907.     m_pMutex->Unlock();
  908.     return theErr;
  909. }
  910. ULONG32
  911. ThreadedConn::get_addr(void)
  912. {
  913.     ULONG32 ulAddr = 0;
  914.     HX_ASSERT(m_pActualConn);
  915.     if (m_pActualConn)
  916.     {
  917.         m_pMutex->Lock();
  918.         ulAddr = m_pActualConn->get_addr();
  919.         m_pMutex->Unlock();
  920.     }
  921.     return ulAddr;
  922. }
  923. UINT16
  924. ThreadedConn::get_local_port(void)
  925. {
  926.     UINT16 nPort = 0;
  927.     HX_ASSERT(m_pActualConn);
  928.     if (m_pActualConn)
  929.     {
  930.         m_pMutex->Lock();
  931.         nPort = m_pActualConn->get_local_port();
  932.         m_pMutex->Unlock();
  933.     }
  934.     return nPort;
  935. }
  936. /* join_multicast_group() has this socket join a multicast group */
  937. HX_RESULT
  938. ThreadedConn::join_multicast_group(ULONG32 addr, ULONG32 if_addr)
  939. {
  940.     HX_RESULT theErr = HXR_UNEXPECTED;
  941.     HX_ASSERT(m_pActualConn);
  942.     if (m_pActualConn)
  943.     {
  944.         m_pMutex->Lock();
  945.         theErr = m_pActualConn->join_multicast_group(addr, if_addr);
  946.         m_pMutex->Unlock();
  947.     }
  948.     return theErr;
  949. }
  950. HX_RESULT
  951. ThreadedConn::leave_multicast_group(ULONG32 addr, ULONG32 if_addr)
  952. {
  953.     HX_RESULT theErr = HXR_UNEXPECTED;
  954.     HX_ASSERT(m_pActualConn);
  955.     if (m_pActualConn)
  956.     {
  957.         m_pMutex->Lock();
  958.         theErr = m_pActualConn->leave_multicast_group(addr, if_addr);
  959.         while (!m_ReadUDPBuffers.IsEmpty())
  960.         {
  961.             UDP_PACKET* pPacket = (UDP_PACKET*)m_ReadUDPBuffers.RemoveHead();
  962.             HX_RELEASE(pPacket->pBuffer);
  963.             HX_DELETE(pPacket);
  964.         }
  965.         m_pMutex->Unlock();
  966.     }
  967.     return theErr;
  968. }
  969. HX_RESULT
  970. ThreadedConn::reuse_addr(BOOL enabled)
  971. {
  972.     HX_RESULT theErr = HXR_UNEXPECTED;
  973.     HX_ASSERT(m_pActualConn);
  974.     if (m_pActualConn)
  975.     {
  976.         m_pMutex->Lock();
  977.         theErr = m_pActualConn->reuse_addr(enabled);
  978.         m_pMutex->Unlock();
  979.     }
  980.     return theErr;
  981. }
  982. HX_RESULT
  983. ThreadedConn::reuse_port(BOOL enabled)
  984. {
  985.     HX_RESULT theErr = HXR_UNEXPECTED;
  986.     HX_ASSERT(m_pActualConn);
  987.     if (m_pActualConn)
  988.     {
  989.         m_pMutex->Lock();
  990.         theErr = m_pActualConn->reuse_port(enabled);
  991.         m_pMutex->Unlock();
  992.     }
  993.     return theErr;
  994. }
  995. HX_RESULT
  996. ThreadedConn::set_broadcast(BOOL enable)
  997. {
  998.         HX_RESULT theErr = HXR_UNEXPECTED;
  999.         HX_ASSERT(m_pActualConn);
  1000.         if(m_pActualConn)
  1001.         {
  1002.         m_pMutex->Lock();
  1003.         theErr = m_pActualConn->set_broadcast(enable);
  1004.         m_pMutex->Unlock();
  1005.         }
  1006.         return theErr;
  1007. }
  1008. HX_RESULT
  1009. ThreadedConn::set_multicast_if(ULONG32 ulInterface)
  1010. {
  1011.     HX_RESULT theErr = HXR_UNEXPECTED;
  1012.     HX_ASSERT(m_pActualConn);
  1013.     if(m_pActualConn)
  1014.     {
  1015.         m_pMutex->Lock();
  1016.         theErr = m_pActualConn->set_multicast_if(ulInterface);
  1017.         m_pMutex->Unlock();
  1018.     }
  1019.     return theErr;
  1020. }
  1021. void
  1022. ThreadedConn::IgnoreWSAECONNRESET(BOOL b)
  1023. {
  1024.     HX_RESULT theErr = HXR_UNEXPECTED;
  1025.     HX_ASSERT(m_pActualConn);
  1026.     if(m_pActualConn)
  1027.     {
  1028.         m_pMutex->Lock();
  1029.         m_pActualConn->IgnoreWSAECONNRESET(b);
  1030.         m_pMutex->Unlock();
  1031.     }
  1032. }
  1033. HX_RESULT
  1034. ThreadedConn::last_error(void)
  1035. {
  1036.     HX_ASSERT(m_pActualConn);
  1037.     if (m_pActualConn)
  1038.     {
  1039.         m_pMutex->Lock();
  1040.         mLastError = m_pActualConn->last_error();
  1041.         m_pMutex->Unlock();
  1042.     }
  1043.     return mLastError;
  1044. }
  1045. void
  1046. ThreadedConn::set_callback(HXAsyncNetCallback* pCallback)
  1047. {
  1048.     m_pMutex->Lock();
  1049.     HX_ASSERT(m_pActualConn);
  1050.     if (m_pActualConn)
  1051.     {
  1052.         /* Set our callback as the callback */
  1053.         m_pActualConn->set_callback(m_pNetCallback);
  1054.     }
  1055.     mCallBack = pCallback;
  1056.     m_pMutex->Unlock();
  1057. }
  1058. UINT16
  1059. ThreadedConn::connection_open(void)
  1060. {
  1061.     UINT16 uConnOpen = 0;
  1062.     HX_ASSERT(m_pActualConn);
  1063.     if (m_pActualConn)
  1064.     {
  1065.         m_pMutex->Lock();
  1066.         uConnOpen = m_pActualConn->connection_open();
  1067.         m_pMutex->Unlock();
  1068.     }
  1069.     return uConnOpen;
  1070. }
  1071. UINT16
  1072. ThreadedConn::connection_really_open(void)
  1073. {
  1074.     UINT16 uConnOpen = 0;
  1075.     //HX_ASSERT(m_pActualConn);
  1076.     if (m_pActualConn)
  1077.     {
  1078.         m_pMutex->Lock();
  1079.         uConnOpen = m_pActualConn->connection_really_open();
  1080.         m_pMutex->Unlock();
  1081.     }
  1082.     return uConnOpen;
  1083. }
  1084. int
  1085. ThreadedConn::get_sock(void)
  1086. {
  1087.     int iSockNum = -1;
  1088.     HX_ASSERT(m_pActualConn);
  1089.     if (m_pActualConn)
  1090.     {
  1091.         m_pMutex->Lock();
  1092.         iSockNum =  m_pActualConn->get_sock();
  1093.         m_pMutex->Unlock();
  1094.     }
  1095.     return iSockNum;
  1096. }
  1097. void
  1098. ThreadedConn::set_sock(int theSock)
  1099. {
  1100.     m_pMutex->Lock();
  1101.     HX_ASSERT(m_pActualConn);
  1102.     if (m_pActualConn)
  1103.     {
  1104.         m_pActualConn->set_sock(theSock);
  1105.     }
  1106.     mSock = theSock;
  1107.     m_pMutex->Unlock();
  1108. }
  1109. BOOL
  1110. ThreadedConn::set_receive_buf_size(int DesiredSize)
  1111. {
  1112.     ThrdConnGenericCallback* pCallback  = new ThrdConnGenericCallback(this, SET_BUFFER_SIZE_CALLBACK_TYPE);
  1113.     pCallback->m_ulBufferSize = (UINT32) DesiredSize;
  1114.     /* Will be released by the thread engine */
  1115.     pCallback->AddRef();
  1116.     HXThreadMessage msg(HXMSG_ASYNC_CALLBACK, this, pCallback);
  1117.     m_pNetworkThread->PostMessage(&msg);
  1118.     return TRUE;
  1119. }
  1120. BOOL
  1121. ThreadedConn::ActualSetReceiveBufSize(UINT32 ulBufferSize)
  1122. {
  1123.     BOOL bResult = FALSE;
  1124.     HX_ASSERT(m_pActualConn);
  1125.     if (m_pActualConn)
  1126.     {
  1127.         m_pMutex->Lock();
  1128.         bResult = m_pActualConn->set_receive_buf_size((int) ulBufferSize);
  1129.         m_pMutex->Unlock();
  1130.     }
  1131.     return bResult;
  1132. }
  1133. void
  1134. ThreadedConn::OnAsyncDNS(BOOL bResult)
  1135. {
  1136.     if (mCallBack)
  1137.     {
  1138.         mCallBack->Func(DNS_NOTIFICATION, bResult);
  1139.     }
  1140. }
  1141. void
  1142. ThreadedConn::OnReadNotification(void)
  1143. {
  1144.     if (mCallBack)
  1145.     {
  1146.         mCallBack->Func(READ_NOTIFICATION);
  1147.     }
  1148. }
  1149. void
  1150. ThreadedConn::OnWriteNotification(void)
  1151. {
  1152.     if (mCallBack)
  1153.     {
  1154.         mCallBack->Func(WRITE_NOTIFICATION);
  1155.     }
  1156. }
  1157. void
  1158. ThreadedConn::OnConnect(BOOL bResult)
  1159. {
  1160.     if (mCallBack)
  1161.     {
  1162.         mCallBack->Func(CONNECT_NOTIFICATION, bResult);
  1163.     }
  1164. }
  1165. void
  1166. ThreadedConn::OnAcceptNotification()
  1167. {
  1168.     if( m_pIncommingConnections )
  1169.     {
  1170.         conn* pConn = (conn*)m_pIncommingConnections->RemoveHead();
  1171. // accept_notification is posted in win_net:checkforconnection
  1172. // callback->func(accept_notification..) calls this function
  1173. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1174.         if (mCallBack)
  1175.         {
  1176.             mCallBack->Func(ACCEPT_NOTIFICATION, TRUE, pConn);
  1177.         }
  1178.         if (pConn)
  1179.         {
  1180.             pConn->Release();
  1181.             pConn = NULL;
  1182.         }
  1183. #else
  1184. // at this point we need to set pengine->reader = pconn
  1185.         HXThreadMessage msg(HXMSG_ASYNC_SETREADER_CONNECTION, this, pConn);
  1186.         m_pNetworkThread->PostMessage(&msg);
  1187. #endif
  1188.     }
  1189. }
  1190. void
  1191. ThreadedConn::HandleDNSNotification(BOOL bSuccess)
  1192. {
  1193. #if !defined( WIN32_PLATFORM_PSPC ) && !defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1194.     HXThreadMessage msg(HXMSG_ASYNC_DNS, this, (void*) bSuccess);
  1195.     m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1196. #else
  1197.     OnAsyncDNS(bSuccess);
  1198. #endif
  1199. }
  1200. void
  1201. ThreadedConn::HandleConnectNotification(BOOL bSuccess)
  1202. {
  1203.     if (bSuccess)
  1204.     {
  1205.         m_bConnected = TRUE;
  1206.     }
  1207. #if !defined( WIN32_PLATFORM_PSPC ) && !defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1208.     HXThreadMessage msg(HXMSG_ASYNC_CONNECT, this, (void*) bSuccess);
  1209.     m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1210. #else // No notifier on CE
  1211.     OnConnect(bSuccess);
  1212. #endif
  1213. }
  1214. void
  1215. ThreadedConn::HandleAcceptNotification(conn* pConn)
  1216. {
  1217.     ThreadedConn* pTConn = (ThreadedConn*)conn::new_socket(HX_TCP_SOCKET);
  1218.     pTConn->SetActualConn(pConn, m_ulUserHandle);
  1219.     m_pIncommingConnections->AddHead((conn*)pTConn);
  1220. #if !defined( WIN32_PLATFORM_PSPC ) && !defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1221.     HXThreadMessage msg(HXMSG_ASYNC_ACCEPT, this, NULL);
  1222.     m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1223. #else // No notifier on CE
  1224.     OnAcceptNotification();
  1225. #endif
  1226. }
  1227. void
  1228. ThreadedConn::HandleCloseNotification()
  1229. {
  1230.     /* make one more read call to get back the actual error */
  1231.     m_bReadPostPendingWouldBlock = FALSE;
  1232. }
  1233. HX_RESULT
  1234. ThreadedConn::SetActualConn(conn* pConn, ULONG32 ulPlatform)
  1235. {
  1236.     if ( m_pActualConn )
  1237.     {
  1238.         m_pActualConn->done();
  1239.         m_pActualConn->Release();
  1240.     }
  1241.     m_pActualConn = pConn;
  1242.     m_pActualConn->AddRef();
  1243.     m_ulUserHandle = ulPlatform;
  1244.     m_bConnected = TRUE;
  1245.     return HXR_OK;
  1246. }
  1247. HX_RESULT
  1248. ThreadedConn::DoRead(BOOL bFromReadNotification)
  1249. {
  1250. #ifdef _CARBON
  1251.     AddRef(); // ensure that this object doesn't encounter its dtor before routine completes
  1252. #endif
  1253.     HX_RESULT theErr = HXR_OK;
  1254.     m_pMutex->Lock();
  1255.     /* Reset reading heuristing if we just got data. */
  1256.     if( bFromReadNotification )
  1257.     {
  1258.         m_bReadNowPending = m_bReadPostPendingWouldBlock = FALSE;
  1259.     }
  1260.     /* If the socket done has already been called, do not attempt to read
  1261.      * any more data
  1262.      */
  1263.     if (m_bIsDone)
  1264.     {
  1265.         goto exit;
  1266.     }
  1267. #ifdef THREADS_SUPPORTED
  1268. #ifdef HELIX_FEATURE_ADD_NETWORK_THREAD_SLEEP
  1269.     Sleep( m_ulNetworkThreadSleep ); // gives other threads a quote to run
  1270. #endif //HELIX_FEATURE_ADD_NETWORK_THREAD_SLEEP
  1271. #endif //THREADS_SUPPORTED
  1272.     if (m_uSocketType == HX_TCP_SOCKET)
  1273.     {
  1274.         UINT16 uCount = m_pReceiveTCP->GetMaxAvailableElements();
  1275.         if (uCount > 0)
  1276.         {
  1277.             UINT32 ulBytesToRead = conn::bytes_to_preparetcpread(this);
  1278.             if (ulBytesToRead > 0)
  1279.             {
  1280.                 if ((UINT32)uCount > ulBytesToRead)
  1281.                 {
  1282.                     uCount = (UINT16)ulBytesToRead;
  1283.                 }
  1284.                 if ( m_bReadPostPendingWouldBlock )
  1285.                 {
  1286.                     /* fake a call return */
  1287.                     theErr = HXR_WOULD_BLOCK;
  1288.                 }
  1289.                 else
  1290.                 {
  1291.                     /* call read and do heuristinc bookkeeping */
  1292.                     theErr = m_pActualConn->read(m_pTempBuffer, &uCount);
  1293. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1294.                     m_bReadPostPendingWouldBlock = (m_bReadNowPending && theErr == HXR_WOULD_BLOCK);
  1295. #endif
  1296.                     m_bReadNowPending = (theErr == HXR_WOULD_BLOCK ? TRUE : FALSE);
  1297.                 }
  1298.                 if (!theErr && uCount > 0)
  1299.                 {
  1300.                     conn::bytes_to_actualtcpread(this, uCount);
  1301.                     m_pReceiveTCP->EnQueue(m_pTempBuffer, uCount);
  1302.                 }
  1303.             }
  1304.         }
  1305. #ifndef _WINCE
  1306.         if (!m_bOutstandingReadNotification && m_pReceiveTCP->GetQueuedItemCount() > 0)
  1307.         {
  1308. #ifdef HELIX_FEATURE_NETWORK_USE_SELECT
  1309.             m_bOutstandingReadNotification  = TRUE;
  1310.             HXThreadMessage msg(HXMSG_ASYNC_READ, this, NULL);
  1311.             theErr = m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1312.     if ( theErr == HXR_NOT_INITIALIZED )
  1313.     {
  1314. theErr = HXR_OK;
  1315.     }
  1316. #endif
  1317.         }
  1318. #endif /* _WINCE */
  1319.     }
  1320.     else /*if (m_uSocketType == HX_UDP_SOCKET)*/
  1321.     {
  1322.         UINT32 ulAddress = 0;
  1323.         UINT16 ulPort = 0;
  1324.         /* Read as much UDP data as possible */
  1325.         while (!theErr)
  1326.         {
  1327.             IHXBuffer* pBuffer = NULL;
  1328.             if ( m_bReadPostPendingWouldBlock )
  1329.             {
  1330.                 /* fake a call return */
  1331.                 theErr = HXR_WOULD_BLOCK;
  1332.             }
  1333.             else
  1334.             {
  1335.                 /* call read and do heuristinc bookkeeping */
  1336.                 theErr = m_pActualConn->readfrom(pBuffer, ulAddress, ulPort);
  1337.                 if( theErr == HXR_OUTOFMEMORY )
  1338.                 {
  1339.                     mLastError = HXR_OUTOFMEMORY;
  1340.                 }
  1341.                 /* If this is a single WOULDBLOCK, ReadNowPending gets set.  If this is the second
  1342.                    consecutive blocking call, ReadPostPendingWouldBlock gets set.
  1343.                    Feel free to suggest better variable names. */
  1344. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1345.                 m_bReadPostPendingWouldBlock = (m_bReadNowPending && theErr == HXR_WOULD_BLOCK);
  1346. #endif
  1347.                 m_bReadNowPending = (theErr == HXR_WOULD_BLOCK ? TRUE : FALSE);
  1348.             }
  1349.             if (!theErr && pBuffer)
  1350.             {
  1351.                 UDP_PACKET* pPacket = new UDP_PACKET;
  1352.                 if(pPacket)
  1353.                 {
  1354.                     pPacket->pBuffer = pBuffer;
  1355.                     pPacket->ulAddress = ulAddress;
  1356.                     pPacket->ulPort = ulPort;
  1357.                     m_ReadUDPBuffers.AddTail((void*)pPacket);
  1358.                 }
  1359.                 else
  1360.                 {
  1361.                     theErr = HXR_OUTOFMEMORY;
  1362.                 }
  1363.             }
  1364.         }
  1365. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1366.         if ( !theErr && !m_bOutstandingReadNotification && m_ReadUDPBuffers.GetCount() > 0)
  1367.         {
  1368.             m_bOutstandingReadNotification  = TRUE;
  1369.             HXThreadMessage msg(HXMSG_ASYNC_READ, this, NULL);
  1370.             m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1371.         }
  1372. #endif
  1373.     }
  1374.     if (!mLastError && theErr)
  1375.     {
  1376.         mLastError = ConvertNetworkError(theErr);
  1377.     }
  1378.     /* If there is an error, issue a Read Available message
  1379.      * so that error can be reported back on next Read
  1380.      */
  1381.     if (!m_bOutstandingReadNotification && mLastError && theErr != HXR_OUTOFMEMORY)
  1382.     {
  1383.         m_bOutstandingReadNotification  = TRUE;
  1384.         HXThreadMessage msg(HXMSG_ASYNC_READ, this, NULL);
  1385. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1386.         m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1387. #else
  1388. m_pNetworkThread->PostMessage(&msg, m_pInternalWindowHandle);
  1389. #endif
  1390.     }
  1391. exit:
  1392.     m_pMutex->Unlock();
  1393. #ifdef _CARBON
  1394.     Release();
  1395. #endif
  1396.     return theErr;
  1397. }
  1398. void
  1399. ThreadedConn::DoWrite()
  1400. {
  1401.     // If we are out of memory, let's just get out of here. Ideally, we should
  1402.     // not ever get to this point, but lots of functions here have void return
  1403.     // types, so it is possible to lose an OOM error.
  1404.     if( mLastError == HXR_OUTOFMEMORY )
  1405.     {
  1406.         return;
  1407.     }
  1408. #ifdef _CARBON
  1409.     AddRef();
  1410. #endif
  1411.     HX_RESULT theErr = HXR_OK;
  1412.     m_pMutex->Lock();
  1413.     if (m_uSocketType == HX_TCP_SOCKET)
  1414.     {
  1415.         UINT16 uCount = m_pSendTCP->GetQueuedItemCount();
  1416.         if (uCount > 0)
  1417.         {
  1418.             m_pSendTCP->DeQueue(m_pTempBuffer, uCount);
  1419.             UINT16 uActualCount = uCount;
  1420.             theErr = m_pActualConn->write(m_pTempBuffer, &uActualCount);
  1421.             switch(theErr)
  1422.             {
  1423.                 case HXR_AT_INTERRUPT:
  1424.                 case HXR_WOULD_BLOCK:
  1425.                 case HXR_OK:
  1426.                     // enqueue the data that was not sent
  1427.                     if(uActualCount != uCount)
  1428.                     {
  1429.                         m_pSendTCP->EnQueue(m_pTempBuffer + uActualCount,
  1430.                                             uCount - uActualCount);
  1431.                     }
  1432.                     // mask out these errors
  1433.                     theErr = HXR_OK;
  1434.                     break;
  1435.                 default:
  1436.                     break;
  1437.             }
  1438.         }
  1439. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1440.         if (!m_bIsDone && !m_bOutstandingWriteNotification && m_pSendTCP->GetMaxAvailableElements() > 0)
  1441.         {
  1442.             m_bOutstandingWriteNotification = TRUE;
  1443.             HXThreadMessage msg(HXMSG_ASYNC_WRITE, this, NULL);
  1444.             m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1445.         }
  1446. #endif
  1447.     }
  1448.     else /*if (m_uSocketType == HX_UDP_SOCKET)*/
  1449.     {
  1450.         while (!theErr && m_WriteUDPBuffers.GetCount() > 0)
  1451.         {
  1452.             UDPPacketInfo* pPacket = (UDPPacketInfo*) m_WriteUDPBuffers.GetHead();
  1453.             UINT16 uLength = (UINT16) pPacket->m_pBuffer->GetSize();
  1454.             theErr = m_pActualConn->writeto(pPacket->m_pBuffer->GetBuffer(),   // sendto
  1455.                                         &uLength,
  1456.                                         pPacket->m_ulAddr,
  1457.                                         pPacket->m_uPort);
  1458.             if (!theErr)
  1459.             {
  1460.                 pPacket->m_pBuffer->Release();
  1461.                 delete pPacket;
  1462.                 m_WriteUDPBuffers.RemoveHead();
  1463.             }
  1464.         }
  1465. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1466.         if (!m_bIsDone && !m_bOutstandingWriteNotification && m_WriteUDPBuffers.GetCount() == 0)
  1467.         {
  1468.             m_bOutstandingWriteNotification = TRUE;
  1469.             HXThreadMessage msg(HXMSG_ASYNC_WRITE, this, NULL);
  1470.             m_pMainAppThread->PostMessage(&msg, m_pInternalWindowHandle);
  1471.         }
  1472. #endif
  1473.     }
  1474.     if (!mLastError && theErr)
  1475.     {
  1476.         mLastError = ConvertNetworkError(theErr);
  1477.     }
  1478. #ifndef HELIX_FEATURE_NETWORK_USE_SELECT
  1479.     if (!mLastError && !m_bNetworkIOPending &&
  1480.         ((m_uSocketType == HX_TCP_SOCKET && m_pSendTCP->GetQueuedItemCount() > 0) ||
  1481.          (m_uSocketType == HX_UDP_SOCKET && m_WriteUDPBuffers.GetCount() > 0)))
  1482.     {
  1483.         theErr = PostIOMessage();
  1484.     }
  1485. #endif
  1486.     m_pMutex->Unlock();
  1487.     if (m_bWriteFlushPending &&
  1488.         ((m_uSocketType == HX_TCP_SOCKET && m_pSendTCP->GetQueuedItemCount() == 0) ||
  1489.          (m_uSocketType == HX_UDP_SOCKET && m_WriteUDPBuffers.GetCount() == 0)))
  1490.     {
  1491.         m_bWriteFlushPending    = FALSE;
  1492.         Release();
  1493.     }
  1494.     /* We are done and there is no more data pending to bw written out */
  1495.     /* This is the time socket actually gets destroyed */
  1496.     if (m_bIsDone && !m_bWriteFlushPending)
  1497.     {
  1498.         m_bConnected = FALSE;
  1499.         PostDoneAndDetach();
  1500.     }
  1501. #ifdef _CARBON
  1502.     Release();
  1503. #endif
  1504. }
  1505. //--------------------------------------------------
  1506. void
  1507. ThreadedConn::DoNetworkIO(void)
  1508. {
  1509.     m_bNetworkIOPending = FALSE;
  1510.     if (m_bConnected)
  1511.     {
  1512.         // DoRead now has a return type, but since DoNetworkIO does not we
  1513.         // are going to ignore any errors returned. This may not be a good idea.
  1514. #if !defined( WIN32_PLATFORM_PSPC ) /*&& !defined( _UNIX )*/
  1515. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1516. if (!m_pNetworkThread->m_bUseReaderWriter)
  1517. #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1518.         DoRead();
  1519.         DoWrite();
  1520. #else
  1521. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1522. if (!m_pNetworkThread->m_bUseReaderWriter)
  1523. #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1524.         DoRead(TRUE);
  1525.         DoWrite();
  1526. #endif
  1527.     }
  1528. }
  1529. HX_RESULT
  1530. ThreadedConn::ConvertNetworkError(HX_RESULT theErr)
  1531. {
  1532.     HX_RESULT lResult = theErr;
  1533.     if (!IS_SERVER_ALERT(theErr))
  1534.     {
  1535.         switch(theErr)
  1536.         {
  1537.             case HXR_AT_INTERRUPT:                      // mask out these errors
  1538.             case HXR_WOULD_BLOCK:
  1539.             case HXR_NO_DATA:
  1540.             case HXR_OK:
  1541.                 lResult = HXR_OK;
  1542.                 break;
  1543.             case HXR_DNR:
  1544.             case HXR_NET_CONNECT:
  1545.             case HXR_DOC_MISSING:
  1546.             case HXR_OUTOFMEMORY:
  1547.             case HXR_ADVANCED_SERVER:
  1548.             case HXR_BAD_SERVER:
  1549.             case HXR_OLD_SERVER:
  1550.             case HXR_INVALID_FILE:
  1551.             case HXR_REDIRECTION:
  1552.             case HXR_PROXY:
  1553.             case HXR_PROXY_RESPONSE:
  1554.             case HXR_ADVANCED_PROXY:
  1555.             case HXR_OLD_PROXY:
  1556.             case HXR_PERFECTPLAY_NOT_SUPPORTED:
  1557.             case HXR_NO_LIVE_PERFECTPLAY:
  1558.             case HXR_PERFECTPLAY_NOT_ALLOWED:
  1559.                 break;
  1560.             default:
  1561.                 lResult = HXR_FAIL;
  1562.                 break;
  1563.         }
  1564.     }
  1565.     return lResult;
  1566. }
  1567. HX_RESULT
  1568. ThreadedConn::PostIOMessage(void)
  1569. {
  1570.     m_bNetworkIOPending = TRUE;
  1571.     HXThreadMessage msg(HXMSG_ASYNC_NETWORKIO, this, NULL);
  1572.     return m_pNetworkThread->PostMessage(&msg);
  1573. }
  1574. HX_RESULT ThreadedConn::ThrConnSocketCallback::Func(NotificationType Type,
  1575.                                                BOOL bSuccess, conn* pConn)
  1576. {
  1577.     ThreadedConn* pContext = m_pContext;
  1578.     // It would be nice to set theErr for all of the calls below, but the
  1579.     // effects of that are unknown to this developer. XXXJHHB
  1580.     HX_RESULT theErr = HXR_OK;
  1581.     if(pContext)
  1582.     {
  1583.         switch (Type)
  1584.         {
  1585.         case READ_NOTIFICATION:
  1586.             theErr = pContext->DoRead(TRUE);
  1587.             break;
  1588.         case WRITE_NOTIFICATION:
  1589.             pContext->DoWrite();
  1590.             break;
  1591.         case CONNECT_NOTIFICATION:
  1592.             pContext->HandleConnectNotification(bSuccess);
  1593.             break;
  1594.         case DNS_NOTIFICATION:
  1595.             pContext->HandleDNSNotification(bSuccess);
  1596.             break;
  1597.         case ACCEPT_NOTIFICATION:
  1598.             pContext->HandleAcceptNotification(pConn);
  1599. #ifdef HELIX_FEATURE_NETWORK_USE_SELECT
  1600.             break;
  1601. #endif
  1602.         case CLOSE_NOTIFICATION:
  1603.             pContext->HandleCloseNotification();
  1604.             break;
  1605. #ifdef HELIX_FEATURE_NETWORK_USE_SELECT
  1606.         case SEND_BUFFER_NOTIFICATION:
  1607.     UINT16 len;
  1608.     len = sizeof(HXThreadMessage);
  1609.     pContext->m_bNetworkIOPending = TRUE;
  1610.             pContext->write((char *)bSuccess,&len);
  1611.             pContext->DoWrite();
  1612.     pContext->m_bNetworkIOPending = FALSE;
  1613.             break;
  1614. #endif
  1615.         default:
  1616.             break;
  1617.         }
  1618.     }
  1619.     return theErr;
  1620. }
  1621. ThreadedConn::ThrdConnGenericCallback::ThrdConnGenericCallback(ThreadedConn* pConn, UINT16 uCallbackType)
  1622.     : m_lRefCount (0)
  1623.     , m_uCallbackType (uCallbackType)
  1624.     , m_pConn (pConn)
  1625.     , m_bBlocking (FALSE)
  1626.     , m_ulLocalAddr (0)
  1627.     , m_uPort (0)
  1628.     , m_ulBufferSize (0)
  1629.     , m_uBacklog(0)
  1630. //    , m_pNewConn(NULL)
  1631. {
  1632. }
  1633. ThreadedConn::ThrdConnGenericCallback::~ThrdConnGenericCallback()
  1634. {
  1635. //    HX_RELEASE(m_pNewConn);
  1636. }
  1637. /*
  1638.  * IUnknown methods
  1639.  */
  1640. /////////////////////////////////////////////////////////////////////////
  1641. //      Method:
  1642. //              IUnknown::QueryInterface
  1643. //      Purpose:
  1644. //              Implement this to export the interfaces supported by your
  1645. //              object.
  1646. //
  1647. STDMETHODIMP ThreadedConn::ThrdConnGenericCallback::QueryInterface(REFIID riid, void** ppvObj)
  1648. {
  1649.     if (IsEqualIID(riid, IID_IUnknown))
  1650.     {
  1651.         AddRef();
  1652.         *ppvObj = this;
  1653.         return HXR_OK;
  1654.     }
  1655.     else if (IsEqualIID(riid, IID_IHXCallback))
  1656.     {
  1657.         AddRef();
  1658.         *ppvObj = (IHXCallback*)this;
  1659.         return HXR_OK;
  1660.     }
  1661.     *ppvObj = NULL;
  1662.     return HXR_NOINTERFACE;
  1663. }
  1664. /////////////////////////////////////////////////////////////////////////
  1665. //      Method:
  1666. //              IUnknown::AddRef
  1667. //      Purpose:
  1668. //              Everyone usually implements this the same... feel free to use
  1669. //              this implementation.
  1670. //
  1671. STDMETHODIMP_(ULONG32) ThreadedConn::ThrdConnGenericCallback::AddRef()
  1672. {
  1673.     return InterlockedIncrement(&m_lRefCount);
  1674. }
  1675. /////////////////////////////////////////////////////////////////////////
  1676. //      Method:
  1677. //              IUnknown::Release
  1678. //      Purpose:
  1679. //              Everyone usually implements this the same... feel free to use
  1680. //              this implementation.
  1681. //
  1682. STDMETHODIMP_(ULONG32) ThreadedConn::ThrdConnGenericCallback::Release()
  1683. {
  1684.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1685.     {
  1686.         return m_lRefCount;
  1687.     }
  1688.     delete this;
  1689.     return 0;
  1690. }
  1691. /*
  1692.  *      IHXCallback methods
  1693.  */
  1694. STDMETHODIMP ThreadedConn::ThrdConnGenericCallback::Func(void)
  1695. {
  1696.     if (m_pConn)
  1697.     {
  1698.         switch (m_uCallbackType)
  1699.         {
  1700.             case DNS_CALLBACK_TYPE:
  1701.                 m_pConn->ActualDnsFindIpAddr(m_HostName, m_bBlocking);
  1702.                 break;
  1703.             case INIT_CALLBACK_TYPE:
  1704.                 m_pConn->ActualInit(m_ulLocalAddr, m_uPort, m_bBlocking);
  1705.                 break;
  1706.             case SETWINDOWHANDLE_CALLBACK_TYPE:
  1707. #if defined (_WIN32) || defined (_WINDOWS)
  1708.                 m_pConn->ActuallSetWindowHandle(m_ulHandle);
  1709. #endif /*defined (_WIN32) || defined (_WINDOWS)*/
  1710.                 break;
  1711.             case CONNECT_CALLBACK_TYPE:
  1712.                 m_pConn->ActualConnect(m_HostName, m_uPort, m_bBlocking,
  1713.                                         m_ulHandle);
  1714.                 break;
  1715. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1716.             case ACCEPT_CALLBACK_TYPE:
  1717.                 m_pConn->ActualAccept(m_ulLocalAddr,
  1718.                                         m_ulHandle);
  1719.                 break;
  1720. #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  1721.             case BLOCKING_CALLBACK_TYPE:
  1722.                 m_pConn->ActualBlocking();
  1723.                 break;
  1724.             case NONBLOCKING_CALLBACK_TYPE:
  1725.                 m_pConn->ActualNonBlocking();
  1726.                 break;
  1727.             case DONE_CALLBACK_TYPE:
  1728.                 m_pConn->ActualDone();
  1729.                 break;
  1730.             case SET_BUFFER_SIZE_CALLBACK_TYPE:
  1731.                 m_pConn->ActualSetReceiveBufSize(m_ulBufferSize);
  1732.                 break;
  1733.             case LISTEN_CALLBACK_TYPE:
  1734.                 m_pConn->ActualListen(m_ulLocalAddr, m_uPort, m_uBacklog,
  1735.                                 m_bBlocking, m_ulHandle);
  1736.                 break;
  1737.             default:
  1738.                 break;
  1739.         }
  1740.     }
  1741.     return HXR_OK;
  1742. }