unix_net.cpp
来自「著名的 helix realplayer 基于手机 symbian 系统的 播放」· C++ 代码 · 共 2,198 行 · 第 1/4 页
CPP
2,198 行
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);
}
}
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?