unix_net.cpp

来自「著名的 helix realplayer 基于手机 symbian 系统的 播放」· C++ 代码 · 共 2,198 行 · 第 1/4 页

CPP
2,198
字号
        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()\r\n"));
    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], "\0", 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 nasty\n");	
	    //Send back \0 for now.
	    ::write( m_anDNSPipe[1], "\0", 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: %s\n", 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=1\n");
            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]='\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]='\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]='\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: %d\r\n", 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)\r\n", 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)\r\n", 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 )
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?