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