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

Symbian

开发平台:

C/C++

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