diff --git a/include/znc/Csocket.h b/include/znc/Csocket.h index 06822fd3..c5ea37e7 100644 --- a/include/znc/Csocket.h +++ b/include/znc/Csocket.h @@ -185,34 +185,9 @@ public: RAF_INET = AF_INET }; - void SinFamily() - { -#ifdef HAVE_IPV6 - m_saddr6.sin6_family = PF_INET6; -#endif /* HAVE_IPV6 */ - m_saddr.sin_family = PF_INET; - } - void SinPort( u_short iPort ) - { -#ifdef HAVE_IPV6 - m_saddr6.sin6_port = htons( iPort ); -#endif /* HAVE_IPV6 */ - m_saddr.sin_port = htons( iPort ); - } - - void SetIPv6( bool b ) - { -#ifndef HAVE_IPV6 - if( b ) - { - CS_DEBUG( "-DHAVE_IPV6 must be set during compile time to enable this feature" ); - m_bIsIPv6 = false; - return; - } -#endif /* HAVE_IPV6 */ - m_bIsIPv6 = b; - SinFamily(); - } + void SinFamily(); + void SinPort( u_short iPort ); + void SetIPv6( bool b ); bool GetIPv6() const { return( m_bIsIPv6 ); } @@ -514,15 +489,15 @@ class Csock : public CSockCommon { public: //! default constructor, sets a timeout of 60 seconds - Csock( int itimeout = 60 ); + Csock( int iTimeout = 60 ); /** * Advanced constructor, for creating a simple connection * * @param sHostname the hostname your are connecting to * @param uPort the port you are connectint to - * @param itimeout how long to wait before ditching the connection, default is 60 seconds + * @param iTimeout how long to wait before ditching the connection, default is 60 seconds */ - Csock( const CS_STRING & sHostname, u_short uPort, 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 ); @@ -601,25 +576,11 @@ public: Csock & operator<<( double i ); /** - * Create the connection + * Create the connection, this is used by the socket manager, and shouldn't be called directly by the user * - * @param sBindHost the ip you want to bind to locally - * @param bSkipSetup if true, setting up the vhost etc is skipped * @return true on success */ - virtual bool Connect( const CS_STRING & sBindHost = "", bool bSkipSetup = false ); - - /** - * WriteSelect on this socket - * Only good if JUST using this socket, otherwise use the CSocketManager - */ - virtual int WriteSelect(); - - /** - * ReadSelect on this socket - * Only good if JUST using this socket, otherwise use the CSocketManager - */ - virtual int ReadSelect(); + virtual bool Connect(); /** * Listens for connections @@ -644,13 +605,14 @@ public: virtual bool SSLServerSetup(); /** - * Create the SSL connection + * Create the SSL connection, this is used by the socket manager, and shouldn't be called directly by the user * - * @param sBindhost the ip you want to bind to locally * @return true on success */ - virtual bool ConnectSSL( const CS_STRING & sBindhost = "" ); + virtual bool ConnectSSL(); + //! start a TLS connection on an existing plain connection + bool StartTLS(); /** * Write data to the socket @@ -803,13 +765,10 @@ public: ECloseType GetCloseType() { return( m_eCloseType ); } bool IsClosed() { return( GetCloseType() != CLT_DONT ); } - //! Set rather to NON Blocking IO on this socket, default is true - void BlockIO( bool bBLOCK ); - //! Use this to change your fd's to blocking or none blocking void NonBlockingIO(); - //! if this connection type is ssl or not + //! Return true if this socket is using ssl. Note this does not mean the SSL state is finished, but simply that its configured to use ssl bool GetSSL(); void SetSSL( bool b ); @@ -853,12 +812,12 @@ public: //! Get the peer's X509 cert #ifdef HAVE_LIBSSL - X509 *getX509(); + X509 *GetX509(); //! Returns the peer's public key CS_STRING GetPeerPubKey(); //! Returns the peer's certificate finger print - int GetPeerFingerprint( CS_STRING & sFP); + long GetPeerFingerprint( CS_STRING & sFP); unsigned int GetRequireClientCertFlags(); //! legacy, deprecated @see SetRequireClientCertFlags @@ -982,30 +941,12 @@ public: //! return how long it has been (in seconds) since the last read or successful write - time_t GetTimeSinceLastDataTransaction( time_t iNow = 0 ) - { - if( m_iLastCheckTimeoutTime == 0 ) - return( 0 ); - return( ( iNow > 0 ? iNow : time( NULL ) ) - m_iLastCheckTimeoutTime ); - } + time_t GetTimeSinceLastDataTransaction( time_t iNow = 0 ); + time_t GetLastCheckTimeout() { return( m_iLastCheckTimeoutTime ); } //! Returns the time when CheckTimeout() should be called next - time_t GetNextCheckTimeout( time_t iNow = 0 ) - { - if( iNow == 0 ) - iNow = time( NULL ); - time_t itimeout = m_itimeout; - time_t iDiff = iNow - m_iLastCheckTimeoutTime; - /* CheckTimeout() wants to be called after half the timeout */ - if( m_iTcount == 0 ) - itimeout /= 2; - if( iDiff > itimeout ) - itimeout = 0; - else - itimeout -= iDiff; - return( iNow + itimeout ); - } + time_t GetNextCheckTimeout( time_t iNow = 0 ); //! return the data imediatly ready for read virtual int GetPending(); @@ -1018,20 +959,7 @@ public: void SetConState( ECONState eState ) { m_eConState = eState; } //! grabs fd's for the sockets - bool CreateSocksFD() - { - if( m_iReadSock != CS_INVALID_SOCK ) - return( true ); - - m_iReadSock = m_iWriteSock = CreateSocket(); - if ( m_iReadSock == CS_INVALID_SOCK ) - return( false ); - - m_address.SinFamily(); - m_address.SinPort( m_uPort ); - - return( true ); - } + bool CreateSocksFD(); //! puts the socks back to the state they were prior to calling CreateSocksFD void CloseSocksFD(); @@ -1090,13 +1018,13 @@ public: private: //! making private for safety - Csock( const Csock & cCopy ) {} + Csock( const Csock & cCopy ) : CSockCommon() {} // NOTE! if you add any new members, be sure to add them to Copy() 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; + int m_iTimeout, m_iConnType, m_iMethod, m_iTcount; + bool m_bUseSSL, m_bIsConnected, m_bBLOCK; bool m_bsslEstablished, m_bEnableReadLine, m_bPauseRead; CS_STRING m_shostname, m_sbuffer, m_sSockName, m_sPemFile, m_sCipherType, m_sParentName; CS_STRING m_sSend, m_sPemPass, m_sLocalIP, m_sRemoteIP; @@ -1126,7 +1054,7 @@ private: //! Create the socket cs_sock_t CreateSocket( bool bListen = false ); - void Init( const CS_STRING & sHostname, u_short uPort, int itimeout = 60 ); + void Init( const CS_STRING & sHostname, u_short uPort, int iTimeout = 60 ); // Connection State Info @@ -1366,9 +1294,8 @@ public: * * @param cCon the connection which should be established * @param pcSock the socket used for the connectiong, can be NULL - * @return true on success */ - bool Connect( const CSConnection & cCon, Csock * pcSock = NULL ); + void Connect( const CSConnection & cCon, Csock * pcSock = NULL ); virtual bool Listen( const CSListener & cListen, Csock * pcSock = NULL, u_short *piRandPort = NULL ); diff --git a/include/znc/Socket.h b/include/znc/Socket.h index af552993..086410c8 100644 --- a/include/znc/Socket.h +++ b/include/znc/Socket.h @@ -95,14 +95,14 @@ public: return(ListenRand(sSockName, "", bSSL, iMaxConns, pcSock, iTimeout, eAddr)); } - bool Connect(const CString& sHostname, u_short iPort , const CString& sSockName, int iTimeout = 60, bool bSSL = false, const CString& sBindHost = "", CZNCSock *pcSock = NULL) { + void Connect(const CString& sHostname, u_short iPort , const CString& sSockName, int iTimeout = 60, bool bSSL = false, const CString& sBindHost = "", CZNCSock *pcSock = NULL) { CSConnection C(sHostname, iPort, iTimeout); C.SetSockName(sSockName); C.SetIsSSL(bSSL); C.SetBindHost(sBindHost); - return TSocketManager::Connect(C, pcSock); + TSocketManager::Connect(C, pcSock); } unsigned int GetAnonConnectionCount(const CString &sIP) const; diff --git a/modules/bouncedcc.cpp b/modules/bouncedcc.cpp index 47b8578f..202602be 100644 --- a/modules/bouncedcc.cpp +++ b/modules/bouncedcc.cpp @@ -422,9 +422,7 @@ Csock* CDCCBounce::GetSockObj(const CString& sHost, unsigned short uPort) { pRemoteSock->SetRemote(true); pSock->SetRemote(false); - if (!CZNC::Get().GetManager().Connect(m_sConnectIP, m_uRemotePort, "DCC::" + CString((m_bIsChat) ? "Chat" : "XFER") + "::Remote::" + m_sRemoteNick, 60, false, m_sLocalIP, pRemoteSock)) { - pRemoteSock->Close(); - } + CZNC::Get().GetManager().Connect(m_sConnectIP, m_uRemotePort, "DCC::" + CString((m_bIsChat) ? "Chat" : "XFER") + "::Remote::" + m_sRemoteNick, 60, false, m_sLocalIP, pRemoteSock); pSock->SetSockName(GetSockName()); return pSock; diff --git a/modules/extra/dcc.cpp b/modules/extra/dcc.cpp index f3b30b35..f9a8b404 100644 --- a/modules/extra/dcc.cpp +++ b/modules/extra/dcc.cpp @@ -126,10 +126,7 @@ public: return false; } - if (!CZNC::Get().GetManager().Connect(sRemoteIP, uRemotePort, "DCC::GET::" + sRemoteNick, 60, false, m_pUser->GetLocalDCCIP(), pSock)) { - PutModule("DCC <- [" + sRemoteNick + "][" + sFileName + "] - Unable to connect."); - return false; - } + CZNC::Get().GetManager().Connect(sRemoteIP, uRemotePort, "DCC::GET::" + sRemoteNick, 60, false, m_pUser->GetLocalDCCIP(), pSock); PutModule("DCC <- [" + sRemoteNick + "][" + sFileName + "] - Attempting to connect to [" + sRemoteIP + "]"); return true; diff --git a/src/Csocket.cpp b/src/Csocket.cpp index 901b05d1..23129d6b 100644 --- a/src/Csocket.cpp +++ b/src/Csocket.cpp @@ -41,6 +41,20 @@ #include #endif /* HAVE_LIBSSL */ +/*** + * doing this because there seems to be a bug that is losing the "short" on htons when in optimize mode turns into a macro + * gcc 4.3.4 + */ +#ifdef __OPTIMIZE__ +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#endif /* __OPTIMIZE__ */ + + #include #define CS_SRANDBUFFER 128 @@ -114,11 +128,14 @@ static inline void set_non_blocking(cs_sock_t fd) ioctlsocket( fd, FIONBIO, &iOpts ); } +/* + * not used by anything anymore static inline void set_blocking(cs_sock_t fd) { u_long iOpts = 0; ioctlsocket( fd, FIONBIO, &iOpts ); } +*/ static inline void set_close_on_exec(cs_sock_t fd) { @@ -135,6 +152,8 @@ static inline void set_non_blocking(cs_sock_t fd) fcntl( fd, F_SETFL, fdflags|O_NONBLOCK ); } +/* + * not used by anything anymore static inline void set_blocking(cs_sock_t fd) { int fdflags = fcntl(fd, F_GETFL, 0); @@ -143,6 +162,7 @@ static inline void set_blocking(cs_sock_t fd) fdflags &= ~O_NONBLOCK; fcntl( fd, F_SETFL, fdflags ); } +*/ static inline void set_close_on_exec(cs_sock_t fd) { @@ -153,6 +173,35 @@ static inline void set_close_on_exec(cs_sock_t fd) } #endif /* _WIN32 */ +void CSSockAddr::SinFamily() +{ +#ifdef HAVE_IPV6 + m_saddr6.sin6_family = PF_INET6; +#endif /* HAVE_IPV6 */ + m_saddr.sin_family = PF_INET; +} +void CSSockAddr::SinPort( u_short iPort ) +{ +#ifdef HAVE_IPV6 + m_saddr6.sin6_port = htons( iPort ); +#endif /* HAVE_IPV6 */ + m_saddr.sin_port = htons( iPort ); +} + +void CSSockAddr::SetIPv6( bool b ) +{ +#ifndef HAVE_IPV6 + if( b ) + { + CS_DEBUG( "-DHAVE_IPV6 must be set during compile time to enable this feature" ); + m_bIsIPv6 = false; + return; + } +#endif /* HAVE_IPV6 */ + m_bIsIPv6 = b; + SinFamily(); +} + #ifdef HAVE_LIBSSL Csock *GetCsockFromCTX( X509_STORE_CTX *pCTX ) { @@ -366,7 +415,7 @@ int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockA if( bTryConnect && it != lpTryAddrs.end() ) { // save the last attempt for the outer loop, the issue then becomes that the error is thrown on the last failure - if( pSock->CreateSocksFD() && pSock->Connect( pSock->GetBindHost(), true ) ) + if( pSock->CreateSocksFD() && pSock->Connect() ) { pSock->SetSkipConnect( true ); // this tells the socket that the connection state has been started bFound = true; @@ -743,20 +792,20 @@ void CSockCommon::DelCronByAddr( CCron *pcCron ) } } -Csock::Csock( int itimeout ) : CSockCommon() +Csock::Csock( int iTimeout ) : CSockCommon() { #ifdef HAVE_LIBSSL m_pCerVerifyCB = NULL; #endif /* HAVE_LIBSSL */ - Init( "", 0, itimeout ); + Init( "", 0, iTimeout ); } -Csock::Csock( const CS_STRING & sHostname, u_short iport, int itimeout ) : CSockCommon() +Csock::Csock( const CS_STRING & sHostname, u_short iport, int iTimeout ) : CSockCommon() { #ifdef HAVE_LIBSSL m_pCerVerifyCB = NULL; #endif /* HAVE_LIBSSL */ - Init( sHostname, iport, itimeout ); + Init( sHostname, iport, iTimeout ); } // override this for accept sockets @@ -828,12 +877,11 @@ void Csock::Copy( const Csock & cCopy ) m_iLocalPort = cCopy.m_iLocalPort; m_iReadSock = cCopy.m_iReadSock; m_iWriteSock = cCopy.m_iWriteSock; - m_itimeout = cCopy.m_itimeout; + m_iTimeout = cCopy.m_iTimeout; m_iConnType = cCopy.m_iConnType; m_iMethod = cCopy.m_iMethod; - m_bssl = cCopy.m_bssl; + m_bUseSSL = cCopy.m_bUseSSL; m_bIsConnected = cCopy.m_bIsConnected; - m_bBLOCK = cCopy.m_bBLOCK; m_bsslEstablished = cCopy.m_bsslEstablished; m_bEnableReadLine = cCopy.m_bEnableReadLine; m_bPauseRead = cCopy.m_bPauseRead; @@ -956,7 +1004,7 @@ Csock & Csock::operator<<( double i ) return( *this ); } -bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup ) +bool Csock::Connect() { if( m_bSkipConnect ) { // this was already called, so skipping now. this is to allow easy pass through @@ -966,45 +1014,6 @@ bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup ) } return( true ); } - // bind to a hostname if requested - m_sBindHost = sBindHost; - if ( !bSkipSetup ) - { - if ( !sBindHost.empty() ) - { - // try to bind 3 times, otherwise exit failure - bool bBound = false; - for( int a = 0; a < 3 && !bBound; a++ ) - { - if ( SetupVHost() ) - bBound = true; -#ifdef _WIN32 - Sleep( 5000 ); -#else - usleep( 5000 ); // quick pause, common lets BIND!)(!*! -#endif /* _WIN32 */ - } - - if ( !bBound ) - { - CS_DEBUG( "Failure to bind to " << sBindHost ); - return( false ); - } - } - - int iDNSRet = ETIMEDOUT; - while( true ) - { - iDNSRet = DNSLookup( DNS_VHOST ); - if ( iDNSRet == EAGAIN ) - continue; - - break; - } - if ( iDNSRet != 0 ) - return( false ); - - } // set it none blocking set_non_blocking( m_iReadSock ); @@ -1029,11 +1038,6 @@ bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup ) return( false ); } - if ( m_bBLOCK ) - { - set_blocking( m_iReadSock ); - } - if ( m_eConState != CST_OK ) { m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK ); @@ -1042,70 +1046,11 @@ bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup ) return( true ); } -int Csock::WriteSelect() -{ - if ( m_iWriteSock == CS_INVALID_SOCK ) - return( SEL_ERR ); - - struct timeval tv; - fd_set wfds; - - TFD_ZERO( &wfds ); - TFD_SET( m_iWriteSock, &wfds ); - - tv.tv_sec = m_itimeout; - tv.tv_usec = 0; - - int ret = select( FD_SETSIZE, NULL, &wfds, NULL, &tv ); - - if ( ret == 0 ) - return( SEL_TIMEOUT ); - - if ( ret == -1 ) - { - if ( GetSockError() == EINTR ) - return( SEL_EAGAIN ); - else - return( SEL_ERR ); - } - - return( SEL_OK ); -} - -int Csock::ReadSelect() -{ - if ( m_iReadSock == CS_INVALID_SOCK ) - return( SEL_ERR ); - - struct timeval tv; - fd_set rfds; - - TFD_ZERO( &rfds ); - TFD_SET( m_iReadSock, &rfds ); - - tv.tv_sec = m_itimeout; - tv.tv_usec = 0; - - int ret = select( FD_SETSIZE, &rfds, NULL, NULL, &tv ); - - if ( ret == 0 ) - return( SEL_TIMEOUT ); - - if ( ret == -1 ) - { - if ( GetSockError() == EINTR ) - return( SEL_EAGAIN ); - else - return( SEL_ERR ); - } - - return( SEL_OK ); -} bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u_int iTimeout ) { m_iConnType = LISTENER; - m_itimeout = iTimeout; + m_iTimeout = iTimeout; m_sBindHost = sBindHost; if ( !sBindHost.empty() ) @@ -1152,11 +1097,8 @@ bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u if ( listen( m_iReadSock, iMaxConns ) == -1 ) return( false ); - if ( !m_bBLOCK ) - { - // set it none blocking - set_non_blocking( m_iReadSock ); - } + // set it none blocking + set_non_blocking( m_iReadSock ); return( true ); } @@ -1196,11 +1138,8 @@ cs_sock_t Csock::Accept( CS_STRING & sHost, u_short & iRPort ) // Make it close-on-exec set_close_on_exec( iSock ); - if ( !m_bBLOCK ) - { - // make it none blocking - set_non_blocking( iSock ); - } + // make it none blocking + set_non_blocking( iSock ); if ( !ConnectionFrom( sHost, iRPort ) ) { @@ -1242,7 +1181,7 @@ bool Csock::AcceptSSL() bool Csock::SSLClientSetup() { #ifdef HAVE_LIBSSL - m_bssl = true; + m_bUseSSL = true; FREE_SSL(); FREE_CTX(); @@ -1318,7 +1257,7 @@ bool Csock::SSLClientSetup() } } - m_ssl = SSL_new ( m_ssl_ctx ); + m_ssl = SSL_new( m_ssl_ctx ); if ( !m_ssl ) return( false ); @@ -1338,7 +1277,7 @@ bool Csock::SSLClientSetup() bool Csock::SSLServerSetup() { #ifdef HAVE_LIBSSL - m_bssl = true; + m_bUseSSL = true; FREE_SSL(); FREE_CTX(); @@ -1478,23 +1417,26 @@ bool Csock::SSLServerSetup() #endif /* HAVE_LIBSSL */ } -bool Csock::ConnectSSL( const CS_STRING & sBindhost ) +bool Csock::StartTLS() +{ + if( m_iConnType == INBOUND ) + return( AcceptSSL() ); + if( m_iConnType == OUTBOUND ) + return( ConnectSSL() ); + CS_DEBUG( "Invalid connection type with StartTLS" ); + return( false ); +} + +bool Csock::ConnectSSL() { #ifdef HAVE_LIBSSL - if ( m_iReadSock == CS_INVALID_SOCK ) - if ( !Connect( sBindhost ) ) - return( false ); - if ( !m_ssl ) - if ( !SSLClientSetup() ) - return( false ); + if( m_iReadSock == CS_INVALID_SOCK ) + return( false ); // this should be long passed at this point + if( !m_ssl && !SSLClientSetup() ) + return( false ); bool bPass = true; - if ( m_bBLOCK ) - { - set_non_blocking( m_iReadSock ); - } - int iErr = SSL_connect( m_ssl ); if ( iErr != 1 ) { @@ -1515,12 +1457,6 @@ bool Csock::ConnectSSL( const CS_STRING & sBindhost ) } else bPass = true; - if ( m_bBLOCK ) - { - // unset the flags afterwords, rather then have connect block - set_blocking( m_iReadSock ); - } - if ( m_eConState != CST_OK ) m_eConState = CST_OK; return( bPass ); @@ -1554,17 +1490,11 @@ bool Csock::Write( const char *data, size_t len ) if ( m_eConState != CST_OK ) return( true ); - if ( m_bBLOCK ) - { - if ( WriteSelect() != SEL_OK ) - return( false ); - - } // rate shaping u_long iBytesToSend = 0; #ifdef HAVE_LIBSSL - if( m_bssl && m_sSSLBuffer.empty() && !m_bsslEstablished ) + if( m_bUseSSL && m_sSSLBuffer.empty() && !m_bsslEstablished ) { // to keep openssl from spinning, just initiate the connection with 1 byte so the connection establishes faster iBytesToSend = 1; @@ -1600,8 +1530,13 @@ bool Csock::Write( const char *data, size_t len ) iBytesToSend = m_sSend.length(); #ifdef HAVE_LIBSSL - if ( m_bssl ) + if ( m_bUseSSL ) { + if( !m_ssl ) + { + CS_DEBUG( "SSL object is NULL but m_bUseSSL is true" ); + return( false ); + } if ( m_sSSLBuffer.empty() ) // on retrying to write data, ssl wants the data in the SAME spot and the SAME size m_sSSLBuffer.append( m_sSend.data(), iBytesToSend ); @@ -1702,22 +1637,15 @@ cs_ssize_t Csock::Read( char *data, size_t len ) if ( IsReadPaused() && SslIsEstablished() ) return( READ_EAGAIN ); // allow the handshake to complete first - if ( m_bBLOCK ) - { - switch( ReadSelect() ) - { - case SEL_OK: - break; - case SEL_TIMEOUT: - return( READ_TIMEDOUT ); - default: - return( READ_ERR ); - } - } - #ifdef HAVE_LIBSSL - if ( m_bssl ) + if( m_bUseSSL ) { + if( !m_ssl ) + { + CS_DEBUG( "SSL object is NULL but m_bUseSSL is true" ); + return( READ_ERR ); + } + bytes = SSL_read( m_ssl, data, (int)len ); if( bytes >= 0 ) m_bsslEstablished = true; // this means all is good in the realm of ssl @@ -1746,7 +1674,7 @@ cs_ssize_t Csock::Read( char *data, size_t len ) #endif /* _WIN32 */ #ifdef HAVE_LIBSSL - if ( m_bssl ) + if ( m_ssl ) { int iErr = SSL_get_error( m_ssl, (int)bytes ); if ( ( iErr != SSL_ERROR_WANT_READ ) && ( iErr != SSL_ERROR_WANT_WRITE ) ) @@ -1875,11 +1803,11 @@ void Csock::UnPauseRead() void Csock::SetTimeout( int iTimeout, u_int iTimeoutType ) { m_iTimeoutType = iTimeoutType; - m_itimeout = iTimeout; + m_iTimeout = iTimeout; } void Csock::SetTimeoutType( u_int iTimeoutType ) { m_iTimeoutType = iTimeoutType; } -int Csock::GetTimeout() const { return m_itimeout; } +int Csock::GetTimeout() const { return m_iTimeout; } u_int Csock::GetTimeoutType() const { return( m_iTimeoutType ); } bool Csock::CheckTimeout( time_t iNow ) @@ -1904,11 +1832,11 @@ bool Csock::CheckTimeout( time_t iNow ) m_iLastCheckTimeoutTime = iNow; } - if ( m_itimeout > 0 ) + if ( m_iTimeout > 0 ) { // this is basically to help stop a clock adjust ahead, stuff could reset immediatly on a clock jump // otherwise - time_t iRealTimeout = m_itimeout; + time_t iRealTimeout = m_iTimeout; if( iRealTimeout <= 1 ) m_iTcount++; else if( m_iTcount == 0 ) @@ -2060,7 +1988,6 @@ void Csock::Close( ECloseType eCloseType ) { m_eCloseType = eCloseType; } -void Csock::BlockIO( bool bBLOCK ) { m_bBLOCK = bBLOCK; } void Csock::NonBlockingIO() { @@ -2070,12 +1997,10 @@ void Csock::NonBlockingIO() { set_non_blocking( m_iWriteSock ); } - - BlockIO( false ); } -bool Csock::GetSSL() { return( m_bssl ); } -void Csock::SetSSL( bool b ) { m_bssl = b; } +bool Csock::GetSSL() { return( m_bUseSSL ); } +void Csock::SetSSL( bool b ) { m_bUseSSL = b; } #ifdef HAVE_LIBSSL void Csock::SetCipher( const CS_STRING & sCipher ) { m_sCipherType = sCipher; } @@ -2172,9 +2097,9 @@ bool Csock::ConnectFD( int iReadFD, int iWriteFD, const CS_STRING & sName, bool if ( bIsSSL ) { - if ( ( eDirection == INBOUND ) && ( !AcceptSSL() ) ) + if( eDirection == INBOUND && !AcceptSSL() ) return( false ); - else if ( ( eDirection == OUTBOUND ) && ( !ConnectSSL() ) ) + else if( eDirection == OUTBOUND && !ConnectSSL() ) return( false ); } @@ -2182,7 +2107,7 @@ bool Csock::ConnectFD( int iReadFD, int iWriteFD, const CS_STRING & sName, bool } #ifdef HAVE_LIBSSL -X509 *Csock::getX509() +X509 *Csock::GetX509() { if ( m_ssl ) return( SSL_get_peer_certificate( m_ssl ) ); @@ -2230,14 +2155,14 @@ CS_STRING Csock::GetPeerPubKey() } return( sKey ); } -int Csock::GetPeerFingerprint( CS_STRING & sFP ) +long Csock::GetPeerFingerprint( CS_STRING & sFP ) { sFP.clear(); - if ( !GetSSL() ) - return 0; + if ( !m_ssl ) + return( 0 ); - X509* pCert = getX509(); + X509* pCert = GetX509(); // Inspired by charybdis if ( pCert ) @@ -2251,7 +2176,7 @@ int Csock::GetPeerFingerprint( CS_STRING & sFP ) X509_free(pCert); } - return SSL_get_verify_result(m_ssl); + return( SSL_get_verify_result( m_ssl ) ); } unsigned int Csock::GetRequireClientCertFlags() { return( m_iRequireClientCertFlags ); } void Csock::SetRequiresClientCert( bool bRequiresCert ) { m_iRequireClientCertFlags = ( bRequiresCert ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER : 0 ); } @@ -2283,6 +2208,29 @@ void Csock::ReachedMaxBuffer() std::cerr << "If you don't care, then set SetMaxBufferThreshold to 0" << endl; } +time_t Csock::GetTimeSinceLastDataTransaction( time_t iNow ) +{ + if( m_iLastCheckTimeoutTime == 0 ) + return( 0 ); + return( ( iNow > 0 ? iNow : time( NULL ) ) - m_iLastCheckTimeoutTime ); +} + +time_t Csock::GetNextCheckTimeout( time_t iNow ) +{ + if( iNow == 0 ) + iNow = time( NULL ); + time_t iTimeout = m_iTimeout; + time_t iDiff = iNow - m_iLastCheckTimeoutTime; + /* CheckTimeout() wants to be called after half the timeout */ + if( m_iTcount == 0 ) + iTimeout /= 2; + if( iDiff > iTimeout ) + iTimeout = 0; + else + iTimeout -= iDiff; + return( iNow + iTimeout ); +} + int Csock::GetPending() { #ifdef HAVE_LIBSSL @@ -2312,6 +2260,21 @@ int Csock::GetPending() #endif /* HAVE_LIBSSL */ } +bool Csock::CreateSocksFD() +{ + if( m_iReadSock != CS_INVALID_SOCK ) + return( true ); + + m_iReadSock = m_iWriteSock = CreateSocket(); + if ( m_iReadSock == CS_INVALID_SOCK ) + return( false ); + + m_address.SinFamily(); + m_address.SinPort( m_uPort ); + + return( true ); +} + int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr ) { #ifdef HAVE_IPV6 @@ -2363,7 +2326,7 @@ int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr ) if( m_iARESStatus == ARES_SUCCESS && csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY && GetIPv6() ) { // this means that ares_host returned an ipv6 host, so try a connect right away - if( CreateSocksFD() && Connect( GetBindHost(), true ) ) + if( CreateSocksFD() && Connect() ) { SetSkipConnect( true ); } @@ -2538,7 +2501,7 @@ cs_sock_t Csock::CreateSocket( bool bListen ) return( iRet ); } -void Csock::Init( const CS_STRING & sHostname, u_short uPort, int itimeout ) +void Csock::Init( const CS_STRING & sHostname, u_short uPort, int iTimeout ) { #ifdef HAVE_LIBSSL m_ssl = NULL; @@ -2548,14 +2511,13 @@ void Csock::Init( const CS_STRING & sHostname, u_short uPort, int itimeout ) m_iTcount = 0; m_iReadSock = CS_INVALID_SOCK; m_iWriteSock = CS_INVALID_SOCK; - m_itimeout = itimeout; - m_bssl = false; + m_iTimeout = iTimeout; + m_bUseSSL = false; m_bIsConnected = false; m_uPort = uPort; m_shostname = sHostname; m_sbuffer.clear(); m_eCloseType = CLT_DONT; - m_bBLOCK = true; m_iMethod = SSL23; m_sCipherType = "ALL"; m_iMaxBytes = 0; @@ -2619,7 +2581,7 @@ Csock * CSocketManager::GetSockObj( const CS_STRING & sHostname, u_short uPort, return( new Csock( sHostname, uPort, iTimeout ) ); } -bool CSocketManager::Connect( const CSConnection & cCon, Csock * pcSock ) +void CSocketManager::Connect( const CSConnection & cCon, Csock * pcSock ) { // create the new object if ( !pcSock ) @@ -2634,9 +2596,6 @@ bool CSocketManager::Connect( const CSConnection & cCon, Csock * pcSock ) if( cCon.GetAFRequire() != CSSockAddr::RAF_ANY ) pcSock->SetAFRequire( cCon.GetAFRequire() ); - // make it NON-Blocking IO - pcSock->BlockIO( false ); - // bind the vhost pcSock->SetBindHost( cCon.GetBindHost() ); @@ -2658,7 +2617,6 @@ bool CSocketManager::Connect( const CSConnection & cCon, Csock * pcSock ) pcSock->SetConState( Csock::CST_START ); AddSock( pcSock, cCon.GetSockName() ); - return( true ); } bool CSocketManager::Listen( const CSListener & cListen, Csock * pcSock, u_short *piRandPort ) @@ -2666,7 +2624,6 @@ bool CSocketManager::Listen( const CSListener & cListen, Csock * pcSock, u_short if ( !pcSock ) pcSock = GetSockObj( "", 0 ); - pcSock->BlockIO( false ); if( cListen.GetAFRequire() != CSSockAddr::RAF_ANY ) { pcSock->SetAFRequire( cListen.GetAFRequire() ); @@ -2765,7 +2722,7 @@ void CSocketManager::Loop() } if ( pcSock->GetConState() == Csock::CST_CONNECT ) { - if ( !pcSock->Connect( pcSock->GetBindHost(), true ) ) + if ( !pcSock->Connect() ) { if ( GetSockError() == ECONNREFUSED ) pcSock->ConnectionRefused(); @@ -3429,7 +3386,6 @@ void CSocketManager::Select( std::map & mpeSocks ) if ( !NewpcSock ) NewpcSock = GetSockObj( sHost, port ); - NewpcSock->BlockIO( false ); NewpcSock->SetType( Csock::INBOUND ); NewpcSock->SetRSock( inSock ); NewpcSock->SetWSock( inSock ); diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index ade7b921..c0b15145 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -863,11 +863,7 @@ bool CIRCNetwork::Connect() { ); CString sSockName = "IRC::" + m_pUser->GetUserName() + "::" + m_sName; - if (!CZNC::Get().GetManager().Connect(pServer->GetName(), pServer->GetPort(), sSockName, 120, bSSL, m_pUser->GetBindHost(), pIRCSock)) { - PutStatus("Unable to connect. (Bad host?)"); - CZNC::Get().AddNetworkToQueue(this); - return false; - } + CZNC::Get().GetManager().Connect(pServer->GetName(), pServer->GetPort(), sSockName, 120, bSSL, m_pUser->GetBindHost(), pIRCSock); return true; } diff --git a/src/Socket.cpp b/src/Socket.cpp index bb7f161c..60947bc7 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -106,7 +106,8 @@ bool CSocket::Connect(const CString& sHostname, unsigned short uPort, bool bSSL, sSockName = GetSockName(); } - return m_pModule->GetManager()->Connect(sHostname, uPort, sSockName, uTimeout, bSSL, sBindHost, this); + m_pModule->GetManager()->Connect(sHostname, uPort, sSockName, uTimeout, bSSL, sBindHost, this); + return true; } bool CSocket::Listen(unsigned short uPort, bool bSSL, unsigned int uTimeout) {