unix_net.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,212 行 · 第 1/4 页
CPP
2,212 行
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: unix_net.cpp,v 1.6.2.4 2004/07/09 01:46:41 hubbe Exp $
*
* Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (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.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL") in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your version of
* this file only under the terms of the GPL, and not to allow others
* to use your version of this file under the terms of either the RPSL
* or RCSL, indicate your decision by deleting the provisions above
* and replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient may
* use your version of this file under the terms of any one of the
* RPSL, the RCSL or the GPL.
*
* 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] = '\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: %d\n", 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("%s\n", pc);
printf("%u\n", ul);
}
else
{
printf("coudn't detect if\n");
}
//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: %d\n", 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_HOST\r\n"));
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_CONNECT\r\n"));
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 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?