From 6ce29e77f26379da2c76e16f415f85826ffbb2e9 Mon Sep 17 00:00:00 2001 From: psychon Date: Sat, 19 Dec 2009 16:29:26 +0000 Subject: [PATCH] Update to latest Csocket git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1683 726aef4b-f618-498e-8847-2d620e286838 --- Csocket.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++-- Csocket.h | 76 ++++++++++++++++++++++-------------- 2 files changed, 151 insertions(+), 33 deletions(-) diff --git a/Csocket.cpp b/Csocket.cpp index dc05a6ba..d6b785c7 100644 --- a/Csocket.cpp +++ b/Csocket.cpp @@ -28,7 +28,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * -* $Revision: 1.105 $ +* $Revision: 1.108 $ */ #include "Csocket.h" @@ -36,7 +36,6 @@ #include #endif /* __NetBSD__ */ - #include #define CS_SRANDBUFFER 128 @@ -197,6 +196,49 @@ static int __GetHostByName( const CS_STRING & sHostName, struct in_addr *paddr, } #endif /* !HAVE_IPV6 */ +#ifdef HAVE_C_ARES +void Csock::FreeAres() +{ + if( m_pARESChannel ) + { + ares_destroy( m_pARESChannel ); + m_pARESChannel = NULL; + } +} +#endif /* HAVE_C_ARES */ + +#ifdef HAVE_C_ARES +void AresHostCallback( void *pArg, int status, int timeouts, struct hostent *hent ) +{ + Csock *pSock = (Csock *)pArg; + if( status == ARES_SUCCESS && hent ) + { + CSSockAddr *pSockAddr = pSock->GetCurrentAddr(); + if( hent->h_addrtype == AF_INET ) + { + pSock->SetIPv6( false ); + memcpy( pSockAddr->GetAddr(), hent->h_addr_list[0], sizeof( *(pSockAddr->GetAddr()) ) ); + } +#ifdef HAVE_IPV6 + else if( hent->h_addrtype == AF_INET6 ) + { + pSock->SetIPv6( true ); + memcpy( pSockAddr->GetAddr6(), hent->h_addr_list[0], sizeof( *(pSockAddr->GetAddr6()) ) ); + } +#endif /* HAVE_IPV6 */ + else + { + status = ARES_ENOTFOUND; + } + } + else + { + CS_DEBUG( ares_strerror( status ) ); + } + pSock->SetAresFinished( status ); +} +#endif /* HAVE_C_ARES */ + int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr ) { #ifndef HAVE_IPV6 @@ -530,6 +572,12 @@ Csock *Csock::GetSockObj( const CS_STRING & sHostname, u_short iPort ) Csock::~Csock() { +#ifdef HAVE_C_ARES + if( m_pARESChannel ) + ares_cancel( m_pARESChannel ); + FreeAres(); +#endif /* HAVE_C_ARES */ + #ifdef HAVE_LIBSSL FREE_SSL(); FREE_CTX(); @@ -610,6 +658,11 @@ void Csock::Copy( const Csock & cCopy ) m_bindhost = cCopy.m_bindhost; m_bIsIPv6 = cCopy.m_bIsIPv6; m_bSkipConnect = cCopy.m_bSkipConnect; +#ifdef HAVE_C_ARES + FreeAres(); // Not copying this state, but making sure its nulled out + m_iARESStatus = -1; // set it to unitialized + m_pCurrAddr = NULL; +#endif /* HAVE_C_ARES */ #ifdef HAVE_LIBSSL m_iRequireClientCertFlags = cCopy.m_iRequireClientCertFlags; @@ -2006,6 +2059,48 @@ int Csock::GetPending() int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr ) { +#ifdef HAVE_IPV6 + if( csSockAddr.GetAFRequire() != AF_INET && inet_pton( AF_INET6, sHostname.c_str(), csSockAddr.GetAddr6() ) > 0 ) + { + SetIPv6( true ); + return( 0 ); + } +#endif /* HAVE_IPV6 */ + if( inet_pton( AF_INET, sHostname.c_str(), csSockAddr.GetAddr() ) > 0 ) + { +#ifdef HAVE_IPV6 + SetIPv6( false ); +#endif /* HAVE_IPV6 */ + return( 0 ); + } + +#ifdef HAVE_C_ARES + if( GetType() != LISTENER ) + { // right now the current function in Listen() is it blocks, the easy way around this at the moment is to use ip + if( !m_pARESChannel ) + { + if( ares_init( &m_pARESChannel ) != ARES_SUCCESS ) + { // TODO throw some debug? + FreeAres(); + return( ETIMEDOUT ); + } + m_pCurrAddr = &csSockAddr; // flag its starting + int iFamily = AF_INET; + +#ifdef HAVE_IPV6 + iFamily = csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY ? AF_INET6 : csSockAddr.GetAFRequire(); +#endif /* HAVE_IPV6 */ + ares_gethostbyname( m_pARESChannel, sHostname.c_str(), iFamily, AresHostCallback, this ); + } + if( !m_pCurrAddr ) + { // this means its finished + FreeAres(); + return( m_iARESStatus == ARES_SUCCESS ? 0 : ETIMEDOUT ); + } + return( EAGAIN ); + } +#endif /* HAVE_C_ARES */ + return( ::GetAddrInfo( sHostname, this, csSockAddr ) ); } @@ -2147,7 +2242,7 @@ int Csock::SOCKET( bool bListen ) return( iRet ); } -void Csock::Init( const CS_STRING & sHostname, u_short iport, int itimeout ) +void Csock::Init( const CS_STRING & sHostname, u_short uPort, int itimeout ) { #ifdef HAVE_LIBSSL m_ssl = NULL; @@ -2160,7 +2255,7 @@ void Csock::Init( const CS_STRING & sHostname, u_short iport, int itimeout ) m_itimeout = itimeout; m_bssl = false; m_bIsConnected = false; - m_iport = iport; + m_iport = uPort; m_shostname = sHostname; m_sbuffer.clear(); m_eCloseType = CLT_DONT; @@ -2189,5 +2284,10 @@ void Csock::Init( const CS_STRING & sHostname, u_short iport, int itimeout ) m_bIsIPv6 = false; m_bSkipConnect = false; m_iLastCheckTimeoutTime = 0; +#ifdef HAVE_C_ARES + m_pARESChannel = NULL; + m_pCurrAddr = NULL; + m_iARESStatus = -1; +#endif /* HAVE_C_ARES */ } diff --git a/Csocket.h b/Csocket.h index d5dc3047..5e6a9f83 100644 --- a/Csocket.h +++ b/Csocket.h @@ -28,7 +28,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * -* $Revision: 1.211 $ +* $Revision: 1.213 $ */ // note to compile with win32 need to link to winsock2, using gcc its -lws2_32 @@ -61,6 +61,10 @@ #endif /* _WIN32 */ +#ifdef HAVE_C_ARES +#include +#endif /* HAVE_C_ARES */ + #include #include #include @@ -923,12 +927,12 @@ public: enum EDNSLType { - DNS_VHOST, - DNS_DEST + DNS_VHOST, //!< this lookup is for the vhost bind + DNS_DEST //!< this lookup is for the destination address }; /** - * nonblocking dns lookup (when -pthread is set to compile) + * dns lookup @see EDNSLType * @return 0 for success, EAGAIN to check back again (same arguments as before), ETIMEDOUT on failure */ int DNSLookup( EDNSLType eDNSLType ); @@ -966,6 +970,12 @@ public: */ virtual int GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr ); +#ifdef HAVE_C_ARES + CSSockAddr * GetCurrentAddr() const { return( m_pCurrAddr ); } + void SetAresFinished( int status ) { m_pCurrAddr = NULL; m_iARESStatus = status; } + ares_channel GetAresChannel() { return( m_pARESChannel ); } +#endif /* HAVE_C_ARES */ + private: //! making private for safety Csock( const Csock & cCopy ) {} @@ -1010,6 +1020,12 @@ private: ECONState m_eConState; CS_STRING m_sBindHost; u_int m_iCurBindCount, m_iDNSTryCount; +#ifdef HAVE_C_ARES + void FreeAres(); + ares_channel m_pARESChannel; + CSSockAddr *m_pCurrAddr; + int m_iARESStatus; +#endif /* HAVE_C_ARES */ }; @@ -1369,7 +1385,6 @@ public: if ( ( pcSock->GetType() != T::OUTBOUND ) || ( pcSock->GetConState() == T::CST_OK ) ) continue; - if ( pcSock->GetConState() == T::CST_DNS ) { if ( pcSock->DNSLookup( T::DNS_VHOST ) == ETIMEDOUT ) @@ -1847,24 +1862,32 @@ protected: TFD_ZERO( &rfds ); TFD_ZERO( &wfds ); - // before we go any further, Process work needing to be done on the job - for( unsigned int i = 0; i < this->size(); i++ ) - { - Csock::ECloseType eCloseType = (*this)[i]->GetCloseType(); - if( eCloseType == T::CLT_NOW || eCloseType == T::CLT_DEREFERENCE || ( eCloseType == T::CLT_AFTERWRITE && (*this)[i]->GetWriteBuffer().empty() ) ) - DelSock( i-- ); // close any socks that have requested it - else - (*this)[i]->Cron(); // call the Cron handler here - } - bool bHasWriteable = false; bool bHasAvailSocks = false; unsigned long long iNOW = 0; - for( unsigned int i = 0; i < this->size(); i++ ) { T *pcSock = (*this)[i]; + Csock::ECloseType eCloseType = pcSock->GetCloseType(); + + if( eCloseType == T::CLT_NOW || eCloseType == T::CLT_DEREFERENCE || ( eCloseType == T::CLT_AFTERWRITE && pcSock->GetWriteBuffer().empty() ) ) + { + DelSock( i-- ); // close any socks that have requested it + continue; + } + else + pcSock->Cron(); // call the Cron handler here + +#ifdef HAVE_C_ARES + ares_channel pChannel = pcSock->GetAresChannel(); + if( pChannel ) + { + ares_fds( pChannel, &rfds, &wfds ); + bHasWriteable = true; + } +#endif /* HAVE_C_ARES */ + if ( pcSock->GetConState() != T::CST_OK ) continue; @@ -1929,18 +1952,8 @@ protected: } else TFD_SET( iRSock, &rfds ); - } - - // first check to see if any ssl sockets are ready for immediate read - // a mini select() type deal for ssl - for( unsigned int i = 0; i < this->size(); i++ ) - { - T *pcSock = (*this)[i]; - - if ( pcSock->GetConState() != T::CST_OK ) - continue; - - if ( ( pcSock->GetSSL() ) && ( pcSock->GetType() != Csock::LISTENER ) ) + + if( pcSock->GetSSL() && pcSock->GetType() != Csock::LISTENER ) { if ( ( pcSock->GetPending() > 0 ) && ( !pcSock->IsReadPaused() ) ) SelectSock( mpeSocks, SUCCESS, pcSock ); @@ -1961,7 +1974,6 @@ protected: tv.tv_sec = 0; } - if ( bHasWriteable ) iSel = Select(FD_SETSIZE, &rfds, &wfds, NULL, &tv); else @@ -2002,6 +2014,12 @@ protected: { T *pcSock = (*this)[i]; +#ifdef HAVE_C_ARES + ares_channel pChannel = pcSock->GetAresChannel(); + if( pChannel ) + ares_process( pChannel, &rfds, &wfds ); +#endif /* HAVE_C_ARES */ + if ( pcSock->GetConState() != T::CST_OK ) continue;