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

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