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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: win_net.cpp,v 1.6.2.3 2004/07/09 01:46:44 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 "hxtypes.h"
  50. #ifdef _WIN16
  51. #include <stdlib.h>
  52. #endif _WIN16
  53. #include <stdio.h>
  54. #include <string.h>
  55. /* mcast_multiple_if test */
  56. #ifndef _WINCE
  57. #include <iostream.h>
  58. #include <winsock2.h>
  59. #include <ws2tcpip.h>
  60. #endif /* _WINCE */
  61. #include "hxslist.h"
  62. #include "platform/win/sock.h"
  63. #include "platform/win/hxsock.h" //  Low level socket calls
  64. #include "hxthread.h"
  65. #include "hxcom.h"
  66. #include "hxengin.h"
  67. #include "threngin.h"
  68. #include "platform/win/win_net.h"      //  Our declaration
  69. #include "platform/win/casynnet.h"     //  Declaration of async socket notifier
  70. #include "netbyte.h"
  71. #include "hxbuffer.h"
  72. #include "timebuff.h"
  73. #include "hxtick.h"
  74. #include "debugout.h" //  Debug macros
  75. #include "hxstrutl.h"
  76. #include "hxheap.h"
  77. #include "thrdconn.h"
  78. #ifdef _DEBUG
  79. #undef HX_THIS_FILE
  80. static const char HX_THIS_FILE[] = __FILE__;
  81. #endif  
  82. static WinsockManager OnlyOneOfThisInTheWholeProgram;
  83. //#define _LOGSMIL    1
  84. win_net::win_net()       // PostThreadMessage
  85. {
  86.     set_sock( INVALID_SOCKET );
  87.     mLastError     = HXR_OK;
  88.     callRaConnect   = 1;    
  89.     bReadyToWrite   = 0;
  90.     m_SocketState   = CONN_CLOSED;
  91. #ifndef WIN32_PLATFORM_PSPC
  92.     m_hAsyncHandle  = NULL;
  93. #endif
  94.     m_AsyncAddress  = NULL;
  95.     CurrentAddr     = 0;
  96.     m_DNSOnly     = FALSE;
  97.     m_pAsyncHost    = NULL;
  98.     InBlockingMode  = 0;
  99.     m_lRefCount     = 0;
  100.     m_pInBuffer = new char[TCP_BUF_SIZE];
  101.     m_bReuseAddr = FALSE;
  102.     m_bReusePort = FALSE;
  103.     m_bIgnoreWSAECONNRESET = FALSE;
  104. }
  105. win_net::~win_net() 
  106. {
  107. #ifndef WIN32_PLATFORM_PSPC
  108.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , FALSE);
  109.     if (m_AsyncNotifier)
  110.     {
  111. m_AsyncNotifier->CancelSelect( this );
  112.     }
  113. #endif
  114.     m_SocketState = CONN_CLOSING;
  115.     if ((get_sock() != INVALID_SOCKET) && sockObj)       
  116.     {       
  117. if (sockObj->HXclosesocket(get_sock()))
  118. {
  119.     int code = 0;
  120.     code = sockObj->HXWSAGetLastError();
  121. }    
  122.     }
  123.     set_sock( INVALID_SOCKET );
  124.     m_SocketState = CONN_CLOSED;
  125.     mConnectionOpen = 0;
  126.     if (m_AsyncAddress)
  127.     {
  128. delete [] m_AsyncAddress;
  129. m_AsyncAddress = NULL;
  130.     }
  131.     HX_VECTOR_DELETE(m_pAsyncHost);
  132.     delete[] m_pInBuffer;
  133. }
  134. win_net * win_net::new_socket(UINT16 type)
  135. {
  136.     win_net* c = NULL;
  137.     if (sockObj)
  138.     { 
  139. switch(type)
  140. {
  141. case HX_TCP_SOCKET:
  142.     c = new win_TCP;
  143.     break;
  144. case HX_UDP_SOCKET:
  145.     c = new win_UDP;
  146.     break;
  147. }
  148.     }
  149.     return(c);
  150. }
  151. // init_drivers() should do any network driver initialization here
  152. // params is a pointer to a platform specfic defined struct that 
  153. // contains an required initialization data
  154. HX_RESULT win_net::init_drivers(void *params)
  155. {
  156.     if(!sockObj)
  157.       sockObj = new CHXSock;  
  158.     if(!sockObj)
  159.       return(HXR_OUTOFMEMORY);
  160.     return(HXR_OK);
  161. }
  162. /*  close_drivers() should close any network drivers used by the program
  163.   NOTE: The program MUST not make any other calls to the network drivers
  164.   until init_drivers() has been called */
  165. HX_RESULT win_net::close_drivers(void *params)
  166. {
  167.     if(sockObj)
  168.     {
  169. sockObj->HXWSACleanup();
  170. delete sockObj;
  171. sockObj = NULL;
  172.     }  
  173.     return(HXR_OK);
  174. }
  175. HX_RESULT win_net::host_to_ip_str( char *host, char *ip, UINT32 ulIPBufLen)
  176. {
  177.     ULONG32 dwAddress;
  178.     IN_ADDR rInAddress;
  179.     HX_RESULT theErr;
  180.     PHOSTENT pHostEntry;
  181.     theErr = HXR_OK;
  182.     // Let's look for this in the cache first
  183.     if (conn::is_cached( host, &dwAddress))
  184.     {
  185. // Found it, copy the 32bit address into rInAddress w/o calling memcpy()
  186. rInAddress = *(IN_ADDR *)&dwAddress;
  187.     }
  188.     else
  189.     {
  190. // Do DNS on the host name
  191. if (!(pHostEntry = sockObj->HXgethostbyname( host )))
  192. {
  193.     // Error
  194.     theErr = HXR_DNR;
  195. }
  196. // Return w/o attempting any copies if there's an error
  197. if (HXR_OK != theErr)
  198. {
  199.     goto FuncExit;
  200. }
  201. // copy the ip address into rInAddress w/o calling memcpy()
  202. rInAddress = *(IN_ADDR *)(pHostEntry->h_addr);
  203.     }
  204.     // Convert the ULONG32 IP address into a string and copy it into ip
  205.     SafeStrCpy( ip, sockObj->HXinet_ntoa( rInAddress ) , ulIPBufLen);
  206.     // Single exit point
  207. FuncExit:
  208.     return( theErr );
  209. }
  210. ULONG32 win_net::AddRef()
  211. {
  212.     return InterlockedIncrement(&m_lRefCount);
  213. }
  214. ULONG32 win_net::Release()
  215. {
  216.     if (InterlockedDecrement(&m_lRefCount) > 0)
  217.     {
  218.         return m_lRefCount;
  219.     }
  220.     delete this;
  221.     return 0;
  222. }
  223. HX_RESULT win_net::init_win(UINT16 type, UINT32 local_addr, 
  224.     UINT16 port, UINT16 blocking)
  225. {                                        
  226.     int            s;
  227.     s = sockObj->HXsocket(PF_INET, type, 0);
  228.     if (s == INVALID_SOCKET) 
  229.     {
  230. mLastError = HXR_NET_SOCKET_INVALID;
  231. return mLastError;
  232.     }
  233.     InBlockingMode = 1;
  234.      
  235.     {
  236. struct linger Ling;
  237. Ling.l_onoff = 0;
  238. Ling.l_linger = 0;
  239. if (callRaConnect && sockObj->HXsetsockopt(s, SOL_SOCKET, SO_LINGER, 
  240.      (char *)&Ling, sizeof(Ling)) != 0)
  241. {                 
  242.     if(!InBlockingMode)
  243. return HXR_BLOCK_CANCELED;                      
  244.     int code;
  245.     code = sockObj->HXWSAGetLastError(); 
  246.     mLastError = HXR_NET_SOCKET_INVALID;
  247.     InBlockingMode = 0;
  248.     return mLastError;
  249. }
  250.     }
  251.     if(!InBlockingMode)
  252. return HXR_BLOCK_CANCELED;
  253.     
  254.     InBlockingMode = 0;
  255.  
  256.     { 
  257. if (sockObj->HXsetsockopt(s, SOL_SOCKET, SO_REUSEADDR, 
  258.                       (const char *)&m_bReuseAddr, sizeof(m_bReuseAddr)) != 0)
  259. {
  260.         int code;
  261.     code = sockObj->HXWSAGetLastError(); 
  262.     mLastError = HXR_NET_SOCKET_INVALID;
  263.     return mLastError;
  264. }
  265. // Reuse port is not supported on win's right now...
  266. /*
  267. if (sockObj->HXsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, 
  268.                       (const char *)&m_bReusePort, sizeof(m_bReusePort)) != 0)
  269. {
  270.         int code;
  271.     code = sockObj->HXWSAGetLastError(); 
  272.     mLastError = HXR_NET_SOCKET_INVALID;
  273.     return mLastError;
  274. }
  275. */
  276.     }    
  277.     
  278.     struct sockaddr_in SockAddr;
  279.     memset(&SockAddr, 0, sizeof(SockAddr));
  280.     SockAddr.sin_family = AF_INET;
  281.     
  282.     SockAddr.sin_addr.s_addr = sockObj->HXhtonl(local_addr);
  283.     SockAddr.sin_port = sockObj->HXhtons(port);
  284.     if (sockObj->HXbind(s, (sockaddr*)&SockAddr, sizeof(SockAddr)) < 0) 
  285.     {
  286. //perror("bind");
  287. goto err;
  288.     } 
  289.     {
  290. unsigned long lMode = 1;                                                            
  291. if (!blocking && sockObj->HXioctlsocket(s, FIONBIO, &lMode) < 0) 
  292. {
  293.     goto err;
  294. }    
  295.     }
  296.     if (!callRaConnect)
  297.     {
  298. m_SocketState = CONN_OPEN;
  299.     }
  300.     else
  301.     {
  302. m_SocketState = CONN_NO_CONN;
  303.     }
  304.     set_sock( s );
  305.     return HXR_OK;
  306. err:
  307.     sockObj->HXclosesocket(s);
  308.     mLastError = HXR_NET_CONNECT;
  309.     return mLastError;
  310. }
  311. HX_RESULT win_net::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform)
  312. {   
  313.     DEBUGOUTSTR( "win_net::connect()rn" );
  314.     m_hInst = (HINSTANCE)ulPlatform;
  315.     if (!blocking)
  316.     {
  317. #ifndef WIN32_PLATFORM_PSPC
  318. return( ConnectAsync( host, port ) );
  319. #else
  320. HX_ASSERT(0 && "No Async connect");
  321. #endif
  322.     }
  323.     else
  324.     {
  325. bReadyToWrite = 0;
  326. if(!host)                 
  327. {
  328.     mLastError = HXR_DNR;
  329.     return mLastError;
  330. }
  331.     
  332. if(get_sock() < 0)                 
  333. {
  334.     mLastError = HXR_NET_SOCKET_INVALID;
  335.     return mLastError;
  336. }
  337.     
  338. struct in_addr addr;
  339.         char* pTemp = strrchr(host, '.');
  340.         if (pTemp && isdigit(*(pTemp + 1)))
  341. {   /* IP address. */
  342.     InBlockingMode = 1;
  343.     addr.s_addr = sockObj->HXinet_addr(host);
  344.     
  345.     if(!InBlockingMode)
  346. return HXR_BLOCK_CANCELED;
  347.     
  348.     InBlockingMode = 0;
  349.     
  350.     if ((UINT)addr.s_addr == (UINT)-1) 
  351.     {
  352. mLastError = HXR_DNR;
  353. return mLastError;
  354.     }
  355.     m_SocketState = CONN_CONNECT_INPROG;
  356. else
  357. {   /* Host name. */
  358.     InBlockingMode = 1;
  359.     struct hostent *h = sockObj->HXgethostbyname(host);
  360.     
  361.     if(!InBlockingMode)
  362. return HXR_BLOCK_CANCELED;
  363.     InBlockingMode = 0;
  364.     if (!h || !h->h_addr ) 
  365.     {
  366. mLastError = HXR_DNR;
  367. return mLastError;
  368.     }
  369.     memcpy(&addr, h->h_addr, sizeof(struct in_addr)); /* Flawfinder: ignore */
  370.     
  371.     // Rahul
  372.     m_AsyncPort = port;
  373.     if (m_pAsyncHost != host)
  374.     {
  375. HX_VECTOR_DELETE(m_pAsyncHost);
  376. m_pAsyncHost = ::new_string(host);
  377.     }
  378. }                    
  379.     
  380. struct sockaddr_in SockAddr;
  381. memset(&SockAddr, 0, sizeof(SockAddr));
  382. SockAddr.sin_family = AF_INET;
  383. SockAddr.sin_addr.s_addr = *(long*)&addr;
  384. SockAddr.sin_port = sockObj->HXhtons(port);
  385. // this stores info about current addr 
  386. CurrentAddr = *(ULONG32*)&addr;
  387.             
  388. InBlockingMode = 1;                
  389. if(callRaConnect && sockObj->HXconnect(get_sock(), (sockaddr*)&SockAddr, sizeof(SockAddr)))
  390. {   
  391.     if(!InBlockingMode)
  392. return HXR_BLOCK_CANCELED;
  393.     InBlockingMode = 0;
  394.     int code;
  395.     code = sockObj->HXWSAGetLastError(); 
  396.     if(!blocking && (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS))
  397.     {  
  398.        mConnectionOpen = 1;
  399.        return HXR_OK;
  400.     }   
  401.     mLastError = HXR_NET_CONNECT;
  402.     return mLastError;
  403. }       
  404.     
  405. if(!InBlockingMode)
  406.     return HXR_BLOCK_CANCELED;
  407.            
  408. InBlockingMode = 0;
  409.           
  410. mConnectionOpen = 1;
  411. m_SocketState = CONN_OPEN; 
  412. bReadyToWrite = 1;
  413. #ifdef WIN32_PLATFORM_PSPC 
  414. // Without asyncronous notification we cannot tolerate Asyncronous connect
  415. // so set non-blocking here rather than at connect
  416. ULONG lMode = 1;
  417. sockObj->HXioctlsocket(get_sock(), FIONBIO, &lMode);
  418. if (mCallBack)
  419. {
  420.     mCallBack->Func(CONNECT_NOTIFICATION);
  421. }
  422. #endif
  423.   return HXR_OK;
  424.     }
  425. }
  426. //-------------------------------------------------
  427. #if defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  428. HX_RESULT 
  429. win_net::WaitforSelect(void *pE,void *pC)
  430. {
  431.     ThreadEngine *pEngine = (ThreadEngine *)pE;
  432.     ThreadedConn *pProcessConn = (ThreadedConn*) pC;
  433.     if (!pEngine)
  434. return HXR_FAIL;
  435.     CHXMapPtrToPtr::Iterator ndxConn;
  436.     CHXMapPtrToPtr* pSockMap = pEngine->GetSockMap();
  437.     fd_set readfds,exceptfds;
  438.     BOOL bHaveSock = FALSE;
  439.     HX_RESULT theErr = HXR_OK;
  440.     FD_ZERO(&readfds);
  441.     FD_ZERO(&exceptfds);
  442.     
  443.     for (ndxConn = pSockMap->Begin(); 
  444.  ndxConn != pSockMap->End(); ++ndxConn)
  445.     {
  446. ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
  447. if (pProcessConn &&
  448.     pConn != pProcessConn)
  449.     continue; // dont process other connections while closing
  450. if (!pConn->connection_really_open())
  451.     continue;
  452. if (!pConn->GetActualConn())
  453.     continue;
  454. unsigned int s = pConn->get_sock();
  455. if (s != INVALID_SOCKET)
  456. {
  457.     FD_SET(s,&readfds);
  458.     FD_SET(s,&exceptfds);
  459.     bHaveSock = TRUE;
  460. }
  461.     }
  462.     if (!bHaveSock)
  463. return HXR_FAIL;
  464.     theErr = sockObj->HXselect(NULL,&readfds,NULL,NULL/*&exceptfds*/,NULL);
  465.     if (theErr == SOCKET_ERROR)
  466.     {
  467. theErr = sockObj->HXWSAGetLastError();
  468.     }
  469.     else
  470.     {
  471. theErr = HXR_OK;
  472.     }
  473.     // check for read ready
  474.     for (ndxConn = pSockMap->Begin(); 
  475.  ndxConn != pSockMap->End(); ++ndxConn)
  476.     {
  477. ThreadedConn* pConn = (ThreadedConn*) (*ndxConn);
  478. if (pProcessConn &&
  479.     pConn != pProcessConn)
  480.     continue; // dont process other connections while closing
  481. if (!pConn->GetActualConn())
  482.     continue;
  483. int s = pConn->get_sock();
  484. if (s != INVALID_SOCKET)
  485. {
  486.     if (FD_ISSET(s,&readfds))
  487.        pConn->DoRead(TRUE);
  488. }
  489.      }
  490.     return theErr;
  491. }
  492. HX_RESULT  
  493. win_net::CheckForConnection()
  494. {
  495.     HX_ASSERT(m_SocketState == CONN_LISTENNING);
  496.     if (m_SocketState != CONN_LISTENNING)
  497. return HXR_FAIL;
  498.     sockaddr_in addr;
  499.     int len = sizeof(sockaddr_in);
  500.     memset(&addr, 0, len);
  501.     
  502.     SOCKET sock = sockObj->HXaccept(get_sock(), (sockaddr*)&addr, &len);
  503.     if ( sock == INVALID_SOCKET )
  504.     {
  505.   int code = sockObj->HXWSAGetLastError();
  506. // igno all errors...  r
  507.     return HXR_WOULD_BLOCK;
  508.     }
  509.     win_net* c = (win_net*)conn::actual_new_socket(HX_TCP_SOCKET);
  510.     c->AddRef();
  511.     conn::add_connection_to_list ( c );
  512.     if ( c )
  513.     {
  514. c->set_sock(sock);
  515. c->connect_accept((ULONG32)m_hInst, addr);
  516. if (mCallBack && (m_SocketState == CONN_LISTENNING))
  517. {
  518.     mCallBack->Func(ACCEPT_NOTIFICATION, TRUE, (conn*)c);
  519. }
  520.     }
  521.     HX_RELEASE(c);
  522.     return HXR_OK;
  523. }
  524. #endif //defined(HELIX_FEATURE_NETWORK_USE_SELECT)
  525. // This function actually starts an async DNS request
  526. // It does it on either the first read or first write after we
  527. #ifndef WIN32_PLATFORM_PSPC
  528. // call ConnectAsync();
  529. HX_RESULT win_net::DoStartAsyncConn()
  530. {
  531.     DEBUGOUTSTR( "win_net::DoStartAsyncConn()rn" );
  532.     
  533.     if (!m_pAsyncHost)
  534.     {
  535. return (mLastError = HXR_FAILED);
  536.     }
  537.     if (!m_AsyncAddress)
  538.     {
  539. m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
  540.     }
  541.     if (!m_AsyncAddress)
  542.     {
  543. return (mLastError = HXR_OUTOFMEMORY);
  544.     }
  545.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , TRUE);
  546.     m_AsyncNotifier->DoAsyncDNS( this, m_pAsyncHost, m_AsyncAddress, MAXGETHOSTSTRUCT );
  547.     m_SocketState = CONN_DNS_INPROG;
  548.     return( mLastError = HXR_WOULD_BLOCK );
  549. }
  550. // This method get's called by connect() in the case of an async request
  551. // It doesn't however actually start the connection.  It just registers
  552. // that we need to do the connection.  DoStartAsyncConn() will really do it.
  553. HX_RESULT win_net::ConnectAsync( LPCSTR host, UINT16 port )
  554. {
  555.     DEBUGOUTSTR( "win_net::ConnectAsync()rn" );
  556.     bReadyToWrite = 0;
  557.     if (!host)                 
  558.     {
  559. mLastError = HXR_DNR;
  560. return mLastError;
  561.     }
  562.     if (get_sock() == INVALID_SOCKET)
  563.     {
  564. mLastError = HXR_NET_SOCKET_INVALID;
  565. return mLastError;
  566.     }
  567.     struct in_addr addr;  
  568.     char* pTemp = strrchr(host, '.');
  569.     if (pTemp && atoi(pTemp + 1))
  570.     {   /* IP address. */
  571. addr.s_addr = sockObj->HXinet_addr(host);
  572. if ((UINT)addr.s_addr == (UINT)-1) 
  573. {
  574.     mLastError = HXR_DNR;
  575.     return mLastError;
  576. }
  577. else
  578. {
  579.     LPSTR pTemp;
  580.     hostent *pHost;
  581.     if (!m_AsyncAddress)
  582.     {
  583. m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
  584.     }
  585.     if (!m_AsyncAddress)
  586.     {
  587. mLastError = HXR_OUTOFMEMORY;
  588. return (mLastError);
  589.     }
  590.     pHost = (hostent *)m_AsyncAddress;
  591.     // this stores info about current addr 
  592.     CurrentAddr = *(ULONG32 *)&addr;
  593.     m_AsyncPort = port;
  594.     pTemp = (LPSTR)&addr.s_addr;
  595.     pHost->h_addr_list = &pTemp;
  596.     CB_DNSComplete( TRUE );
  597. }
  598.     } 
  599.     else if (conn::is_cached((char *)host,(ULONG32 *) &addr))
  600.     {
  601. LPSTR pTemp;
  602. hostent *pHost;
  603. if (!m_AsyncAddress)
  604. {
  605.     m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
  606. }
  607. if (!m_AsyncAddress)
  608. {
  609.     mLastError = HXR_OUTOFMEMORY;
  610.     return (mLastError);
  611. }
  612. pHost = (hostent *)m_AsyncAddress;
  613. // this stores info about current addr 
  614. CurrentAddr = *(ULONG32 *)&addr;
  615. m_AsyncPort = port;
  616. pTemp = (LPSTR)&addr.s_addr;
  617. pHost->h_addr_list = &pTemp;
  618. CB_DNSComplete( TRUE );
  619.     }
  620.     else
  621.     {
  622. // Save the parameters, and tell ourselves we're starting up
  623. m_AsyncPort = port;
  624. if (m_pAsyncHost != host)
  625. {
  626.     HX_VECTOR_DELETE(m_pAsyncHost);
  627.     m_pAsyncHost = ::new_string(host);
  628. }
  629. m_SocketState = CONN_NO_CONN;
  630. return(DoStartAsyncConn());
  631.     }
  632.     return( HXR_OK );
  633. }
  634. // Once async DNS has commpleted then we'll call this guy to do the
  635. // connection (again asynchronously).
  636. void win_net::ContinueAsyncConnect()
  637. {
  638.     hostent *pHost;
  639.     struct in_addr addr;
  640.     DEBUGOUTSTR( "win_net::ContinueAsyncConnect()rn" );
  641.     pHost = (hostent *)m_AsyncAddress;
  642.     if (!pHost)
  643. return;
  644.     memcpy( &(addr.s_addr), pHost->h_addr, sizeof( addr.s_addr ) ); /* Flawfinder: ignore */
  645.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst ,TRUE);
  646.     m_AsyncNotifier->DoAsyncSelect( this );
  647.     
  648.     struct sockaddr_in SockAddr;
  649.     memset( &SockAddr, 0, sizeof( SockAddr ) );
  650.     SockAddr.sin_family = AF_INET;
  651.     SockAddr.sin_addr.s_addr = *(long*)&(addr.s_addr);
  652.     SockAddr.sin_port = sockObj->HXhtons( m_AsyncPort );
  653.                 
  654.     if(callRaConnect && sockObj->HXconnect( get_sock(), (sockaddr*)&SockAddr, sizeof( SockAddr ) ))
  655.     {   
  656. int code;
  657. code = sockObj->HXWSAGetLastError(); 
  658. if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS)
  659. {  
  660.     m_SocketState = CONN_CONNECT_INPROG;
  661.     mConnectionOpen = 1;
  662.     return;
  663. }   
  664. mLastError = HXR_NET_CONNECT;
  665. m_SocketState = CONN_CONNECT_FAILED;
  666. return;
  667.     }       
  668.     m_SocketState = CONN_CONNECT_INPROG;
  669.               
  670.     mConnectionOpen = 1;
  671.     return;
  672. }
  673. // Called by the notifier to tell us that the DNS request completed
  674. void win_net::CB_DNSComplete( int iSuccess )
  675. {
  676.     DEBUGOUTSTR( "CB_DNSComplete()rn" );
  677.     mDNSDone  = TRUE;
  678.     if (iSuccess && m_pAsyncHost)
  679.     {
  680. conn::add_to_cache(m_pAsyncHost, get_addr());
  681.     }
  682.     if (m_DNSOnly)
  683.     {
  684. if (iSuccess)
  685. {
  686.     mHostIPValid = TRUE;
  687.     mHostIPAddr = get_addr();
  688. }
  689. else
  690. {
  691.     mHostIPValid = FALSE;
  692. }
  693.     }
  694.     else
  695.     {
  696. if (iSuccess)
  697. {
  698.     m_SocketState = CONN_CONNECT_INPROG;
  699.     ContinueAsyncConnect();
  700. }
  701. else
  702. {
  703.     m_SocketState = CONN_DNS_FAILED;
  704. }
  705.     }
  706.     if (mCallBack)  
  707.     {
  708. mCallBack->Func(DNS_NOTIFICATION, iSuccess);
  709.     }
  710. }
  711. // Called by the notifier to tell us that the Connection completed
  712. void win_net::CB_ConnectionComplete( int iSuccess )
  713. {
  714.     DEBUGOUTSTR( "CB_ConnectionComplete()rn" );
  715.     if (iSuccess)
  716.     {
  717. m_SocketState = CONN_OPEN;
  718. if (mCallBack)
  719. {
  720.     mCallBack->Func(CONNECT_NOTIFICATION);
  721. }
  722.     }
  723.     else
  724.     {
  725. m_SocketState = CONN_CONNECT_FAILED;
  726. if (mCallBack)  
  727. {
  728.     mCallBack->Func(CONNECT_NOTIFICATION, FALSE);
  729. }
  730.     }
  731. }
  732. // Called by the notifier when data ready for read/write
  733. void win_net::CB_ReadWriteNotification( int iType )
  734. {
  735. #ifndef _DEMPSEY
  736. // noisy output
  737.     DEBUGOUTSTR( "CB_ReadWriteNotification()....rn" );
  738. #endif // _DEMPSEY
  739.     // Should do something here....
  740.     if (mCallBack && (m_SocketState == CONN_OPEN))
  741.     {
  742. if (iType == FD_WRITE)
  743. {
  744.     mCallBack->Func(WRITE_NOTIFICATION);
  745. }
  746. else if (iType == FD_READ)
  747. {
  748.     mCallBack->Func(READ_NOTIFICATION);
  749. }
  750. //mCallBack->callback_task( HX_UDP_CALLBACK, NULL );
  751.     }
  752. }
  753. void win_net::CB_AcceptNotification()
  754. {
  755.     DEBUGOUTSTR( "CB_AcceptNotification()....rn" );
  756.     HX_ASSERT(m_SocketState == CONN_LISTENNING);
  757.     
  758.     win_net* c = (win_net*)conn::actual_new_socket(HX_TCP_SOCKET);
  759.     c->AddRef();
  760.     conn::add_connection_to_list ( c );
  761.     if ( c )
  762.     {
  763. sockaddr_in addr;
  764. int len = sizeof(addr);
  765. SOCKET sock = sockObj->HXaccept(get_sock(), (sockaddr*)&addr, &len);
  766. if ( sock != INVALID_SOCKET)
  767. {
  768.     c->set_sock(sock);
  769.     c->connect_accept((ULONG32)m_hInst, addr);
  770.     if (mCallBack && (m_SocketState == CONN_LISTENNING))
  771.     {
  772. mCallBack->Func(ACCEPT_NOTIFICATION, TRUE, (conn*)c);
  773.     }
  774. }
  775.     }
  776.     HX_RELEASE(c);
  777. }
  778. void win_net::CB_CloseNotification()
  779. {
  780.     DEBUGOUTSTR( "CB_CloseNotification()....rn" );
  781.     m_SocketState = CONN_CLOSED;
  782.     if (mCallBack)
  783.     {
  784. mCallBack->Func(CLOSE_NOTIFICATION);
  785.     }
  786. }
  787. #endif
  788. HX_RESULT win_net::connect( sockaddr_in *addr )
  789. {
  790.     if(callRaConnect && sockObj->HXconnect( get_sock(), (sockaddr*)addr, sizeof( addr ) ))
  791.     {
  792. mLastError = HXR_NET_CONNECT;
  793. return mLastError;
  794.     }                   
  795.     
  796.     mConnectionOpen = 1;
  797.     return HXR_OK;     
  798. }
  799. HX_RESULT win_net::write(void * buf, UINT16  *len) 
  800. {
  801.     int got;
  802.     DEBUGOUTSTR( "win_net::write()rn" );
  803.     if (get_sock() == INVALID_SOCKET) 
  804.     {
  805. // Not connected
  806. return( mLastError = HXR_NET_SOCKET_INVALID );
  807.     }
  808.     if (m_SocketState != CONN_OPEN ) //&& m_SocketState != CONN_DNS_INPROG)
  809.     {
  810. // We won't be able to write anything here, so clear this
  811. // we'll return why we didn't write anything.
  812. *len = 0;
  813. switch( m_SocketState )
  814. {
  815. case CONN_DNS_INPROG:
  816. case CONN_CONNECT_INPROG:
  817. case CONN_CLOSING:
  818. return( mLastError = HXR_WOULD_BLOCK );
  819. case CONN_CLOSED:
  820. return( mLastError = HXR_NET_SOCKET_INVALID );
  821. case CONN_NO_CONN:
  822. #ifndef WIN32_PLATFORM_PSPC
  823. return( DoStartAsyncConn() );
  824. #else
  825.         HX_ASSERT(0 && "No Async net");
  826.         return( HXR_NET_READ );
  827. #endif
  828. case CONN_DNS_FAILED:
  829. return( mLastError = HXR_DNR );
  830. case CONN_CONNECT_FAILED:
  831. return( mLastError = HXR_NET_CONNECT );
  832. default:
  833. // HUH???
  834. assert( 0 );
  835. return( mLastError = HXR_NET_READ );
  836. };
  837.     }
  838.     else
  839.     {
  840. got = sockObj->HXsend( get_sock(), (char *)buf, *len, 0 );
  841. if (got == -1)
  842. {
  843.     int code;
  844.     *len = 0;
  845.     code = sockObj->HXWSAGetLastError();
  846.     // Mask the "so what?" errors
  847.     if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS) 
  848.     {
  849. return HXR_WOULD_BLOCK;
  850.     }
  851.     else
  852.     {
  853. mLastError = HXR_NET_WRITE;
  854. return mLastError;
  855.     }
  856. }
  857. //#if defined(_DEBUG) && defined(_LOGSMIL)
  858. // if (::HXDebugOptionEnabled("zLogSMIL"))
  859. //{FILE* f1 = ::fopen("e:\temp\foo.txt", "a+"); ::fwrite(buf, got, 1, f1);::fclose(f1);}
  860. //#endif
  861. *len = got;
  862. return HXR_OK;
  863.     }
  864. }
  865. HX_RESULT win_net::writeto(void * buf, UINT16  *len, ULONG32 addr, UINT16 port) 
  866. {
  867.     //sendto
  868.     int got;
  869.     sockaddr_in resend_addr;
  870.     
  871.     ::memset( &resend_addr, 0, sizeof( resend_addr ) );
  872.     resend_addr.sin_family = AF_INET;
  873.     resend_addr.sin_addr.s_addr = addr;
  874.     resend_addr.sin_port = sockObj->HXhtons(port);
  875.     got = sockObj->HXsendto(get_sock(), (char *) buf, *len, 0, (sockaddr *)&resend_addr, sizeof (resend_addr)); 
  876.     if (got == -1)
  877.     {
  878. int code;
  879. *len = 0;
  880. code = sockObj->HXWSAGetLastError();
  881. // Mask the "so what?" errors
  882. if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS) 
  883. {
  884.     return HXR_WOULD_BLOCK;
  885. }
  886. else
  887. {
  888.     mLastError = HXR_NET_WRITE;
  889.     return mLastError;
  890. }
  891.     }
  892.     *len = got;
  893.     return HXR_OK;
  894. }
  895. HX_RESULT win_net::WriteComplete   (char * Buffer, int length)
  896. {
  897.     int sent = 0;
  898.     unsigned short cur_sent=0;
  899.     while(sent < length)
  900.     {
  901. cur_sent = length - sent;
  902. HX_RESULT ret = write(Buffer + sent, &cur_sent);
  903. if(ret != HXR_OK && ret != HXR_WOULD_BLOCK)
  904.     break;
  905. sent += cur_sent;
  906.     }
  907. // m_SocketState = CONN_NO_CONN;
  908.     if(sent < length)
  909.     {
  910. mLastError = HXR_NET_WRITE;
  911. return mLastError;
  912.     }
  913.     return HXR_OK;
  914. }
  915. int win_net::ReadyToWrite()
  916. {
  917.     if(get_sock() < 0)
  918.     {
  919. bReadyToWrite = 0;
  920. return bReadyToWrite;
  921.     }
  922.     if(bReadyToWrite)
  923. return 1;
  924.     
  925.     fd_set writefds;
  926.     FD_ZERO(&writefds);
  927.     FD_SET((UINT32)get_sock(), &writefds);
  928.     
  929.     TIMEVAL timeout;
  930.     timeout.tv_sec = 1;
  931.     timeout.tv_usec = 0;
  932.     if(sockObj->HXselect(0, NULL, &writefds,NULL, &timeout) == 1)
  933. bReadyToWrite = 1;
  934.     
  935.     return bReadyToWrite;        
  936. }
  937. void win_net::done (void)
  938. {
  939. #ifndef WIN32_PLATFORM_PSPC
  940.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , FALSE);
  941.     if (m_AsyncNotifier)
  942.     {
  943. m_AsyncNotifier->CancelSelect( this );
  944.     }
  945. #endif
  946.     m_SocketState = CONN_CLOSING;
  947.     if ((get_sock() != INVALID_SOCKET) && sockObj)
  948.     {       
  949. if (sockObj->HXclosesocket(get_sock()))
  950. {
  951.     int code = 0;
  952.     code = sockObj->HXWSAGetLastError();
  953. }    
  954.     }
  955.     set_sock( INVALID_SOCKET );
  956.     m_SocketState = CONN_CLOSED;
  957.     mConnectionOpen = 0;
  958. }
  959. inline HX_RESULT win_net::listen(ULONG32 ulLocalAddr, UINT16 port, 
  960.  UINT16 backlog, UINT16 blocking,
  961.  ULONG32 ulPlatform)
  962. {
  963.     m_hInst = (HINSTANCE)ulPlatform;
  964. // accept is polled
  965. #ifndef WIN32_PLATFORM_PSPC
  966.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier(m_hInst ,TRUE);
  967.     m_AsyncNotifier->DoAsyncSelect((win_net*)this );
  968. #endif
  969.     HX_RESULT ret = sockObj->HXlisten(get_sock(), backlog);
  970.     if ( SUCCEEDED(ret) )
  971.     {
  972. m_SocketState = CONN_LISTENNING;
  973. ret = HXR_OK;
  974.     }
  975.     else
  976.     {
  977. ret = HXR_NET_SOCKET_INVALID;
  978.     }
  979.     return ret;
  980. }
  981. inline HX_RESULT win_net::blocking (void)
  982. {
  983.     unsigned long nonblocking = 0;
  984.     return sockObj->HXioctlsocket(get_sock(), FIONBIO, &nonblocking); 
  985. }
  986. inline HX_RESULT win_net::nonblocking (void) 
  987. {
  988.     unsigned long nonblocking = 1;
  989.     return sockObj->HXioctlsocket(get_sock(), FIONBIO, &nonblocking); 
  990. }
  991. HX_RESULT win_net::connect_accept(ULONG32 ulPlatform, sockaddr_in addr)
  992. {
  993.     m_hInst = (HINSTANCE)ulPlatform;
  994.     
  995.     CurrentAddr = addr.sin_addr.s_addr;
  996.     // set up the new connection so it will use its own notifier. 
  997.     // now we want to add this so it will recieve messages.
  998. #ifndef WIN32_PLATFORM_PSPC
  999.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst, TRUE);
  1000.     m_AsyncNotifier->DoAsyncSelect(this);
  1001. #endif
  1002.     m_SocketState = CONN_OPEN;
  1003.     mConnectionOpen = 1;
  1004.     return HXR_OK;
  1005. }
  1006. CHXMapPtrToPtr win_net::zm_MapObjectsToWinsockTasks;
  1007. CHXMapPtrToPtr win_net::zm_WinsockTasksRefCounts;
  1008. int win_net::zm_LibRefCount = 0;
  1009. BOOL win_net::IsWinsockAvailable(void* pObject)
  1010. {
  1011.     BOOL bWinSockInitedForTask = FALSE;
  1012.     // First check to see that the drivers are loaded...
  1013.     //
  1014.     // NOTE: this doesn't include initializing Winsock for 
  1015.     // the object's task...
  1016.     if(!OnlyOneOfThisInTheWholeProgram.IsInitialized())
  1017.     {
  1018. OnlyOneOfThisInTheWholeProgram.Initialize();
  1019.     }
  1020.     if(OnlyOneOfThisInTheWholeProgram.IsInitialized())
  1021.     {
  1022. zm_LibRefCount++;
  1023.     
  1024.     // Make sure Winsock is initialized for the object's task...
  1025. // get current task.
  1026. #if defined( WIN32 )
  1027. void* ulTask = (void*)GetCurrentProcessId();
  1028. #else
  1029. void* ulTask = (void*)GetCurrentTask();
  1030. #endif
  1031. // add map of object (http or session) to task
  1032. zm_MapObjectsToWinsockTasks[pObject] = ulTask;
  1033. // bump up ref count for task
  1034. void* pVoid;
  1035. ULONG32 TaskRefCount = 0;
  1036. if (zm_WinsockTasksRefCounts.Lookup(ulTask,pVoid))
  1037. {
  1038. TaskRefCount = (ULONG32)pVoid;
  1039. }
  1040. TaskRefCount++;
  1041. bWinSockInitedForTask = TRUE;
  1042. HX_ASSERT_VALID_PTR(sockObj);
  1043. zm_WinsockTasksRefCounts[ulTask] = (void*)TaskRefCount;
  1044.     }
  1045.     return bWinSockInitedForTask;
  1046. }
  1047. BOOL win_net::ReleaseWinsockUsage(void* pObject)
  1048. {
  1049.     // Only do any of this if we've first called IsWinsockAvailable()
  1050.     if (zm_LibRefCount > 0)
  1051.     {
  1052. // get previous task from map of object (http or session) to task
  1053. void* ulTask;
  1054. if (zm_MapObjectsToWinsockTasks.Lookup(pObject,ulTask))
  1055. {
  1056.     zm_MapObjectsToWinsockTasks.RemoveKey(pObject);
  1057.     // bump up ref count for task
  1058.     void* pVoid;
  1059.     ULONG32 TaskRefCount = 0;
  1060.     if (zm_WinsockTasksRefCounts.Lookup(ulTask,pVoid))
  1061.     {
  1062. TaskRefCount = (ULONG32)pVoid;
  1063.     }
  1064.     TaskRefCount--;
  1065.     // if 0 then call WSACleanup
  1066.     if (TaskRefCount == 0)
  1067.     {
  1068. zm_WinsockTasksRefCounts.RemoveKey(ulTask);
  1069.     }
  1070. }
  1071. // Decerement total ref count
  1072. zm_LibRefCount--;
  1073.     }
  1074.     return TRUE;
  1075. }
  1076. HX_RESULT win_net::read(void * buf, UINT16 *len) 
  1077. {
  1078.     int  got;
  1079.     static int breakpoint = 0;
  1080.     assert( buf );
  1081.     assert( len );
  1082. // This DEBUGOUTSTR is noisy.
  1083. #ifndef _DEMPSEY
  1084.     DEBUGOUTSTR( "win_net::read()rn" );
  1085. #endif // !_DEMPSEY
  1086.     if (get_sock() == INVALID_SOCKET || !callRaConnect) 
  1087.     {
  1088. // Not connected
  1089. return( mLastError = HXR_NET_SOCKET_INVALID );
  1090.     }
  1091.     // Is the TCP socket actually connected yet?
  1092.     /* We want to read data even if we have received CloseNotification. 
  1093.      * This is because some unread data may be still be in the pipe
  1094.      * - RA 10/01/1997
  1095.      */
  1096.     if (m_SocketState != CONN_OPEN && m_SocketState != CONN_CLOSED)
  1097.     {
  1098. // No
  1099. // We won't be able to write anything here, so clear this
  1100. // we'll return why we didn't write anything.
  1101. *len = 0;
  1102. switch( m_SocketState )
  1103. {
  1104. case CONN_DNS_INPROG:
  1105. case CONN_CONNECT_INPROG:
  1106. case CONN_CLOSING:
  1107. return( mLastError = HXR_WOULD_BLOCK );
  1108. case CONN_CLOSED:
  1109. return( mLastError = HXR_NET_SOCKET_INVALID );
  1110. case CONN_NO_CONN:
  1111. #ifndef WIN32_PLATFORM_PSPC
  1112. return( DoStartAsyncConn() );
  1113. #else
  1114.         HX_ASSERT(0 && "No Async net");
  1115.         return( HXR_NET_READ );
  1116. #endif
  1117. case CONN_DNS_FAILED:
  1118. return( mLastError = HXR_DNR );
  1119. case CONN_CONNECT_FAILED:
  1120. return( mLastError = HXR_NET_CONNECT );
  1121. default:
  1122. // HUH???
  1123. HX_ASSERT (FALSE);
  1124. return( mLastError = HXR_NET_READ );
  1125. };
  1126.     }
  1127.     else
  1128.     {
  1129. // Now we can actually do the read
  1130. if (callRaConnect)
  1131. {
  1132.     got = sockObj->HXrecv( get_sock(), (char *)buf, *len, 0 );
  1133. }
  1134. else
  1135. {
  1136.     int  fromlen;
  1137.     struct sockaddr  from;
  1138.     fromlen = sizeof( from );
  1139.     got = sockObj->HXrecvfrom( get_sock(), (char *)buf, *len, 0, &from, &fromlen );
  1140.     if (got > 0) breakpoint++;
  1141. }
  1142. // Did we get an error?
  1143. if (got == SOCKET_ERROR) 
  1144. {   
  1145.     *len = 0;
  1146.     if (m_SocketState == CONN_CLOSED)
  1147.     {
  1148. return( mLastError = HXR_NET_SOCKET_INVALID );
  1149.     }
  1150.     int code;
  1151.     code = sockObj->HXWSAGetLastError();
  1152.     // Translate the error
  1153.     switch (code)
  1154.     {
  1155.     case WSAEWOULDBLOCK:
  1156.     case WSAEINPROGRESS:
  1157.     return( mLastError = HXR_WOULD_BLOCK );
  1158.     case WSAEFAULT:
  1159.     case WSAENOTCONN:
  1160.     case WSAENOTSOCK:
  1161.     return( mLastError = HXR_NET_SOCKET_INVALID );
  1162.     case WSAENETDOWN:
  1163.     return( mLastError = HXR_GENERAL_NONET );
  1164.     case WSAEINTR:
  1165.     return( mLastError = HXR_BLOCK_CANCELED );
  1166.     case WSAEMSGSIZE:
  1167.     return( mLastError = HXR_MSG_TOOLARGE);
  1168.     case WSAETIMEDOUT:
  1169.     case WSAESHUTDOWN:
  1170.     case WSAECONNABORTED:
  1171.     return( mLastError = HXR_SERVER_DISCONNECTED );
  1172.     case WSAECONNRESET:
  1173. /*
  1174.  * WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out (Q263823)
  1175.  * workaround
  1176.  */
  1177. if (!m_bIgnoreWSAECONNRESET)
  1178. {
  1179.     return( mLastError = HXR_SERVER_DISCONNECTED );
  1180. }
  1181. else
  1182. {
  1183.     return( mLastError = HXR_WOULD_BLOCK );
  1184. }
  1185.     default:
  1186.     return( mLastError = HXR_NET_READ );   // Error we don't know what to do about
  1187.     }
  1188.     // Shouldn't really get here
  1189.     return( mLastError );
  1190. }
  1191. else if (got == 0 && *len != 0)
  1192. {
  1193.     *len = 0;
  1194.     if (m_SocketState == CONN_CLOSED)
  1195.     {
  1196. return( mLastError = HXR_NET_SOCKET_INVALID );
  1197.     }
  1198.     else
  1199.     {
  1200. return( mLastError = HXR_SERVER_DISCONNECTED );
  1201.     }
  1202. }
  1203. else
  1204. {
  1205.     // This should be our exit point for successful read
  1206.     *len = got;
  1207.     return( HXR_OK );
  1208. }
  1209.     }
  1210. }
  1211. HX_RESULT
  1212. win_net::readfrom (REF(IHXBuffer*) pBuffer,
  1213.    REF(UINT32)     ulAddress,
  1214.    REF(UINT16)     ulPort)
  1215. {
  1216.     int  got = 0;
  1217.     UINT16 size = 0;
  1218. #ifndef _DEMPSEY
  1219.     DEBUGOUTSTR( "win_net::readfrom()rn" );
  1220. #endif // !_DEMPSEY
  1221.     pBuffer = NULL;
  1222.     ulAddress = 0;
  1223.     ulPort = 0;
  1224.     if (get_sock() == INVALID_SOCKET || callRaConnect) 
  1225.     {
  1226. // Not connected
  1227. return( mLastError = HXR_NET_SOCKET_INVALID );
  1228.     }
  1229.     /* We want to read data even if we have received CloseNotification. 
  1230.      * This is because some unread data may be still be in the pipe
  1231.      * - RA 10/01/1997
  1232.      */
  1233.     if (m_SocketState != CONN_OPEN && m_SocketState != CONN_CLOSED)
  1234.     {
  1235. // No
  1236. // We won't be able to write anything here, so clear this
  1237. // we'll return why we didn't write anything.
  1238. switch( m_SocketState )
  1239. {
  1240. case CONN_DNS_INPROG:
  1241. case CONN_CONNECT_INPROG:
  1242. case CONN_CLOSING:
  1243. return( mLastError = HXR_WOULD_BLOCK );
  1244. case CONN_CLOSED:
  1245. return( mLastError = HXR_NET_SOCKET_INVALID );
  1246. case CONN_NO_CONN:
  1247. #ifndef WIN32_PLATFORM_PSPC
  1248. return( DoStartAsyncConn() );
  1249. #else
  1250.         HX_ASSERT(0 && "No Async net");
  1251.         return( HXR_NET_READ );
  1252. #endif
  1253. case CONN_DNS_FAILED:
  1254. return( mLastError = HXR_DNR );
  1255. case CONN_CONNECT_FAILED:
  1256. return( mLastError = HXR_NET_CONNECT );
  1257. default:
  1258. // HUH???
  1259. HX_ASSERT (FALSE);
  1260. return( mLastError = HXR_NET_READ );
  1261. };
  1262.     }
  1263.     else
  1264.     {
  1265. int  fromlen;
  1266. struct sockaddr_in  from;
  1267.     
  1268. fromlen = sizeof( from );
  1269. got = sockObj->HXrecvfrom( get_sock(), m_pInBuffer, TCP_BUF_SIZE, 0, (struct sockaddr*)&from, &fromlen );
  1270. // Did we get an error?
  1271. if (got == SOCKET_ERROR) 
  1272. {   
  1273.     if (m_SocketState == CONN_CLOSED)
  1274.     {
  1275. return( mLastError = HXR_NET_SOCKET_INVALID );
  1276.     }
  1277.     int code;
  1278.     code = sockObj->HXWSAGetLastError();
  1279.     // Translate the error
  1280.     switch (code)
  1281.     {
  1282.     case WSAEWOULDBLOCK:
  1283.     case WSAEINPROGRESS:
  1284.     return( mLastError = HXR_WOULD_BLOCK );
  1285.     case WSAEFAULT:
  1286.     case WSAENOTCONN:
  1287.     case WSAENOTSOCK:
  1288.     return( mLastError = HXR_NET_SOCKET_INVALID );
  1289.     case WSAENETDOWN:
  1290.     return( mLastError = HXR_GENERAL_NONET );
  1291.     case WSAEINTR:
  1292.     return( mLastError = HXR_BLOCK_CANCELED );
  1293.     case WSAEMSGSIZE:
  1294.     return( mLastError = HXR_MSG_TOOLARGE);
  1295.     case WSAETIMEDOUT:
  1296.     case WSAESHUTDOWN:
  1297.     case WSAECONNABORTED:
  1298.     return( mLastError = HXR_SERVER_DISCONNECTED );
  1299.     case WSAECONNRESET:
  1300. /*
  1301.  * WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out (Q263823)
  1302.  * workaround
  1303.  */
  1304. if (!m_bIgnoreWSAECONNRESET)
  1305. {
  1306.     return( mLastError = HXR_SERVER_DISCONNECTED );
  1307. }
  1308. else
  1309. {
  1310.     return( mLastError = HXR_WOULD_BLOCK );
  1311. }
  1312.     
  1313.     default:
  1314.     return( mLastError = HXR_NET_READ );   // Error we don't know what to do about
  1315.     }
  1316.     // Shouldn't really get here
  1317.     return( mLastError );
  1318. }
  1319. else if (got == 0)
  1320. {
  1321.     if (m_SocketState == CONN_CLOSED)
  1322.     {
  1323. return( mLastError = HXR_NET_SOCKET_INVALID );
  1324.     }
  1325.     else
  1326.     {
  1327. return( mLastError = HXR_SERVER_DISCONNECTED );
  1328.     }
  1329. }
  1330. else
  1331. {
  1332.     // This should be our exit point for successful read
  1333.     CHXTimeStampedBuffer* pTimeBuffer = new CHXTimeStampedBuffer;
  1334.     pTimeBuffer->AddRef();
  1335.     pTimeBuffer->SetTimeStamp(HX_GET_TICKCOUNT());
  1336.     pTimeBuffer->Set((UCHAR*)m_pInBuffer, got);
  1337.     pBuffer = (IHXBuffer*) pTimeBuffer;
  1338.     ulAddress = DwToHost(from.sin_addr.s_addr);
  1339.     ulPort = WToHost(from.sin_port);
  1340.     
  1341.     return( HXR_OK );
  1342. }
  1343.     }
  1344. }
  1345.     
  1346. ULONG32 win_net::get_addr()
  1347. {
  1348.     hostent *pHost = (hostent *)m_AsyncAddress;
  1349.     ULONG32 addr = 0;
  1350.     
  1351.     // if CurrentAddr is set, we must have passed
  1352.     // a dotted IP address...
  1353.     if (CurrentAddr)
  1354.     {
  1355. addr = CurrentAddr;
  1356.     }
  1357.     else if (pHost)
  1358.     {
  1359. addr = (ULONG32) (*(ULONG32*)pHost->h_addr);
  1360.     }
  1361.     return addr;
  1362. }
  1363. UINT16 win_net::get_local_port()
  1364. {
  1365.     sockaddr_in addr;
  1366.     int addr_len = sizeof addr;
  1367.     memset(&addr, 0, HX_SAFESIZE_T(addr_len));
  1368.     int ret = sockObj->HXgetsockname(get_sock(), (sockaddr*)&addr, &addr_len);
  1369.  
  1370.     return (ret < 0) ? -1: WToHost(addr.sin_port);
  1371. }
  1372. // we need it for dns_find_ip_addr since async stuff needs a window handle...
  1373. HX_RESULT win_net::SetWindowHandle(ULONG32 handle) 
  1374. {
  1375.     m_hInst = (HINSTANCE)handle; 
  1376.     return HXR_OK;
  1377. }
  1378. HX_RESULT win_net::dns_find_ip_addr(const char * host, UINT16 blocking)
  1379. {
  1380.     if(!host)                 
  1381.     {
  1382. mLastError = HXR_DNR;
  1383. return mLastError;
  1384.     }
  1385.     if(get_sock() < 0)                 
  1386.     {
  1387. mLastError = HXR_NET_SOCKET_INVALID;
  1388. return mLastError;
  1389.     }
  1390.     if (conn::is_cached((char *) host, &mHostIPAddr))
  1391.     {
  1392. mHostIPValid = TRUE;
  1393. mDNSDone = TRUE;
  1394. mLastError = HXR_OK;
  1395. if (mCallBack)  
  1396. {
  1397.     mCallBack->Func(DNS_NOTIFICATION, TRUE);
  1398. }
  1399. return mLastError;
  1400.     }
  1401.     char* pTemp = strrchr(host, '.');
  1402.     if (pTemp && atoi(pTemp + 1))
  1403.     {   /* IP address. */
  1404. struct in_addr addr;  
  1405. mHostIPValid = FALSE;
  1406. mHostIPAddr = 0;
  1407. mDNSDone = TRUE;
  1408. addr.s_addr = sockObj->HXinet_addr(host);
  1409. if ((UINT)addr.s_addr == (UINT)-1) 
  1410. {
  1411.     mLastError = HXR_DNR;
  1412.     return mLastError;
  1413. }
  1414. mHostIPValid = TRUE;
  1415. mHostIPAddr = *(ULONG32 *) &addr;
  1416. conn::add_to_cache((char *) host, mHostIPAddr);
  1417. if (mCallBack)  
  1418. {
  1419.     mCallBack->Func(DNS_NOTIFICATION, TRUE);
  1420. }
  1421. return HXR_OK;
  1422.     } 
  1423.     if (blocking)
  1424.     {
  1425. struct in_addr addr;  
  1426.             
  1427. mHostIPValid = FALSE;
  1428. mHostIPAddr = 0;
  1429. mDNSDone = TRUE;
  1430. struct hostent *h = sockObj->HXgethostbyname(host);
  1431. if (!h || !h->h_addr ) 
  1432. {
  1433.     mLastError = HXR_DNR;
  1434.     return mLastError;
  1435. }
  1436. memcpy(&addr, h->h_addr, sizeof(struct in_addr)); /* Flawfinder: ignore */
  1437. mHostIPValid = TRUE;
  1438. mHostIPAddr = *(ULONG32 *) &addr;
  1439. conn::add_to_cache((char *) host, mHostIPAddr);
  1440. if (mCallBack)  
  1441. {
  1442.     mCallBack->Func(DNS_NOTIFICATION, TRUE);
  1443. }
  1444. return( mLastError = HXR_OK);
  1445.     }
  1446.     else
  1447.     {
  1448. if (m_pAsyncHost != host)
  1449. {
  1450.     // Save the parameters, and tell ourselves we're starting up
  1451.     HX_VECTOR_DELETE(m_pAsyncHost);
  1452.     m_pAsyncHost = ::new_string(host);
  1453. }
  1454. if (!m_AsyncAddress)
  1455. {
  1456.     m_AsyncAddress = new char[MAXGETHOSTSTRUCT];
  1457. }
  1458. if (!m_AsyncAddress)
  1459. {
  1460.     return (mLastError = HXR_OUTOFMEMORY);
  1461. }
  1462. // set the boolean variable that we are only doing async DNs and
  1463. // do not intend to connect
  1464. #ifndef WIN32_PLATFORM_PSPC
  1465. m_DNSOnly   = TRUE;
  1466. m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst , TRUE);
  1467. m_AsyncNotifier->DoAsyncDNS( this, m_pAsyncHost, m_AsyncAddress, MAXGETHOSTSTRUCT );
  1468. m_SocketState = CONN_DNS_INPROG;
  1469. #else 
  1470. m_DNSOnly   = FALSE;
  1471. #endif
  1472. return( mLastError = HXR_WOULD_BLOCK );
  1473.     }
  1474. }
  1475. BOOL win_net::dns_ip_addr_found(BOOL * valid, ULONG32 *addr)
  1476. {
  1477.     if (mDNSDone)
  1478.     {
  1479. // reset DNS only flag...
  1480. m_DNSOnly   = FALSE;
  1481. *valid = mHostIPValid;
  1482. *addr  = mHostIPAddr;
  1483. return TRUE;
  1484.     }
  1485.     else
  1486. return FALSE;
  1487. }
  1488. BOOL win_net::set_receive_buf_size(int DesiredSize)
  1489. {
  1490.     int s = get_sock();
  1491.     if (s == INVALID_SOCKET) 
  1492.     {
  1493. mLastError = HXR_NET_SOCKET_INVALID;
  1494. return FALSE;
  1495.     }
  1496.     int RcvBufSize = 0;
  1497.     int iSize = sizeof(RcvBufSize);
  1498.     if (sockObj->HXgetsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&RcvBufSize, 
  1499.       &iSize))
  1500.     {
  1501. RcvBufSize = 0;
  1502.     }
  1503.     if (RcvBufSize < DesiredSize)
  1504.     {
  1505. RcvBufSize = DesiredSize;
  1506. if(sockObj->HXsetsockopt(s, SOL_SOCKET, SO_RCVBUF, 
  1507. (char *)&RcvBufSize, sizeof(RcvBufSize)))
  1508. {
  1509.     int code;
  1510.     code = sockObj->HXWSAGetLastError(); 
  1511.     return FALSE;
  1512. }
  1513.     }
  1514.     return TRUE;
  1515. }
  1516. /*
  1517. *   reuse_addr/reuse_port has to be called before a sock binds.  however, 
  1518. *   socket is not available until it binds as it is implemented.  So, set a 
  1519. *   flag here and do the actual setsockopt right before a sock binds.
  1520. *   Look in init_win().
  1521. */
  1522. HX_RESULT
  1523. win_net::reuse_addr(BOOL enable)
  1524. {
  1525.     m_bReuseAddr = enable;
  1526.     return HXR_OK;
  1527. }
  1528. HX_RESULT
  1529. win_net::reuse_port(BOOL enable)
  1530. {
  1531.     m_bReusePort = enable;
  1532.     return HXR_OK;
  1533. }
  1534. HX_RESULT
  1535. win_net::get_host_name(char* name, int namelen)
  1536. {
  1537.     HX_ASSERT(sockObj);
  1538.     
  1539.     if (sockObj->HXgethostname(name, namelen) != 0)
  1540.     {
  1541. return HXR_FAILED;
  1542.     }
  1543.     else
  1544.     {
  1545. return HXR_OK;
  1546.     }   
  1547. }
  1548. HX_RESULT
  1549. win_net::get_host_by_name(char* name, REF(struct hostent*) h)
  1550. {
  1551.     HX_ASSERT(sockObj);
  1552.     
  1553.     h = sockObj->HXgethostbyname(name);
  1554.     if (!h || !h->h_addr_list)
  1555.     {
  1556. return HXR_DNR;
  1557.     }
  1558.     else
  1559.     {
  1560. return HXR_OK;
  1561.     }
  1562. }
  1563. HX_RESULT win_UDP::set_broadcast(BOOL enable)
  1564. {
  1565. int ret;
  1566. SOCKET s = get_sock();
  1567. if(s == INVALID_SOCKET)
  1568. {
  1569. return( mLastError = HXR_NET_SOCKET_INVALID );
  1570. }
  1571. ret = sockObj->HXsetsockopt( s, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(UINT32) );
  1572. if(ret == -1)
  1573. ret = HXR_BIND;
  1574. return ret;
  1575. }
  1576. HX_RESULT 
  1577. win_UDP::set_send_size(UINT32 send_size)
  1578. {
  1579.     int s = get_sock();
  1580.     int ret = 0;
  1581. again:
  1582.     ret = sockObj->HXsetsockopt(s, SOL_SOCKET, SO_SNDBUF,
  1583.      (char*)&send_size, sizeof(INT32));
  1584.     if (ret < 0 && send_size > 8192)
  1585.     {
  1586. send_size >>= 1;
  1587.         goto again;
  1588.     }
  1589.     return ret;
  1590. }
  1591. HX_RESULT win_UDP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform ) 
  1592. {
  1593.     HX_RESULT ret;
  1594.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1595.     {                
  1596. if(ret == HXR_BLOCK_CANCELED)
  1597.     return ret;
  1598.   
  1599. mLastError = HXR_NET_CONNECT;
  1600. return mLastError;
  1601.     }
  1602.     return win_net::connect(host, port, blocking, ulPlatform );
  1603. }
  1604. HX_RESULT win_UDP::SetWindowHandle(ULONG32 handle)
  1605. {
  1606.     m_hInst = (HINSTANCE)handle;
  1607. #ifndef WIN32_PLATFORM_PSPC
  1608.     m_AsyncNotifier = CAsyncSockN::GetCAsyncSockNotifier( m_hInst ,TRUE);
  1609.     m_AsyncNotifier->DoAsyncSelect( this );
  1610. #endif
  1611.     return HXR_OK;
  1612. }
  1613. HX_RESULT win_UDP::connect(sockaddr_in * addr, UINT16 blocking) 
  1614. {                
  1615.     HX_RESULT ret;
  1616.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1617.     { 
  1618. if(ret == HXR_BLOCK_CANCELED)
  1619.     return ret;                                          
  1620.   
  1621. mLastError = HXR_NET_CONNECT;
  1622. return mLastError;
  1623.     }
  1624.     return win_net::connect(addr);
  1625. }                                  
  1626. HX_RESULT win_TCP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform ) 
  1627. {   
  1628.     HX_RESULT ret;
  1629.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1630.     {    
  1631. if(ret == HXR_BLOCK_CANCELED)
  1632.     return ret;                                          
  1633.       
  1634. mLastError = HXR_NET_CONNECT;
  1635. return mLastError;
  1636.     }
  1637.     return win_net::connect(host, port, blocking, ulPlatform );
  1638. }
  1639. HX_RESULT win_TCP::connect(sockaddr_in * addr, UINT16 blocking) 
  1640. {
  1641.     HX_RESULT ret;
  1642.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1643.     { 
  1644. if(ret == HXR_BLOCK_CANCELED)
  1645.     return ret;                                          
  1646.   
  1647. mLastError = HXR_NET_CONNECT;
  1648. return mLastError;
  1649.     }
  1650.     return win_net::connect(addr);
  1651. }
  1652. inline HX_RESULT win_UDP::listen(ULONG32 ulLocalAddr, UINT16 port, 
  1653.  UINT16 backlog, UINT16 blocking,
  1654.  ULONG32 ulPlatform)
  1655. {
  1656.     return HXR_INVALID_OPERATION;
  1657. }
  1658. inline HX_RESULT win_TCP::listen(ULONG32 ulLocalAddr, UINT16 port, 
  1659.  UINT16 backlog, UINT16 blocking,
  1660.  ULONG32 ulPlatform)
  1661. {
  1662.     HX_RESULT ret = HXR_NET_SOCKET_INVALID;
  1663.     if ( get_sock() < 0 )
  1664.     {
  1665. if ( ulLocalAddr == HX_INADDR_ANY )
  1666.     ret = init(INADDR_ANY, port, blocking);
  1667. else
  1668.     ret = init(ulLocalAddr, port, blocking);
  1669.     }
  1670.     if ( FAILED(ret) )
  1671.     {
  1672. if(ret == HXR_BLOCK_CANCELED)
  1673.     return ret;
  1674. mLastError = HXR_NET_SOCKET_INVALID;
  1675. return mLastError;
  1676.     }
  1677.     return win_net::listen(ulLocalAddr, port, backlog, blocking, ulPlatform);
  1678. }
  1679. HX_RESULT
  1680. win_UDP::set_multicast()
  1681. {
  1682. #ifdef NO_MULTICAST
  1683.     return HXR_MULTICAST_UDP;
  1684. #else
  1685.     INT32          ret;
  1686.     sockaddr_in addr;
  1687.     int addr_len = sizeof addr;
  1688.     if (get_sock() == INVALID_SOCKET) 
  1689.     {
  1690.         // Not connected
  1691.         return( mLastError = HXR_NET_SOCKET_INVALID );
  1692.     }
  1693.     memset(&addr, 0, HX_SAFESIZE_T(addr_len));
  1694.     ret = sockObj->HXgetsockname(get_sock(), (sockaddr*)&addr, &addr_len);
  1695.     if (ret < 0)
  1696.     {
  1697.         return HXR_MULTICAST_UDP;
  1698.     }
  1699.     ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_IF,
  1700.                        (char*) &addr.sin_addr.s_addr,
  1701.                        sizeof (addr.sin_addr.s_addr));
  1702.     if (ret < 0)
  1703.     {
  1704. return HXR_MULTICAST_UDP;
  1705.     }
  1706.     return HXR_OK;
  1707. #endif /* NO_MULTICAST */
  1708. }
  1709. HX_RESULT
  1710. win_UDP::set_multicast_ttl(unsigned char ttl)
  1711. {
  1712. #ifdef NO_MULTICAST
  1713.     return HXR_MULTICAST_UDP;
  1714. #else
  1715.     if (get_sock() == INVALID_SOCKET) 
  1716.     {
  1717.         // Not connected
  1718.         return( mLastError = HXR_NET_SOCKET_INVALID );
  1719.     }
  1720.     
  1721.     INT32         ret;
  1722.     INT32         ttl_proxy = ttl;
  1723.     ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
  1724.                        (char*) &ttl_proxy, sizeof (ttl_proxy));
  1725.     if (ret < 0)
  1726.     {
  1727.         return HXR_MULTICAST_UDP;
  1728.     }
  1729.     return HXR_OK;
  1730. #endif /* ! NO_MULTICAST */
  1731. }
  1732. HX_RESULT win_UDP::join_multicast_group(ULONG32 addr, ULONG32 if_addr)
  1733. {
  1734.     int ret;
  1735.     ip_mreq multicast_group;
  1736.     if (get_sock() == INVALID_SOCKET) 
  1737.     {
  1738. // Not connected
  1739. return( mLastError = HXR_NET_SOCKET_INVALID );
  1740.     }
  1741.     
  1742.     multicast_group.imr_multiaddr.s_addr = sockObj->HXhtonl(addr);
  1743.     multicast_group.imr_interface.s_addr = sockObj->HXhtonl(if_addr);
  1744.     
  1745.     ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multicast_group , sizeof (multicast_group) );
  1746.     if (ret == -1)
  1747.     {
  1748. int err;
  1749. err = sockObj->HXWSAGetLastError();
  1750. return HXR_MULTICAST_JOIN;
  1751.     }
  1752.     return HXR_OK;
  1753. }
  1754. HX_RESULT win_UDP::leave_multicast_group(ULONG32 addr, ULONG32 if_addr)
  1755. {
  1756.     int ret;
  1757.     ip_mreq multicast_group;
  1758.     if (get_sock() == INVALID_SOCKET) 
  1759.     {
  1760. // Not connected
  1761. return( mLastError = HXR_NET_SOCKET_INVALID );
  1762.     }
  1763.     multicast_group.imr_multiaddr.s_addr = sockObj->HXhtonl(addr);
  1764. // multicast_group.imr_multiaddr.s_addr = sockObj->HXinet_addr("226.0.0.8");
  1765.     multicast_group.imr_interface.s_addr = sockObj->HXhtonl(if_addr);
  1766.     
  1767.     ret = sockObj->HXsetsockopt(get_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&multicast_group , sizeof (multicast_group) );
  1768.     if (ret == -1)
  1769.     {
  1770. return HXR_GENERAL_MULTICAST;
  1771.     }
  1772.     return HXR_OK;
  1773. }
  1774. HX_RESULT 
  1775. win_UDP::set_multicast_if(ULONG32 ulInterface)
  1776. {
  1777.     int ret;
  1778.     int s = get_sock();
  1779.     if(s == INVALID_SOCKET)
  1780.     {
  1781. return( mLastError = HXR_NET_SOCKET_INVALID );
  1782.     }
  1783.     unsigned long addr = sockObj->HXhtonl(ulInterface);    
  1784.     ret = sockObj->HXsetsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, 
  1785. (char*)&addr, sizeof(addr));
  1786.     if(ret == -1)
  1787. ret = HXR_GENERAL_MULTICAST;
  1788.     return ret;
  1789. }
  1790. HX_RESULT
  1791. win_UDP::GetFromInfo(ULONG32& ulAddr, UINT16& nPort)
  1792. {
  1793.     return HXR_OK;
  1794. }
  1795. WinsockManager::WinsockManager()
  1796. {
  1797.     bInitialized = FALSE;
  1798.     Initialize();
  1799. }
  1800. WinsockManager::~WinsockManager()
  1801. {
  1802.     conn::close_drivers(NULL);
  1803.     bInitialized = FALSE;
  1804. }
  1805. void
  1806. WinsockManager::Initialize()
  1807. {
  1808.     bInitialized = FALSE;
  1809.     HX_ASSERT(!sockObj);
  1810.     if(!sockObj)
  1811. sockObj = new CHXSock;  
  1812.     if(conn::init_drivers(NULL) != HXR_OK)
  1813.     return;
  1814.     if(sockObj && sockObj->WinSockAvail() && sockObj->InitWinsock())
  1815.     {
  1816. bInitialized = TRUE;
  1817.     }
  1818.     UINT8 nWinSockVersion = sockObj->HXGetVersion();
  1819.     /*
  1820.      * Check to see what platform we are on
  1821.      */
  1822.     OSVERSIONINFO winver;
  1823.     winver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1824. #ifndef WIN32_PLATFORM_PSPC
  1825.     if(GetVersionEx(&winver))
  1826.     {
  1827. if(nWinSockVersion == 2 &&
  1828.    winver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  1829.    winver.dwMinorVersion == 0)
  1830. {
  1831.     /*
  1832.      * Async lookup in Win 95 with WinSock2.0 installed returns the same handle for
  1833.      * multiple requests. If there are multiple outstanding requests, there is
  1834.      * no way to map the handle in the response to the outstansing request since
  1835.      * all replies get mapped to one request. NT 4.0 returns different handles so
  1836.      * name resolution works fine.
  1837.      *
  1838.      * We workaround this by queueing up the DNS requests.
  1839.      */
  1840.     sockGlobals.m_bWinSock2Suck = TRUE;
  1841. }
  1842.     }
  1843. #endif
  1844. }
  1845. BOOL    
  1846. WinsockManager::IsInitialized()
  1847. {
  1848.     return bInitialized && sockObj;
  1849. }