📄 unix_net.cpp
字号:
#ifdef _UNIX_THREADS_SUPPORTEDvoid *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;}#endifHX_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; HX_SOCKLEN_T 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 completedvoid 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 completedvoid 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -