mirror of
https://github.com/znc/znc.git
synced 2026-05-01 02:52:30 +02:00
Pulled in changes for Csocket.. temporarily added old style Listen*() and Connect() functions to CSockManager wrapper class
git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@651 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
231
Csocket.cpp
231
Csocket.cpp
@@ -40,94 +40,54 @@ namespace Csocket
|
||||
{
|
||||
#endif /* _NO_CSOCKET_NS */
|
||||
|
||||
int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr )
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo hints;
|
||||
memset( (struct addrinfo *)&hints, '\0', sizeof( hints ) );
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
int iRet = getaddrinfo( sHostname.c_str(), NULL, &hints, &res );
|
||||
if( iRet == EAI_AGAIN )
|
||||
return( EAGAIN );
|
||||
else if( ( iRet == 0 ) && ( res ) )
|
||||
{
|
||||
bool bFoundEntry = false;
|
||||
for( struct addrinfo *pRes = res; pRes; pRes = pRes->ai_next )
|
||||
{
|
||||
if( ( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP ) )
|
||||
continue;
|
||||
if( pRes->ai_family == AF_INET )
|
||||
{
|
||||
if( pSock )
|
||||
pSock->SetIPv6( false );
|
||||
csSockAddr.SetIPv6( false );
|
||||
struct sockaddr_in *pTmp = (struct sockaddr_in *)pRes->ai_addr;
|
||||
memcpy( csSockAddr.GetAddr(), &(pTmp->sin_addr), sizeof( *(csSockAddr.GetAddr()) ) );
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
int GetHostByName6( const CS_STRING & sHostName, in6_addr * paddr, u_int iNumRetries )
|
||||
{
|
||||
int iReturn = HOST_NOT_FOUND;
|
||||
struct hostent *hent = NULL;
|
||||
if( ( sHostName.find( ":" ) != CS_STRING::npos ) && ( inet_pton( AF_INET6, sHostName.c_str(), paddr ) > 0 ) )
|
||||
return( 0 );
|
||||
|
||||
#ifdef __linux__
|
||||
char hbuff[2048];
|
||||
struct hostent hentbuff;
|
||||
|
||||
int err;
|
||||
for( u_int a = 0; a < iNumRetries; a++ )
|
||||
{
|
||||
memset( (char *)hbuff, '\0', 2048 );
|
||||
iReturn = gethostbyname2_r( sHostName.c_str(), AF_INET6, &hentbuff, hbuff, 2048, &hent, &err );
|
||||
if ( iReturn == 0 )
|
||||
break;
|
||||
|
||||
if ( iReturn != TRY_AGAIN )
|
||||
break;
|
||||
|
||||
PERROR( "gethostbyname_r" );
|
||||
}
|
||||
if ( ( !hent ) && ( iReturn == 0 ) )
|
||||
iReturn = HOST_NOT_FOUND;
|
||||
#else
|
||||
hent = gethostbyname2( sHostName.c_str(), AF_INET6 );
|
||||
|
||||
if ( hent )
|
||||
iReturn = 0;
|
||||
else
|
||||
{
|
||||
PERROR( "gethostbyname2" );
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
if ( iReturn == 0 )
|
||||
memcpy( &paddr->s6_addr, hent->h_addr_list[0], sizeof( paddr->s6_addr ) );
|
||||
|
||||
return( iReturn );
|
||||
}
|
||||
else if( pRes->ai_family == AF_INET6 )
|
||||
{
|
||||
if( pSock )
|
||||
pSock->SetIPv6( true );
|
||||
csSockAddr.SetIPv6( true );
|
||||
struct sockaddr_in6 *pTmp = (struct sockaddr_in6 *)pRes->ai_addr;
|
||||
memcpy( csSockAddr.GetAddr6(), &(pTmp->sin6_addr), sizeof( *(csSockAddr.GetAddr6()) ) );
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
int GetHostByName( const CS_STRING & sHostName, in_addr * paddr, u_int iNumRetries )
|
||||
{
|
||||
int iReturn = HOST_NOT_FOUND;
|
||||
struct hostent *hent = NULL;
|
||||
|
||||
#ifdef __linux__
|
||||
char hbuff[2048];
|
||||
struct hostent hentbuff;
|
||||
|
||||
int err;
|
||||
for( u_int a = 0; a < iNumRetries; a++ )
|
||||
{
|
||||
memset( (char *)hbuff, '\0', 2048 );
|
||||
iReturn = gethostbyname_r( sHostName.c_str(), &hentbuff, hbuff, 2048, &hent, &err );
|
||||
|
||||
if ( iReturn == 0 )
|
||||
else
|
||||
continue;
|
||||
bFoundEntry = true;
|
||||
break;
|
||||
|
||||
if ( iReturn != TRY_AGAIN )
|
||||
break;
|
||||
|
||||
PERROR( "gethostbyname_r" );
|
||||
}
|
||||
freeaddrinfo( res );
|
||||
if( bFoundEntry )
|
||||
return( 0 );
|
||||
}
|
||||
if ( ( !hent ) && ( iReturn == 0 ) )
|
||||
iReturn = HOST_NOT_FOUND;
|
||||
#else
|
||||
hent = gethostbyname( sHostName.c_str() );
|
||||
|
||||
if ( hent )
|
||||
iReturn = 0;
|
||||
else
|
||||
{
|
||||
PERROR( "gethostbyname" );
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
if ( iReturn == 0 )
|
||||
memcpy( &paddr->s_addr, hent->h_addr_list[0], sizeof( paddr->s_addr ) );
|
||||
|
||||
return( iReturn );
|
||||
return( ETIMEDOUT );
|
||||
}
|
||||
|
||||
#ifdef ___DO_THREADS
|
||||
CSMutex::CSMutex()
|
||||
{
|
||||
@@ -207,33 +167,18 @@ void *CSThread::start_thread( void *args )
|
||||
pthread_exit( NULL );
|
||||
}
|
||||
|
||||
void CDNSResolver::Lookup( const CS_STRING & sHostname, bool bIsIPv6 )
|
||||
void CDNSResolver::Lookup( const CS_STRING & sHostname )
|
||||
{
|
||||
m_bSuccess = false;
|
||||
m_sHostname = sHostname;
|
||||
memset( (struct in_addr *)&m_inAddr, '\0', sizeof( m_inAddr ) );
|
||||
#ifdef HAVE_IPV6
|
||||
m_bIsIPv6 = bIsIPv6;
|
||||
memset( (struct in6_addr *)&m_inAddr6, '\0', sizeof( m_inAddr6 ) );
|
||||
#endif /* HAVE_IPV6 */
|
||||
start();
|
||||
}
|
||||
|
||||
void CDNSResolver::run()
|
||||
{
|
||||
m_bSuccess = false;
|
||||
if( !m_bIsIPv6 )
|
||||
{
|
||||
if ( GetHostByName( m_sHostname, &m_inAddr ) == 0 )
|
||||
m_bSuccess = true;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
if ( GetHostByName6( m_sHostname, &m_inAddr6 ) == 0 )
|
||||
m_bSuccess = true;
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
if( GetAddrInfo( m_sHostname, NULL, m_cSockAddr ) == 0 )
|
||||
m_bSuccess = true;
|
||||
}
|
||||
|
||||
bool CDNSResolver::IsCompleted()
|
||||
@@ -246,13 +191,6 @@ bool CDNSResolver::IsCompleted()
|
||||
return( false );
|
||||
}
|
||||
|
||||
CS_STRING CDNSResolver::CreateIP( const struct in_addr *pAddr )
|
||||
{
|
||||
struct in_addr inAddr;
|
||||
memcpy( (struct in_addr *)&inAddr, pAddr, sizeof( inAddr ) );
|
||||
return( inet_ntoa( inAddr ) );
|
||||
}
|
||||
|
||||
#endif /* ___DO_THREADS */
|
||||
#ifdef HAVE_LIBSSL
|
||||
bool InitSSL( ECompType eCompressionType )
|
||||
@@ -540,9 +478,6 @@ bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup )
|
||||
m_sBindHost = sBindHost;
|
||||
if ( !bSkipSetup )
|
||||
{
|
||||
if ( !CreateSocksFD() )
|
||||
return( false );
|
||||
|
||||
int iDNSRet = ETIMEDOUT;
|
||||
while( true )
|
||||
{
|
||||
@@ -688,30 +623,22 @@ int Csock::ReadSelect()
|
||||
|
||||
bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u_int iTimeout )
|
||||
{
|
||||
m_iReadSock = m_iWriteSock = SOCKET( true );
|
||||
m_iConnType = LISTENER;
|
||||
m_itimeout = iTimeout;
|
||||
|
||||
m_sBindHost = sBindHost;
|
||||
if ( !sBindHost.empty() )
|
||||
{
|
||||
if( GetAddrInfo( sBindHost, this, m_address ) != 0 )
|
||||
return( false );
|
||||
}
|
||||
|
||||
m_iReadSock = m_iWriteSock = SOCKET( true );
|
||||
|
||||
if ( m_iReadSock == -1 )
|
||||
return( false );
|
||||
|
||||
m_sBindHost = sBindHost;
|
||||
m_address.SinFamily();
|
||||
if ( !sBindHost.empty() )
|
||||
{
|
||||
if( !GetIPv6() )
|
||||
{
|
||||
if ( GetHostByName( sBindHost, m_address.GetAddr() ) != 0 )
|
||||
return( false );
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
if ( GetHostByName6( sBindHost, m_address.GetAddr6() ) != 0 )
|
||||
return( false );
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
}
|
||||
m_address.SinPort( iPort );
|
||||
|
||||
if( !GetIPv6() )
|
||||
@@ -1812,7 +1739,7 @@ int Csock::DNSLookup( EDNSLType eDNSLType )
|
||||
#ifdef ___DO_THREADS
|
||||
if ( m_iDNSTryCount == 0 )
|
||||
{
|
||||
m_cResolver.Lookup( ( eDNSLType == DNS_VHOST ) ? m_sBindHost : m_shostname, GetIPv6() );
|
||||
m_cResolver.Lookup( ( eDNSLType == DNS_VHOST ) ? m_sBindHost : m_shostname );
|
||||
m_iDNSTryCount++;
|
||||
}
|
||||
|
||||
@@ -1823,25 +1750,40 @@ int Csock::DNSLookup( EDNSLType eDNSLType )
|
||||
{
|
||||
if ( eDNSLType == DNS_VHOST )
|
||||
{
|
||||
if( !GetIPv6() )
|
||||
memcpy( m_bindhost.GetAddr(), m_cResolver.GetAddr(), sizeof( *(m_bindhost.GetAddr()) ) );
|
||||
if( !m_cResolver.GetSockAddr()->GetIPv6() )
|
||||
{
|
||||
SetIPv6( false );
|
||||
memcpy( m_bindhost.GetAddr(), m_cResolver.GetSockAddr()->GetAddr(), sizeof( *(m_bindhost.GetAddr()) ) );
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy( m_bindhost.GetAddr6(), m_cResolver.GetAddr6(), sizeof( *(m_bindhost.GetAddr6()) ) );
|
||||
{
|
||||
SetIPv6( true );
|
||||
memcpy( m_bindhost.GetAddr6(), m_cResolver.GetSockAddr()->GetAddr6(), sizeof( *(m_bindhost.GetAddr6()) ) );
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !GetIPv6() )
|
||||
memcpy( m_address.GetAddr(), m_cResolver.GetAddr(), sizeof( *(m_address.GetAddr()) ) );
|
||||
if( m_cResolver.GetSockAddr()->GetIPv6() )
|
||||
{
|
||||
SetIPv6( false );
|
||||
memcpy( m_address.GetAddr(), m_cResolver.GetSockAddr()->GetAddr(), sizeof( *(m_address.GetAddr()) ) );
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy( m_address.GetAddr6(), m_cResolver.GetAddr6(), sizeof( *(m_address.GetAddr6()) ) );
|
||||
{
|
||||
SetIPv6( true );
|
||||
memcpy( m_address.GetAddr6(), m_cResolver.GetSockAddr()->GetAddr6(), sizeof( *(m_address.GetAddr6()) ) );
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
}
|
||||
|
||||
if ( m_eConState != CST_OK )
|
||||
m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_BINDVHOST : CST_VHOSTDNS );
|
||||
|
||||
if( !CreateSocksFD() )
|
||||
return( ETIMEDOUT );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@@ -1854,25 +1796,16 @@ int Csock::DNSLookup( EDNSLType eDNSLType )
|
||||
int iRet = ETIMEDOUT;
|
||||
if ( eDNSLType == DNS_VHOST )
|
||||
{
|
||||
if( !GetIPv6() )
|
||||
iRet = GetHostByName( m_sBindHost, m_bindhost.GetAddr(), 1 );
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
iRet = GetHostByName6( m_sBindHost, m_bindhost.GetAddr6(), 1 );
|
||||
#endif /* HAVE_IPV6 */
|
||||
iRet = GetAddrInfo( m_sBindHost, this, m_bindhost );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !GetIPv6() )
|
||||
iRet = GetHostByName( m_shostname, m_address.GetAddr(), 1 );
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
iRet = GetHostByName6( m_shostname, m_address.GetAddr6(), 1 );
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
iRet = GetAddrInfo( m_shostname, this, m_address );
|
||||
}
|
||||
|
||||
if( !CreateSocksFD() )
|
||||
iRet = ETIMEDOUT;
|
||||
|
||||
if ( iRet == 0 )
|
||||
{
|
||||
if ( m_eConState != CST_OK )
|
||||
|
||||
332
Csocket.h
332
Csocket.h
@@ -112,11 +112,6 @@ namespace Csocket
|
||||
{
|
||||
#endif /* _NO_CSOCKET_NS */
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
int GetHostByName6( const CS_STRING & sHostName, in6_addr * paddr, u_int iNumRetries = 20 );
|
||||
#endif /* HAVE_IPV6 */
|
||||
int GetHostByName( const CS_STRING & sHostName, in_addr * paddr, u_int iNumRetries = 20 );
|
||||
|
||||
class CSSockAddr
|
||||
{
|
||||
public:
|
||||
@@ -165,6 +160,7 @@ public:
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
m_bIsIPv6 = b;
|
||||
SinFamily();
|
||||
}
|
||||
bool GetIPv6() const { return( m_bIsIPv6 ); }
|
||||
|
||||
@@ -188,6 +184,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class Csock;
|
||||
int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr );
|
||||
|
||||
#if defined( _REENTRANT ) && defined( _USE_THREADED_DNS )
|
||||
#define ___DO_THREADS
|
||||
#include <pthread.h>
|
||||
@@ -242,36 +241,25 @@ private:
|
||||
class CDNSResolver : public CSThread
|
||||
{
|
||||
public:
|
||||
CDNSResolver() : CSThread() { m_bSuccess = false; m_bIsIPv6 = false; }
|
||||
CDNSResolver() : CSThread() { m_bSuccess = false; }
|
||||
virtual ~CDNSResolver() {}
|
||||
//! returns imediatly, from here out check if IsCompleted() returns true before looking at ANY of the data
|
||||
void Lookup( const CS_STRING & sHostname, bool bIsIPv6 = false );
|
||||
void Lookup( const CS_STRING & sHostname );
|
||||
|
||||
virtual void run();
|
||||
|
||||
//! returns the underlying in_addr structure containing the resolved hostname
|
||||
const struct in_addr * GetAddr() const { return( &m_inAddr ); }
|
||||
#ifdef HAVE_IPV6
|
||||
const struct in6_addr * GetAddr6() const { return( &m_inAddr6 ); }
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
//! true if dns entry was successfuly found
|
||||
bool Suceeded() const { return( m_bSuccess ); }
|
||||
|
||||
//! true if task is finished, this function is thread safe
|
||||
bool IsCompleted();
|
||||
|
||||
//! note!! inet_ntoa uses an internally static buffer, its not thread safe
|
||||
static CS_STRING CreateIP( const struct in_addr *pAddr );
|
||||
CSSockAddr * GetSockAddr() { return( &m_cSockAddr ); }
|
||||
|
||||
private:
|
||||
bool m_bSuccess, m_bIsIPv6;
|
||||
bool m_bSuccess;
|
||||
CS_STRING m_sHostname;
|
||||
struct in_addr m_inAddr;
|
||||
#ifdef HAVE_IPV6
|
||||
struct in6_addr m_inAddr6;
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
CSSockAddr m_cSockAddr;
|
||||
};
|
||||
|
||||
|
||||
@@ -396,11 +384,12 @@ public:
|
||||
const CS_STRING & GetName() const;
|
||||
void SetName( const CS_STRING & sName );
|
||||
|
||||
protected:
|
||||
public:
|
||||
|
||||
//! this is the method you should override
|
||||
virtual void RunJob();
|
||||
|
||||
private:
|
||||
time_t m_iTime;
|
||||
bool m_bActive, m_bPause;
|
||||
int m_iTimeSequence;
|
||||
@@ -876,6 +865,9 @@ public:
|
||||
//! grabs fd's for the sockets
|
||||
bool CreateSocksFD()
|
||||
{
|
||||
if( m_iReadSock != -1 )
|
||||
return( true );
|
||||
|
||||
m_iReadSock = m_iWriteSock = SOCKET();
|
||||
if ( m_iReadSock == -1 )
|
||||
return( false );
|
||||
@@ -956,6 +948,178 @@ private:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @class CSConnection
|
||||
* @brief options for creating a connection
|
||||
*/
|
||||
class CSConnection
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param sHostname hostname to connect to
|
||||
* @param iPort port to connect to
|
||||
* @param iTimeout connection timeout
|
||||
*/
|
||||
CSConnection( const CS_STRING & sHostname, u_short iPort, int iTimeout = 60 )
|
||||
{
|
||||
m_sHostname = sHostname;
|
||||
m_iPort = iPort;
|
||||
m_iTimeout = iTimeout;
|
||||
m_bIsSSL = false;
|
||||
m_bIsIPv6 = false;
|
||||
#ifdef HAVE_LIBSSL
|
||||
m_sCipher = "HIGH";
|
||||
#endif /* HAVE_LIBSSL */
|
||||
}
|
||||
virtual ~CSConnection() {}
|
||||
|
||||
const CS_STRING & GetHostname() const { return( m_sHostname ); }
|
||||
const CS_STRING & GetSockName() const { return( m_sSockName ); }
|
||||
const CS_STRING & GetBindHost() const { return( m_sBindHost ); }
|
||||
u_short GetPort() const { return( m_iPort ); }
|
||||
int GetTimeout() const { return( m_iTimeout ); }
|
||||
bool GetIsSSL() const { return( m_bIsSSL ); }
|
||||
bool GetIsIPv6() const { return( m_bIsIPv6 ); }
|
||||
#ifdef HAVE_LIBSSL
|
||||
const CS_STRING & GetCipher() const { return( m_sCipher ); }
|
||||
const CS_STRING & GetPemLocation() const { return( m_sPemLocation ); }
|
||||
const CS_STRING & GetPemPass() const { return( m_sPemPass ); }
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
//! sets the hostname to connect to
|
||||
void SetHostname( const CS_STRING & s ) { m_sHostname = s; }
|
||||
//! sets the name of the socket, used for reference, ie in FindSockByName()
|
||||
void SetSockName( const CS_STRING & s ) { m_sSockName = s; }
|
||||
//! sets the hostname to bind to (vhost support)
|
||||
void SetBindHost( const CS_STRING & s ) { m_sBindHost = s; }
|
||||
//! sets the port to connect to
|
||||
void SetPort( u_short i ) { m_iPort = i; }
|
||||
//! sets the connection timeout
|
||||
void SetTimeout( int i ) { m_iTimeout = i; }
|
||||
//! set to true to enable SSL
|
||||
void SetIsSSL( bool b ) { m_bIsSSL = b; }
|
||||
//! set to true to enable ipv6
|
||||
void SetIsIPv6( bool b ) { m_bIsIPv6 = b; }
|
||||
//! set the cipher strength to use, default is HIGH
|
||||
#ifdef HAVE_LIBSSL
|
||||
void SetCipher( const CS_STRING & s ) { m_sCipher = s; }
|
||||
//! set the location of the pemfile
|
||||
void SetPemLocation( const CS_STRING & s ) { m_sPemLocation = s; }
|
||||
//! set the pemfile pass
|
||||
void SetPemPass( const CS_STRING & s ) { m_sPemPass = s; }
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
protected:
|
||||
CS_STRING m_sHostname, m_sSockName, m_sBindHost;
|
||||
u_short m_iPort;
|
||||
int m_iTimeout;
|
||||
bool m_bIsSSL, m_bIsIPv6;
|
||||
#ifdef HAVE_LIBSSL
|
||||
CS_STRING m_sPemLocation, m_sPemPass, m_sCipher;
|
||||
#endif /* HAVE_LIBSSL */
|
||||
};
|
||||
|
||||
class CSSSLConnection : public CSConnection
|
||||
{
|
||||
public:
|
||||
CSSSLConnection( const CS_STRING & sHostname, u_short iPort, int iTimeout = 60 ) :
|
||||
CSConnection( sHostname, iPort, iTimeout )
|
||||
{
|
||||
SetIsSSL( true );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class CSListener
|
||||
* @brief options container to create a listener
|
||||
*/
|
||||
class CSListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param iPort port to listen on. Set to 0 to listen on a random port
|
||||
* @param sBindHost host to bind to
|
||||
*/
|
||||
CSListener( u_short iPort, const CS_STRING & sBindHost = "" )
|
||||
{
|
||||
m_iPort = iPort;
|
||||
m_sBindHost = sBindHost;
|
||||
m_bIsSSL = false;
|
||||
m_bIsIPv6 = false;
|
||||
m_iMaxConns = SOMAXCONN;
|
||||
m_iTimeout = 0;
|
||||
#ifdef HAVE_LIBSSL
|
||||
m_sCipher = "HIGH";
|
||||
m_bRequiresClientCert = false;
|
||||
#endif /* HAVE_LIBSSL */
|
||||
}
|
||||
virtual ~CSListener() {}
|
||||
|
||||
const u_short GetPort() const { return( m_iPort ); }
|
||||
const CS_STRING & GetSockName() const { return( m_sSockName ); }
|
||||
const CS_STRING & GetBindHost() const { return( m_sBindHost ); }
|
||||
bool GetIsSSL() const { return( m_bIsSSL ); }
|
||||
bool GetIsIPv6() const { return( m_bIsIPv6 ); }
|
||||
int GetMaxConns() const { return( m_iMaxConns ); }
|
||||
u_int GetTimeout() const { return( m_iTimeout ); }
|
||||
#ifdef HAVE_LIBSSL
|
||||
const CS_STRING & GetCipher() const { return( m_sCipher ); }
|
||||
const CS_STRING & GetPemLocation() const { return( m_sPemLocation ); }
|
||||
const CS_STRING & GetPemPass() const { return( m_sPemPass ); }
|
||||
bool GetRequiresClientCert() const { return( m_bRequiresClientCert ); }
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
//! sets the port to listen on. Set to 0 to listen on a random port
|
||||
void SetPort( u_short iPort ) { m_iPort = iPort; }
|
||||
//! sets the sock name for later reference (ie FindSockByName)
|
||||
void SetSockName( const CS_STRING & sSockName ) { m_sSockName = sSockName; }
|
||||
//! sets the host to bind to
|
||||
void SetBindHost( const CS_STRING & sBindHost ) { m_sBindHost = sBindHost; }
|
||||
//! set to true to enable SSL
|
||||
void SetIsSSL( bool b ) { m_bIsSSL = b; }
|
||||
//! set to true to enable ipv6
|
||||
void SetIsIPv6( bool b ) { m_bIsIPv6 = b; }
|
||||
//! set max connections as called by accept()
|
||||
void SetMaxConns( int i ) { m_iMaxConns = i; }
|
||||
//! sets the listen timeout. The listener class will close after timeout has been reached if not 0
|
||||
void SetTimeout( u_int i ) { m_iTimeout = i; }
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
//! set the cipher strength to use, default is HIGH
|
||||
void SetCipher( const CS_STRING & s ) { m_sCipher = s; }
|
||||
//! set the location of the pemfile
|
||||
void SetPemLocation( const CS_STRING & s ) { m_sPemLocation = s; }
|
||||
//! set the pemfile pass
|
||||
void SetPemPass( const CS_STRING & s ) { m_sPemPass = s; }
|
||||
//! set to true if require a client certificate
|
||||
void SetRequiresClientCert( bool b ) { m_bRequiresClientCert = b; }
|
||||
#endif /* HAVE_LIBSSL */
|
||||
private:
|
||||
u_short m_iPort;
|
||||
CS_STRING m_sSockName, m_sBindHost;
|
||||
bool m_bIsSSL, m_bIsIPv6;
|
||||
int m_iMaxConns;
|
||||
u_int m_iTimeout;
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
CS_STRING m_sPemLocation, m_sPemPass, m_sCipher;
|
||||
bool m_bRequiresClientCert;
|
||||
#endif /* HAVE_LIBSSL */
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
class CSSSListener : public CSListener
|
||||
{
|
||||
public:
|
||||
CSSSListener( u_short iPort, const CS_STRING & sBindHost = "" ) :
|
||||
CSListener( iPort, sBindHost )
|
||||
{
|
||||
SetIsSSL( true );
|
||||
}
|
||||
};
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
/**
|
||||
* @class TSocketManager
|
||||
* @brief Best class to use to interact with the sockets
|
||||
@@ -1032,113 +1196,90 @@ public:
|
||||
* \param bIsIPv6 set to true to connect to an ipv6 host, requires HAVE_IPV6 at compile time to work
|
||||
* \return true on success
|
||||
*/
|
||||
virtual bool Connect( const CS_STRING & sHostname, u_short iPort , const CS_STRING & sSockName, int iTimeout = 60, bool isSSL = false, const CS_STRING & sBindHost = "", T *pcSock = NULL, bool bIsIPv6 = false )
|
||||
bool Connect( const CSConnection & cCon, T * pcSock = NULL )
|
||||
{
|
||||
// create the new object
|
||||
if ( !pcSock )
|
||||
pcSock = new T( sHostname, iPort, iTimeout );
|
||||
pcSock = new T( cCon.GetHostname(), cCon.GetPort(), cCon.GetTimeout() );
|
||||
else
|
||||
{
|
||||
pcSock->SetHostName( sHostname );
|
||||
pcSock->SetPort( iPort );
|
||||
pcSock->SetTimeout( iTimeout );
|
||||
pcSock->SetHostName( cCon.GetHostname() );
|
||||
pcSock->SetPort( cCon.GetPort() );
|
||||
pcSock->SetTimeout( cCon.GetTimeout() );
|
||||
}
|
||||
pcSock->SetIPv6( bIsIPv6 );
|
||||
pcSock->SetIPv6( cCon.GetIsIPv6() );
|
||||
|
||||
// make it NON-Blocking IO
|
||||
pcSock->BlockIO( false );
|
||||
|
||||
// bind the vhost
|
||||
pcSock->SetBindHost( sBindHost );
|
||||
pcSock->SetBindHost( cCon.GetBindHost() );
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
pcSock->SetSSL( isSSL );
|
||||
pcSock->SetSSL( cCon.GetIsSSL() );
|
||||
if( cCon.GetIsSSL() )
|
||||
{
|
||||
if( !cCon.GetPemLocation().empty() )
|
||||
{
|
||||
pcSock->SetPemLocation( cCon.GetPemLocation() );
|
||||
pcSock->SetPemPass( cCon.GetPemPass() );
|
||||
}
|
||||
if( !cCon.GetCipher().empty() )
|
||||
pcSock->SetCipher( cCon.GetCipher() );
|
||||
}
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
if ( !pcSock->CreateSocksFD() )
|
||||
return( false );
|
||||
|
||||
pcSock->SetType( T::OUTBOUND );
|
||||
|
||||
pcSock->SetConState( T::CST_START );
|
||||
AddSock( pcSock, sSockName );
|
||||
AddSock( pcSock, cCon.GetSockName() );
|
||||
return( true );
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
virtual bool Connect6( const CS_STRING & sHostname, u_short iPort , const CS_STRING & sSockName, int iTimeout = 60, bool isSSL = false, const CS_STRING & sBindHost = "", T *pcSock = NULL )
|
||||
{
|
||||
return( Connect( sHostname, iPort, sSockName, iTimeout, isSSL, sBindHost, pcSock, true ) );
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
/**
|
||||
* @brief Create a listening socket
|
||||
*
|
||||
* Given the design of this function, when binding to a hostname, its best to use an
|
||||
* since dns lookups are blocking, but since your binding to a local ip, it should never be
|
||||
* problem anyhow.
|
||||
*
|
||||
* @param iPort the port to listen on
|
||||
* @param sSockName the name of the socket
|
||||
* @param isSSL if the sockets created require an ssl layer
|
||||
* @param iMaxConns the maximum amount of connections to accept
|
||||
* @param bIsIPv6 set to true to listen on an ipv6 host, requires HAVE_IPV6 at compile time to work
|
||||
* @return pointer to sock, NULL if not successfull
|
||||
*/
|
||||
virtual T * ListenHost( u_short iPort, const CS_STRING & sSockName, const CS_STRING & sBindHost, int isSSL = false, int iMaxConns = SOMAXCONN, T *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false )
|
||||
virtual bool Listen( const CSListener & cListen, T * pcSock = NULL, u_short *piRandPort = NULL )
|
||||
{
|
||||
if ( !pcSock )
|
||||
pcSock = new T();
|
||||
|
||||
pcSock->BlockIO( false );
|
||||
pcSock->SetIPv6( bIsIPv6 );
|
||||
|
||||
pcSock->SetSSL( isSSL );
|
||||
|
||||
if ( pcSock->Listen( iPort, iMaxConns, sBindHost, iTimeout ) )
|
||||
pcSock->SetIPv6( cListen.GetIsIPv6() );
|
||||
#ifdef HAVE_LIBSSL
|
||||
pcSock->SetSSL( cListen.GetIsSSL() );
|
||||
if( ( cListen.GetIsSSL() ) && ( !cListen.GetPemLocation().empty() ) )
|
||||
{
|
||||
AddSock( pcSock, sSockName );
|
||||
return( pcSock );
|
||||
pcSock->SetPemLocation( cListen.GetPemLocation() );
|
||||
pcSock->SetPemPass( cListen.GetPemPass() );
|
||||
pcSock->SetCipher( cListen.GetCipher() );
|
||||
pcSock->SetRequiresClientCert( cListen.GetRequiresClientCert() );
|
||||
}
|
||||
CS_Delete( pcSock );
|
||||
return( NULL );
|
||||
}
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
virtual bool ListenAll( u_short iPort, const CS_STRING & sSockName, int isSSL = false, int iMaxConns = SOMAXCONN, T *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false )
|
||||
{
|
||||
return( ListenHost( iPort, sSockName, "", isSSL, iMaxConns, pcSock, iTimeout, bIsIPv6 ) );
|
||||
}
|
||||
if( piRandPort )
|
||||
*piRandPort = 0;
|
||||
|
||||
/*
|
||||
* @return the port number being listened on
|
||||
*/
|
||||
virtual u_short ListenRand( const CS_STRING & sSockName, const CS_STRING & sBindHost, int isSSL = false, int iMaxConns = SOMAXCONN, T *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false )
|
||||
{
|
||||
u_short iPort = 0;
|
||||
T *pNewSock = ListenHost( 0, sSockName, sBindHost, isSSL, iMaxConns, pcSock, iTimeout, bIsIPv6 );
|
||||
if ( pNewSock )
|
||||
if ( pcSock->Listen( cListen.GetPort(), cListen.GetMaxConns(), cListen.GetBindHost(), cListen.GetTimeout() ) )
|
||||
{
|
||||
int iSock = pNewSock->GetSock();
|
||||
|
||||
if ( iSock < 0 )
|
||||
AddSock( pcSock, cListen.GetSockName() );
|
||||
if( ( piRandPort ) && ( cListen.GetPort() == 0 ) )
|
||||
{
|
||||
CS_DEBUG( "Failed to attain a valid file descriptor" );
|
||||
pNewSock->Close();
|
||||
return( 0 );
|
||||
int iSock = pcSock->GetSock();
|
||||
|
||||
if ( iSock < 0 )
|
||||
{
|
||||
CS_DEBUG( "Failed to attain a valid file descriptor" );
|
||||
pcSock->Close();
|
||||
return( false );
|
||||
}
|
||||
struct sockaddr_in mLocalAddr;
|
||||
socklen_t mLocalLen = sizeof( mLocalAddr );
|
||||
getsockname( iSock, (struct sockaddr *) &mLocalAddr, &mLocalLen );
|
||||
*piRandPort = ntohs( mLocalAddr.sin_port );
|
||||
}
|
||||
|
||||
struct sockaddr_in mLocalAddr;
|
||||
socklen_t mLocalLen = sizeof(struct sockaddr);
|
||||
getsockname( iSock, (struct sockaddr *) &mLocalAddr, &mLocalLen );
|
||||
|
||||
iPort = ntohs( mLocalAddr.sin_port );
|
||||
return( true );
|
||||
}
|
||||
|
||||
return( iPort );
|
||||
}
|
||||
virtual u_short ListenAllRand( const CS_STRING & sSockName, int isSSL = false, int iMaxConns = SOMAXCONN, T *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false )
|
||||
{
|
||||
return( ListenRand( sSockName, "", isSSL, iMaxConns, pcSock, iTimeout, bIsIPv6 ) );
|
||||
CS_Delete( pcSock );
|
||||
return( false );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1187,7 +1328,6 @@ public:
|
||||
|
||||
if ( pcSock->GetConState() == T::CST_CONNECT )
|
||||
{
|
||||
|
||||
if ( !pcSock->Connect( pcSock->GetBindHost(), true ) )
|
||||
{
|
||||
if ( GetSockError() == ECONNREFUSED )
|
||||
@@ -1795,7 +1935,7 @@ private:
|
||||
///////////
|
||||
// members
|
||||
EMessages m_errno;
|
||||
std::vector<CCron *> m_vcCrons;
|
||||
std::vector<CCron *> m_vcCrons;
|
||||
unsigned long long m_iCallTimeouts;
|
||||
u_int m_iSelectWait;
|
||||
};
|
||||
|
||||
45
znc.h
45
znc.h
@@ -20,6 +20,51 @@ public:
|
||||
CSockManager() : TSocketManager<Csock>() {}
|
||||
virtual ~CSockManager() {}
|
||||
|
||||
virtual bool ListenHost(u_short iPort, const CString& sSockName, const CString& sBindHost, int isSSL = false, int iMaxConns = SOMAXCONN, Csock *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false) {
|
||||
CSListener L(iPort, sBindHost);
|
||||
|
||||
L.SetSockName(sSockName);
|
||||
L.SetIsSSL(isSSL);
|
||||
L.SetIsIPv6(bIsIPv6);
|
||||
L.SetTimeout(iTimeout);
|
||||
L.SetMaxConns(iMaxConns);
|
||||
|
||||
return Listen(L, pcSock);
|
||||
}
|
||||
|
||||
virtual bool ListenAll(u_short iPort, const CString& sSockName, int isSSL = false, int iMaxConns = SOMAXCONN, Csock *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false) {
|
||||
return ListenHost(iPort, sSockName, "", isSSL, iMaxConns, pcSock, iTimeout, bIsIPv6);
|
||||
}
|
||||
|
||||
virtual u_short ListenRand(const CString& sSockName, const CString& sBindHost, int isSSL = false, int iMaxConns = SOMAXCONN, Csock *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false) {
|
||||
unsigned short uPort = 0;
|
||||
CSListener L(0, sBindHost);
|
||||
|
||||
L.SetSockName(sSockName);
|
||||
L.SetIsSSL(isSSL);
|
||||
L.SetIsIPv6(bIsIPv6);
|
||||
L.SetTimeout(iTimeout);
|
||||
L.SetMaxConns(iMaxConns);
|
||||
|
||||
Listen(L, pcSock, &uPort);
|
||||
|
||||
return uPort;
|
||||
}
|
||||
|
||||
virtual u_short ListenAllRand(const CString& sSockName, int isSSL = false, int iMaxConns = SOMAXCONN, Csock *pcSock = NULL, u_int iTimeout = 0, bool bIsIPv6 = false) {
|
||||
return( ListenRand( sSockName, "", isSSL, iMaxConns, pcSock, iTimeout, bIsIPv6 ) );
|
||||
}
|
||||
|
||||
virtual bool Connect(const CString& sHostname, u_short iPort , const CString& sSockName, int iTimeout = 60, bool isSSL = false, const CString& sBindHost = "", Csock *pcSock = NULL, bool bIsIPv6 = false) {
|
||||
CSConnection C(sHostname, iPort, iTimeout);
|
||||
|
||||
C.SetSockName(sSockName);
|
||||
C.SetIsSSL(isSSL);
|
||||
C.SetIsIPv6(bIsIPv6);
|
||||
C.SetBindHost(sBindHost);
|
||||
|
||||
return TSocketManager<Csock>::Connect(C, pcSock);
|
||||
}
|
||||
private:
|
||||
protected:
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user