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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: unix_net.cpp,v 1.6.2.4 2004/07/09 01:46:41 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. #if defined _LINUX && defined __GLIBC__ && 0
  50. #define _JAVA_GREENTHREADS
  51. #endif
  52. // Java with green threads needs you to use the internal entry points
  53. // for these system calls
  54. #ifdef _JAVA_GREENTHREADS
  55. #define READ ::__read
  56. #define CONNECT ::__connect
  57. #define RECVFROM ::__recvfrom
  58. #else
  59. #define READ ::read
  60. #define CONNECT ::connect
  61. #define RECVFROM ::recvfrom
  62. #endif
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include <unistd.h>
  67. #include <assert.h>
  68. #include "hxcom.h"
  69. #include "hxbuffer.h"
  70. #include "timebuff.h"
  71. #include "hxtick.h"
  72. #include "netbyte.h"
  73. #include "platform/unix/unix_net.h" // Our declaration
  74. #include "hxheap.h"
  75. #include "hxslist.h"
  76. #include "hxcom.h"
  77. #include "hxengin.h"
  78. #include "hxstrutl.h"
  79. #include <errno.h>
  80. #ifdef _IRIX
  81. #include <bstring.h> //  used in FD_ZERO
  82. #endif
  83. // #include "netplay.h" // why?
  84. #ifdef _AIX
  85. #include <sys/select.h>
  86. #endif
  87. #include <sys/types.h> //for waitpid
  88. #include <sys/wait.h>  //for waitpid
  89. #include <fcntl.h>
  90. #ifdef _UNIX_THREADS_SUPPORTED
  91. #include "hxthread.h"
  92. #endif  
  93. int unix_net::InBlockingMode = 0;
  94. // This thing doesn't get initialized if this is linked into a shared library
  95. CHXSimpleList* unix_net::readers = NULL;
  96. // So I've done a silly thing and labelled it so.
  97. static BOOL silly_unix_hack_initialized = FALSE;
  98. const int HOSTSTRUCTSIZE = sizeof( hostent ); 
  99. unix_net::unix_net() 
  100. {
  101. set_sock( INVALID_SOCKET );
  102. mLastError = HXR_OK;
  103. callRaConnect = 1;    
  104. bReadyToWrite = 0;
  105. m_SocketState = CONN_CLOSED;
  106. //Async DNS vars.
  107. CurrentAddr    = 0;
  108. m_DNSOnly      = FALSE;
  109. m_anDNSPipe[0] = nInvalidPipe;
  110. m_anDNSPipe[1] = nInvalidPipe;
  111. m_nChildProcID = 0;
  112. m_szPipeIP[0]  = '';
  113. read_pending = FALSE;
  114. m_lRefCount     = 0;
  115. // Don't allocate this yet. Not all unix_net instances are actually
  116. // used to read, and if one isn't, allocating here wastes memory.
  117. m_pInBuffer = NULL;
  118. m_bReuseAddr = FALSE;
  119. m_bReusePort = FALSE;
  120. m_pAsyncHost = NULL;
  121.         
  122. #ifdef _UNIX_THREADS_SUPPORTED
  123.         m_pResolver  = NULL;
  124. #endif        
  125. }
  126. unix_net::~unix_net() 
  127. {
  128.     m_SocketState = CONN_CLOSING;
  129.     if ((get_sock() != INVALID_SOCKET) )       
  130.     {
  131. ::close(get_sock());
  132. set_sock( INVALID_SOCKET );
  133.     }
  134.     m_SocketState = CONN_CLOSED;
  135.     mConnectionOpen = 0;
  136.     
  137.     LISTPOSITION listpos = readers->Find(this);
  138.     if(listpos)
  139.     {
  140. readers->RemoveAt(listpos);
  141.     }
  142.     HX_VECTOR_DELETE(m_pInBuffer); 
  143.     //If the DNS forked proccess is still running lets
  144.     //kill it here.
  145.     //Ignore any returned error, what would we do anyway?
  146.     CleanUpChildProc();
  147.     HX_VECTOR_DELETE(m_pAsyncHost);
  148. #ifdef _UNIX_THREADS_SUPPORTED
  149.     if( m_bThreadedDNS )
  150.     {
  151.         if(m_pResolver)
  152.             m_pResolver->Exit(0);
  153.         m_nResolved    = 0;
  154.         HX_DELETE( m_pResolver );
  155.     }
  156. #endif  
  157. }
  158. void unix_net::CleanUpChildProc()
  159. {
  160.     //Close any open pipes as well.
  161.     if( m_anDNSPipe[0] >= 0 )
  162.     {
  163. ::close( m_anDNSPipe[0] );
  164. m_anDNSPipe[0] = nInvalidPipe;
  165.     }
  166.     
  167.     if( m_anDNSPipe[1] >= 0 )
  168.     {
  169. ::close( m_anDNSPipe[1] );
  170. m_anDNSPipe[1] = nInvalidPipe;
  171.     }
  172.     
  173.     if( m_nChildProcID != 0 )
  174.     {
  175. kill( m_nChildProcID, SIGKILL );
  176. m_nChildProcID = 0;
  177.     }
  178. }
  179. unix_net * unix_net::new_socket(UINT16 type)
  180. {
  181.     unix_net *c = NULL;
  182.     
  183.     if(!silly_unix_hack_initialized)
  184.     {
  185. readers = new CHXSimpleList;
  186. silly_unix_hack_initialized = TRUE; 
  187.     }
  188.     
  189.     switch(type)
  190.     {
  191.     case HX_TCP_SOCKET:
  192. c = new unix_TCP;
  193. readers->AddTail(c);
  194. break;
  195.     case HX_UDP_SOCKET:
  196. c = new unix_UDP;
  197. readers->AddTail(c);
  198. break;
  199.     }
  200.     
  201.     return(c);
  202. }
  203. // init_drivers() should do any network driver initialization here
  204. // params is a pointer to a platform specfic defined struct that 
  205. // contains an required initialization data
  206. HX_RESULT unix_net::init_drivers(void *params)
  207. {
  208. return(HXR_OK);
  209. }
  210. /*  close_drivers() should close any network drivers used by the program
  211.   NOTE: The program MUST not make any other calls to the network drivers
  212.   until init_drivers() has been called */
  213. HX_RESULT unix_net::close_drivers(void *params)
  214. {
  215. return(HXR_OK);
  216. }
  217. HX_RESULT 
  218. unix_net::get_host_name(char *name, int namelen)
  219. {
  220.     if (::gethostname(name, namelen) == 0)
  221.     {
  222. return HXR_OK;
  223.     }
  224.     else
  225.     {
  226. return HXR_FAIL;
  227.     }
  228. }
  229. HX_RESULT 
  230. unix_net::get_host_by_name(char *name, REF(struct hostent*) pHostent)
  231. {
  232.     if (pHostent = ::gethostbyname(name))
  233.     {
  234.         return HXR_OK;
  235.     }
  236.     else
  237.     {
  238.         return HXR_FAIL;
  239.     }    
  240. }
  241. HX_RESULT unix_net::host_to_ip_str( char *host, char *ip, UINT32 ulIPBufLen)
  242. {
  243.     HX_RESULT           theErr = HXR_OK;
  244.     ULONG32             dwAddress;
  245.     struct sockaddr_in  rInAddress;
  246.     struct hostent*     pHostEntry;
  247.     // Let's look for this in the cache first
  248.     if (conn::is_cached( host, &dwAddress))
  249.     {
  250. //Found it, copy the 32bit address into rInAddress
  251. //w/o calling memcpy()
  252. rInAddress.sin_addr.s_addr  = dwAddress;
  253.     }
  254.     else
  255.     { 
  256. // Do DNS on the host name
  257. if (!(pHostEntry = gethostbyname( host )))
  258. {
  259.     // Error
  260.     theErr = HXR_DNR;
  261. }
  262. // Return w/o attempting any copies if there's an error
  263. if (theErr != HXR_OK)
  264. {
  265.     goto FuncExit;
  266. }
  267. // copy the ip address into rInAddress w/o calling memcpy()                    
  268.         struct in_addr** ppAddr = (struct in_addr**)(pHostEntry->h_addr_list);
  269.         memcpy(&rInAddress.sin_addr, ppAddr[0], sizeof(struct in_addr)); /* Flawfinder: ignore */
  270. // add to the dns cache
  271. conn::add_to_cache(host, (ULONG32) rInAddress.sin_addr.s_addr ); 
  272.     }
  273.     // Convert the ULONG32 IP address into a string and copy it into ip
  274.     SafeStrCpy( ip, inet_ntoa( rInAddress.sin_addr ) , ulIPBufLen);
  275.     // Single exit point
  276.  FuncExit:
  277.     return( theErr );
  278. }
  279. ULONG32 unix_net::AddRef()
  280. {
  281.     return InterlockedIncrement(&m_lRefCount);
  282. }
  283. ULONG32 unix_net::Release()
  284. {
  285.     if (InterlockedDecrement(&m_lRefCount) > 0)
  286.     {
  287.         return m_lRefCount;
  288.     }
  289.     delete this;
  290.     return 0;
  291. }
  292. /*
  293. *   reuse_addr/reuse_port has to be called before a sock binds.  however, 
  294. *   socket is not available until it binds as it is implemented.  So, set a 
  295. *   flag here and do the actual setsockopt right before a sock binds.
  296. *   Look in init_unix().
  297. */
  298. HX_RESULT
  299. unix_net::reuse_addr(BOOL enable)
  300. {
  301.     m_bReuseAddr = enable;
  302.     return HXR_OK;
  303. }
  304. HX_RESULT
  305. unix_net::reuse_port(BOOL enable)
  306. {
  307.     m_bReusePort = enable;
  308.     return HXR_OK;
  309. }
  310. HX_RESULT unix_net::init_unix(UINT16 type, UINT32 local_addr, UINT16 port, 
  311.                               UINT16 blocking)
  312. {                                        
  313.     int                s = INVALID_SOCKET;
  314.     struct sockaddr_in addr;
  315. #ifdef _BEOS
  316.     char    mode = 1;
  317. #else
  318.     int     mode = 1;
  319. #endif
  320.     
  321.     mLastError = HXR_OK;
  322. #ifdef _BEOS
  323.     s = socket(AF_INET, type, 0);
  324. #else
  325.     s = socket(PF_INET, type, 0);
  326. #endif
  327.     if (s < 0) 
  328.     {
  329. mLastError = HXR_NET_SOCKET_INVALID;
  330. return mLastError;
  331.     }
  332.     
  333.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&m_bReuseAddr, sizeof(m_bReuseAddr)) < 0) 
  334.     {
  335. mLastError = HXR_NET_SOCKET_INVALID;
  336. goto sock_err;
  337.     }
  338. #if defined SO_REUSEPORT
  339.     if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (const char*)&m_bReusePort, sizeof(m_bReusePort)) < 0) 
  340.     {
  341. mLastError = HXR_NET_SOCKET_INVALID;
  342. goto sock_err;
  343.     }
  344. #endif    
  345.         
  346.     memset(&addr, 0, sizeof addr);
  347.     addr.sin_family = AF_INET;
  348.     addr.sin_addr.s_addr = htonl(local_addr);
  349.     addr.sin_port = htons(port);
  350.     
  351.     if (::bind(s, (sockaddr*)&addr, sizeof addr) < 0) 
  352.     {
  353. mLastError = HXR_NET_SOCKET_INVALID;
  354. goto sock_err;
  355.     }
  356. #ifdef FIONBIO
  357.     if (!blocking && ioctl(s, FIONBIO, &mode) < 0) 
  358. #elif SO_NONBLOCK
  359.     if (!blocking && setsockopt(s,SOL_SOCKET,SO_NONBLOCK,&mode,1)<0)
  360. #else
  361.     if (!blocking && ::fcntl(get_sock(), F_SETFL, ::fcntl(get_sock(), F_GETFL, 0) | O_NONBLOCK) < 0)
  362. #endif
  363.     {
  364. mLastError = HXR_NET_SOCKET_INVALID;
  365. goto sock_err;
  366.     }
  367.     DPRINTF(D_MSG,("unix_net::socket opened: %dn", s));
  368.     m_SocketState = CONN_OPEN;
  369.     set_sock( s );
  370.     return mLastError;
  371.     
  372. sock_err:
  373.     ::close(s);
  374.     m_SocketState = CONN_NO_CONN;
  375.     return mLastError;
  376. }
  377. #if 0
  378. /* mcast_multiple_if test */
  379. /*
  380.  *  it returns a number of multicast enabled NICs with a default multicast
  381.  *  interface as the very first entry in the pIFList
  382.  */
  383. UINT32
  384. unix_net::detectMcastIF(REF(BYTE**) pIFList) 
  385. {
  386.     struct ifconf ifc;
  387.     int i;
  388.     ifc.ifc_len = sizeof(buff);
  389.     ifc.ifc_buf = buff;
  390. if (ioctl(skfd, SIOCGIFCONF, &ifc) >= 0) {
  391.     {
  392.         // XXXGo
  393.         //printf("%sn", pc);
  394. printf("%un", ul);
  395.     }
  396.     else
  397.     {   
  398.         printf("coudn't detect ifn");
  399.     }
  400.     //HX_VECTOR_DELETE(pc);
  401.  
  402. }
  403. #endif
  404. HX_RESULT unix_net::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform)
  405. {
  406.     DPRINTF(D_MSG,("unix_net::connect(): b: %dn", blocking));
  407.     
  408.     bReadyToWrite = 0;
  409.     
  410.     //Get a host at all?
  411.     if(!host)                 
  412.     {
  413. mLastError = HXR_DNR;
  414. return mLastError;
  415.     }
  416.     //Do we have a socket yet?
  417.     if(get_sock() < 0)                 
  418.     {
  419. mLastError = HXR_NET_SOCKET_INVALID;
  420. return mLastError;
  421.     }
  422.     
  423.     if( blocking )
  424.     {
  425. //Set our state.
  426. m_SocketState = CONN_DNS_INPROG;
  427. //check and see if we were passed a dot format IP address.
  428. memset(&m_sSockAddrIn, 0, sizeof(struct sockaddr_in));    
  429. char* pTemp = (char*)strrchr(host, '.');
  430. if (pTemp && atoi(pTemp + 1))
  431. {
  432.     m_sSockAddrIn.sin_addr.s_addr = inet_addr(host);
  433.     
  434.     if ((ULONG32)m_sSockAddrIn.sin_addr.s_addr == (ULONG32)-1) 
  435.     {
  436. mLastError = HXR_DNR;
  437. return mLastError;
  438.     }
  439.     //Set state to show we have the address ready to go.
  440.     m_SocketState = CONN_CONNECT_INPROG;
  441. //do a blocking gethostbyname() call.
  442. if( m_SocketState == CONN_DNS_INPROG )
  443.     struct hostent *h = gethostbyname(host);
  444.     if (!h || !h->h_addr ) 
  445.     {
  446. mLastError = HXR_DNR;
  447.                 DPRINTF(D_MSG,("unix_net::connect() HXR_INVALID_HOSTrn"));
  448. CB_ConnectionComplete(0);
  449. return HXR_DNR;
  450.     }
  451.             
  452.             struct in_addr** ppAddr = (struct in_addr**)(h->h_addr_list);
  453.             memcpy(&m_sSockAddrIn.sin_addr, ppAddr[0], sizeof(struct in_addr)); /* Flawfinder: ignore */
  454.     if (m_pAsyncHost != host)
  455.     {
  456. HX_VECTOR_DELETE(m_pAsyncHost);
  457. m_pAsyncHost = ::new_string(host);
  458.     }
  459.     m_AsyncPort = port; 
  460. }
  461. m_sSockAddrIn.sin_family = AF_INET;
  462. m_sSockAddrIn.sin_port = htons(port);
  463. // this stores info about current addr 
  464. CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
  465. if(CONNECT(get_sock(), (sockaddr*)&m_sSockAddrIn, sizeof(struct sockaddr_in)))
  466. {   
  467.     if(!blocking && (errno == EWOULDBLOCK || errno == EINPROGRESS))
  468.     {  
  469. mConnectionOpen = 1;
  470. nonblocking();
  471. CB_ConnectionComplete(1);
  472. return HXR_OK;
  473.     }
  474.             
  475.             DPRINTF(D_MSG,("unix_net::connect() HXR_NET_CONNECTrn"));
  476.             mLastError = HXR_NET_CONNECT;
  477.     CB_ConnectionComplete(0);
  478.     return HXR_NET_CONNECT;
  479. }       
  480.         
  481. mConnectionOpen = 1;
  482. nonblocking();
  483. m_SocketState = CONN_OPEN; // Rahul
  484. bReadyToWrite = 1;
  485. CB_ConnectionComplete(1);
  486. return HXR_OK;
  487.     }//blocking
  488.     return ConnectAsync( host, port );
  489. }
  490. #ifdef _UNIX_THREADS_SUPPORTED
  491. void *unix_net::_ResolveIt( void* pArg )
  492. {
  493.     unix_net* pIt = (unix_net*)pArg;
  494.     struct hostent *h = gethostbyname(pIt->m_pAsyncHost);
  495.     if( (NULL!=h) && (NULL!=h->h_addr) ) 
  496.     {
  497.         //Got good IP, send it back in dot format.
  498.         const u_char *src = (u_char*)h->h_addr_list[0];
  499.         static const char fmt[] = "%u.%u.%u.%u";
  500.         sprintf(pIt->m_szPipeIP, fmt, src[0], src[1], src[2], src[3]); /* Flawfinder: ignore */
  501.     }
  502.     pIt->m_nResolved = 1;
  503.     return NULL;
  504. }
  505. #endif
  506. HX_RESULT unix_net::DoStartAsyncConn()
  507. {
  508.     DPRINTF(D_MSG,("unix_net::DoStartAsyncConn()rn"));
  509.     m_SocketState = CONN_DNS_INPROG;
  510.     
  511. #ifdef _UNIX_THREADS_SUPPORTED
  512.     //Make the thread if we haven't already.
  513.     if( m_bThreadedDNS )
  514.     {
  515.         if( NULL == m_pResolver)
  516.         {
  517.             m_nResolved    = 0;
  518.             HXThread::MakeThread( m_pResolver );
  519.             HX_ASSERT( m_pResolver );
  520.         }
  521.         
  522.         //Set the state
  523.         m_nResolved = 0;
  524.         //Start the thread
  525.         m_pResolver->CreateThread( _ResolveIt, (void*)this );
  526.         //That is it!
  527.         return( mLastError = HXR_WOULD_BLOCK );
  528.     }
  529. #endif
  530.     //
  531.     // Fork here to start the DNS process. The process will
  532.     // be monitored by calls from proccess_idle to the method
  533.     // 'CheckOnDNS()'.
  534.     //
  535.     //Create pipe to communicate between the child and parent.
  536.     if ( 0 != pipe(m_anDNSPipe) )
  537.     {
  538. //Can't create pipe.
  539. m_anDNSPipe[0] = nInvalidPipe;
  540. m_anDNSPipe[1] = nInvalidPipe;
  541. mLastError = HXR_GENERAL_NONET;
  542. return mLastError;
  543.     }
  544.     if( 0 > (m_nChildProcID = fork()))
  545.     {
  546. //Error trying to fork.
  547. //What should we do?
  548. mLastError = HXR_GENERAL_NONET;
  549. m_SocketState = CONN_DNS_FAILED;
  550. CB_DNSComplete( 0 );
  551. return HXR_GENERAL_NONET;
  552.     }
  553.     
  554.     if( 0 == m_nChildProcID )
  555.     {
  556. //This is the child proc....
  557. //Close the read end of the pipe.
  558. if ( 0 != ::close( m_anDNSPipe[0]) )
  559. {
  560.     //close, error. Kill this child proc.
  561.     //This proc just exits. Return codes will come
  562.     //from the parent proc. Just write a NULL to 
  563.     //the pipe.
  564.     ::write( m_anDNSPipe[1], "", 1 );
  565.     exit(1);
  566. }
  567. m_anDNSPipe[0] = nInvalidPipe;
  568. //
  569. // Do the blocking DNS here
  570. //
  571. struct hostent *h = gethostbyname(m_pAsyncHost);
  572. if ( (NULL==h) || (NULL==h->h_addr) ) 
  573. {
  574.     //Bad host or other nasty.
  575.         //printf("Bad host or some other nastyn");
  576.     //Send back  for now.
  577.     ::write( m_anDNSPipe[1], "", 1 );
  578.     exit(1);
  579. }
  580. //Got good IP, send it back in dot format.
  581. const u_char *src = (u_char*)h->h_addr_list[0];
  582. char szTmp[20]; /* Flawfinder: ignore */ //Just big enough to hold "255.255.255.255"
  583. static const char fmt[] = "%u.%u.%u.%u";
  584. SafeSprintf(szTmp, 20, fmt, src[0], src[1], src[2], src[3]);
  585.         //printf("The Address is: %sn", szTmp);
  586.         ::write( m_anDNSPipe[1], szTmp, strlen(szTmp)+1 );
  587.         //Now close the pipe to ensure an EOF is written.
  588.         //Close the read end of the pipe.
  589. if ( 0 != ::close( m_anDNSPipe[1]) )
  590. {
  591.             //Unlikly, but if it does happend then we won't get
  592.             //an EOF written to the pipe and the AsyncDNS will
  593.             //never complete.
  594. #ifdef _DEBUG            
  595.             fprintf( stderr, "AsyncDNS can't close pipe. Disable AsyncDNS with NoAsyncDNS=1n");
  596.             fprintf( stderr, "If you have problems connecting.n");
  597. #endif            
  598. }
  599. _exit(0);
  600.     }//m_nChildProcID
  601.     //In parent....
  602.     //Close the write end of the pipe.
  603.     if ( 0 != ::close(m_anDNSPipe[1]) )
  604.     {
  605. //close error.
  606. m_anDNSPipe[0] = nInvalidPipe;
  607. m_anDNSPipe[1] = nInvalidPipe;
  608. mLastError = HXR_GENERAL_NONET;
  609. return mLastError;
  610.     }
  611.     m_anDNSPipe[1] = nInvalidPipe;
  612.     
  613.     //We are now ready to read off of anDNSPipe[0] the
  614.     //IP address of the host in dot format.
  615.     //Set the pipes to non blocking.
  616.     int flags;
  617.     if( (flags = fcntl( m_anDNSPipe[0], F_GETFL, 0)) < 0 )
  618.     {
  619. //Error, can't get the current flags for this pipe.
  620. mLastError = HXR_GENERAL_NONET;
  621. m_SocketState = CONN_DNS_FAILED;
  622. //Close the pipes and kill the child proc.
  623. CleanUpChildProc();
  624. //Report the disaster.
  625. CB_DNSComplete(0);
  626. return HXR_GENERAL_NONET;
  627.     }
  628.     flags |= O_NONBLOCK;
  629.     if( fcntl( m_anDNSPipe[0], F_SETFL, flags) < 0 )
  630.     {
  631. //Error, can't set the flags for this pipe.
  632. mLastError = HXR_GENERAL_NONET;
  633. m_SocketState = CONN_DNS_FAILED;
  634. //Close the pipes and kill the child proc.
  635. CleanUpChildProc();
  636. //Report the disaster.
  637. CB_DNSComplete(0);
  638. return HXR_GENERAL_NONET;
  639.     }
  640.     return( mLastError = HXR_WOULD_BLOCK );
  641. }
  642. HX_RESULT unix_net::CheckOnDNS()
  643. {
  644.     //Return this if nothing changes.
  645.     mLastError = HXR_WOULD_BLOCK;
  646. #ifdef _UNIX_THREADS_SUPPORTED
  647.     if( m_bThreadedDNS )
  648.     {
  649. AddRef();
  650.         //Is the thread done yet?
  651.         if( m_nResolved == 1 )
  652.         {
  653.             //Yeah, we are done. Wait on the thread.
  654.             m_pResolver->Exit(0);
  655.             //use it.
  656.             if( strlen(m_szPipeIP) == 0 )
  657.             {
  658.                 //badhost or DNS error. Close the pipe and go home.
  659.                 mLastError = HXR_DNR;
  660.                 CB_DNSComplete(0);
  661.             }
  662.             else
  663.             {
  664.                 //Assume at this point that m_szPipeIP has a good IP in it.
  665.                 m_sSockAddrIn.sin_addr.s_addr = inet_addr(m_szPipeIP);
  666.                 if((ULONG32)m_sSockAddrIn.sin_addr.s_addr == (ULONG32)-1) 
  667.                 {
  668.                     mLastError = HXR_DNR;
  669.                     CB_DNSComplete(0);
  670.                 }
  671.                 else
  672.                 {
  673.                     //Clear it for next time.
  674.                     m_szPipeIP[0]='';
  675.                     
  676.                     //Set our current address...
  677.                     CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
  678.                     
  679.                     CB_DNSComplete(1);
  680.                     mLastError = HXR_OK;
  681.                 }
  682.             }
  683.         }
  684. HX_RESULT res = mLastError;
  685. Release();
  686.         return res;
  687.     }
  688.     
  689. #endif
  690.     //Keep checking and see if the the DNS lookup is
  691.     //done or not.
  692.     char      szBuff[256]; /* Flawfinder: ignore */
  693.     int       status = 0;
  694.     //If its there grab it.
  695.     memset(szBuff, 0, 256);
  696.     status = ::read(m_anDNSPipe[0], szBuff, 255);
  697.     
  698.     if( status > 0 )
  699.     {
  700. strncat( m_szPipeIP, szBuff, status ); /* Flawfinder: ignore */
  701.     }
  702.     //Did we find EOF?
  703.     if( 0 == status )
  704.     {
  705. //At this point m_szPipeIP has a good IP address or
  706. //an error (NULL byte)
  707. //close the last pipe.
  708. ::close(m_anDNSPipe[0]); //Don't care about an error here.
  709. m_anDNSPipe[0] = nInvalidPipe;
  710. if( strlen(m_szPipeIP) == 0 )
  711. {
  712.     //badhost or DNS error. Close the pipe and go home.
  713.     mLastError = HXR_DNR;
  714.     CB_DNSComplete(0);
  715. }
  716. else
  717. {
  718.     //Assume at this point that m_szPipeIP has a good IP in it.
  719.     m_sSockAddrIn.sin_addr.s_addr = inet_addr(m_szPipeIP);
  720.     if((ULONG32)m_sSockAddrIn.sin_addr.s_addr == (ULONG32)-1) 
  721.     {
  722. mLastError = HXR_DNR;
  723. CB_DNSComplete(0);
  724.     }
  725.     else
  726.     {
  727. //Clear it for next time.
  728. m_szPipeIP[0]='';
  729. //grab the zombie child.
  730. ::waitpid( m_nChildProcID, NULL,  0 );
  731. m_nChildProcID = 0;
  732. //Set our current address...
  733. CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
  734. CB_DNSComplete(1);
  735. mLastError = HXR_OK;
  736.     }
  737. }
  738.     } else if( status<0 && EAGAIN!=errno )
  739.     {
  740. //Just make sure the read returned EAGAIN and not
  741. //some other error on the pipe.
  742. m_szPipeIP[0]='';
  743. //Kill the DNS child proc and close the pipe we're going home.
  744. CleanUpChildProc();
  745. //Report the problem.
  746. mLastError = HXR_GENERAL_NONET;
  747. CB_DNSComplete(0);
  748.     }
  749.     return mLastError;
  750. }
  751. HX_RESULT unix_net::CheckForConnection()
  752. {
  753.     sockaddr_in cliaddr;
  754.     HX_SOCKLEN_T addrlen = sizeof(sockaddr_in);
  755.     //memset(&cliaddr, 0, addrlen);
  756.     
  757.     //Return this if nothing changes.
  758.     mLastError = HXR_WOULD_BLOCK;
  759.     
  760.     int newSock = accept(&cliaddr, &addrlen);
  761.     if ( newSock == INVALID_SOCKET )
  762.     {
  763. // igno all errors...  r
  764.     return HXR_WOULD_BLOCK;
  765.     }
  766.     else
  767.     {
  768.         unix_net* pNewConn = (unix_net*)conn::actual_new_socket(HX_TCP_SOCKET);
  769.         pNewConn->AddRef();
  770.         conn::add_connection_to_list(pNewConn);
  771. if ( pNewConn )
  772. {
  773.     pNewConn->set_sock(newSock);
  774.     if ( SUCCEEDED(pNewConn->connect_accept(&cliaddr)) )
  775.     {
  776.      mLastError = HXR_OK;
  777.         CB_NewConnectionReady (TRUE, pNewConn);
  778.     }
  779.     else
  780.     {
  781.         CB_NewConnectionReady(FALSE, NULL);
  782.     }
  783. }
  784. else
  785. {
  786.     mLastError = HXR_OUTOFMEMORY;
  787. }
  788.     }
  789.     return mLastError;
  790. }
  791. // This method get's called by connect() in the case of an async request
  792. // It doesn't however actually start the connection.  It just registers
  793. // that we need to do the connection.  DoStartAsyncConn() will really do it.
  794. HX_RESULT unix_net::ConnectAsync( const char* host, UINT16 port )
  795. {
  796.     
  797.     //If we have our child(forked) process going on then
  798.     //make sure we kill it and start a new one. Also, close
  799.     //any open pipes.
  800.     CleanUpChildProc();
  801.     bReadyToWrite = 0;
  802.     if (!host)                 
  803.     {
  804. mLastError = HXR_DNR;
  805. return mLastError;
  806.     }
  807.     if (get_sock() == INVALID_SOCKET)
  808.     {
  809. mLastError = HXR_NET_SOCKET_INVALID;
  810. return mLastError;
  811.     }
  812.     char* pTemp = (char*)strrchr(host, '.');
  813.     if (pTemp && atoi(pTemp + 1))
  814.     {   /* IP address. */
  815. m_sSockAddrIn.sin_addr.s_addr = inet_addr(host);
  816. if ((UINT)m_sSockAddrIn.sin_addr.s_addr == (UINT)-1) 
  817. {
  818.     mLastError = HXR_DNR;
  819.     CB_DNSComplete(0);
  820.     return mLastError;
  821. }
  822. else
  823. {
  824.     // this stores info about current addr 
  825.     CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
  826.     m_AsyncPort = port;
  827.     if (m_pAsyncHost != host)
  828.     {
  829. HX_VECTOR_DELETE(m_pAsyncHost);
  830. m_pAsyncHost = ::new_string(host);
  831.     }
  832.     CB_DNSComplete(1);
  833. }
  834.     } 
  835.     else if (conn::is_cached((char *)host,(ULONG32 *) &m_sSockAddrIn.sin_addr.s_addr))
  836.     {
  837. // this stores info about current addr 
  838. CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
  839. m_AsyncPort = port;
  840. if (m_pAsyncHost != host)
  841. {
  842.     HX_VECTOR_DELETE(m_pAsyncHost);
  843.     m_pAsyncHost = ::new_string(host);
  844. }
  845. CB_DNSComplete(1);
  846.     }
  847.     else
  848.     {
  849. //We are going to do Async DNS.....
  850. m_AsyncPort = port;
  851. if (m_pAsyncHost != host)
  852. {
  853.     HX_VECTOR_DELETE(m_pAsyncHost);
  854.     m_pAsyncHost = ::new_string(host);
  855. }
  856. m_SocketState = CONN_NO_CONN;
  857. return(DoStartAsyncConn());
  858.     }
  859.     return( HXR_OK );
  860. }
  861.  
  862. // Once async DNS has commpleted then we'll call this guy to do the
  863. // connection (again asynchronously).
  864. void unix_net::ContinueAsyncConnect()
  865. {
  866.     DPRINTF(D_MSG,("unix_net::ContinueAsyncConnect() socket: %drn", get_sock()));
  867.     int nResult=0;
  868.     nResult = CONNECT( get_sock(),
  869.        (sockaddr*)&m_sSockAddrIn,
  870.        sizeof(m_sSockAddrIn) );
  871.     if( nResult != 0 && errno != EISCONN )
  872.     {   
  873. if( errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY )
  874. {
  875.     m_SocketState = CONN_CONNECT_INPROG;
  876. }
  877. else
  878. {
  879.     mLastError = HXR_NET_CONNECT;
  880.     m_SocketState = CONN_CONNECT_FAILED;
  881.     nonblocking();
  882.             DPRINTF(D_MSG,("unix_net::ContinueAsyncConnect() CONN_CONNECT_FAILED nResult: %d errno: %d(%s)rn", nResult, errno, strerror(errno)));
  883.     CB_ConnectionComplete(0);
  884. }
  885.     }
  886.     else
  887.     {
  888. mConnectionOpen = 1;
  889. CB_ConnectionComplete(1);
  890.     }
  891.     return;
  892. }
  893. // Called by the notifier to tell us that the DNS request completed
  894. void unix_net::CB_DNSComplete( int iSuccess )
  895. {
  896.     ULONG32 ulNotUsed;
  897.     
  898.     mDNSDone = TRUE;
  899.     //Put it into the cache if its good and not there.
  900.     if( iSuccess && 
  901. m_pAsyncHost &&
  902. 0 == conn::is_cached(m_pAsyncHost, &ulNotUsed)
  903. )
  904.     {
  905. conn::add_to_cache(m_pAsyncHost, m_sSockAddrIn.sin_addr.s_addr);
  906.     }
  907.     if( TRUE == m_DNSOnly )
  908.     {
  909. //This is an DNSOnly object. Don't do the connect.
  910. if (iSuccess)
  911. {
  912.     mHostIPValid = TRUE;
  913.     mHostIPAddr = get_addr();   
  914. }
  915. else
  916. {
  917.     mHostIPValid = FALSE;
  918. }
  919.     }
  920.     else 
  921.     {
  922. if(iSuccess)
  923. {
  924.     m_SocketState = CONN_CONNECT_INPROG;
  925. }
  926. else
  927. {
  928.     m_SocketState = CONN_DNS_FAILED;
  929. }
  930.     }//TRUE==m_DNSOnly
  931.     //
  932.     // Handle any DNS notification callbacks.
  933.     //
  934.     if (mCallBack)
  935.     {
  936. mCallBack->Func(DNS_NOTIFICATION, iSuccess);
  937.     }
  938.     if( FALSE==m_DNSOnly && iSuccess )
  939.     {
  940. m_sSockAddrIn.sin_family = AF_INET;
  941. m_sSockAddrIn.sin_port = htons( m_AsyncPort );
  942. ContinueAsyncConnect();
  943.     }
  944.     return;
  945. }
  946. void unix_net::CB_NewConnectionReady(int iSuccess, unix_net* pConn)
  947. {
  948.     if ( mCallBack )
  949.     {
  950.         mCallBack->Func(ACCEPT_NOTIFICATION, iSuccess?TRUE:FALSE, (conn*)pConn);
  951.     }
  952. }
  953. // Called by the notifier to tell us that the Connection completed
  954. void unix_net::CB_ConnectionComplete( int iSuccess )
  955. {
  956.     DPRINTF(D_MSG,("CB_ConnectionComplete(%d)rn", iSuccess) );
  957.     if (iSuccess)
  958.     {
  959. m_SocketState = CONN_OPEN;
  960.     }
  961.     else
  962.     {
  963. m_SocketState = CONN_CONNECT_FAILED;
  964.     }
  965.     
  966.     if (mCallBack)
  967.     {
  968. mCallBack->Func(CONNECT_NOTIFICATION, iSuccess?TRUE:FALSE);
  969.     }
  970. }
  971. // Called by the notifier when data ready for read/write
  972. void unix_net::CB_ReadWriteNotification( int iType )
  973. {
  974.     DPRINTF(D_MSG,("CB_ReadWriteNotification()....rn") );
  975.     // Should do something here....
  976.     if (mCallBack && (m_SocketState == CONN_OPEN))
  977.     {
  978. #if 0
  979. if (iType == FD_WRITE)
  980. {
  981.     mCallBack->Func(WRITE_NOTIFICATION);
  982. }
  983. else if (iType == FD_READ)
  984. {
  985.     mCallBack->Func(READ_NOTIFICATION);
  986. }
  987. #endif // 0
  988. mCallBack->Func(READ_NOTIFICATION);
  989. //mCallBack->callback_task( HX_UDP_CALLBACK, NULL );
  990.     }
  991. }
  992. void unix_net::CB_CloseNotification()
  993. {
  994.     DPRINTF(D_MSG,("CB_CloseNotification()....rn") );
  995.     m_SocketState = CONN_CLOSED;
  996. }
  997. HX_RESULT unix_net::connect( sockaddr_in *addr )
  998. {
  999.     //XXXgfw Is this method used?????
  1000.     //XXXgfw If this is used, should there be a non-blocking
  1001.     //XXXgfw version of this? If so, we need to pass in a flag
  1002.     //XXXgfw or something. Eitherway, I can't see where this is
  1003.     //XXXgfw used at all. Only blocking for now I guess.
  1004.     
  1005.     if(CONNECT( get_sock(), (sockaddr*)addr, sizeof( addr ) ))
  1006.     {
  1007. mLastError = HXR_NET_CONNECT;
  1008. return mLastError;
  1009.     }                   
  1010.     
  1011.     mConnectionOpen = 1;
  1012.     return HXR_OK;     
  1013. }
  1014. HX_RESULT unix_net::write(void * buf, UINT16  *len) 
  1015. {
  1016. int got;
  1017. DPRINTF(D_MSG, ("unix_net::write() s: %d l: %dn",get_sock(),*len));
  1018. if (get_sock() == INVALID_SOCKET) 
  1019. {
  1020. // Not connected
  1021. return( mLastError = HXR_NET_SOCKET_INVALID );
  1022. }
  1023. if (m_SocketState != CONN_OPEN ) //&& m_SocketState != CONN_DNS_INPROG)
  1024. {
  1025. // We won't be able to write anything here, so clear this
  1026. // we'll return why we didn't write anything.
  1027. *len = 0;
  1028. switch( m_SocketState )
  1029. {
  1030. case CONN_DNS_INPROG:
  1031. case CONN_CONNECT_INPROG:
  1032. case CONN_CLOSING:
  1033. return( mLastError = HXR_WOULD_BLOCK );
  1034. case CONN_CLOSED:
  1035. return( mLastError = HXR_NET_SOCKET_INVALID );
  1036. case CONN_NO_CONN:
  1037. return( mLastError = HXR_NET_CONNECT );
  1038. // return( DoStartAsyncConn() );
  1039. case CONN_DNS_FAILED:
  1040. return( mLastError = HXR_DNR );
  1041. case CONN_CONNECT_FAILED:
  1042. return( mLastError = HXR_NET_CONNECT );
  1043. default:
  1044. // HUH???
  1045. assert( 0 );
  1046. return( mLastError = HXR_NET_READ );
  1047. };
  1048. }
  1049. else
  1050. {
  1051. #if defined(_BEOS)
  1052. got = ::send( get_sock(), (void *)buf, *len, 0 );
  1053. #else
  1054. got = ::write( get_sock(), (char *)buf, *len );
  1055. #endif
  1056. if (got == -1)
  1057. {
  1058. *len = 0;
  1059. // Mask the "so what?" errors
  1060. if (errno == EWOULDBLOCK || errno == EINPROGRESS) 
  1061. {
  1062.    return HXR_WOULD_BLOCK;
  1063. }
  1064. else
  1065. {
  1066.    mLastError = HXR_NET_WRITE;
  1067.    return mLastError;
  1068. }
  1069. }
  1070. *len = got;
  1071. return HXR_OK;
  1072. }
  1073. }
  1074. HX_RESULT unix_net::WriteComplete   (char * Buffer, int length)
  1075. {
  1076. int sent = 0;
  1077. unsigned short cur_sent=0;
  1078. while(sent < length)
  1079. {
  1080.   cur_sent = length - sent;
  1081.   HX_RESULT ret = write(Buffer + sent, &cur_sent);
  1082.   if(ret != HXR_OK && ret != HXR_WOULD_BLOCK)
  1083. break;
  1084.   sent += cur_sent;
  1085. }
  1086. // m_SocketState = CONN_NO_CONN;
  1087. if(sent < length)
  1088. {
  1089.   mLastError = HXR_NET_WRITE;
  1090.   return mLastError;
  1091. }
  1092. return HXR_OK;
  1093. }
  1094. int unix_net::ReadyToWrite()
  1095. {
  1096. if(get_sock() < 0)
  1097. {
  1098. bReadyToWrite = 0;
  1099. return bReadyToWrite;
  1100. }
  1101. if(bReadyToWrite)
  1102.     return 1;
  1103. fd_set writefds;
  1104. FD_ZERO(&writefds);
  1105. FD_SET(get_sock(), &writefds);
  1106. struct timeval timeout;
  1107. timeout.tv_sec = 1;
  1108. timeout.tv_usec = 0;
  1109. #ifdef _HPUX
  1110. // mwebb added HP-specifix lines (for the curious, do "man select")
  1111. // also changed timeout call to be a non-blocking "poll"
  1112. timeout.tv_sec = 0;
  1113. timeout.tv_usec = 0;
  1114. #endif
  1115. if(select(0, NULL, &writefds,NULL, &timeout) == 1)
  1116.     bReadyToWrite = 1;
  1117. return bReadyToWrite;        
  1118. }
  1119. void unix_net::done (void)
  1120. {
  1121.     m_SocketState = CONN_CLOSING;
  1122.     if ((get_sock() != INVALID_SOCKET))
  1123.     {
  1124.         ::close(get_sock());
  1125.     }
  1126.     set_sock( INVALID_SOCKET );
  1127.     m_SocketState = CONN_CLOSED;
  1128.     mConnectionOpen = 0;
  1129.     
  1130.     LISTPOSITION listpos = readers->Find(this);
  1131.     if(listpos)
  1132.     {
  1133. readers->RemoveAt(listpos);
  1134.     }
  1135. }
  1136. inline HX_RESULT unix_net::listen (UINT16  backlog)
  1137. {
  1138.     if ( ::listen(get_sock(), backlog) != -1 )
  1139.     {
  1140.         m_SocketState = CONN_LISTENNING;
  1141. mConnectionOpen = 0;
  1142. return HXR_OK;
  1143.     }
  1144.     else
  1145.     {
  1146. m_SocketState = CONN_NO_CONN;
  1147. mLastError = HXR_NET_CONNECT;
  1148. return mLastError;
  1149.     }
  1150. }
  1151. /*
  1152. inline HX_RESULT unix_net::blocking (void)
  1153. {
  1154.     unsigned long nonblocking = 0;
  1155.     return ::ioctl(get_sock(), FIONBIO, (char*)&nonblocking); 
  1156. }
  1157. inline HX_RESULT unix_net::nonblocking (void) 
  1158. {
  1159.     unsigned long nonblocking = 1;
  1160.     return ::ioctl(get_sock(), FIONBIO, (char*)&nonblocking); 
  1161. }
  1162. */
  1163. inline HX_RESULT unix_net::connect_accept(sockaddr_in *addr)
  1164. {
  1165.     CurrentAddr = addr->sin_addr.s_addr;
  1166.     memcpy(&m_sSockAddrIn, addr, sizeof(sockaddr_in)); /* Flawfinder: ignore */
  1167.     mConnectionOpen = 1;
  1168.     m_SocketState = CONN_OPEN;
  1169.     mLastError = HXR_OK;
  1170.     nonblocking();
  1171.     return HXR_OK;
  1172. }
  1173. /*  
  1174. inline HX_RESULT unix_net::accept (sockaddr_in *addr, UINT16 *addrlen)
  1175. {
  1176.     return ::accept(get_sock(), (sockaddr*)addr, (int *)addrlen);
  1177. }
  1178. inline HX_RESULT unix_net::bind (sockaddr_in *addr)
  1179. {
  1180.     return ::bind(get_sock(), (sockaddr*)addr, sizeof(addr));
  1181. }
  1182. */
  1183. HX_RESULT unix_net::read(void * buf, UINT16 *len) 
  1184. {
  1185. int  got;
  1186. static int breakpoint = 0;
  1187. assert( (PTR_INT)buf );
  1188. assert( (PTR_INT)len );
  1189. if (get_sock() == INVALID_SOCKET || !callRaConnect) 
  1190. {
  1191. // Not connected
  1192. return( mLastError = HXR_NET_SOCKET_INVALID );
  1193. }
  1194. // Is the TCP socket actually connected yet?
  1195. if (m_SocketState != CONN_OPEN)
  1196. {
  1197. // No
  1198. // We won't be able to write anything here, so clear this
  1199. // we'll return why we didn't write anything.
  1200. *len = 0;
  1201. switch( m_SocketState )
  1202. {
  1203. case CONN_DNS_INPROG:
  1204. case CONN_CONNECT_INPROG:
  1205. case CONN_CLOSING:
  1206. return( mLastError = HXR_WOULD_BLOCK );
  1207. case CONN_CLOSED:
  1208. return( mLastError = HXR_NET_SOCKET_INVALID );
  1209. case CONN_NO_CONN:
  1210. return( mLastError = HXR_NET_CONNECT );
  1211. // return( DoStartAsyncConn() );
  1212. case CONN_DNS_FAILED:
  1213. return( mLastError = HXR_DNR );
  1214. case CONN_CONNECT_FAILED:
  1215. return( mLastError = HXR_NET_CONNECT );
  1216. default:
  1217. // HUH???
  1218. assert( 0 );
  1219. return( mLastError = HXR_NET_READ );
  1220. };
  1221. }
  1222. else
  1223. {
  1224. // Now we can actually do the read
  1225. #ifdef _BEOS
  1226.         got = ::recv( get_sock(), (char *)buf, *len, 0 ); 
  1227. #else
  1228. got = READ( get_sock(), (char *)buf, *len );
  1229. #endif
  1230. // Did we get an error?
  1231. if (got < 0 ) 
  1232. {   
  1233. *len = 0;
  1234. // Translate the error
  1235. switch (errno)
  1236. {
  1237. case EWOULDBLOCK:
  1238.     add_read_request();
  1239.     return( mLastError = HXR_WOULD_BLOCK );
  1240. case ECONNRESET:
  1241. return( mLastError = HXR_SERVER_DISCONNECTED );
  1242. default:
  1243. return( mLastError = HXR_NET_READ );   // Error we don't know what to do about
  1244. }
  1245. }
  1246. else if (got == 0) 
  1247. {
  1248. return (mLastError = HXR_SERVER_DISCONNECTED);
  1249. }
  1250. else
  1251. {
  1252. // This should be our exit point for successful read
  1253. DPRINTF(D_MSG, ("unix_net::read() s: %d l: %dn",get_sock(),*len));
  1254. *len = got;
  1255. return( HXR_OK );
  1256. }
  1257. }
  1258. }
  1259. HX_RESULT unix_net::readfrom (REF(IHXBuffer*) pBuffer,
  1260.       REF(UINT32)       ulAddress,
  1261.       REF(UINT16)       ulPort)
  1262. {
  1263.     int  got = 0;
  1264.     UINT16 size = 0;
  1265.     pBuffer = NULL;
  1266.     ulAddress = 0;
  1267.     ulPort = 0;
  1268.     // Allocate m_pInBuffer now, since we know we need it.
  1269.     if( m_pInBuffer == NULL )
  1270.     {
  1271. m_pInBuffer = new char[TCP_BUF_SIZE];
  1272.     }
  1273.     if (get_sock() == INVALID_SOCKET || callRaConnect)
  1274.     {
  1275. // Not connected
  1276. return( mLastError = HXR_NET_SOCKET_INVALID );
  1277.     }
  1278.     // Is the TCP socket actually connected yet?
  1279.     if (m_SocketState != CONN_OPEN)
  1280.     {
  1281. // No
  1282. // We won't be able to write anything here, so clear this
  1283. // we'll return why we didn't write anything.
  1284. switch( m_SocketState )
  1285. {
  1286. case CONN_DNS_INPROG:
  1287. case CONN_CONNECT_INPROG:
  1288. case CONN_CLOSING:
  1289. return( mLastError = HXR_WOULD_BLOCK );
  1290. case CONN_CLOSED:
  1291. return( mLastError = HXR_NET_SOCKET_INVALID );
  1292. case CONN_NO_CONN:
  1293. return( mLastError = HXR_NET_CONNECT );
  1294. // return( DoStartAsyncConn() );
  1295. case CONN_DNS_FAILED:
  1296. return( mLastError = HXR_DNR );
  1297. case CONN_CONNECT_FAILED:
  1298. return( mLastError = HXR_NET_CONNECT );
  1299. default:
  1300. // HUH???
  1301. assert( 0 );
  1302. return( mLastError = HXR_NET_READ );
  1303. }
  1304.     }
  1305.     else
  1306.     {
  1307. #if defined _AIX42
  1308. //SCO's Unixware compiler will choke and die otherwise:
  1309.    size_t     fromlen = 0;
  1310. #elif defined _HPUX
  1311. int fromlen = 0;
  1312. #else
  1313. socklen_t   fromlen = 0;
  1314. #endif
  1315. struct sockaddr_in from;
  1316. fromlen = sizeof(from);
  1317. // Now we can actually do the read
  1318. got = RECVFROM( get_sock(), m_pInBuffer, TCP_BUF_SIZE, 0, (struct sockaddr*)&from, (HX_SOCKLEN_T *)&fromlen);
  1319. // Did we get an error?
  1320. if (got <= 0 ) 
  1321. {   
  1322.     // Translate the error
  1323.     switch (errno)
  1324.     {
  1325.     case EWOULDBLOCK:
  1326. add_read_request();
  1327. return( mLastError = HXR_WOULD_BLOCK );
  1328.     case ECONNRESET:
  1329.     return( mLastError = HXR_SERVER_DISCONNECTED );
  1330.     default:
  1331.     return( mLastError = HXR_NET_READ );   // Error we don't know what to do about
  1332.     }
  1333. }
  1334.         // This should be our exit point for successful read
  1335.         CHXTimeStampedBuffer* pTimeBuffer = new CHXTimeStampedBuffer;
  1336.         pTimeBuffer->AddRef();
  1337.         pTimeBuffer->SetTimeStamp(HX_GET_TICKCOUNT());
  1338.         pTimeBuffer->Set((UCHAR*)m_pInBuffer, got);
  1339.         pBuffer = (IHXBuffer*) pTimeBuffer;
  1340.         ulAddress = DwToHost(from.sin_addr.s_addr);
  1341.         ulPort = WToHost(from.sin_port);
  1342.     
  1343.         return( HXR_OK );
  1344.     }
  1345. }
  1346. HX_RESULT unix_UDP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform ) 
  1347. {
  1348.     blocking = GetAsyncDNSPref() ? 1 : blocking;
  1349.     HX_RESULT ret = HXR_OK;
  1350.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1351.     {                
  1352. if(ret == HXR_BLOCK_CANCELED)
  1353.     return ret;
  1354.       
  1355. mLastError = HXR_NET_CONNECT;
  1356. return mLastError;
  1357.     }
  1358.     ret = unix_net::connect(host, port, blocking, ulPlatform );
  1359.     if ( !ret )
  1360. nonblocking();
  1361.     return ret;
  1362. }
  1363. HX_RESULT unix_UDP::connect(sockaddr_in * addr, UINT16 blocking) 
  1364. {
  1365.     blocking = GetAsyncDNSPref() ? 1 : blocking;
  1366.     HX_RESULT ret = HXR_OK;
  1367.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1368.     { 
  1369. if(ret == HXR_BLOCK_CANCELED)
  1370.     return ret;                                          
  1371.       
  1372. mLastError = HXR_NET_CONNECT;
  1373. return mLastError;
  1374.     }
  1375.     return unix_net::connect(addr);
  1376. }                                  
  1377. HX_RESULT unix_TCP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform ) 
  1378. {
  1379.     blocking = GetAsyncDNSPref() ? 1 : blocking;
  1380.     HX_RESULT ret = HXR_OK;
  1381.     
  1382.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1383.     {    
  1384. if(ret == HXR_BLOCK_CANCELED)
  1385.     return ret;                                          
  1386.         
  1387. mLastError = HXR_NET_CONNECT;
  1388. return mLastError;
  1389.     }
  1390.     ret = unix_net::connect(host, port, blocking, ulPlatform );
  1391. #if 0
  1392.     if ( !ret )
  1393. nonblocking();
  1394. #endif
  1395.     return  ret;
  1396. }
  1397. HX_RESULT unix_TCP::connect(sockaddr_in * addr, UINT16 blocking) 
  1398. {
  1399.     blocking = GetAsyncDNSPref() ? 1 : blocking;
  1400.     HX_RESULT ret = HXR_OK;
  1401.     if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
  1402.     { 
  1403. if(ret == HXR_BLOCK_CANCELED)
  1404.     return ret;                                          
  1405.       
  1406. mLastError = HXR_NET_CONNECT;
  1407. return mLastError;
  1408.     }
  1409.     return unix_net::connect(addr);
  1410. }
  1411. HX_RESULT unix_TCP::listen(ULONG32 ulLocalAddr, UINT16 port,
  1412.    UINT16 backlog, UINT16 blocking, 
  1413.    ULONG32 ulPlatform) 
  1414. {
  1415.     // We will ignor the blockng parameter, and block for this
  1416.     // function but leave the socket in a non blocking state...
  1417.     HX_RESULT ret = HXR_OK;
  1418.     if ( get_sock() < 0 )
  1419.     {
  1420. if ( ulLocalAddr == HX_INADDR_ANY )
  1421.     ret = init(INADDR_ANY, port, 1);
  1422. else
  1423.     ret = init(ulLocalAddr, port, 1);
  1424.     }
  1425.     if ( FAILED(ret) )
  1426.     {
  1427. if(ret == HXR_BLOCK_CANCELED)
  1428.     return ret;
  1429. mLastError = HXR_NET_CONNECT;
  1430. return mLastError;
  1431.     }
  1432.     if ( unix_net::listen(backlog) != HXR_OK)
  1433.     {
  1434.         ret = HXR_NET_CONNECT;
  1435.     }
  1436.     if ( SUCCEEDED(ret) )
  1437.     {
  1438.         ret = unix_net::nonblocking();
  1439.     }
  1440.     return ret;
  1441. }
  1442. HX_RESULT
  1443. unix_UDP::set_multicast()
  1444. {
  1445. #ifdef NO_MULTICAST
  1446.     return HXR_MULTICAST_UDP;
  1447. #endif /* NO_MULTICAST */
  1448.     INT32          ret;
  1449.     sockaddr_in  addr;
  1450. #if defined _AIX42
  1451.     size_t addr_len = sizeof addr;
  1452. #elif defined _HPUX || defined _OSF1
  1453.     int addr_len = sizeof addr;
  1454. #else
  1455.     socklen_t addr_len = sizeof addr;
  1456. #endif
  1457.     if (get_sock() == INVALID_SOCKET) 
  1458.     {
  1459.         // Not connected
  1460.         mLastError = HXR_NET_SOCKET_INVALID;
  1461.         return mLastError;
  1462.     }
  1463.     memset(&addr, 0, HX_SAFESIZE_T(addr_len));
  1464.     ret = getsockname(get_sock(), (sockaddr*)&addr, &addr_len);
  1465.     if (ret < 0)
  1466.     {
  1467.         return HXR_MULTICAST_UDP;
  1468.     }
  1469. /*
  1470.  * Linux and Solairs seem to return 127.0.0.1 from getsockname() which they
  1471.  * don't accept as a valid interface in setsockopt(IP_MULTICAST_IF)
  1472.  */
  1473. #if defined _LINUX || defined _SOLARIS
  1474.     addr.sin_addr.s_addr = INADDR_ANY;
  1475. #endif /* _LINUX || _SOLARIS */
  1476. #ifdef _BEOS
  1477.     // FIXME no multicast for BeOS
  1478.     return HXR_MULTICAST_UDP;
  1479. #else
  1480.     ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_IF,
  1481.                        (char*) &addr.sin_addr.s_addr,
  1482.                        sizeof (addr.sin_addr.s_addr));
  1483.     if (ret < 0)
  1484.     {
  1485.         return HXR_MULTICAST_UDP;
  1486.     }
  1487.     return HXR_OK;
  1488. #endif /* _BEOS */
  1489. }
  1490. HX_RESULT
  1491. unix_UDP::set_multicast_ttl(unsigned char ttl)
  1492. {
  1493. #ifdef NO_MULTICAST
  1494.     return HXR_MULTICAST_UDP;
  1495. #endif /* NO_MULTICAST */
  1496.     INT32         ret;
  1497.     unsigned char       ttl_proxy;
  1498.     ttl_proxy = ttl;
  1499. #ifdef _BEOS
  1500.     // FIXME no multicast for BeOS
  1501.     return HXR_MULTICAST_UDP;
  1502. #else
  1503.     if (get_sock() == INVALID_SOCKET) 
  1504.     {
  1505.         // Not connected
  1506.         return( mLastError = HXR_NET_SOCKET_INVALID );
  1507.     }
  1508.     
  1509.     ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
  1510.                        (char*) &ttl_proxy, sizeof (ttl_proxy));
  1511.     if (ret < 0)
  1512.     {
  1513.         return HXR_MULTICAST_UDP;
  1514.     }
  1515.     return HXR_OK;
  1516. #endif /* _BEOS */
  1517. }
  1518. HX_RESULT unix_UDP::join_multicast_group(ULONG32 addr, ULONG32 if_addr)
  1519. {   
  1520. #if defined(_BEOS) 
  1521.     return HXR_NOTIMPL; 
  1522. #else
  1523.     
  1524.     int ret;
  1525.     ip_mreq multicast_group;
  1526.     if (get_sock() == INVALID_SOCKET) 
  1527.     {
  1528.         // Not connected
  1529.         return( mLastError = HXR_NET_SOCKET_INVALID );
  1530.     }
  1531.     u_char ttl = 254; // As Per Sujal.
  1532.     ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 
  1533.                                                         sizeof(ttl));
  1534.     if (ret == -1)
  1535.     {
  1536.         return HXR_MULTICAST_JOIN;
  1537.     }
  1538.     multicast_group.imr_multiaddr.s_addr = htonl(addr);
  1539. #ifdef _UNIX    
  1540.     multicast_group.imr_interface.s_addr = htonl(INADDR_ANY);
  1541. #elif    
  1542.     multicast_group.imr_interface.s_addr = htonl(if_addr);
  1543. #endif    
  1544.     ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, 
  1545.                (char*) &multicast_group, 
  1546.                sizeof (multicast_group));
  1547.     if (ret < 0)
  1548.     {
  1549.         return HXR_MULTICAST_JOIN;
  1550.     }
  1551.     return HXR_OK;
  1552. #endif
  1553. }
  1554. HX_RESULT unix_UDP::leave_multicast_group(ULONG32 addr, ULONG32 if_addr)
  1555. {
  1556. #if defined(_BEOS) 
  1557.     return HXR_NOTIMPL; 
  1558. #else
  1559.     
  1560.     int ret;
  1561.     ip_mreq     multicast_group;
  1562.     if (get_sock() == INVALID_SOCKET) 
  1563.     {
  1564.         // Not connected
  1565.         return( mLastError = HXR_NET_SOCKET_INVALID );
  1566.     }
  1567.     multicast_group.imr_multiaddr.s_addr = htonl(addr);
  1568.     multicast_group.imr_interface.s_addr = htonl(if_addr);
  1569.     ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP,
  1570.                 (char*) &multicast_group, sizeof (multicast_group));
  1571.     if (ret == -1)
  1572.     {
  1573.         return HXR_GENERAL_MULTICAST;
  1574.     }
  1575.     return HXR_OK;
  1576. #endif
  1577. }
  1578. HX_RESULT 
  1579. unix_UDP::set_multicast_if(ULONG32 ulInterface)
  1580. {
  1581.     int ret;
  1582.     int s = get_sock();
  1583.     if(s == INVALID_SOCKET)
  1584.     {
  1585. return( mLastError = HXR_NET_SOCKET_INVALID );
  1586.     }
  1587.     unsigned long addr = htonl(ulInterface);
  1588.     ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, 
  1589. (char*)&addr, sizeof(addr));
  1590.     if(ret == -1)
  1591. ret = HXR_GENERAL_MULTICAST;
  1592.     return ret;
  1593. }
  1594. HX_RESULT 
  1595. unix_UDP::set_broadcast(BOOL enable)
  1596. {
  1597. int ret;
  1598. int s = get_sock();
  1599. if(s == INVALID_SOCKET)
  1600. {
  1601. return( mLastError = HXR_NET_SOCKET_INVALID );
  1602. }
  1603. ret = setsockopt( s, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(UINT32) );
  1604. if(ret == -1)
  1605. ret = HXR_BIND;
  1606. return ret;
  1607. }
  1608. HX_RESULT 
  1609. unix_UDP::set_send_size(UINT32 send_size)
  1610. {
  1611. #ifdef _BEOS
  1612.     // Be is messed up
  1613.     return -1;
  1614. #else
  1615.     int s = get_sock();
  1616.     int ret = 0;
  1617. again:
  1618.     ret = setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  1619.      (char*)&send_size, sizeof(INT32));
  1620.     if (ret < 0 && send_size > 8192)
  1621.     {
  1622. send_size >>= 1;
  1623.         goto again;
  1624.     }
  1625.     return ret;
  1626. #endif
  1627. }
  1628. HX_RESULT unix_net::writeto( void * buf, 
  1629. UINT16  *len, 
  1630. ULONG32 addr, 
  1631. UINT16 port)
  1632. {
  1633.     int got;
  1634. sockaddr_in resend_addr;
  1635.     
  1636. ::memset( &resend_addr, 0, sizeof( resend_addr ) );
  1637. resend_addr.sin_family = AF_INET;
  1638. resend_addr.sin_addr.s_addr = addr;
  1639. resend_addr.sin_port = htons(port);
  1640. got = sendto(get_sock(), (char *) buf, *len, 0, (sockaddr *)&resend_addr, sizeof (resend_addr)); 
  1641. if (got == -1)
  1642. {
  1643.   /* int code;
  1644. *len = 0;
  1645. code = sockObj->HXWSAGetLastError();
  1646. // Mask the "so what?" errors
  1647. if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS) 
  1648. {
  1649. return HXR_WOULD_BLOCK;
  1650. }
  1651. else
  1652. {
  1653. mLastError = HXR_NET_WRITE;
  1654. return mLastError;
  1655. }
  1656.        */
  1657. }
  1658. *len = got;
  1659. return HXR_OK;
  1660. }
  1661. ULONG32 unix_net::get_addr()
  1662. {
  1663.     return m_sSockAddrIn.sin_addr.s_addr;
  1664. }
  1665. UINT16 unix_net::get_local_port()
  1666. {
  1667.     sockaddr_in addr;
  1668. #if defined _AIX42
  1669.     size_t addr_len = sizeof addr;
  1670. #elif defined _HPUX || defined _OSF1
  1671.     int addr_len = sizeof addr;
  1672. #else
  1673.     socklen_t addr_len = sizeof addr;
  1674. #endif
  1675.     memset(&addr, 0, HX_SAFESIZE_T(addr_len));
  1676.     int ret = getsockname(get_sock(), (sockaddr*)&addr, &addr_len);
  1677.  
  1678.     return (ret < 0) ? -1 : WToHost(addr.sin_port);
  1679. }
  1680. HX_RESULT unix_net::dns_find_ip_addr(const char * host, UINT16 blocking)
  1681. {
  1682.     mHostIPValid = FALSE;
  1683.     mDNSDone  = TRUE;
  1684.     blocking = GetAsyncDNSPref() ? 1 : blocking;
  1685.     if(!host)                 
  1686.     {
  1687. mLastError = HXR_DNR;
  1688. return mLastError;
  1689.     }
  1690.     if(get_sock() < 0)                 
  1691.     {
  1692. mLastError = HXR_NET_SOCKET_INVALID;
  1693. return mLastError;
  1694.     }
  1695.     if (conn::is_cached((char *) host, &mHostIPAddr))
  1696.     {
  1697. mHostIPValid  = TRUE;
  1698. mLastError = HXR_OK;
  1699. if (mCallBack) 
  1700. {       
  1701.     mCallBack->Func(DNS_NOTIFICATION, TRUE);
  1702. }
  1703. return HXR_OK;
  1704.     }
  1705.     //Check for a dot format IP string.
  1706.     char* pTemp = (char*)strrchr(host, '.');
  1707.     if (pTemp && isdigit(*(pTemp + 1)))
  1708.     {   /* IP address. */
  1709. mHostIPValid = FALSE;
  1710. mHostIPAddr  = 0;
  1711. mDNSDone     = TRUE;
  1712. m_sSockAddrIn.sin_addr.s_addr = inet_addr(host);
  1713. if ((UINT)m_sSockAddrIn.sin_addr.s_addr == (UINT)-1) 
  1714. {
  1715.     mLastError = HXR_DNR;
  1716.     return mLastError;
  1717. }
  1718. mHostIPValid = TRUE;
  1719. mHostIPAddr = m_sSockAddrIn.sin_addr.s_addr;
  1720. conn::add_to_cache((char *)host, mHostIPAddr);
  1721. if (mCallBack)  
  1722. {
  1723.     mCallBack->Func(DNS_NOTIFICATION, TRUE);
  1724. }
  1725. return HXR_OK;
  1726.     } 
  1727.     if( blocking )
  1728.     { 
  1729. hostent *pHost = gethostbyname((char *) host);
  1730.         
  1731. mHostIPValid = FALSE;
  1732. mHostIPAddr  = 0;
  1733. mDNSDone     = TRUE;
  1734. if( !pHost || !pHost->h_addr )
  1735. {
  1736.     mLastError = HXR_DNR;
  1737.     return mLastError;
  1738. }
  1739. mHostIPValid = TRUE;
  1740.         
  1741.         struct in_addr** ppAddr = (struct in_addr**)(pHost->h_addr_list);
  1742. mHostIPAddr = ppAddr[0]->s_addr;
  1743.         conn::add_to_cache((char *) host, mHostIPAddr); 
  1744. if (mCallBack) 
  1745. {       
  1746.     mCallBack->Func(DNS_NOTIFICATION, TRUE);
  1747. }
  1748. return HXR_OK;
  1749.     }
  1750.     else
  1751.     {
  1752. //Non blocking code here.
  1753. if (m_pAsyncHost != host)
  1754. {
  1755.     HX_VECTOR_DELETE(m_pAsyncHost);
  1756.     m_pAsyncHost = ::new_string(host);
  1757. }
  1758. //Tell everyone we just want DNS and no connect.
  1759. m_DNSOnly = TRUE;
  1760. //Start up the non-blocking DNS.
  1761. DoStartAsyncConn();
  1762.     }//blocking
  1763.     mLastError = HXR_OK;
  1764.     return mLastError;
  1765. }
  1766. BOOL unix_net::dns_ip_addr_found(BOOL* valid, ULONG32* addr)
  1767. {
  1768.     if (mDNSDone)
  1769.     {
  1770. *valid = mHostIPValid;
  1771. *addr  = mHostIPAddr;
  1772. return TRUE;
  1773.     }
  1774.     else
  1775. return FALSE;
  1776. }
  1777. void unix_net::add_read_request()
  1778. {
  1779.     read_pending = TRUE;
  1780. }
  1781. void 
  1782. unix_net::add_select(int *n, 
  1783.      fd_set* readfds, 
  1784.      fd_set* writefds, 
  1785.      fd_set* exceptfds)
  1786. {
  1787.     unix_net* un;
  1788.     int sock;
  1789.     if(!silly_unix_hack_initialized)
  1790.     {
  1791. readers = new CHXSimpleList;
  1792. silly_unix_hack_initialized = TRUE; 
  1793.     }
  1794.     if(!unix_net::readers->IsEmpty())
  1795.     {
  1796. CHXSimpleList::Iterator i;
  1797. for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); ++i)
  1798. {
  1799.     un = (unix_net*)(*i);
  1800.     
  1801.     sock = un->get_sock();
  1802.     if(un->read_pending && sock >= 0)
  1803.     {
  1804. if(sock > *n)
  1805.     *n = sock + 1;
  1806. FD_SET(sock, readfds);
  1807.     }
  1808. }
  1809.     }
  1810. }
  1811. void 
  1812. unix_net::process_select(int n, 
  1813.  fd_set* readfds, 
  1814.  fd_set* writefds, 
  1815.  fd_set* exceptfds)
  1816. {
  1817.     unix_net* un;
  1818.     int sock;
  1819.     if(!unix_net::readers->IsEmpty())
  1820.     {
  1821. CHXSimpleList::Iterator i, next;
  1822. for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); i = next)
  1823. {
  1824.     next = i;
  1825.     ++next;
  1826.     un = (unix_net*)(*i);
  1827.     
  1828.     sock = un->get_sock();
  1829.     if(sock >= 0)
  1830.     {
  1831. if(FD_ISSET(sock, readfds))
  1832. {
  1833.     un->read_pending = FALSE;
  1834.     un->CB_ReadWriteNotification(0);
  1835. }
  1836.     }
  1837. }
  1838.     }
  1839. }
  1840. void unix_net::process_idle()
  1841. {
  1842.     unix_net* un;
  1843.     fd_set read_fds;
  1844.     struct timeval tv;
  1845.     int maxfd = 0;
  1846.     int sock = INVALID_SOCKET;
  1847.     if(!silly_unix_hack_initialized)
  1848.     {
  1849. readers = new CHXSimpleList;
  1850. silly_unix_hack_initialized = TRUE; 
  1851.     }
  1852.     FD_ZERO(&read_fds);
  1853.     if(!unix_net::readers->IsEmpty())
  1854.     {
  1855. CHXSimpleList::Iterator i;
  1856. for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); ++i)
  1857. {
  1858.     un = (unix_net*)(*i);
  1859.     //Hold on to this reference.
  1860.     un->AddRef();
  1861.     //Check the progress of each unix_net object's async DNS
  1862.     //and connect.
  1863.     if( un->GetSocketState() == CONN_DNS_INPROG )
  1864. un->CheckOnDNS();
  1865.     else if( un->GetSocketState() == CONN_CONNECT_INPROG )
  1866. un->ContinueAsyncConnect();
  1867.     else if ( un->GetSocketState() == CONN_LISTENNING )
  1868.         un->CheckForConnection();
  1869.     
  1870.     sock = un->get_sock();
  1871.     if(un->read_pending && sock >= 0)
  1872.     {
  1873. if(sock > maxfd)
  1874.     maxfd = sock;
  1875. FD_SET(sock, &read_fds);
  1876.     }
  1877.     //Release this reference.
  1878.     if( 0 == un->Release() )
  1879.     {
  1880. //This object just got deleted. Make sure we adjust
  1881. //the iterator back to a valid one because deleting
  1882. //the object an iterator points to invalidates the 
  1883. //iterator.
  1884. //Make sure we don't iterate past the end with the
  1885. //upcoming i++ in the for loop above.
  1886. if( unix_net::readers->IsEmpty() )
  1887. {
  1888.     break;
  1889. }
  1890. //XXXgfw Can we do better then just setting it all
  1891. //XXXgfw the way back to the begining?
  1892. i = unix_net::readers->Begin();
  1893.     }
  1894. }
  1895.     }
  1896.     tv.tv_sec = 0;
  1897.     tv.tv_usec = 0;
  1898.     
  1899.     if(select(maxfd + 1, &read_fds, 0, 0, &tv) > 0)
  1900.     {
  1901. if(!unix_net::readers->IsEmpty())
  1902. {
  1903.     CHXSimpleList::Iterator i, next;
  1904.     for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); i = next)
  1905.     {
  1906. next = i;
  1907. ++next;
  1908. un = (unix_net*)(*i);
  1909. sock = un->get_sock();
  1910. if(un->read_pending && sock >= 0)
  1911. {
  1912.     if(FD_ISSET(sock, &read_fds))
  1913.     {
  1914. un->read_pending = FALSE;
  1915. un->CB_ReadWriteNotification(0);
  1916.     }
  1917. }
  1918.     }
  1919. }
  1920.     }
  1921. }