Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
unix_net.cpp
Package: helix.src.0812.rar [view]
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 50k
Category:
Symbian
Development Platform:
C/C++
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #if defined _LINUX && defined __GLIBC__ && 0
- #define _JAVA_GREENTHREADS
- #endif
- // Java with green threads needs you to use the internal entry points
- // for these system calls
- #ifdef _JAVA_GREENTHREADS
- #define READ ::__read
- #define CONNECT ::__connect
- #define RECVFROM ::__recvfrom
- #else
- #define READ ::read
- #define CONNECT ::connect
- #define RECVFROM ::recvfrom
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <assert.h>
- #include "hxcom.h"
- #include "hxbuffer.h"
- #include "timebuff.h"
- #include "hxtick.h"
- #include "netbyte.h"
- #include "platform/unix/unix_net.h" // Our declaration
- #include "hxheap.h"
- #include "hxslist.h"
- #include "hxcom.h"
- #include "hxengin.h"
- #include "hxstrutl.h"
- #include <errno.h>
- #ifdef _IRIX
- #include <bstring.h> // used in FD_ZERO
- #endif
- // #include "netplay.h" // why?
- #ifdef _AIX
- #include <sys/select.h>
- #endif
- #include <sys/types.h> //for waitpid
- #include <sys/wait.h> //for waitpid
- #include <fcntl.h>
- #ifdef _UNIX_THREADS_SUPPORTED
- #include "hxthread.h"
- #endif
- int unix_net::InBlockingMode = 0;
- // This thing doesn't get initialized if this is linked into a shared library
- CHXSimpleList* unix_net::readers = NULL;
- // So I've done a silly thing and labelled it so.
- static BOOL silly_unix_hack_initialized = FALSE;
- const int HOSTSTRUCTSIZE = sizeof( hostent );
- unix_net::unix_net()
- {
- set_sock( INVALID_SOCKET );
- mLastError = HXR_OK;
- callRaConnect = 1;
- bReadyToWrite = 0;
- m_SocketState = CONN_CLOSED;
- //Async DNS vars.
- CurrentAddr = 0;
- m_DNSOnly = FALSE;
- m_anDNSPipe[0] = nInvalidPipe;
- m_anDNSPipe[1] = nInvalidPipe;
- m_nChildProcID = 0;
- m_szPipeIP[0] = '';
- read_pending = FALSE;
- m_lRefCount = 0;
- // Don't allocate this yet. Not all unix_net instances are actually
- // used to read, and if one isn't, allocating here wastes memory.
- m_pInBuffer = NULL;
- m_bReuseAddr = FALSE;
- m_bReusePort = FALSE;
- m_pAsyncHost = NULL;
- #ifdef _UNIX_THREADS_SUPPORTED
- m_pResolver = NULL;
- #endif
- }
- unix_net::~unix_net()
- {
- m_SocketState = CONN_CLOSING;
- if ((get_sock() != INVALID_SOCKET) )
- {
- ::close(get_sock());
- set_sock( INVALID_SOCKET );
- }
- m_SocketState = CONN_CLOSED;
- mConnectionOpen = 0;
- LISTPOSITION listpos = readers->Find(this);
- if(listpos)
- {
- readers->RemoveAt(listpos);
- }
- HX_VECTOR_DELETE(m_pInBuffer);
- //If the DNS forked proccess is still running lets
- //kill it here.
- //Ignore any returned error, what would we do anyway?
- CleanUpChildProc();
- HX_VECTOR_DELETE(m_pAsyncHost);
- #ifdef _UNIX_THREADS_SUPPORTED
- if( m_bThreadedDNS )
- {
- if(m_pResolver)
- m_pResolver->Exit(0);
- m_nResolved = 0;
- HX_DELETE( m_pResolver );
- }
- #endif
- }
- void unix_net::CleanUpChildProc()
- {
- //Close any open pipes as well.
- if( m_anDNSPipe[0] >= 0 )
- {
- ::close( m_anDNSPipe[0] );
- m_anDNSPipe[0] = nInvalidPipe;
- }
- if( m_anDNSPipe[1] >= 0 )
- {
- ::close( m_anDNSPipe[1] );
- m_anDNSPipe[1] = nInvalidPipe;
- }
- if( m_nChildProcID != 0 )
- {
- kill( m_nChildProcID, SIGKILL );
- m_nChildProcID = 0;
- }
- }
- unix_net * unix_net::new_socket(UINT16 type)
- {
- unix_net *c = NULL;
- if(!silly_unix_hack_initialized)
- {
- readers = new CHXSimpleList;
- silly_unix_hack_initialized = TRUE;
- }
- switch(type)
- {
- case HX_TCP_SOCKET:
- c = new unix_TCP;
- readers->AddTail(c);
- break;
- case HX_UDP_SOCKET:
- c = new unix_UDP;
- readers->AddTail(c);
- break;
- }
- return(c);
- }
- // init_drivers() should do any network driver initialization here
- // params is a pointer to a platform specfic defined struct that
- // contains an required initialization data
- HX_RESULT unix_net::init_drivers(void *params)
- {
- return(HXR_OK);
- }
- /* close_drivers() should close any network drivers used by the program
- NOTE: The program MUST not make any other calls to the network drivers
- until init_drivers() has been called */
- HX_RESULT unix_net::close_drivers(void *params)
- {
- return(HXR_OK);
- }
- HX_RESULT
- unix_net::get_host_name(char *name, int namelen)
- {
- if (::gethostname(name, namelen) == 0)
- {
- return HXR_OK;
- }
- else
- {
- return HXR_FAIL;
- }
- }
- HX_RESULT
- unix_net::get_host_by_name(char *name, REF(struct hostent*) pHostent)
- {
- if (pHostent = ::gethostbyname(name))
- {
- return HXR_OK;
- }
- else
- {
- return HXR_FAIL;
- }
- }
- HX_RESULT unix_net::host_to_ip_str( char *host, char *ip, UINT32 ulIPBufLen)
- {
- HX_RESULT theErr = HXR_OK;
- ULONG32 dwAddress;
- struct sockaddr_in rInAddress;
- struct hostent* pHostEntry;
- // Let's look for this in the cache first
- if (conn::is_cached( host, &dwAddress))
- {
- //Found it, copy the 32bit address into rInAddress
- //w/o calling memcpy()
- rInAddress.sin_addr.s_addr = dwAddress;
- }
- else
- {
- // Do DNS on the host name
- if (!(pHostEntry = gethostbyname( host )))
- {
- // Error
- theErr = HXR_DNR;
- }
- // Return w/o attempting any copies if there's an error
- if (theErr != HXR_OK)
- {
- goto FuncExit;
- }
- // copy the ip address into rInAddress w/o calling memcpy()
- struct in_addr** ppAddr = (struct in_addr**)(pHostEntry->h_addr_list);
- memcpy(&rInAddress.sin_addr, ppAddr[0], sizeof(struct in_addr)); /* Flawfinder: ignore */
- // add to the dns cache
- conn::add_to_cache(host, (ULONG32) rInAddress.sin_addr.s_addr );
- }
- // Convert the ULONG32 IP address into a string and copy it into ip
- SafeStrCpy( ip, inet_ntoa( rInAddress.sin_addr ) , ulIPBufLen);
- // Single exit point
- FuncExit:
- return( theErr );
- }
- ULONG32 unix_net::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- ULONG32 unix_net::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- /*
- * reuse_addr/reuse_port has to be called before a sock binds. however,
- * socket is not available until it binds as it is implemented. So, set a
- * flag here and do the actual setsockopt right before a sock binds.
- * Look in init_unix().
- */
- HX_RESULT
- unix_net::reuse_addr(BOOL enable)
- {
- m_bReuseAddr = enable;
- return HXR_OK;
- }
- HX_RESULT
- unix_net::reuse_port(BOOL enable)
- {
- m_bReusePort = enable;
- return HXR_OK;
- }
- HX_RESULT unix_net::init_unix(UINT16 type, UINT32 local_addr, UINT16 port,
- UINT16 blocking)
- {
- int s = INVALID_SOCKET;
- struct sockaddr_in addr;
- #ifdef _BEOS
- char mode = 1;
- #else
- int mode = 1;
- #endif
- mLastError = HXR_OK;
- #ifdef _BEOS
- s = socket(AF_INET, type, 0);
- #else
- s = socket(PF_INET, type, 0);
- #endif
- if (s < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&m_bReuseAddr, sizeof(m_bReuseAddr)) < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- goto sock_err;
- }
- #if defined SO_REUSEPORT
- if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (const char*)&m_bReusePort, sizeof(m_bReusePort)) < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- goto sock_err;
- }
- #endif
- memset(&addr, 0, sizeof addr);
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(local_addr);
- addr.sin_port = htons(port);
- if (::bind(s, (sockaddr*)&addr, sizeof addr) < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- goto sock_err;
- }
- #ifdef FIONBIO
- if (!blocking && ioctl(s, FIONBIO, &mode) < 0)
- #elif SO_NONBLOCK
- if (!blocking && setsockopt(s,SOL_SOCKET,SO_NONBLOCK,&mode,1)<0)
- #else
- if (!blocking && ::fcntl(get_sock(), F_SETFL, ::fcntl(get_sock(), F_GETFL, 0) | O_NONBLOCK) < 0)
- #endif
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- goto sock_err;
- }
- DPRINTF(D_MSG,("unix_net::socket opened: %dn", s));
- m_SocketState = CONN_OPEN;
- set_sock( s );
- return mLastError;
- sock_err:
- ::close(s);
- m_SocketState = CONN_NO_CONN;
- return mLastError;
- }
- #if 0
- /* mcast_multiple_if test */
- /*
- * it returns a number of multicast enabled NICs with a default multicast
- * interface as the very first entry in the pIFList
- */
- UINT32
- unix_net::detectMcastIF(REF(BYTE**) pIFList)
- {
- struct ifconf ifc;
- int i;
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if (ioctl(skfd, SIOCGIFCONF, &ifc) >= 0) {
- {
- // XXXGo
- //printf("%sn", pc);
- printf("%un", ul);
- }
- else
- {
- printf("coudn't detect ifn");
- }
- //HX_VECTOR_DELETE(pc);
- }
- #endif
- HX_RESULT unix_net::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform)
- {
- DPRINTF(D_MSG,("unix_net::connect(): b: %dn", blocking));
- bReadyToWrite = 0;
- //Get a host at all?
- if(!host)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- //Do we have a socket yet?
- if(get_sock() < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- if( blocking )
- {
- //Set our state.
- m_SocketState = CONN_DNS_INPROG;
- //check and see if we were passed a dot format IP address.
- memset(&m_sSockAddrIn, 0, sizeof(struct sockaddr_in));
- char* pTemp = (char*)strrchr(host, '.');
- if (pTemp && atoi(pTemp + 1))
- {
- m_sSockAddrIn.sin_addr.s_addr = inet_addr(host);
- if ((ULONG32)m_sSockAddrIn.sin_addr.s_addr == (ULONG32)-1)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- //Set state to show we have the address ready to go.
- m_SocketState = CONN_CONNECT_INPROG;
- }
- //do a blocking gethostbyname() call.
- if( m_SocketState == CONN_DNS_INPROG )
- {
- struct hostent *h = gethostbyname(host);
- if (!h || !h->h_addr )
- {
- mLastError = HXR_DNR;
- DPRINTF(D_MSG,("unix_net::connect() HXR_INVALID_HOSTrn"));
- CB_ConnectionComplete(0);
- return HXR_DNR;
- }
- struct in_addr** ppAddr = (struct in_addr**)(h->h_addr_list);
- memcpy(&m_sSockAddrIn.sin_addr, ppAddr[0], sizeof(struct in_addr)); /* Flawfinder: ignore */
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- m_AsyncPort = port;
- }
- m_sSockAddrIn.sin_family = AF_INET;
- m_sSockAddrIn.sin_port = htons(port);
- // this stores info about current addr
- CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
- if(CONNECT(get_sock(), (sockaddr*)&m_sSockAddrIn, sizeof(struct sockaddr_in)))
- {
- if(!blocking && (errno == EWOULDBLOCK || errno == EINPROGRESS))
- {
- mConnectionOpen = 1;
- nonblocking();
- CB_ConnectionComplete(1);
- return HXR_OK;
- }
- DPRINTF(D_MSG,("unix_net::connect() HXR_NET_CONNECTrn"));
- mLastError = HXR_NET_CONNECT;
- CB_ConnectionComplete(0);
- return HXR_NET_CONNECT;
- }
- mConnectionOpen = 1;
- nonblocking();
- m_SocketState = CONN_OPEN; // Rahul
- bReadyToWrite = 1;
- CB_ConnectionComplete(1);
- return HXR_OK;
- }//blocking
- return ConnectAsync( host, port );
- }
- #ifdef _UNIX_THREADS_SUPPORTED
- void *unix_net::_ResolveIt( void* pArg )
- {
- unix_net* pIt = (unix_net*)pArg;
- struct hostent *h = gethostbyname(pIt->m_pAsyncHost);
- if( (NULL!=h) && (NULL!=h->h_addr) )
- {
- //Got good IP, send it back in dot format.
- const u_char *src = (u_char*)h->h_addr_list[0];
- static const char fmt[] = "%u.%u.%u.%u";
- sprintf(pIt->m_szPipeIP, fmt, src[0], src[1], src[2], src[3]); /* Flawfinder: ignore */
- }
- pIt->m_nResolved = 1;
- return NULL;
- }
- #endif
- HX_RESULT unix_net::DoStartAsyncConn()
- {
- DPRINTF(D_MSG,("unix_net::DoStartAsyncConn()rn"));
- m_SocketState = CONN_DNS_INPROG;
- #ifdef _UNIX_THREADS_SUPPORTED
- //Make the thread if we haven't already.
- if( m_bThreadedDNS )
- {
- if( NULL == m_pResolver)
- {
- m_nResolved = 0;
- HXThread::MakeThread( m_pResolver );
- HX_ASSERT( m_pResolver );
- }
- //Set the state
- m_nResolved = 0;
- //Start the thread
- m_pResolver->CreateThread( _ResolveIt, (void*)this );
- //That is it!
- return( mLastError = HXR_WOULD_BLOCK );
- }
- #endif
- //
- // Fork here to start the DNS process. The process will
- // be monitored by calls from proccess_idle to the method
- // 'CheckOnDNS()'.
- //
- //Create pipe to communicate between the child and parent.
- if ( 0 != pipe(m_anDNSPipe) )
- {
- //Can't create pipe.
- m_anDNSPipe[0] = nInvalidPipe;
- m_anDNSPipe[1] = nInvalidPipe;
- mLastError = HXR_GENERAL_NONET;
- return mLastError;
- }
- if( 0 > (m_nChildProcID = fork()))
- {
- //Error trying to fork.
- //What should we do?
- mLastError = HXR_GENERAL_NONET;
- m_SocketState = CONN_DNS_FAILED;
- CB_DNSComplete( 0 );
- return HXR_GENERAL_NONET;
- }
- if( 0 == m_nChildProcID )
- {
- //This is the child proc....
- //Close the read end of the pipe.
- if ( 0 != ::close( m_anDNSPipe[0]) )
- {
- //close, error. Kill this child proc.
- //This proc just exits. Return codes will come
- //from the parent proc. Just write a NULL to
- //the pipe.
- ::write( m_anDNSPipe[1], "", 1 );
- exit(1);
- }
- m_anDNSPipe[0] = nInvalidPipe;
- //
- // Do the blocking DNS here
- //
- struct hostent *h = gethostbyname(m_pAsyncHost);
- if ( (NULL==h) || (NULL==h->h_addr) )
- {
- //Bad host or other nasty.
- //printf("Bad host or some other nastyn");
- //Send back for now.
- ::write( m_anDNSPipe[1], "", 1 );
- exit(1);
- }
- //Got good IP, send it back in dot format.
- const u_char *src = (u_char*)h->h_addr_list[0];
- char szTmp[20]; /* Flawfinder: ignore */ //Just big enough to hold "255.255.255.255"
- static const char fmt[] = "%u.%u.%u.%u";
- SafeSprintf(szTmp, 20, fmt, src[0], src[1], src[2], src[3]);
- //printf("The Address is: %sn", szTmp);
- ::write( m_anDNSPipe[1], szTmp, strlen(szTmp)+1 );
- //Now close the pipe to ensure an EOF is written.
- //Close the read end of the pipe.
- if ( 0 != ::close( m_anDNSPipe[1]) )
- {
- //Unlikly, but if it does happend then we won't get
- //an EOF written to the pipe and the AsyncDNS will
- //never complete.
- #ifdef _DEBUG
- fprintf( stderr, "AsyncDNS can't close pipe. Disable AsyncDNS with NoAsyncDNS=1n");
- fprintf( stderr, "If you have problems connecting.n");
- #endif
- }
- _exit(0);
- }//m_nChildProcID
- //In parent....
- //Close the write end of the pipe.
- if ( 0 != ::close(m_anDNSPipe[1]) )
- {
- //close error.
- m_anDNSPipe[0] = nInvalidPipe;
- m_anDNSPipe[1] = nInvalidPipe;
- mLastError = HXR_GENERAL_NONET;
- return mLastError;
- }
- m_anDNSPipe[1] = nInvalidPipe;
- //We are now ready to read off of anDNSPipe[0] the
- //IP address of the host in dot format.
- //Set the pipes to non blocking.
- int flags;
- if( (flags = fcntl( m_anDNSPipe[0], F_GETFL, 0)) < 0 )
- {
- //Error, can't get the current flags for this pipe.
- mLastError = HXR_GENERAL_NONET;
- m_SocketState = CONN_DNS_FAILED;
- //Close the pipes and kill the child proc.
- CleanUpChildProc();
- //Report the disaster.
- CB_DNSComplete(0);
- return HXR_GENERAL_NONET;
- }
- flags |= O_NONBLOCK;
- if( fcntl( m_anDNSPipe[0], F_SETFL, flags) < 0 )
- {
- //Error, can't set the flags for this pipe.
- mLastError = HXR_GENERAL_NONET;
- m_SocketState = CONN_DNS_FAILED;
- //Close the pipes and kill the child proc.
- CleanUpChildProc();
- //Report the disaster.
- CB_DNSComplete(0);
- return HXR_GENERAL_NONET;
- }
- return( mLastError = HXR_WOULD_BLOCK );
- }
- HX_RESULT unix_net::CheckOnDNS()
- {
- //Return this if nothing changes.
- mLastError = HXR_WOULD_BLOCK;
- #ifdef _UNIX_THREADS_SUPPORTED
- if( m_bThreadedDNS )
- {
- AddRef();
- //Is the thread done yet?
- if( m_nResolved == 1 )
- {
- //Yeah, we are done. Wait on the thread.
- m_pResolver->Exit(0);
- //use it.
- if( strlen(m_szPipeIP) == 0 )
- {
- //badhost or DNS error. Close the pipe and go home.
- mLastError = HXR_DNR;
- CB_DNSComplete(0);
- }
- else
- {
- //Assume at this point that m_szPipeIP has a good IP in it.
- m_sSockAddrIn.sin_addr.s_addr = inet_addr(m_szPipeIP);
- if((ULONG32)m_sSockAddrIn.sin_addr.s_addr == (ULONG32)-1)
- {
- mLastError = HXR_DNR;
- CB_DNSComplete(0);
- }
- else
- {
- //Clear it for next time.
- m_szPipeIP[0]='';
- //Set our current address...
- CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
- CB_DNSComplete(1);
- mLastError = HXR_OK;
- }
- }
- }
- HX_RESULT res = mLastError;
- Release();
- return res;
- }
- #endif
- //Keep checking and see if the the DNS lookup is
- //done or not.
- char szBuff[256]; /* Flawfinder: ignore */
- int status = 0;
- //If its there grab it.
- memset(szBuff, 0, 256);
- status = ::read(m_anDNSPipe[0], szBuff, 255);
- if( status > 0 )
- {
- strncat( m_szPipeIP, szBuff, status ); /* Flawfinder: ignore */
- }
- //Did we find EOF?
- if( 0 == status )
- {
- //At this point m_szPipeIP has a good IP address or
- //an error (NULL byte)
- //close the last pipe.
- ::close(m_anDNSPipe[0]); //Don't care about an error here.
- m_anDNSPipe[0] = nInvalidPipe;
- if( strlen(m_szPipeIP) == 0 )
- {
- //badhost or DNS error. Close the pipe and go home.
- mLastError = HXR_DNR;
- CB_DNSComplete(0);
- }
- else
- {
- //Assume at this point that m_szPipeIP has a good IP in it.
- m_sSockAddrIn.sin_addr.s_addr = inet_addr(m_szPipeIP);
- if((ULONG32)m_sSockAddrIn.sin_addr.s_addr == (ULONG32)-1)
- {
- mLastError = HXR_DNR;
- CB_DNSComplete(0);
- }
- else
- {
- //Clear it for next time.
- m_szPipeIP[0]='';
- //grab the zombie child.
- ::waitpid( m_nChildProcID, NULL, 0 );
- m_nChildProcID = 0;
- //Set our current address...
- CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
- CB_DNSComplete(1);
- mLastError = HXR_OK;
- }
- }
- } else if( status<0 && EAGAIN!=errno )
- {
- //Just make sure the read returned EAGAIN and not
- //some other error on the pipe.
- m_szPipeIP[0]='';
- //Kill the DNS child proc and close the pipe we're going home.
- CleanUpChildProc();
- //Report the problem.
- mLastError = HXR_GENERAL_NONET;
- CB_DNSComplete(0);
- }
- return mLastError;
- }
- HX_RESULT unix_net::CheckForConnection()
- {
- sockaddr_in cliaddr;
- UINT16 addrlen = sizeof(sockaddr_in);
- //memset(&cliaddr, 0, addrlen);
- //Return this if nothing changes.
- mLastError = HXR_WOULD_BLOCK;
- int newSock = accept(&cliaddr, &addrlen);
- if ( newSock == INVALID_SOCKET )
- {
- // igno all errors... r
- return HXR_WOULD_BLOCK;
- }
- else
- {
- unix_net* pNewConn = (unix_net*)conn::actual_new_socket(HX_TCP_SOCKET);
- pNewConn->AddRef();
- conn::add_connection_to_list(pNewConn);
- if ( pNewConn )
- {
- pNewConn->set_sock(newSock);
- if ( SUCCEEDED(pNewConn->connect_accept(&cliaddr)) )
- {
- mLastError = HXR_OK;
- CB_NewConnectionReady (TRUE, pNewConn);
- }
- else
- {
- CB_NewConnectionReady(FALSE, NULL);
- }
- }
- else
- {
- mLastError = HXR_OUTOFMEMORY;
- }
- }
- return mLastError;
- }
- // This method get's called by connect() in the case of an async request
- // It doesn't however actually start the connection. It just registers
- // that we need to do the connection. DoStartAsyncConn() will really do it.
- HX_RESULT unix_net::ConnectAsync( const char* host, UINT16 port )
- {
- //If we have our child(forked) process going on then
- //make sure we kill it and start a new one. Also, close
- //any open pipes.
- CleanUpChildProc();
- bReadyToWrite = 0;
- if (!host)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- if (get_sock() == INVALID_SOCKET)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- char* pTemp = (char*)strrchr(host, '.');
- if (pTemp && atoi(pTemp + 1))
- { /* IP address. */
- m_sSockAddrIn.sin_addr.s_addr = inet_addr(host);
- if ((UINT)m_sSockAddrIn.sin_addr.s_addr == (UINT)-1)
- {
- mLastError = HXR_DNR;
- CB_DNSComplete(0);
- return mLastError;
- }
- else
- {
- // this stores info about current addr
- CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
- m_AsyncPort = port;
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- CB_DNSComplete(1);
- }
- }
- else if (conn::is_cached((char *)host,(ULONG32 *) &m_sSockAddrIn.sin_addr.s_addr))
- {
- // this stores info about current addr
- CurrentAddr = m_sSockAddrIn.sin_addr.s_addr;
- m_AsyncPort = port;
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- CB_DNSComplete(1);
- }
- else
- {
- //We are going to do Async DNS.....
- m_AsyncPort = port;
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- m_SocketState = CONN_NO_CONN;
- return(DoStartAsyncConn());
- }
- return( HXR_OK );
- }
- // Once async DNS has commpleted then we'll call this guy to do the
- // connection (again asynchronously).
- void unix_net::ContinueAsyncConnect()
- {
- DPRINTF(D_MSG,("unix_net::ContinueAsyncConnect() socket: %drn", get_sock()));
- int nResult=0;
- nResult = CONNECT( get_sock(),
- (sockaddr*)&m_sSockAddrIn,
- sizeof(m_sSockAddrIn) );
- if( nResult != 0 && errno != EISCONN )
- {
- if( errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY )
- {
- m_SocketState = CONN_CONNECT_INPROG;
- }
- else
- {
- mLastError = HXR_NET_CONNECT;
- m_SocketState = CONN_CONNECT_FAILED;
- nonblocking();
- DPRINTF(D_MSG,("unix_net::ContinueAsyncConnect() CONN_CONNECT_FAILED nResult: %d errno: %d(%s)rn", nResult, errno, strerror(errno)));
- CB_ConnectionComplete(0);
- }
- }
- else
- {
- mConnectionOpen = 1;
- CB_ConnectionComplete(1);
- }
- return;
- }
- // Called by the notifier to tell us that the DNS request completed
- void unix_net::CB_DNSComplete( int iSuccess )
- {
- ULONG32 ulNotUsed;
- mDNSDone = TRUE;
- //Put it into the cache if its good and not there.
- if( iSuccess &&
- m_pAsyncHost &&
- 0 == conn::is_cached(m_pAsyncHost, &ulNotUsed)
- )
- {
- conn::add_to_cache(m_pAsyncHost, m_sSockAddrIn.sin_addr.s_addr);
- }
- if( TRUE == m_DNSOnly )
- {
- //This is an DNSOnly object. Don't do the connect.
- if (iSuccess)
- {
- mHostIPValid = TRUE;
- mHostIPAddr = get_addr();
- }
- else
- {
- mHostIPValid = FALSE;
- }
- }
- else
- {
- if(iSuccess)
- {
- m_SocketState = CONN_CONNECT_INPROG;
- }
- else
- {
- m_SocketState = CONN_DNS_FAILED;
- }
- }//TRUE==m_DNSOnly
- //
- // Handle any DNS notification callbacks.
- //
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, iSuccess);
- }
- if( FALSE==m_DNSOnly && iSuccess )
- {
- m_sSockAddrIn.sin_family = AF_INET;
- m_sSockAddrIn.sin_port = htons( m_AsyncPort );
- ContinueAsyncConnect();
- }
- return;
- }
- void unix_net::CB_NewConnectionReady(int iSuccess, unix_net* pConn)
- {
- if ( mCallBack )
- {
- mCallBack->Func(ACCEPT_NOTIFICATION, iSuccess?TRUE:FALSE, (conn*)pConn);
- }
- }
- // Called by the notifier to tell us that the Connection completed
- void unix_net::CB_ConnectionComplete( int iSuccess )
- {
- DPRINTF(D_MSG,("CB_ConnectionComplete(%d)rn", iSuccess) );
- if (iSuccess)
- {
- m_SocketState = CONN_OPEN;
- }
- else
- {
- m_SocketState = CONN_CONNECT_FAILED;
- }
- if (mCallBack)
- {
- mCallBack->Func(CONNECT_NOTIFICATION, iSuccess?TRUE:FALSE);
- }
- }
- // Called by the notifier when data ready for read/write
- void unix_net::CB_ReadWriteNotification( int iType )
- {
- DPRINTF(D_MSG,("CB_ReadWriteNotification()....rn") );
- // Should do something here....
- if (mCallBack && (m_SocketState == CONN_OPEN))
- {
- #if 0
- if (iType == FD_WRITE)
- {
- mCallBack->Func(WRITE_NOTIFICATION);
- }
- else if (iType == FD_READ)
- {
- mCallBack->Func(READ_NOTIFICATION);
- }
- #endif // 0
- mCallBack->Func(READ_NOTIFICATION);
- //mCallBack->callback_task( HX_UDP_CALLBACK, NULL );
- }
- }
- void unix_net::CB_CloseNotification()
- {
- DPRINTF(D_MSG,("CB_CloseNotification()....rn") );
- m_SocketState = CONN_CLOSED;
- }
- HX_RESULT unix_net::connect( sockaddr_in *addr )
- {
- //XXXgfw Is this method used?????
- //XXXgfw If this is used, should there be a non-blocking
- //XXXgfw version of this? If so, we need to pass in a flag
- //XXXgfw or something. Eitherway, I can't see where this is
- //XXXgfw used at all. Only blocking for now I guess.
- if(CONNECT( get_sock(), (sockaddr*)addr, sizeof( addr ) ))
- {
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- mConnectionOpen = 1;
- return HXR_OK;
- }
- HX_RESULT unix_net::write(void * buf, UINT16 *len)
- {
- int got;
- DPRINTF(D_MSG, ("unix_net::write() s: %d l: %dn",get_sock(),*len));
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- if (m_SocketState != CONN_OPEN ) //&& m_SocketState != CONN_DNS_INPROG)
- {
- // We won't be able to write anything here, so clear this
- // we'll return why we didn't write anything.
- *len = 0;
- switch( m_SocketState )
- {
- case CONN_DNS_INPROG:
- case CONN_CONNECT_INPROG:
- case CONN_CLOSING:
- return( mLastError = HXR_WOULD_BLOCK );
- case CONN_CLOSED:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case CONN_NO_CONN:
- return( mLastError = HXR_NET_CONNECT );
- // return( DoStartAsyncConn() );
- case CONN_DNS_FAILED:
- return( mLastError = HXR_DNR );
- case CONN_CONNECT_FAILED:
- return( mLastError = HXR_NET_CONNECT );
- default:
- // HUH???
- assert( 0 );
- return( mLastError = HXR_NET_READ );
- };
- }
- else
- {
- #if defined(_BEOS)
- got = ::send( get_sock(), (void *)buf, *len, 0 );
- #else
- got = ::write( get_sock(), (char *)buf, *len );
- #endif
- if (got == -1)
- {
- *len = 0;
- // Mask the "so what?" errors
- if (errno == EWOULDBLOCK || errno == EINPROGRESS)
- {
- return HXR_WOULD_BLOCK;
- }
- else
- {
- mLastError = HXR_NET_WRITE;
- return mLastError;
- }
- }
- *len = got;
- return HXR_OK;
- }
- }
- HX_RESULT unix_net::WriteComplete (char * Buffer, int length)
- {
- int sent = 0;
- unsigned short cur_sent=0;
- while(sent < length)
- {
- cur_sent = length - sent;
- HX_RESULT ret = write(Buffer + sent, &cur_sent);
- if(ret != HXR_OK && ret != HXR_WOULD_BLOCK)
- break;
- sent += cur_sent;
- }
- // m_SocketState = CONN_NO_CONN;
- if(sent < length)
- {
- mLastError = HXR_NET_WRITE;
- return mLastError;
- }
- return HXR_OK;
- }
- int unix_net::ReadyToWrite()
- {
- if(get_sock() < 0)
- {
- bReadyToWrite = 0;
- return bReadyToWrite;
- }
- if(bReadyToWrite)
- return 1;
- fd_set writefds;
- FD_ZERO(&writefds);
- FD_SET(get_sock(), &writefds);
- struct timeval timeout;
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- #ifdef _HPUX
- // mwebb added HP-specifix lines (for the curious, do "man select")
- // also changed timeout call to be a non-blocking "poll"
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- #endif
- if(select(0, NULL, &writefds,NULL, &timeout) == 1)
- bReadyToWrite = 1;
- return bReadyToWrite;
- }
- void unix_net::done (void)
- {
- m_SocketState = CONN_CLOSING;
- if ((get_sock() != INVALID_SOCKET))
- {
- ::close(get_sock());
- }
- set_sock( INVALID_SOCKET );
- m_SocketState = CONN_CLOSED;
- mConnectionOpen = 0;
- LISTPOSITION listpos = readers->Find(this);
- if(listpos)
- {
- readers->RemoveAt(listpos);
- }
- }
- inline HX_RESULT unix_net::listen (UINT16 backlog)
- {
- if ( ::listen(get_sock(), backlog) != -1 )
- {
- m_SocketState = CONN_LISTENNING;
- mConnectionOpen = 0;
- return HXR_OK;
- }
- else
- {
- m_SocketState = CONN_NO_CONN;
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- }
- /*
- inline HX_RESULT unix_net::blocking (void)
- {
- unsigned long nonblocking = 0;
- return ::ioctl(get_sock(), FIONBIO, (char*)&nonblocking);
- }
- inline HX_RESULT unix_net::nonblocking (void)
- {
- unsigned long nonblocking = 1;
- return ::ioctl(get_sock(), FIONBIO, (char*)&nonblocking);
- }
- */
- inline HX_RESULT unix_net::connect_accept(sockaddr_in *addr)
- {
- CurrentAddr = addr->sin_addr.s_addr;
- memcpy(&m_sSockAddrIn, addr, sizeof(sockaddr_in)); /* Flawfinder: ignore */
- mConnectionOpen = 1;
- m_SocketState = CONN_OPEN;
- mLastError = HXR_OK;
- nonblocking();
- return HXR_OK;
- }
- /*
- inline HX_RESULT unix_net::accept (sockaddr_in *addr, UINT16 *addrlen)
- {
- return ::accept(get_sock(), (sockaddr*)addr, (int *)addrlen);
- }
- inline HX_RESULT unix_net::bind (sockaddr_in *addr)
- {
- return ::bind(get_sock(), (sockaddr*)addr, sizeof(addr));
- }
- */
- HX_RESULT unix_net::read(void * buf, UINT16 *len)
- {
- int got;
- static int breakpoint = 0;
- assert( (PTR_INT)buf );
- assert( (PTR_INT)len );
- if (get_sock() == INVALID_SOCKET || !callRaConnect)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- // Is the TCP socket actually connected yet?
- if (m_SocketState != CONN_OPEN)
- {
- // No
- // We won't be able to write anything here, so clear this
- // we'll return why we didn't write anything.
- *len = 0;
- switch( m_SocketState )
- {
- case CONN_DNS_INPROG:
- case CONN_CONNECT_INPROG:
- case CONN_CLOSING:
- return( mLastError = HXR_WOULD_BLOCK );
- case CONN_CLOSED:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case CONN_NO_CONN:
- return( mLastError = HXR_NET_CONNECT );
- // return( DoStartAsyncConn() );
- case CONN_DNS_FAILED:
- return( mLastError = HXR_DNR );
- case CONN_CONNECT_FAILED:
- return( mLastError = HXR_NET_CONNECT );
- default:
- // HUH???
- assert( 0 );
- return( mLastError = HXR_NET_READ );
- };
- }
- else
- {
- // Now we can actually do the read
- #ifdef _BEOS
- got = ::recv( get_sock(), (char *)buf, *len, 0 );
- #else
- got = READ( get_sock(), (char *)buf, *len );
- #endif
- // Did we get an error?
- if (got < 0 )
- {
- *len = 0;
- // Translate the error
- switch (errno)
- {
- case EWOULDBLOCK:
- add_read_request();
- return( mLastError = HXR_WOULD_BLOCK );
- case ECONNRESET:
- return( mLastError = HXR_SERVER_DISCONNECTED );
- default:
- return( mLastError = HXR_NET_READ ); // Error we don't know what to do about
- }
- }
- else if (got == 0)
- {
- return (mLastError = HXR_SERVER_DISCONNECTED);
- }
- else
- {
- // This should be our exit point for successful read
- DPRINTF(D_MSG, ("unix_net::read() s: %d l: %dn",get_sock(),*len));
- *len = got;
- return( HXR_OK );
- }
- }
- }
- HX_RESULT unix_net::readfrom (REF(IHXBuffer*) pBuffer,
- REF(UINT32) ulAddress,
- REF(UINT16) ulPort)
- {
- int got = 0;
- UINT16 size = 0;
- pBuffer = NULL;
- ulAddress = 0;
- ulPort = 0;
- // Allocate m_pInBuffer now, since we know we need it.
- if( m_pInBuffer == NULL )
- {
- m_pInBuffer = new char[TCP_BUF_SIZE];
- }
- if (get_sock() == INVALID_SOCKET || callRaConnect)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- // Is the TCP socket actually connected yet?
- if (m_SocketState != CONN_OPEN)
- {
- // No
- // We won't be able to write anything here, so clear this
- // we'll return why we didn't write anything.
- switch( m_SocketState )
- {
- case CONN_DNS_INPROG:
- case CONN_CONNECT_INPROG:
- case CONN_CLOSING:
- return( mLastError = HXR_WOULD_BLOCK );
- case CONN_CLOSED:
- return( mLastError = HXR_NET_SOCKET_INVALID );
- case CONN_NO_CONN:
- return( mLastError = HXR_NET_CONNECT );
- // return( DoStartAsyncConn() );
- case CONN_DNS_FAILED:
- return( mLastError = HXR_DNR );
- case CONN_CONNECT_FAILED:
- return( mLastError = HXR_NET_CONNECT );
- default:
- // HUH???
- assert( 0 );
- return( mLastError = HXR_NET_READ );
- }
- }
- else
- {
- #if defined _AIX42
- //SCO's Unixware compiler will choke and die otherwise:
- size_t fromlen = 0;
- #elif defined _HPUX
- int fromlen = 0;
- #else
- socklen_t fromlen = 0;
- #endif
- struct sockaddr_in from;
- fromlen = sizeof(from);
- // Now we can actually do the read
- got = RECVFROM( get_sock(), m_pInBuffer, TCP_BUF_SIZE, 0, (struct sockaddr*)&from, (HX_SOCKLEN_T *)&fromlen);
- // Did we get an error?
- if (got <= 0 )
- {
- // Translate the error
- switch (errno)
- {
- case EWOULDBLOCK:
- add_read_request();
- return( mLastError = HXR_WOULD_BLOCK );
- case ECONNRESET:
- return( mLastError = HXR_SERVER_DISCONNECTED );
- default:
- return( mLastError = HXR_NET_READ ); // Error we don't know what to do about
- }
- }
- // This should be our exit point for successful read
- CHXTimeStampedBuffer* pTimeBuffer = new CHXTimeStampedBuffer;
- pTimeBuffer->AddRef();
- pTimeBuffer->SetTimeStamp(HX_GET_TICKCOUNT());
- pTimeBuffer->Set((UCHAR*)m_pInBuffer, got);
- pBuffer = (IHXBuffer*) pTimeBuffer;
- ulAddress = DwToHost(from.sin_addr.s_addr);
- ulPort = WToHost(from.sin_port);
- return( HXR_OK );
- }
- }
- HX_RESULT unix_UDP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform )
- {
- blocking = GetAsyncDNSPref() ? 1 : blocking;
- HX_RESULT ret = HXR_OK;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- ret = unix_net::connect(host, port, blocking, ulPlatform );
- if ( !ret )
- nonblocking();
- return ret;
- }
- HX_RESULT unix_UDP::connect(sockaddr_in * addr, UINT16 blocking)
- {
- blocking = GetAsyncDNSPref() ? 1 : blocking;
- HX_RESULT ret = HXR_OK;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- return unix_net::connect(addr);
- }
- HX_RESULT unix_TCP::connect(const char* host, UINT16 port, UINT16 blocking, ULONG32 ulPlatform )
- {
- blocking = GetAsyncDNSPref() ? 1 : blocking;
- HX_RESULT ret = HXR_OK;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- ret = unix_net::connect(host, port, blocking, ulPlatform );
- #if 0
- if ( !ret )
- nonblocking();
- #endif
- return ret;
- }
- HX_RESULT unix_TCP::connect(sockaddr_in * addr, UINT16 blocking)
- {
- blocking = GetAsyncDNSPref() ? 1 : blocking;
- HX_RESULT ret = HXR_OK;
- if (get_sock() < 0 && (ret = init(INADDR_ANY, 0, blocking)) != HXR_OK)
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- return unix_net::connect(addr);
- }
- HX_RESULT unix_TCP::listen(ULONG32 ulLocalAddr, UINT16 port,
- UINT16 backlog, UINT16 blocking,
- ULONG32 ulPlatform)
- {
- // We will ignor the blockng parameter, and block for this
- // function but leave the socket in a non blocking state...
- HX_RESULT ret = HXR_OK;
- if ( get_sock() < 0 )
- {
- if ( ulLocalAddr == HX_INADDR_ANY )
- ret = init(INADDR_ANY, port, 1);
- else
- ret = init(ulLocalAddr, port, 1);
- }
- if ( FAILED(ret) )
- {
- if(ret == HXR_BLOCK_CANCELED)
- return ret;
- mLastError = HXR_NET_CONNECT;
- return mLastError;
- }
- if ( unix_net::listen(backlog) != HXR_OK)
- {
- ret = HXR_NET_CONNECT;
- }
- if ( SUCCEEDED(ret) )
- {
- ret = unix_net::nonblocking();
- }
- return ret;
- }
- HX_RESULT
- unix_UDP::set_multicast()
- {
- #ifdef NO_MULTICAST
- return HXR_MULTICAST_UDP;
- #endif /* NO_MULTICAST */
- INT32 ret;
- sockaddr_in addr;
- #if defined _AIX42
- size_t addr_len = sizeof addr;
- #elif defined _HPUX || defined _OSF1
- int addr_len = sizeof addr;
- #else
- socklen_t addr_len = sizeof addr;
- #endif
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- memset(&addr, 0, HX_SAFESIZE_T(addr_len));
- ret = getsockname(get_sock(), (sockaddr*)&addr, &addr_len);
- if (ret < 0)
- {
- return HXR_MULTICAST_UDP;
- }
- /*
- * Linux and Solairs seem to return 127.0.0.1 from getsockname() which they
- * don't accept as a valid interface in setsockopt(IP_MULTICAST_IF)
- */
- #if defined _LINUX || defined _SOLARIS
- addr.sin_addr.s_addr = INADDR_ANY;
- #endif /* _LINUX || _SOLARIS */
- #ifdef _BEOS
- // FIXME no multicast for BeOS
- return HXR_MULTICAST_UDP;
- #else
- ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_IF,
- (char*) &addr.sin_addr.s_addr,
- sizeof (addr.sin_addr.s_addr));
- if (ret < 0)
- {
- return HXR_MULTICAST_UDP;
- }
- return HXR_OK;
- #endif /* _BEOS */
- }
- HX_RESULT
- unix_UDP::set_multicast_ttl(unsigned char ttl)
- {
- #ifdef NO_MULTICAST
- return HXR_MULTICAST_UDP;
- #endif /* NO_MULTICAST */
- INT32 ret;
- unsigned char ttl_proxy;
- ttl_proxy = ttl;
- #ifdef _BEOS
- // FIXME no multicast for BeOS
- return HXR_MULTICAST_UDP;
- #else
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
- (char*) &ttl_proxy, sizeof (ttl_proxy));
- if (ret < 0)
- {
- return HXR_MULTICAST_UDP;
- }
- return HXR_OK;
- #endif /* _BEOS */
- }
- HX_RESULT unix_UDP::join_multicast_group(ULONG32 addr, ULONG32 if_addr)
- {
- #if defined(_BEOS)
- return HXR_NOTIMPL;
- #else
- int ret;
- ip_mreq multicast_group;
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- u_char ttl = 254; // As Per Sujal.
- ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
- sizeof(ttl));
- if (ret == -1)
- {
- return HXR_MULTICAST_JOIN;
- }
- multicast_group.imr_multiaddr.s_addr = htonl(addr);
- #ifdef _UNIX
- multicast_group.imr_interface.s_addr = htonl(INADDR_ANY);
- #elif
- multicast_group.imr_interface.s_addr = htonl(if_addr);
- #endif
- ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char*) &multicast_group,
- sizeof (multicast_group));
- if (ret < 0)
- {
- return HXR_MULTICAST_JOIN;
- }
- return HXR_OK;
- #endif
- }
- HX_RESULT unix_UDP::leave_multicast_group(ULONG32 addr, ULONG32 if_addr)
- {
- #if defined(_BEOS)
- return HXR_NOTIMPL;
- #else
- int ret;
- ip_mreq multicast_group;
- if (get_sock() == INVALID_SOCKET)
- {
- // Not connected
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- multicast_group.imr_multiaddr.s_addr = htonl(addr);
- multicast_group.imr_interface.s_addr = htonl(if_addr);
- ret = ::setsockopt(get_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char*) &multicast_group, sizeof (multicast_group));
- if (ret == -1)
- {
- return HXR_GENERAL_MULTICAST;
- }
- return HXR_OK;
- #endif
- }
- HX_RESULT
- unix_UDP::set_multicast_if(ULONG32 ulInterface)
- {
- int ret;
- int s = get_sock();
- if(s == INVALID_SOCKET)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- unsigned long addr = htonl(ulInterface);
- ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
- (char*)&addr, sizeof(addr));
- if(ret == -1)
- ret = HXR_GENERAL_MULTICAST;
- return ret;
- }
- HX_RESULT
- unix_UDP::set_broadcast(BOOL enable)
- {
- int ret;
- int s = get_sock();
- if(s == INVALID_SOCKET)
- {
- return( mLastError = HXR_NET_SOCKET_INVALID );
- }
- ret = setsockopt( s, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(UINT32) );
- if(ret == -1)
- ret = HXR_BIND;
- return ret;
- }
- HX_RESULT
- unix_UDP::set_send_size(UINT32 send_size)
- {
- #ifdef _BEOS
- // Be is messed up
- return -1;
- #else
- int s = get_sock();
- int ret = 0;
- again:
- ret = setsockopt(s, SOL_SOCKET, SO_SNDBUF,
- (char*)&send_size, sizeof(INT32));
- if (ret < 0 && send_size > 8192)
- {
- send_size >>= 1;
- goto again;
- }
- return ret;
- #endif
- }
- HX_RESULT unix_net::writeto( void * buf,
- UINT16 *len,
- ULONG32 addr,
- UINT16 port)
- {
- int got;
- sockaddr_in resend_addr;
- ::memset( &resend_addr, 0, sizeof( resend_addr ) );
- resend_addr.sin_family = AF_INET;
- resend_addr.sin_addr.s_addr = addr;
- resend_addr.sin_port = htons(port);
- got = sendto(get_sock(), (char *) buf, *len, 0, (sockaddr *)&resend_addr, sizeof (resend_addr));
- if (got == -1)
- {
- /* int code;
- *len = 0;
- code = sockObj->HXWSAGetLastError();
- // Mask the "so what?" errors
- if (code == WSAEWOULDBLOCK || code == WSAEINPROGRESS)
- {
- return HXR_WOULD_BLOCK;
- }
- else
- {
- mLastError = HXR_NET_WRITE;
- return mLastError;
- }
- */
- }
- *len = got;
- return HXR_OK;
- }
- ULONG32 unix_net::get_addr()
- {
- return m_sSockAddrIn.sin_addr.s_addr;
- }
- UINT16 unix_net::get_local_port()
- {
- sockaddr_in addr;
- #if defined _AIX42
- size_t addr_len = sizeof addr;
- #elif defined _HPUX || defined _OSF1
- int addr_len = sizeof addr;
- #else
- socklen_t addr_len = sizeof addr;
- #endif
- memset(&addr, 0, HX_SAFESIZE_T(addr_len));
- int ret = getsockname(get_sock(), (sockaddr*)&addr, &addr_len);
- return (ret < 0) ? -1 : WToHost(addr.sin_port);
- }
- HX_RESULT unix_net::dns_find_ip_addr(const char * host, UINT16 blocking)
- {
- mHostIPValid = FALSE;
- mDNSDone = TRUE;
- blocking = GetAsyncDNSPref() ? 1 : blocking;
- if(!host)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- if(get_sock() < 0)
- {
- mLastError = HXR_NET_SOCKET_INVALID;
- return mLastError;
- }
- if (conn::is_cached((char *) host, &mHostIPAddr))
- {
- mHostIPValid = TRUE;
- mLastError = HXR_OK;
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, TRUE);
- }
- return HXR_OK;
- }
- //Check for a dot format IP string.
- char* pTemp = (char*)strrchr(host, '.');
- if (pTemp && isdigit(*(pTemp + 1)))
- { /* IP address. */
- mHostIPValid = FALSE;
- mHostIPAddr = 0;
- mDNSDone = TRUE;
- m_sSockAddrIn.sin_addr.s_addr = inet_addr(host);
- if ((UINT)m_sSockAddrIn.sin_addr.s_addr == (UINT)-1)
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- mHostIPValid = TRUE;
- mHostIPAddr = m_sSockAddrIn.sin_addr.s_addr;
- conn::add_to_cache((char *)host, mHostIPAddr);
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, TRUE);
- }
- return HXR_OK;
- }
- if( blocking )
- {
- hostent *pHost = gethostbyname((char *) host);
- mHostIPValid = FALSE;
- mHostIPAddr = 0;
- mDNSDone = TRUE;
- if( !pHost || !pHost->h_addr )
- {
- mLastError = HXR_DNR;
- return mLastError;
- }
- mHostIPValid = TRUE;
- struct in_addr** ppAddr = (struct in_addr**)(pHost->h_addr_list);
- mHostIPAddr = ppAddr[0]->s_addr;
- conn::add_to_cache((char *) host, mHostIPAddr);
- if (mCallBack)
- {
- mCallBack->Func(DNS_NOTIFICATION, TRUE);
- }
- return HXR_OK;
- }
- else
- {
- //Non blocking code here.
- if (m_pAsyncHost != host)
- {
- HX_VECTOR_DELETE(m_pAsyncHost);
- m_pAsyncHost = ::new_string(host);
- }
- //Tell everyone we just want DNS and no connect.
- m_DNSOnly = TRUE;
- //Start up the non-blocking DNS.
- DoStartAsyncConn();
- }//blocking
- mLastError = HXR_OK;
- return mLastError;
- }
- BOOL unix_net::dns_ip_addr_found(BOOL* valid, ULONG32* addr)
- {
- if (mDNSDone)
- {
- *valid = mHostIPValid;
- *addr = mHostIPAddr;
- return TRUE;
- }
- else
- return FALSE;
- }
- void unix_net::add_read_request()
- {
- read_pending = TRUE;
- }
- void
- unix_net::add_select(int *n,
- fd_set* readfds,
- fd_set* writefds,
- fd_set* exceptfds)
- {
- unix_net* un;
- int sock;
- if(!silly_unix_hack_initialized)
- {
- readers = new CHXSimpleList;
- silly_unix_hack_initialized = TRUE;
- }
- if(!unix_net::readers->IsEmpty())
- {
- CHXSimpleList::Iterator i;
- for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); ++i)
- {
- un = (unix_net*)(*i);
- sock = un->get_sock();
- if(un->read_pending && sock >= 0)
- {
- if(sock > *n)
- *n = sock + 1;
- FD_SET(sock, readfds);
- }
- }
- }
- }
- void
- unix_net::process_select(int n,
- fd_set* readfds,
- fd_set* writefds,
- fd_set* exceptfds)
- {
- unix_net* un;
- int sock;
- if(!unix_net::readers->IsEmpty())
- {
- CHXSimpleList::Iterator i, next;
- for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); i = next)
- {
- next = i;
- ++next;
- un = (unix_net*)(*i);
- sock = un->get_sock();
- if(sock >= 0)
- {
- if(FD_ISSET(sock, readfds))
- {
- un->read_pending = FALSE;
- un->CB_ReadWriteNotification(0);
- }
- }
- }
- }
- }
- void unix_net::process_idle()
- {
- unix_net* un;
- fd_set read_fds;
- struct timeval tv;
- int maxfd = 0;
- int sock = INVALID_SOCKET;
- if(!silly_unix_hack_initialized)
- {
- readers = new CHXSimpleList;
- silly_unix_hack_initialized = TRUE;
- }
- FD_ZERO(&read_fds);
- if(!unix_net::readers->IsEmpty())
- {
- CHXSimpleList::Iterator i;
- for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); ++i)
- {
- un = (unix_net*)(*i);
- //Hold on to this reference.
- un->AddRef();
- //Check the progress of each unix_net object's async DNS
- //and connect.
- if( un->GetSocketState() == CONN_DNS_INPROG )
- un->CheckOnDNS();
- else if( un->GetSocketState() == CONN_CONNECT_INPROG )
- un->ContinueAsyncConnect();
- else if ( un->GetSocketState() == CONN_LISTENNING )
- un->CheckForConnection();
- sock = un->get_sock();
- if(un->read_pending && sock >= 0)
- {
- if(sock > maxfd)
- maxfd = sock;
- FD_SET(sock, &read_fds);
- }
- //Release this reference.
- if( 0 == un->Release() )
- {
- //This object just got deleted. Make sure we adjust
- //the iterator back to a valid one because deleting
- //the object an iterator points to invalidates the
- //iterator.
- //Make sure we don't iterate past the end with the
- //upcoming i++ in the for loop above.
- if( unix_net::readers->IsEmpty() )
- {
- break;
- }
- //XXXgfw Can we do better then just setting it all
- //XXXgfw the way back to the begining?
- i = unix_net::readers->Begin();
- }
- }
- }
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- if(select(maxfd + 1, &read_fds, 0, 0, &tv) > 0)
- {
- if(!unix_net::readers->IsEmpty())
- {
- CHXSimpleList::Iterator i, next;
- for(i = unix_net::readers->Begin(); i != unix_net::readers->End(); i = next)
- {
- next = i;
- ++next;
- un = (unix_net*)(*i);
- sock = un->get_sock();
- if(un->read_pending && sock >= 0)
- {
- if(FD_ISSET(sock, &read_fds))
- {
- un->read_pending = FALSE;
- un->CB_ReadWriteNotification(0);
- }
- }
- }
- }
- }
- }