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 + -
显示快捷键?