mirror of
https://github.com/znc/znc.git
synced 2026-05-02 03:22:33 +02:00
Update to latest Csocket. A Thank You goes out to DGandalf for noticing a bug in Csocket's c-ares code and another one of course to Imaginos for promptly looking into and fixing this.
The issue was that a timeout was being applied when c-ares really takes care of timeouts. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1707 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
89
Csocket.cpp
89
Csocket.cpp
@@ -28,7 +28,7 @@
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $Revision: 1.108 $
|
||||
* $Revision: 1.115 $
|
||||
*/
|
||||
|
||||
#include "Csocket.h"
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#ifndef _NO_CSOCKET_NS // some people may not want to use a namespace
|
||||
namespace Csocket
|
||||
{
|
||||
@@ -77,26 +78,26 @@ static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static inline void set_non_blocking(int fd)
|
||||
static inline void set_non_blocking(cs_sock_t fd)
|
||||
{
|
||||
u_long iOpts = 1;
|
||||
ioctlsocket( fd, FIONBIO, &iOpts );
|
||||
}
|
||||
|
||||
static inline void set_blocking(int fd)
|
||||
static inline void set_blocking(cs_sock_t fd)
|
||||
{
|
||||
u_long iOpts = 0;
|
||||
ioctlsocket( fd, FIONBIO, &iOpts );
|
||||
}
|
||||
|
||||
static inline void set_close_on_exec(int fd)
|
||||
static inline void set_close_on_exec(cs_sock_t fd)
|
||||
{
|
||||
// TODO add this for windows
|
||||
// see http://gcc.gnu.org/ml/java-patches/2002-q1/msg00696.html
|
||||
// for infos on how to do this
|
||||
}
|
||||
#else
|
||||
static inline void set_non_blocking(int fd)
|
||||
static inline void set_non_blocking(cs_sock_t fd)
|
||||
{
|
||||
int fdflags = fcntl(fd, F_GETFL, 0);
|
||||
if ( fdflags < 0 )
|
||||
@@ -104,7 +105,7 @@ static inline void set_non_blocking(int fd)
|
||||
fcntl( fd, F_SETFL, fdflags|O_NONBLOCK );
|
||||
}
|
||||
|
||||
static inline void set_blocking(int fd)
|
||||
static inline void set_blocking(cs_sock_t fd)
|
||||
{
|
||||
int fdflags = fcntl(fd, F_GETFL, 0);
|
||||
if ( fdflags < 0 )
|
||||
@@ -113,7 +114,7 @@ static inline void set_blocking(int fd)
|
||||
fcntl( fd, F_SETFL, fdflags );
|
||||
}
|
||||
|
||||
static inline void set_close_on_exec(int fd)
|
||||
static inline void set_close_on_exec(cs_sock_t fd)
|
||||
{
|
||||
int fdflags = fcntl(fd, F_GETFD, 0);
|
||||
if ( fdflags < 0 )
|
||||
@@ -592,8 +593,8 @@ Csock::~Csock()
|
||||
} else if( m_iReadSock >= 0 )
|
||||
CS_CLOSE( m_iReadSock );
|
||||
|
||||
m_iReadSock = -1;
|
||||
m_iWriteSock = -1;
|
||||
m_iReadSock = CS_INVALID_SOCK;
|
||||
m_iWriteSock = CS_INVALID_SOCK;
|
||||
|
||||
// delete any left over crons
|
||||
for( vector<CCron *>::size_type i = 0; i < m_vcCrons.size(); i++ )
|
||||
@@ -602,7 +603,7 @@ Csock::~Csock()
|
||||
|
||||
void Csock::Dereference()
|
||||
{
|
||||
m_iWriteSock = m_iReadSock = -1;
|
||||
m_iWriteSock = m_iReadSock = CS_INVALID_SOCK;
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
m_ssl = NULL;
|
||||
@@ -617,7 +618,7 @@ void Csock::Copy( const Csock & cCopy )
|
||||
{
|
||||
m_iTcount = cCopy.m_iTcount;
|
||||
m_iLastCheckTimeoutTime = cCopy.m_iLastCheckTimeoutTime;
|
||||
m_iport = cCopy.m_iport;
|
||||
m_uPort = cCopy.m_uPort;
|
||||
m_iRemotePort = cCopy.m_iRemotePort;
|
||||
m_iLocalPort = cCopy.m_iLocalPort;
|
||||
m_iReadSock = cCopy.m_iReadSock;
|
||||
@@ -916,9 +917,9 @@ bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u
|
||||
return( false );
|
||||
}
|
||||
|
||||
m_iReadSock = m_iWriteSock = SOCKET( true );
|
||||
m_iReadSock = m_iWriteSock = CreateSocket( true );
|
||||
|
||||
if ( m_iReadSock == -1 )
|
||||
if ( m_iReadSock == CS_INVALID_SOCK )
|
||||
return( false );
|
||||
|
||||
m_address.SinFamily();
|
||||
@@ -1041,6 +1042,15 @@ bool Csock::SSLClientSetup()
|
||||
FREE_SSL();
|
||||
FREE_CTX();
|
||||
|
||||
#ifdef _WIN64
|
||||
if( m_iReadSock != (int)m_iReadSock || m_iWriteSock != (int)m_iWriteSock )
|
||||
{
|
||||
// sanity check the FD to be sure its compatible with openssl
|
||||
CS_DEBUG( "ERROR: sockfd larger than OpenSSL can handle" );
|
||||
return( false );
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
switch( m_iMethod )
|
||||
{
|
||||
case SSL2:
|
||||
@@ -1106,8 +1116,8 @@ bool Csock::SSLClientSetup()
|
||||
if ( !m_ssl )
|
||||
return( false );
|
||||
|
||||
SSL_set_rfd( m_ssl, m_iReadSock );
|
||||
SSL_set_wfd( m_ssl, m_iWriteSock );
|
||||
SSL_set_rfd( m_ssl, (int)m_iReadSock );
|
||||
SSL_set_wfd( m_ssl, (int)m_iWriteSock );
|
||||
SSL_set_verify( m_ssl, SSL_VERIFY_PEER, ( m_pCerVerifyCB ? m_pCerVerifyCB : CertVerifyCB ) );
|
||||
SSL_set_ex_data( m_ssl, GetCsockClassIdx(), this );
|
||||
|
||||
@@ -1126,6 +1136,16 @@ bool Csock::SSLServerSetup()
|
||||
FREE_SSL();
|
||||
FREE_CTX();
|
||||
|
||||
#ifdef _WIN64
|
||||
if( m_iReadSock != (int)m_iReadSock || m_iWriteSock != (int)m_iWriteSock )
|
||||
{
|
||||
// sanity check the FD to be sure its compatible with openssl
|
||||
CS_DEBUG( "ERROR: sockfd larger than OpenSSL can handle" );
|
||||
return( false );
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
switch( m_iMethod )
|
||||
{
|
||||
case SSL2:
|
||||
@@ -1207,8 +1227,8 @@ bool Csock::SSLServerSetup()
|
||||
return( false );
|
||||
|
||||
// Call for client Verification
|
||||
SSL_set_rfd( m_ssl, m_iReadSock );
|
||||
SSL_set_wfd( m_ssl, m_iWriteSock );
|
||||
SSL_set_rfd( m_ssl, (int)m_iReadSock );
|
||||
SSL_set_wfd( m_ssl, (int)m_iWriteSock );
|
||||
SSL_set_accept_state( m_ssl );
|
||||
if ( m_iRequireClientCertFlags )
|
||||
{
|
||||
@@ -1226,7 +1246,7 @@ bool Csock::SSLServerSetup()
|
||||
bool Csock::ConnectSSL( const CS_STRING & sBindhost )
|
||||
{
|
||||
#ifdef HAVE_LIBSSL
|
||||
if ( m_iReadSock == -1 )
|
||||
if ( m_iReadSock == CS_INVALID_SOCK )
|
||||
if ( !Connect( sBindhost ) )
|
||||
return( false );
|
||||
if ( !m_ssl )
|
||||
@@ -1580,12 +1600,12 @@ CS_STRING Csock::GetRemoteIP()
|
||||
bool Csock::IsConnected() { return( m_bIsConnected ); }
|
||||
void Csock::SetIsConnected( bool b ) { m_bIsConnected = b; }
|
||||
|
||||
int & Csock::GetRSock() { return( m_iReadSock ); }
|
||||
void Csock::SetRSock( int iSock ) { m_iReadSock = iSock; }
|
||||
int & Csock::GetWSock() { return( m_iWriteSock ); }
|
||||
void Csock::SetWSock( int iSock ) { m_iWriteSock = iSock; }
|
||||
void Csock::SetSock( int iSock ) { m_iWriteSock = iSock; m_iReadSock = iSock; }
|
||||
int & Csock::GetSock() { return( m_iReadSock ); }
|
||||
cs_sock_t & Csock::GetRSock() { return( m_iReadSock ); }
|
||||
void Csock::SetRSock( cs_sock_t iSock ) { m_iReadSock = iSock; }
|
||||
cs_sock_t & Csock::GetWSock() { return( m_iWriteSock ); }
|
||||
void Csock::SetWSock( cs_sock_t iSock ) { m_iWriteSock = iSock; }
|
||||
void Csock::SetSock( cs_sock_t iSock ) { m_iWriteSock = iSock; m_iReadSock = iSock; }
|
||||
cs_sock_t & Csock::GetSock() { return( m_iReadSock ); }
|
||||
void Csock::ResetTimer() { m_iLastCheckTimeoutTime = 0; m_iTcount = 0; }
|
||||
void Csock::PauseRead() { m_bPauseRead = true; }
|
||||
bool Csock::IsReadPaused() { return( m_bPauseRead ); }
|
||||
@@ -1779,8 +1799,8 @@ u_short Csock::GetLocalPort()
|
||||
return( m_iLocalPort );
|
||||
}
|
||||
|
||||
u_short Csock::GetPort() { return( m_iport ); }
|
||||
void Csock::SetPort( u_short iPort ) { m_iport = iPort; }
|
||||
u_short Csock::GetPort() { return( m_uPort ); }
|
||||
void Csock::SetPort( u_short iPort ) { m_uPort = iPort; }
|
||||
void Csock::Close( ECloseType eCloseType )
|
||||
{
|
||||
m_eCloseType = eCloseType;
|
||||
@@ -2059,6 +2079,7 @@ int Csock::GetPending()
|
||||
|
||||
int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr )
|
||||
{
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_IPV6
|
||||
if( csSockAddr.GetAFRequire() != AF_INET && inet_pton( AF_INET6, sHostname.c_str(), csSockAddr.GetAddr6() ) > 0 )
|
||||
{
|
||||
@@ -2073,6 +2094,7 @@ int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr )
|
||||
#endif /* HAVE_IPV6 */
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef HAVE_C_ARES
|
||||
if( GetType() != LISTENER )
|
||||
@@ -2088,6 +2110,7 @@ int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr )
|
||||
int iFamily = AF_INET;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
// as of ares 1.6.0 if it fails on af_inet6, it falls back to af_inet, this code was here in the previous Csocket version, just adding the comment as a reminder
|
||||
iFamily = csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY ? AF_INET6 : csSockAddr.GetAFRequire();
|
||||
#endif /* HAVE_IPV6 */
|
||||
ares_gethostbyname( m_pARESChannel, sHostname.c_str(), iFamily, AresHostCallback, this );
|
||||
@@ -2153,12 +2176,14 @@ int Csock::DNSLookup( EDNSLType eDNSLType )
|
||||
}
|
||||
else if ( iRet == EAGAIN )
|
||||
{
|
||||
#ifndef HAVE_C_ARES
|
||||
m_iDNSTryCount++;
|
||||
if ( m_iDNSTryCount > 20 )
|
||||
{
|
||||
m_iDNSTryCount = 0;
|
||||
return( ETIMEDOUT );
|
||||
}
|
||||
#endif /* HAVE_C_ARES */
|
||||
return( EAGAIN );
|
||||
}
|
||||
m_iDNSTryCount = 0;
|
||||
@@ -2218,12 +2243,12 @@ void Csock::FREE_CTX()
|
||||
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
int Csock::SOCKET( bool bListen )
|
||||
cs_sock_t Csock::CreateSocket( bool bListen )
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
int iRet = socket( ( GetIPv6() ? PF_INET6 : PF_INET ), SOCK_STREAM, IPPROTO_TCP );
|
||||
cs_sock_t iRet = socket( ( GetIPv6() ? PF_INET6 : PF_INET ), SOCK_STREAM, IPPROTO_TCP );
|
||||
#else
|
||||
int iRet = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
cs_sock_t iRet = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
if ( iRet >= 0 ) {
|
||||
@@ -2250,12 +2275,12 @@ void Csock::Init( const CS_STRING & sHostname, u_short uPort, int itimeout )
|
||||
m_iRequireClientCertFlags = 0;
|
||||
#endif /* HAVE_LIBSSL */
|
||||
m_iTcount = 0;
|
||||
m_iReadSock = -1;
|
||||
m_iWriteSock = -1;
|
||||
m_iReadSock = CS_INVALID_SOCK;
|
||||
m_iWriteSock = CS_INVALID_SOCK;
|
||||
m_itimeout = itimeout;
|
||||
m_bssl = false;
|
||||
m_bIsConnected = false;
|
||||
m_iport = uPort;
|
||||
m_uPort = uPort;
|
||||
m_shostname = sHostname;
|
||||
m_sbuffer.clear();
|
||||
m_eCloseType = CLT_DONT;
|
||||
|
||||
76
Csocket.h
76
Csocket.h
@@ -28,7 +28,7 @@
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $Revision: 1.213 $
|
||||
* $Revision: 1.216 $
|
||||
*/
|
||||
|
||||
// note to compile with win32 need to link to winsock2, using gcc its -lws2_32
|
||||
@@ -83,6 +83,7 @@
|
||||
#endif /* __sun */
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -115,6 +116,14 @@
|
||||
#endif /* __DEBUG__ */
|
||||
#endif /* PERROR */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef SOCKET cs_sock_t;
|
||||
#define CS_INVALID_SOCK INVALID_SOCKET
|
||||
#else
|
||||
typedef int cs_sock_t;
|
||||
#define CS_INVALID_SOCK -1
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifndef _NO_CSOCKET_NS // some people may not want to use a namespace
|
||||
namespace Csocket
|
||||
{
|
||||
@@ -412,10 +421,10 @@ public:
|
||||
* Advanced constructor, for creating a simple connection
|
||||
*
|
||||
* @param sHostname the hostname your are connecting to
|
||||
* @param iport the port you are connectint to
|
||||
* @param uPort the port you are connectint to
|
||||
* @param itimeout how long to wait before ditching the connection, default is 60 seconds
|
||||
*/
|
||||
Csock( const CS_STRING & sHostname, u_short iport, int itimeout = 60 );
|
||||
Csock( const CS_STRING & sHostname, u_short uPort, int itimeout = 60 );
|
||||
|
||||
//! override this for accept sockets
|
||||
virtual Csock *GetSockObj( const CS_STRING & sHostname, u_short iPort );
|
||||
@@ -588,13 +597,13 @@ public:
|
||||
virtual void SetIsConnected( bool b );
|
||||
|
||||
//! returns a reference to the sock
|
||||
int & GetRSock();
|
||||
void SetRSock( int iSock );
|
||||
int & GetWSock();
|
||||
void SetWSock( int iSock );
|
||||
cs_sock_t & GetRSock();
|
||||
void SetRSock( cs_sock_t iSock );
|
||||
cs_sock_t & GetWSock();
|
||||
void SetWSock( cs_sock_t iSock );
|
||||
|
||||
void SetSock( int iSock );
|
||||
int & GetSock();
|
||||
void SetSock( cs_sock_t iSock );
|
||||
cs_sock_t & GetSock();
|
||||
|
||||
//! resets the time counter, this is virtual in the event you need an event on the timer being Reset
|
||||
virtual void ResetTimer();
|
||||
@@ -909,15 +918,15 @@ public:
|
||||
//! grabs fd's for the sockets
|
||||
bool CreateSocksFD()
|
||||
{
|
||||
if( m_iReadSock != -1 )
|
||||
if( m_iReadSock != CS_INVALID_SOCK )
|
||||
return( true );
|
||||
|
||||
m_iReadSock = m_iWriteSock = SOCKET();
|
||||
if ( m_iReadSock == -1 )
|
||||
m_iReadSock = m_iWriteSock = CreateSocket();
|
||||
if ( m_iReadSock == CS_INVALID_SOCK )
|
||||
return( false );
|
||||
|
||||
m_address.SinFamily();
|
||||
m_address.SinPort( m_iport );
|
||||
m_address.SinPort( m_uPort );
|
||||
|
||||
return( true );
|
||||
}
|
||||
@@ -981,8 +990,9 @@ private:
|
||||
Csock( const Csock & cCopy ) {}
|
||||
|
||||
// NOTE! if you add any new members, be sure to add them to Copy()
|
||||
u_short m_iport, m_iRemotePort, m_iLocalPort;
|
||||
int m_iReadSock, m_iWriteSock, m_itimeout, m_iConnType, m_iMethod, m_iTcount;
|
||||
u_short m_uPort, m_iRemotePort, m_iLocalPort;
|
||||
cs_sock_t m_iReadSock, m_iWriteSock;
|
||||
int m_itimeout, m_iConnType, m_iMethod, m_iTcount;
|
||||
bool m_bssl, m_bIsConnected, m_bBLOCK, m_bFullsslAccept;
|
||||
bool m_bsslEstablished, m_bEnableReadLine, m_bPauseRead;
|
||||
CS_STRING m_shostname, m_sbuffer, m_sSockName, m_sPemFile, m_sCipherType, m_sParentName;
|
||||
@@ -1012,8 +1022,8 @@ private:
|
||||
std::vector<CCron *> m_vcCrons;
|
||||
|
||||
//! Create the socket
|
||||
int SOCKET( bool bListen = false );
|
||||
void Init( const CS_STRING & sHostname, u_short iport, int itimeout = 60 );
|
||||
cs_sock_t CreateSocket( bool bListen = false );
|
||||
void Init( const CS_STRING & sHostname, u_short uPort, int itimeout = 60 );
|
||||
|
||||
|
||||
// Connection State Info
|
||||
@@ -1631,7 +1641,7 @@ public:
|
||||
}
|
||||
|
||||
//! returns a pointer to the FIRST sock found by filedescriptor or NULL on no match
|
||||
virtual T * FindSockByFD( int iFD )
|
||||
virtual T * FindSockByFD( cs_sock_t iFD )
|
||||
{
|
||||
for( unsigned int i = 0; i < this->size(); i++ )
|
||||
if ( ( (*this)[i]->GetRSock() == iFD ) || ( (*this)[i]->GetWSock() == iFD ) )
|
||||
@@ -1840,7 +1850,7 @@ protected:
|
||||
{
|
||||
return( select( nfds, readfds, writefds, exceptfds, timeout ) );
|
||||
}
|
||||
protected:
|
||||
private:
|
||||
/**
|
||||
* fills a map of socks to a message for check
|
||||
* map is empty if none are ready, check GetErrno() for the error, if not SUCCESS Select() failed
|
||||
@@ -1893,15 +1903,15 @@ protected:
|
||||
|
||||
bHasAvailSocks = true;
|
||||
|
||||
int & iRSock = pcSock->GetRSock();
|
||||
int & iWSock = pcSock->GetWSock();
|
||||
cs_sock_t & iRSock = pcSock->GetRSock();
|
||||
cs_sock_t & iWSock = pcSock->GetWSock();
|
||||
bool bIsReadPaused = pcSock->IsReadPaused();
|
||||
if ( bIsReadPaused )
|
||||
{
|
||||
pcSock->ReadPaused();
|
||||
bIsReadPaused = pcSock->IsReadPaused(); // re-read it again, incase it changed status)
|
||||
}
|
||||
if ( ( iRSock < 0 ) || ( iWSock < 0 ) )
|
||||
if ( iRSock == CS_INVALID_SOCK || iWSock == CS_INVALID_SOCK )
|
||||
{
|
||||
SelectSock( mpeSocks, SUCCESS, pcSock );
|
||||
continue; // invalid sock fd
|
||||
@@ -1996,7 +2006,8 @@ protected:
|
||||
m_errno = SUCCESS;
|
||||
|
||||
return;
|
||||
} else if ( iSel == -1 )
|
||||
}
|
||||
else if ( iSel == -1 )
|
||||
{
|
||||
if ( mpeSocks.empty() )
|
||||
m_errno = SELECT_ERROR;
|
||||
@@ -2004,7 +2015,8 @@ protected:
|
||||
m_errno = SUCCESS;
|
||||
|
||||
return;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errno = SUCCESS;
|
||||
}
|
||||
@@ -2017,17 +2029,25 @@ protected:
|
||||
#ifdef HAVE_C_ARES
|
||||
ares_channel pChannel = pcSock->GetAresChannel();
|
||||
if( pChannel )
|
||||
ares_process( pChannel, &rfds, &wfds );
|
||||
{
|
||||
int iAresFD;
|
||||
ares_getsock( pChannel, &iAresFD, 1 );
|
||||
// only process the channels that are actually set in the read/write set
|
||||
// this should effectively be the same as finding the max timeout amongst ares fd's
|
||||
// as this fd is either ready or its not
|
||||
if( TFD_ISSET( iAresFD, &rfds ) || TFD_ISSET( iAresFD, &wfds ) )
|
||||
ares_process( pChannel, &rfds, &wfds );
|
||||
}
|
||||
#endif /* HAVE_C_ARES */
|
||||
|
||||
if ( pcSock->GetConState() != T::CST_OK )
|
||||
continue;
|
||||
|
||||
int & iRSock = pcSock->GetRSock();
|
||||
int & iWSock = pcSock->GetWSock();
|
||||
cs_sock_t & iRSock = pcSock->GetRSock();
|
||||
cs_sock_t & iWSock = pcSock->GetWSock();
|
||||
EMessages iErrno = SUCCESS;
|
||||
|
||||
if ( ( iRSock < 0 ) || ( iWSock < 0 ) )
|
||||
if ( iRSock == CS_INVALID_SOCK || iWSock == CS_INVALID_SOCK )
|
||||
{
|
||||
// trigger a success so it goes through the normal motions
|
||||
// and an error is produced
|
||||
|
||||
Reference in New Issue
Block a user