diff --git a/include/znc/Csocket.h b/include/znc/Csocket.h index 83f905fc..733d632f 100644 --- a/include/znc/Csocket.h +++ b/include/znc/Csocket.h @@ -1,60 +1,61 @@ /** -* -* Copyright (c) 1999-2012 Jim Hull -* All rights reserved -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* Redistributions in any form must be accompanied by information on how to obtain -* complete source code for this software and any accompanying software that uses this software. -* The source code must either be included in the distribution or be available for no more than -* the cost of distribution plus a nominal fee, and must be freely redistributable -* under reasonable conditions. For an executable file, complete source code means the source -* code for all modules it contains. It does not include source code for modules or files -* that typically accompany the major components of the operating system on which the executable file runs. -* -* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, -* OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, -* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* -*/ + * @file Csocket.h + * @author Jim Hull + * + * Copyright (c) 1999-2012 Jim Hull + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * Redistributions in any form must be accompanied by information on how to obtain + * complete source code for this software and any accompanying software that uses this software. + * The source code must either be included in the distribution or be available for no more than + * the cost of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source code means the source + * code for all modules it contains. It does not include source code for modules or files + * that typically accompany the major components of the operating system on which the executable file runs. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, + * OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ -/*** +/* * NOTES ... * - You should always compile with -Woverloaded-virtual to detect callbacks that may have been redefined since your last update * - If you want to use gethostbyname instead of getaddrinfo, the use -DUSE_GETHOSTBYNAME when compiling * - To compile with win32 need to link to winsock2, using gcc its -lws2_32 * - Code is formated with 'astyle --style=ansi -t4 --unpad-paren --pad-paren-in --keep-one-line-blocks' - ***/ - + */ #ifndef _HAS_CSOCKET_ #define _HAS_CSOCKET_ + #include // require this as a general rule, most projects have a defines.h or the like #include #include #include -#include #include #include #ifndef _WIN32 + #include #include #include #include #include + #else #include @@ -148,7 +149,7 @@ namespace Csocket /** * @class CSCharBuffer - * @brief ease of use self deleting char * class + * @brief Ease of use self deleting char * class. */ class CSCharBuffer { @@ -167,15 +168,20 @@ private: char * m_pBuffer; }; + +/** + * @class CSSockAddr + * @brief sockaddr wrapper. + */ class CSSockAddr { public: CSSockAddr() { m_bIsIPv6 = false; - memset(( struct sockaddr_in * )&m_saddr, '\0', sizeof( m_saddr ) ); + memset( (struct sockaddr_in *) &m_saddr, '\0', sizeof( m_saddr ) ); #ifdef HAVE_IPV6 - memset(( struct sockaddr_in6 * )&m_saddr6, '\0', sizeof( m_saddr6 ) ); + memset( (struct sockaddr_in6 *) &m_saddr6, '\0', sizeof( m_saddr6 ) ); #endif /* HAVE_IPV6 */ m_iAFRequire = RAF_ANY; } @@ -192,11 +198,10 @@ public: }; void SinFamily(); - void SinPort( u_short iPort ); + void SinPort( uint16_t iPort ); void SetIPv6( bool b ); bool GetIPv6() const { return( m_bIsIPv6 ); } - socklen_t GetSockAddrLen() { return( sizeof( m_saddr ) ); } sockaddr_in * GetSockAddr() { return( &m_saddr ); } in_addr * GetAddr() { return( &( m_saddr.sin_addr ) ); } @@ -218,8 +223,10 @@ private: EAFRequire m_iAFRequire; }; + class Csock; + /** * @class CGetAddrInfo * @brief this function is a wrapper around getaddrinfo (for ipv6) @@ -243,7 +250,7 @@ public: * @param pSock the sock being setup, this option can be NULL, if it is null csSockAddr is only setup * @param csSockAddr the struct that sockaddr data is being copied to */ - CGetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr ); + CGetAddrInfo( const CS_STRING & sHostname, Csock * pSock, CSSockAddr & csSockAddr ); ~CGetAddrInfo(); //! simply sets up m_cHints for use in process @@ -263,18 +270,18 @@ private: }; //! backwards compatible wrapper around CGetAddrInfo and gethostbyname -int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr ); +int GetAddrInfo( const CS_STRING & sHostname, Csock * pSock, CSSockAddr & csSockAddr ); //! used to retrieve the context position of the socket to its associated ssl connection. Setup once in InitSSL() via SSL_get_ex_new_index int GetCsockClassIdx(); #ifdef HAVE_LIBSSL //! returns the sock object associated to the particular context. returns NULL on failure or if not available -Csock *GetCsockFromCTX( X509_STORE_CTX *pCTX ); +Csock * GetCsockFromCTX( X509_STORE_CTX * pCTX ); #endif /* HAVE_LIBSSL */ -const u_int CS_BLOCKSIZE = 4096; +const uint32_t CS_BLOCKSIZE = 4096; template inline void CS_Delete( T * & p ) { if( p ) { delete p; p = NULL; } } #ifdef HAVE_LIBSSL @@ -288,14 +295,13 @@ enum ECompType //! adjusts tv with a new timeout if iTimeoutMS is smaller void CSAdjustTVTimeout( struct timeval & tv, long iTimeoutMS ); -void SSLErrors( const char *filename, u_int iLineNum ); +void SSLErrors( const char *filename, uint32_t iLineNum ); /** * @brief You HAVE to call this in order to use the SSL library, calling InitCsocket() also calls this * so unless you need to call InitSSL for a specific reason call InitCsocket() * @return true on success */ - bool InitSSL( ECompType eCompressionType = CT_NONE ); #endif /* HAVE_LIBSSL */ @@ -332,10 +338,7 @@ inline void TFD_SET( cs_sock_t iSock, fd_set *set ) inline bool TFD_ISSET( cs_sock_t iSock, fd_set *set ) { - if( FD_ISSET( iSock, set ) ) - return( true ); - - return( false ); + return( FD_ISSET( iSock, set ) ); } inline void TFD_CLR( cs_sock_t iSock, fd_set *set ) @@ -343,18 +346,17 @@ inline void TFD_CLR( cs_sock_t iSock, fd_set *set ) FD_CLR( iSock, set ); } -void __Perror( const CS_STRING & s, const char *pszFile, unsigned int iLineNo ); -unsigned long long millitime(); +void __Perror( const CS_STRING & s, const char * pszFile, uint32_t iLineNo ); +uint64_t millitime(); /** -* @class CCron -* @brief this is the main cron job class -* -* You should derive from this class, and override RunJob() with your code -* @author Jim Hull -*/ - + * @class CCron + * @brief this is the main cron job class + * + * You should derive from this class, and override RunJob() with your code + * @author Jim Hull + */ class CCron { public: @@ -368,11 +370,11 @@ public: * @param TimeSequence how often to run in seconds * @param iMaxCycles how many times to run, 0 makes it run forever */ - void StartMaxCycles( double fTimeSequence, u_int iMaxCycles ); - void StartMaxCycles( const timeval& tTimeSequence, u_int iMaxCycles ); + void StartMaxCycles( double dTimeSequence, uint32_t iMaxCycles ); + void StartMaxCycles( const timeval& tTimeSequence, uint32_t iMaxCycles ); //! starts and runs infinity amount of times - void Start( double fTimeSequence ); + void Start( double dTimeSequence ); void Start( const timeval& TimeSequence ); //! call this to turn off your cron, it will be removed @@ -385,8 +387,8 @@ public: void UnPause(); timeval GetInterval() const; - u_int GetMaxCycles() const; - u_int GetCyclesLeft() const; + uint32_t GetMaxCycles() const; + uint32_t GetCyclesLeft() const; //! returns true if cron is active bool isValid(); @@ -409,13 +411,13 @@ private: timeval m_tTime; bool m_bActive, m_bPause; timeval m_tTimeSequence; - u_int m_iMaxCycles, m_iCycles; + uint32_t m_iMaxCycles, m_iCycles; CS_STRING m_sName; }; /** * @class CSMonitorFD - * @brief class to tie sockets to for monitoring by Csocket at either the Csock or TSockManager + * @brief Class to tie sockets to for monitoring by Csocket at either the Csock or TSockManager. */ class CSMonitorFD { @@ -463,6 +465,7 @@ protected: bool m_bEnabled; }; + /** * @class CSockCommon * @brief simple class to share common code to both TSockManager and Csock @@ -491,9 +494,9 @@ public: */ virtual void DelCron( const CS_STRING & sName, bool bDeleteAll = true, bool bCaseSensitive = true ); //! delete cron by idx - virtual void DelCron( u_int iPos ); + virtual void DelCron( uint32_t iPos ); //! delete cron by address - virtual void DelCronByAddr( CCron *pcCron ); + virtual void DelCronByAddr( CCron * pcCron ); void CheckFDs( const std::map< int, short > & miiReadyFds ); void AssignFDs( std::map< int, short > & miiReadyFds, struct timeval * tvtimeout ); @@ -506,35 +509,37 @@ protected: std::vector m_vcMonitorFD; }; + #ifdef HAVE_LIBSSL typedef int ( *FPCertVerifyCB )( int, X509_STORE_CTX * ); #endif /* HAVE_LIBSSL */ + /** -* @class Csock -* @brief Basic Socket Class -* The most basic level socket class -* You can use this class directly for quick things -* or use the socket manager -* @see TSocketManager -* @author Jim Hull -*/ + * @class Csock + * @brief Basic socket class. + * + * The most basic level socket class. + * You can use this class directly for quick things + * or use the socket manager. + * @see TSocketManager + * @author Jim Hull + */ class Csock : public CSockCommon { public: //! default constructor, sets a timeout of 60 seconds 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 - */ - Csock( const CS_STRING & sHostname, u_short uPort, int iTimeout = 60 ); + * @brief Advanced constructor, for creating a simple connection + * @param sHostname the hostname your are connecting to + * @param uPort the port you are connecting to + * @param itimeout how long to wait before ditching the connection, default is 60 seconds + */ + Csock( const CS_STRING & sHostname, uint16_t uPort, int itimeout = 60 ); //! override this for accept sockets - virtual Csock *GetSockObj( const CS_STRING & sHostname, u_short iPort ); + virtual Csock *GetSockObj( const CS_STRING & sHostname, uint16_t iPort ); virtual ~Csock(); @@ -552,16 +557,16 @@ public: { OUTBOUND = 0, //!< outbound connection LISTENER = 1, //!< a socket accepting connections - INBOUND = 2 //!< an inbound connection, passed from LISTENER + INBOUND = 2 //!< an inbound connection, passed from LISTENER }; enum EFRead { - READ_EOF = 0, //!< End Of File, done reading - READ_ERR = -1, //!< Error on the socket, socket closed, done reading - READ_EAGAIN = -2, //!< Try to get data again - READ_CONNREFUSED = -3, //!< Connection Refused - READ_TIMEDOUT = -4 //!< Connection timed out + READ_EOF = 0, //!< End Of File, done reading + READ_ERR = -1, //!< Error on the socket, socket closed, done reading + READ_EAGAIN = -2, //!< Try to get data again + READ_CONNREFUSED = -3, //!< Connection Refused + READ_TIMEDOUT = -4 //!< Connection timed out }; enum EFSelect @@ -593,42 +598,39 @@ public: enum ECloseType { - CLT_DONT = 0, //! don't close DER - CLT_NOW = 1, //! close immediatly - CLT_AFTERWRITE = 2, //! close after finishing writing the buffer - CLT_DEREFERENCE = 3 //! used after copy in Csock::Dereference() to cleanup a sock thats being shutdown + CLT_DONT = 0, //!< don't close DER + CLT_NOW = 1, //!< close immediatly + CLT_AFTERWRITE = 2, //!< close after finishing writing the buffer + CLT_DEREFERENCE = 3 //!< used after copy in Csock::Dereference() to cleanup a sock thats being shutdown }; Csock & operator<<( const CS_STRING & s ); Csock & operator<<( std::ostream & ( *io )( std::ostream & ) ); - Csock & operator<<( int i ); - Csock & operator<<( unsigned int i ); - Csock & operator<<( long i ); - Csock & operator<<( unsigned long i ); - Csock & operator<<( unsigned long long i ); + Csock & operator<<( int32_t i ); + Csock & operator<<( uint32_t i ); + Csock & operator<<( int64_t i ); + Csock & operator<<( uint64_t i ); Csock & operator<<( float i ); Csock & operator<<( double i ); /** - * Create the connection, this is used by the socket manager, and shouldn't be called directly by the user - * - * @return true on success - */ + * @brief Create the connection, this is used by the socket manager, and shouldn't be called directly by the user + * @return true on success + */ virtual bool Connect(); /** - * Listens for connections - * - * @param iPort the port to listen on - * @param iMaxConns the maximum amount of pending connections to allow - * @param sBindHost the vhost on which to listen - * @param iTimeout if no connections come in by this timeout, the listener is closed - * @param bDetach don't block waiting for port to come up, instead detach and return immediately - */ - virtual bool Listen( u_short iPort, int iMaxConns = SOMAXCONN, const CS_STRING & sBindHost = "", u_int iTimeout = 0, bool bDetach = false ); + * @brief Listens for connections + * @param iPort the port to listen on + * @param iMaxConns the maximum amount of pending connections to allow + * @param sBindHost the vhost on which to listen + * @param iTimeout if no connections come in by this timeout, the listener is closed + * @param bDetach don't block waiting for port to come up, instead detach and return immediately + */ + virtual bool Listen( uint16_t iPort, int iMaxConns = SOMAXCONN, const CS_STRING & sBindHost = "", uint32_t iTimeout = 0, bool bDetach = false ); //! Accept an inbound connection, this is used internally - virtual cs_sock_t Accept( CS_STRING & sHost, u_short & iRPort ); + virtual cs_sock_t Accept( CS_STRING & sHost, uint16_t & iRPort ); //! Accept an inbound SSL connection, this is used internally and called after Accept virtual bool AcceptSSL(); @@ -640,48 +642,49 @@ public: virtual bool SSLServerSetup(); /** - * Create the SSL connection, this is used by the socket manager, and shouldn't be called directly by the user - * - * @return true on success - */ + * @brief Create the SSL connection + * @return true on success + * + * This is used by the socket manager, and shouldn't be called directly by the user. + */ virtual bool ConnectSSL(); //! start a TLS connection on an existing plain connection bool StartTLS(); /** - * Write data to the socket - * if not all of the data is sent, it will be stored on - * an internal buffer, and tried again with next call to Write - * if the socket is blocking, it will send everything, its ok to check ernno after this (nothing else is processed) - * - * @param data the data to send - * @param len the length of data - * - */ + * @brief Write data to the socket + * + * If not all of the data is sent, it will be stored on + * an internal buffer, and tried again with next call to Write + * if the socket is blocking, it will send everything, its ok to check ernno after this (nothing else is processed) + * + * @param data the data to send + * @param len the length of data + */ virtual bool Write( const char *data, size_t len ); /** - * convience function - * @see Write( const char *, int ) - */ + * convenience function + * @see Write( const char *, int ) + */ virtual bool Write( const CS_STRING & sData ); /** - * Read from the socket - * Just pass in a pointer, big enough to hold len bytes - * - * @param data the buffer to read into - * @param len the size of the buffer - * - * @return - * Returns READ_EOF for EOF - * Returns READ_ERR for ERROR - * Returns READ_EAGAIN for Try Again ( EAGAIN ) - * Returns READ_CONNREFUSED for connection refused - * Returns READ_TIMEDOUT for a connection that timed out at the TCP level - * Otherwise returns the bytes read into data - */ + * Read from the socket + * Just pass in a pointer, big enough to hold len bytes + * + * @param data the buffer to read into + * @param len the size of the buffer + * + * @return + * Returns READ_EOF for EOF + * Returns READ_ERR for ERROR + * Returns READ_EAGAIN for Try Again ( EAGAIN ) + * Returns READ_CONNREFUSED for connection refused + * Returns READ_TIMEDOUT for a connection that timed out at the TCP level + * Otherwise returns the bytes read into data + */ virtual cs_ssize_t Read( char *data, size_t len ); CS_STRING GetLocalIP(); CS_STRING GetRemoteIP(); @@ -714,11 +717,11 @@ public: void UnPauseRead(); bool IsReadPaused(); /** - * this timeout isn't just connection timeout, but also timeout on - * NOT recieving data, to disable this set it to 0 - * then the normal TCP timeout will apply (basically TCP will kill a dead connection) - * Set the timeout, set to 0 to never timeout - */ + * this timeout isn't just connection timeout, but also timeout on + * NOT recieving data, to disable this set it to 0 + * then the normal TCP timeout will apply (basically TCP will kill a dead connection) + * Set the timeout, set to 0 to never timeout + */ enum { TMO_READ = 1, @@ -729,10 +732,10 @@ public: //! Currently this uses the same value for all timeouts, and iTimeoutType merely states which event will be checked //! for timeouts - void SetTimeout( int iTimeout, u_int iTimeoutType = TMO_ALL ); - void SetTimeoutType( u_int iTimeoutType ); + void SetTimeout( int iTimeout, uint32_t iTimeoutType = TMO_ALL ); + void SetTimeoutType( uint32_t iTimeoutType ); int GetTimeout() const; - u_int GetTimeoutType() const; + uint32_t GetTimeoutType() const; //! returns true if the socket has timed out virtual bool CheckTimeout( time_t iNow ); @@ -753,8 +756,8 @@ public: CS_STRING & GetInternalWriteBuffer(); //! sets the max buffered threshold when EnableReadLine() is enabled - void SetMaxBufferThreshold( u_int iThreshold ); - u_int GetMaxBufferThreshold() const; + void SetMaxBufferThreshold( uint32_t iThreshold ); + uint32_t GetMaxBufferThreshold() const; //! Returns the connection type from enum eConnType int GetType() const; @@ -770,33 +773,33 @@ public: //! Gets the starting time of this socket - unsigned long long GetStartTime() const; + uint64_t GetStartTime() const; //! Resets the start time void ResetStartTime(); //! Gets the amount of data read during the existence of the socket - unsigned long long GetBytesRead() const; + uint64_t GetBytesRead() const; void ResetBytesRead(); //! Gets the amount of data written during the existence of the socket - unsigned long long GetBytesWritten() const; + uint64_t GetBytesWritten() const; void ResetBytesWritten(); //! Get Avg Read Speed in sample milliseconds (default is 1000 milliseconds or 1 second) - double GetAvgRead( unsigned long long iSample = 1000 ); + double GetAvgRead( uint64_t iSample = 1000 ); //! Get Avg Write Speed in sample milliseconds (default is 1000 milliseconds or 1 second) - double GetAvgWrite( unsigned long long iSample = 1000 ); + double GetAvgWrite( uint64_t iSample = 1000 ); //! Returns the remote port - u_short GetRemotePort(); + uint16_t GetRemotePort(); //! Returns the local port - u_short GetLocalPort(); + uint16_t GetLocalPort(); //! Returns the port - u_short GetPort(); - void SetPort( u_short iPort ); + uint16_t GetPort(); + void SetPort( uint16_t iPort ); //! just mark us as closed, the parent can pick it up void Close( ECloseType eCloseType = CLT_NOW ); @@ -821,8 +824,6 @@ public: const CS_STRING & GetPemLocation(); void SetPemPass( const CS_STRING & sPassword ); const CS_STRING & GetPemPass() const; - static int PemPassCB( char *buf, int size, int rwflag, void *pcSocket ); - static int CertVerifyCB( int preverify_ok, X509_STORE_CTX *x509_ctx ); //! Set the SSL method type void SetSSLMethod( int iMethod ); @@ -858,12 +859,11 @@ public: //! Returns the peer's certificate finger print long GetPeerFingerprint( CS_STRING & sFP ); - unsigned int GetRequireClientCertFlags(); + uint32_t GetRequireClientCertFlags(); //! legacy, deprecated @see SetRequireClientCertFlags void SetRequiresClientCert( bool bRequiresCert ); - //! bitwise flags, 0 means don't require cert, SSL_VERIFY_PEER verifies peers, SSL_VERIFY_FAIL_IF_NO_PEER_CERT will cause the connection to fail if no cert - void SetRequireClientCertFlags( unsigned int iRequireClientCertFlags ) { m_iRequireClientCertFlags = iRequireClientCertFlags; } - + //! bitwise flags, 0 means don't require cert, SSL_VERIFY_PEER verifies peers, SSL_VERIFY_FAIL_IF_NO_PEER_CERT will cause the connection to fail if no cert + void SetRequireClientCertFlags( uint32_t iRequireClientCertFlags ) { m_iRequireClientCertFlags = iRequireClientCertFlags; } #endif /* HAVE_LIBSSL */ //! Set The INBOUND Parent sockname @@ -871,55 +871,55 @@ public: const CS_STRING & GetParentSockName(); /** - * sets the rate at which we can send data - * @param iBytes the amount of bytes we can write - * @param iMilliseconds the amount of time we have to rate to iBytes - */ - virtual void SetRate( u_int iBytes, unsigned long long iMilliseconds ); + * sets the rate at which we can send data + * @param iBytes the amount of bytes we can write + * @param iMilliseconds the amount of time we have to rate to iBytes + */ + virtual void SetRate( uint32_t iBytes, uint64_t iMilliseconds ); - u_int GetRateBytes(); - unsigned long long GetRateTime(); + uint32_t GetRateBytes(); + uint64_t GetRateTime(); /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks - * - * Connected event - */ + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks + * + * Connected event + */ virtual void Connected() {} /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks - * - * Disconnected event - */ + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks + * + * Disconnected event + */ virtual void Disconnected() {} /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks - * - * Sock Timed out event - */ + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks + * + * Sock Timed out event + */ virtual void Timeout() {} /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks - * - * Ready to read data event - */ + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks + * + * Ready to read data event + */ virtual void ReadData( const char *data, size_t len ) {} /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks. - * With ReadLine, if your not going to use it IE a data stream, @see EnableReadLine() - * - * Ready to Read a full line event - */ + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks. + * With ReadLine, if your not going to use it IE a data stream, @see EnableReadLine() + * + * Ready to Read a full line event + */ virtual void ReadLine( const CS_STRING & sLine ) {} //! set the value of m_bEnableReadLine to true, we don't want to store a buffer for ReadLine, unless we want it void EnableReadLine(); @@ -937,31 +937,31 @@ public: */ virtual void ReachedMaxBuffer(); /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks - * - * A sock error occured event - */ + * @brief A sock error occured event + * + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks + */ virtual void SockError( int iErrno, const CS_STRING & sDescription ) {} /** - * Override these functions for an easy interface when using the Socket Manager - * Don't bother using these callbacks if you are using this class directly (without Socket Manager) - * as the Socket Manager calls most of these callbacks - * - * - * Incoming Connection Event - * return false and the connection will fail - * default returns true - */ - virtual bool ConnectionFrom( const CS_STRING & sHost, u_short iPort ) { return( true ); } + * Override these functions for an easy interface when using the Socket Manager + * Don't bother using these callbacks if you are using this class directly (without Socket Manager) + * as the Socket Manager calls most of these callbacks + * + * + * Incoming Connection Event + * return false and the connection will fail + * default returns true + */ + virtual bool ConnectionFrom( const CS_STRING & sHost, uint16_t iPort ) { return( true ); } /** * @brief called when type is LISTENER and the listening port is up and running * @param sBindIP the IP that is being bound to. Empty if no bind restriction * @param uPort the listening port */ - virtual void Listening( const CS_STRING & sBindIP, u_short uPort ) {} + virtual void Listening( const CS_STRING & sBindIP, uint16_t uPort ) {} /** * Override these functions for an easy interface when using the Socket Manager @@ -982,7 +982,7 @@ public: * Gets called immediatly after the m_ssl member is setup and initialized, useful if you need to assign anything * to this ssl session via SSL_set_ex_data */ - virtual void SSLFinishSetup( SSL *pSSL ) {} + virtual void SSLFinishSetup( SSL * pSSL ) {} #endif /* HAVE_LIBSSL */ @@ -1043,7 +1043,7 @@ public: } //! returns true if this socket can write its data, primarily used with rate shaping, initialize iNOW to 0 and it sets it on the first call - bool AllowWrite( unsigned long long & iNOW ) const; + bool AllowWrite( uint64_t & iNOW ) const; void SetSkipConnect( bool b ) { m_bSkipConnect = b; } @@ -1060,7 +1060,7 @@ public: * @brief retrieve name info (numeric only) for a given sockaddr_storage * @param pAddr the sockaddr_storage * @param iAddrLen the length - * @param sHostname filled with the IP from getnameinfo + * @param sIP filled with the IP from getnameinfo * @param piPort if not null, filled with the port * @return 0 on success. * @@ -1068,7 +1068,7 @@ public: * One example is in the event that an ipv6 ip is a mapped ipv4 mapped, you can check like so. * - if( pAddr->ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED( &(((const struct sockaddr_in6 *)pAddr)->sin6_addr ) ) */ - virtual int ConvertAddress( const struct sockaddr_storage * pAddr, socklen_t iAddrLen, CS_STRING & sIP, u_short * piPort ); + virtual int ConvertAddress( const struct sockaddr_storage * pAddr, socklen_t iAddrLen, CS_STRING & sIP, uint16_t * piPort ); #ifdef HAVE_C_ARES CSSockAddr * GetCurrentAddr() const { return( m_pCurrAddr ); } @@ -1084,28 +1084,28 @@ private: 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; + uint16_t m_uPort, m_iRemotePort, m_iLocalPort; cs_sock_t m_iReadSock, m_iWriteSock; - int m_iTimeout, m_iConnType, m_iMethod, m_iTcount, m_iMaxConns; + int m_iTimeout, m_iConnType, m_iMethod, m_iTcount, m_iMaxConns; 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; ECloseType m_eCloseType; - unsigned long long m_iMaxMilliSeconds, m_iLastSendTime, m_iBytesRead, m_iBytesWritten, m_iStartTime; - unsigned int m_iMaxBytes, m_iMaxStoredBufferLength, m_iTimeoutType; - size_t m_iLastSend; + uint64_t m_iMaxMilliSeconds, m_iLastSendTime, m_iBytesRead, m_iBytesWritten, m_iStartTime; + uint32_t m_iMaxBytes, m_iMaxStoredBufferLength, m_iTimeoutType; + size_t m_iLastSend; - CSSockAddr m_address, m_bindhost; - bool m_bIsIPv6, m_bSkipConnect; - time_t m_iLastCheckTimeoutTime; + CSSockAddr m_address, m_bindhost; + bool m_bIsIPv6, m_bSkipConnect; + time_t m_iLastCheckTimeoutTime; #ifdef HAVE_LIBSSL - CS_STRING m_sSSLBuffer; - SSL *m_ssl; - SSL_CTX *m_ssl_ctx; - unsigned int m_iRequireClientCertFlags; + CS_STRING m_sSSLBuffer; + SSL * m_ssl; + SSL_CTX * m_ssl_ctx; + uint32_t m_iRequireClientCertFlags; FPCertVerifyCB m_pCerVerifyCB; @@ -1114,20 +1114,18 @@ private: #endif /* HAVE_LIBSSL */ - //! 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, uint16_t uPort, int iTimeout = 60 ); // Connection State Info ECONState m_eConState; CS_STRING m_sBindHost; - u_int m_iCurBindCount, m_iDNSTryCount; + uint32_t m_iCurBindCount, m_iDNSTryCount; #ifdef HAVE_C_ARES void FreeAres(); ares_channel m_pARESChannel; - CSSockAddr *m_pCurrAddr; + CSSockAddr * m_pCurrAddr; int m_iARESStatus; #endif /* HAVE_C_ARES */ @@ -1145,7 +1143,7 @@ public: * @param iPort port to connect to * @param iTimeout connection timeout */ - CSConnection( const CS_STRING & sHostname, u_short iPort, int iTimeout = 60 ) + CSConnection( const CS_STRING & sHostname, uint16_t iPort, int iTimeout = 60 ) { m_sHostname = sHostname; m_iPort = iPort; @@ -1161,7 +1159,7 @@ public: 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 ); } + uint16_t GetPort() const { return( m_iPort ); } int GetTimeout() const { return( m_iTimeout ); } bool GetIsSSL() const { return( m_bIsSSL ); } CSSockAddr::EAFRequire GetAFRequire() const { return( m_iAFrequire ); } @@ -1179,7 +1177,7 @@ public: //! 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; } + void SetPort( uint16_t i ) { m_iPort = i; } //! sets the connection timeout void SetTimeout( int i ) { m_iTimeout = i; } //! set to true to enable SSL @@ -1198,7 +1196,7 @@ public: protected: CS_STRING m_sHostname, m_sSockName, m_sBindHost; - u_short m_iPort; + uint16_t m_iPort; int m_iTimeout; bool m_bIsSSL; CSSockAddr::EAFRequire m_iAFrequire; @@ -1210,7 +1208,7 @@ protected: class CSSSLConnection : public CSConnection { public: - CSSSLConnection( const CS_STRING & sHostname, u_short iPort, int iTimeout = 60 ) : + CSSSLConnection( const CS_STRING & sHostname, uint16_t iPort, int iTimeout = 60 ) : CSConnection( sHostname, iPort, iTimeout ) { SetIsSSL( true ); @@ -1230,7 +1228,7 @@ public: * @param sBindHost host to bind to * @param bDetach don't block while waiting for the port to come up, instead detach and return immediately */ - CSListener( u_short iPort, const CS_STRING & sBindHost = "", bool bDetach = false ) + CSListener( uint16_t iPort, const CS_STRING & sBindHost = "", bool bDetach = false ) { m_iPort = iPort; m_sBindHost = sBindHost; @@ -1248,22 +1246,22 @@ public: void SetDetach( bool b ) { m_bDetach = b; } bool GetDetach() const { return( m_bDetach ); } - u_short GetPort() const { return( m_iPort ); } + uint16_t 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 ); } int GetMaxConns() const { return( m_iMaxConns ); } - u_int GetTimeout() const { return( m_iTimeout ); } + uint32_t GetTimeout() const { return( m_iTimeout ); } CSSockAddr::EAFRequire GetAFRequire() const { return( m_iAFrequire ); } #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 ); } - unsigned int GetRequireClientCertFlags() const { return( m_iRequireCertFlags ); } + uint32_t GetRequireClientCertFlags() const { return( m_iRequireCertFlags ); } #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; } + void SetPort( uint16_t 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 @@ -1273,7 +1271,7 @@ public: //! 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; } + void SetTimeout( uint32_t i ) { m_iTimeout = i; } //! sets the AF family type required void SetAFRequire( CSSockAddr::EAFRequire iAFRequire ) { m_iAFrequire = iAFRequire; } @@ -1290,17 +1288,17 @@ public: void SetRequireClientCertFlags( unsigned int iRequireCertFlags ) { m_iRequireCertFlags = iRequireCertFlags; } #endif /* HAVE_LIBSSL */ private: - u_short m_iPort; + uint16_t m_iPort; CS_STRING m_sSockName, m_sBindHost; bool m_bIsSSL; bool m_bDetach; int m_iMaxConns; - u_int m_iTimeout; + uint32_t m_iTimeout; CSSockAddr::EAFRequire m_iAFrequire; #ifdef HAVE_LIBSSL CS_STRING m_sPemLocation, m_sPemPass, m_sCipher; - unsigned int m_iRequireCertFlags; + uint32_t m_iRequireCertFlags; #endif /* HAVE_LIBSSL */ }; @@ -1308,7 +1306,7 @@ private: class CSSSListener : public CSListener { public: - CSSSListener( u_short iPort, const CS_STRING & sBindHost = "" ) : + CSSSListener( uint16_t iPort, const CS_STRING & sBindHost = "" ) : CSListener( iPort, sBindHost ) { SetIsSSL( true ); @@ -1317,28 +1315,26 @@ public: #endif /* HAVE_LIBSSL */ /** -* @class CSocketManager -* @brief Best class to use to interact with the sockets -* -* handles SSL and NON Blocking IO -* Its a template class since Csock derives need to be new'd correctly -* Makes it easier to use overall -* Rather then use it directly, you'll probably get more use deriving from it -* Another thing to note, is that all sockets are deleted implicitly, so obviously you -* cant pass in Csock classes created on the stack. For those of you who don't -* know STL very well, the reason I did this is because whenever you add to certain stl containers -* (ie vector, or map), its completely rebuilt using the copy constructor on each element. -* That then means the constructor and destructor are called on every item in the container. -* Not only is this more overhead then just moving pointers around, its dangerous as if you have -* an object that is newed and deleted in the destructor the value of its pointer is copied in the -* default copy constructor. This means everyone has to know better and create a copy constructor, -* or I just make everyone new their object :) -* -* class CBlahSock : public TSocketManager -* -* @author Jim Hull -*/ - + * @class CSocketManager + * @brief Best class to use to interact with the sockets + * + * Handles SSL and NON Blocking IO. + * Rather then use it directly, you'll probably get more use deriving from it. + * Override GetSockObj since Csock derivatives need to be new'd correctly. + * Makes it easier to use overall. + * Another thing to note, is that all sockets are deleted implicitly, so obviously you + * can't pass in Csock classes created on the stack. For those of you who don't + * know STL very well, the reason I did this is because whenever you add to certain stl containers + * (e.g. vector, or map), it is completely rebuilt using the copy constructor on each element. + * That then means the constructor and destructor are called on every item in the container. + * Not only is this more overhead then just moving pointers around, its dangerous as if you have + * an object that is newed and deleted in the destructor the value of its pointer is copied in the + * default copy constructor. This means everyone has to know better and create a copy constructor, + * or I just make everyone new their object :). + * + * @see TSocketManager + * @author Jim Hull + */ class CSocketManager : public std::vector, public CSockCommon { public: @@ -1347,22 +1343,21 @@ public: virtual void clear(); virtual void Cleanup(); - virtual Csock * GetSockObj( const CS_STRING & sHostname, u_short uPort, int iTimeout = 60 ); + virtual Csock * GetSockObj( const CS_STRING & sHostname, uint16_t uPort, int iTimeout = 60 ); enum EMessages { - SUCCESS = 0, //! Select returned at least 1 fd ready for action - SELECT_ERROR = -1, //! An Error Happened, Probably dead socket. That socket is returned if available - SELECT_TIMEOUT = -2, //! Select Timeout - SELECT_TRYAGAIN = -3 //! Select calls for you to try again + SUCCESS = 0, //!< Select returned at least 1 fd ready for action + SELECT_ERROR = -1, //!< An Error Happened, Probably dead socket. That socket is returned if available + SELECT_TIMEOUT = -2, //!< Select Timeout + SELECT_TRYAGAIN = -3 //!< Select calls for you to try again }; /** - * Create a connection - * - * @param cCon the connection which should be established - * @param pcSock the socket used for the connectiong, can be NULL - */ + * @brief Create a connection + * @param cCon the connection which should be established + * @param pcSock the socket used for the connection, can be NULL + */ void Connect( const CSConnection & cCon, Csock * pcSock = NULL ); /** @@ -1374,17 +1369,17 @@ public: * IF you provide piRandPort to be assigned, AND you set bDetach to true, then Listen() still blocks. If you don't want this * behavior, then look for the port assignment to be called in Csock::Listening */ - virtual bool Listen( const CSListener & cListen, Csock * pcSock = NULL, u_short *piRandPort = NULL ); + virtual bool Listen( const CSListener & cListen, Csock * pcSock = NULL, uint16_t * piRandPort = NULL ); //! simple method to see if there are file descriptors being processed, useful to know if all the work is done in the manager bool HasFDs() const; /** - * Best place to call this class for running, all the call backs are called. - * You should through this in your main while loop (long as its not blocking) - * all the events are called as needed. - */ + * Best place to call this class for running, all the call backs are called. + * You should through this in your main while loop (long as its not blocking) + * all the events are called as needed. + */ virtual void Loop(); /** @@ -1402,19 +1397,19 @@ public: * @param iUpperBounds the upper bounds to use in MICROSECONDS * @param iMaxResolution the maximum time to calculate overall in seconds */ - void DynamicSelectLoop( u_long iLowerBounds, u_long iUpperBounds, time_t iMaxResolution = 3600 ); + void DynamicSelectLoop( uint64_t iLowerBounds, uint64_t iUpperBounds, time_t iMaxResolution = 3600 ); /** - * Make this method virtual, so you can override it when a socket is added. - * Assuming you might want to do some extra stuff - */ - virtual void AddSock( Csock *pcSock, const CS_STRING & sSockName ); + * Make this method virtual, so you can override it when a socket is added. + * Assuming you might want to do some extra stuff + */ + virtual void AddSock( Csock * pcSock, const CS_STRING & sSockName ); //! returns a pointer to the FIRST sock found by port or NULL on no match - virtual Csock * FindSockByRemotePort( u_short iPort ); + virtual Csock * FindSockByRemotePort( uint16_t iPort ); //! returns a pointer to the FIRST sock found by port or NULL on no match - virtual Csock * FindSockByLocalPort( u_short iPort ); + virtual Csock * FindSockByLocalPort( uint16_t iPort ); //! returns a pointer to the FIRST sock found by name or NULL on no match virtual Csock * FindSockByName( const CS_STRING & sName ); @@ -1430,26 +1425,24 @@ public: //! return the last known error as set by this class int GetErrno() { return( m_errno ); } - - //! Get the Select Timeout in MICROSECONDS ( 1000 == 1 millisecond ) - u_long GetSelectTimeout() { return( m_iSelectWait ); } + uint64_t GetSelectTimeout() { return( m_iSelectWait ); } //! Set the Select Timeout in MICROSECONDS ( 1000 == 1 millisecond ) //! Setting this to 0 will cause no timeout to happen, Select() will return instantly - void SetSelectTimeout( u_long iTimeout ) { m_iSelectWait = iTimeout; } + void SetSelectTimeout( uint64_t iTimeout ) { m_iSelectWait = iTimeout; } //! Delete a sock by addr //! its position is looked up //! the socket is deleted, the appropriate call backs are peformed //! and its instance is removed from the manager - virtual void DelSockByAddr( Csock *pcSock ); + virtual void DelSockByAddr( Csock * pcSock ); //! Delete a sock by position in the vector //! the socket is deleted, the appropriate call backs are peformed //! and its instance is removed from the manager //! deleting in a loop can be tricky, be sure you watch your position. - //! ie for( u_int a = 0; a < size(); a++ ) DelSock( a-- ); - virtual void DelSock( u_int iPos ); + //! ie for( uint32_t a = 0; a < size(); a++ ) DelSock( a-- ); + virtual void DelSock( size_t iPos ); /** * @brief swaps out a sock with a copy of the original sock @@ -1457,7 +1450,7 @@ public: * @param iOrginalSockIdx the position in this sockmanager of the original sock * @return true on success */ - virtual bool SwapSockByIdx( Csock *pNewSock, u_long iOrginalSockIdx ); + virtual bool SwapSockByIdx( Csock * pNewSock, size_t iOrginalSockIdx ); /** * @brief swaps out a sock with a copy of the original sock @@ -1465,13 +1458,13 @@ public: * @param pOrigSock the address of the original socket * @return true on success */ - virtual bool SwapSockByAddr( Csock *pNewSock, Csock *pOrigSock ); + virtual bool SwapSockByAddr( Csock * pNewSock, Csock * pOrigSock ); //! Get the bytes read from all sockets current and past - unsigned long long GetBytesRead() const; + uint64_t GetBytesRead() const; //! Get the bytes written to all sockets current and past - unsigned long long GetBytesWritten() const; + uint64_t GetBytesWritten() const; //! this is a strict wrapper around C-api select(). Added in the event you need to do special work here enum ECheckType @@ -1489,11 +1482,11 @@ 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 - * each struct contains the socks error - * @see GetErrno() - */ + * @brief 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 + * each struct contains the socks error + * @see GetErrno() + */ void Select( std::map & mpeSocks ); timeval GetDynamicSleepTime( const timeval& tNow, const timeval& tMaxResolution ) const; @@ -1506,16 +1499,19 @@ private: /////////// // members - EMessages m_errno; - unsigned long long m_iCallTimeouts; - unsigned long long m_iBytesRead; - unsigned long long m_iBytesWritten; - u_long m_iSelectWait; + EMessages m_errno; + uint64_t m_iCallTimeouts; + uint64_t m_iBytesRead; + uint64_t m_iBytesWritten; + uint64_t m_iSelectWait; }; + /** * @class TSocketManager - * @brief ease of use templated socket manager + * @brief Ease of use templated socket manager + * + * class CBlahSock : public TSocketManager */ template class TSocketManager : public CSocketManager @@ -1523,7 +1519,7 @@ class TSocketManager : public CSocketManager public: TSocketManager() : CSocketManager() {} virtual ~TSocketManager() {} - virtual T * GetSockObj( const CS_STRING & sHostname, u_short uPort, int iTimeout = 60 ) + virtual T * GetSockObj( const CS_STRING & sHostname, uint16_t uPort, int iTimeout = 60 ) { return( new T( sHostname, uPort, iTimeout ) ); } diff --git a/src/Csocket.cpp b/src/Csocket.cpp index 6ba945bf..4e5b71aa 100644 --- a/src/Csocket.cpp +++ b/src/Csocket.cpp @@ -1,34 +1,34 @@ -/** @file -* -* Copyright (c) 1999-2012 Jim Hull -* All rights reserved -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* Redistributions in any form must be accompanied by information on how to obtain -* complete source code for this software and any accompanying software that uses this software. -* The source code must either be included in the distribution or be available for no more than -* the cost of distribution plus a nominal fee, and must be freely redistributable -* under reasonable conditions. For an executable file, complete source code means the source -* code for all modules it contains. It does not include source code for modules or files -* that typically accompany the major components of the operating system on which the executable file runs. -* -* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, -* OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, -* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* -*/ +/** + * @file Csocket.cc + * @author Jim Hull + * + * Copyright (c) 1999-2012 Jim Hull + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * Redistributions in any form must be accompanied by information on how to obtain + * complete source code for this software and any accompanying software that uses this software. + * The source code must either be included in the distribution or be available for no more than + * the cost of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source code means the source + * code for all modules it contains. It does not include source code for modules or files + * that typically accompany the major components of the operating system on which the executable file runs. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, + * OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ /*** * doing this because there seems to be a bug that is losing the "short" on htons when in optimize mode turns into a macro @@ -49,8 +49,6 @@ #include #endif /* HAVE_LIBSSL */ - - #include #define CS_SRANDBUFFER 128 @@ -79,7 +77,7 @@ static int inet_pton( int af, const char *src, void *dst ) sockaddr_storage aAddress; int iAddrLen = sizeof( sockaddr_storage ); memset( &aAddress, 0, iAddrLen ); - char *pTmp = strdup( src ); + char * pTmp = strdup( src ); aAddress.ss_family = af; // this is important: // The function fails if the sin_family member of the SOCKADDR_IN structure is not set to AF_INET or AF_INET6. int iRet = WSAStringToAddressA( pTmp, af, NULL, ( sockaddr * )&aAddress, &iAddrLen ); @@ -87,9 +85,9 @@ static int inet_pton( int af, const char *src, void *dst ) if( iRet == 0 ) { if( af == AF_INET6 ) - memcpy( dst, &(( sockaddr_in6 * )&aAddress )->sin6_addr, sizeof( in6_addr ) ); + memcpy( dst, &((sockaddr_in6 *) &aAddress )->sin6_addr, sizeof( in6_addr ) ); else - memcpy( dst, &(( sockaddr_in * )&aAddress )->sin_addr, sizeof( in_addr ) ); + memcpy( dst, &((sockaddr_in *) &aAddress )->sin_addr, sizeof( in_addr ) ); return( 1 ); } return( -1 ); @@ -117,7 +115,9 @@ static inline void set_close_on_exec( cs_sock_t fd ) // see http://gcc.gnu.org/ml/java-patches/2002-q1/msg00696.html // for infos on how to do this } -#else + +#else // _WIN32 + static inline void set_non_blocking( cs_sock_t fd ) { int fdflags = fcntl( fd, F_GETFL, 0 ); @@ -131,7 +131,7 @@ static inline void set_non_blocking( cs_sock_t fd ) static inline void set_blocking(cs_sock_t fd) { int fdflags = fcntl(fd, F_GETFL, 0); - if ( fdflags < 0 ) + if( fdflags < 0 ) return; // Ignore errors fdflags &= ~O_NONBLOCK; fcntl( fd, F_SETFL, fdflags ); @@ -154,7 +154,8 @@ void CSSockAddr::SinFamily() #endif /* HAVE_IPV6 */ m_saddr.sin_family = PF_INET; } -void CSSockAddr::SinPort( u_short iPort ) + +void CSSockAddr::SinPort( uint16_t iPort ) { #ifdef HAVE_IPV6 m_saddr6.sin6_port = htons( iPort ); @@ -178,12 +179,39 @@ void CSSockAddr::SetIPv6( bool b ) #ifdef HAVE_LIBSSL -Csock *GetCsockFromCTX( X509_STORE_CTX *pCTX ) +static int _PemPassCB( char *pBuff, int iBuffLen, int rwflag, void * pcSocket ) { - Csock *pSock = NULL; - SSL *pSSL = ( SSL * )X509_STORE_CTX_get_ex_data( pCTX, SSL_get_ex_data_X509_STORE_CTX_idx() ); + Csock * pSock = static_cast( pcSocket ); + const CS_STRING & sPassword = pSock->GetPemPass(); + if( iBuffLen <= 0 ) + return( 0 ); + memset( pBuff, '\0', iBuffLen ); + if( sPassword.empty() ) + return( 0 ); + int iUseBytes = min( iBuffLen - 1, (int)sPassword.length() ); + memcpy( pBuff, sPassword.data(), iUseBytes ); + return( iUseBytes ); +} + +static int _CertVerifyCB( int preverify_ok, X509_STORE_CTX *x509_ctx ) +{ + /* + * A small quick example on how to get ahold of the Csock in the data portion of x509_ctx + Csock * pSock = GetCsockFromCTX( x509_ctx ); + assert( pSock ); + cerr << pSock->GetRemoteIP() << endl; + */ + + /* return 1 always for now, probably want to add some code for cert verification */ + return( 1 ); +} + +Csock * GetCsockFromCTX( X509_STORE_CTX * pCTX ) +{ + Csock * pSock = NULL; + SSL * pSSL = (SSL *) X509_STORE_CTX_get_ex_data( pCTX, SSL_get_ex_data_X509_STORE_CTX_idx() ); if( pSSL ) - pSock = ( Csock * )SSL_get_ex_data( pSSL, GetCsockClassIdx() ); + pSock = (Csock *) SSL_get_ex_data( pSSL, GetCsockClassIdx() ); return( pSock ); } #endif /* HAVE_LIBSSL */ @@ -194,19 +222,18 @@ Csock *GetCsockFromCTX( X509_STORE_CTX *pCTX ) // this issue here is getaddrinfo has a significant behavior difference when dealing with round robin dns on an // ipv4 network. This is not desirable IMHO. so when this is compiled without ipv6 support backwards compatibility // is maintained. - -static int __GetHostByName( const CS_STRING & sHostName, struct in_addr *paddr, u_int iNumRetries ) +static int __GetHostByName( const CS_STRING & sHostName, struct in_addr * paddr, u_int iNumRetries ) { int iReturn = HOST_NOT_FOUND; - struct hostent *hent = NULL; + struct hostent * hent = NULL; #ifdef __linux__ char hbuff[2048]; struct hostent hentbuff; int err; - for( u_int a = 0; a < iNumRetries; a++ ) + for( u_int a = 0; a < iNumRetries; ++a ) { - memset(( char * )hbuff, '\0', 2048 ); + memset( (char *) hbuff, '\0', 2048 ); iReturn = gethostbyname_r( sHostName.c_str(), &hentbuff, hbuff, 2048, &hent, &err ); if( iReturn == 0 ) @@ -217,12 +244,11 @@ static int __GetHostByName( const CS_STRING & sHostName, struct in_addr *paddr, CS_DEBUG( "gethostyname_r: " << hstrerror( h_errno ) ); break; } - } if( !hent && iReturn == 0 ) iReturn = HOST_NOT_FOUND; #else - for( u_int a = 0; a < iNumRetries; a++ ) + for( u_int a = 0; a < iNumRetries; ++a ) { iReturn = HOST_NOT_FOUND; hent = gethostbyname( sHostName.c_str() ); @@ -251,6 +277,7 @@ static int __GetHostByName( const CS_STRING & sHostName, struct in_addr *paddr, } #endif /* !USE_GETHOSTBYNAME */ + #ifdef HAVE_C_ARES void Csock::FreeAres() { @@ -260,15 +287,13 @@ void Csock::FreeAres() m_pARESChannel = NULL; } } -#endif /* HAVE_C_ARES */ -#ifdef HAVE_C_ARES -static void AresHostCallback( void *pArg, int status, int timeouts, struct hostent *hent ) +static void AresHostCallback( void * pArg, int status, int timeouts, struct hostent *hent ) { - Csock *pSock = ( Csock * )pArg; + Csock * pSock = ( Csock * )pArg; if( status == ARES_SUCCESS && hent && hent->h_addr_list[0] != NULL ) { - CSSockAddr *pSockAddr = pSock->GetCurrentAddr(); + CSSockAddr * pSockAddr = pSock->GetCurrentAddr(); if( hent->h_addrtype == AF_INET ) { pSock->SetIPv6( false ); @@ -299,13 +324,14 @@ static void AresHostCallback( void *pArg, int status, int timeouts, struct hoste } #endif /* HAVE_C_ARES */ -CGetAddrInfo::CGetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr ) - : m_pSock( pSock ), m_csSockAddr( csSockAddr ) +CGetAddrInfo::CGetAddrInfo( const CS_STRING & sHostname, Csock * pSock, CSSockAddr & csSockAddr ) + : m_pSock( pSock ), m_csSockAddr( csSockAddr ) { m_sHostname = sHostname; m_pAddrRes = NULL; m_iRet = ETIMEDOUT; } + CGetAddrInfo::~CGetAddrInfo() { if( m_pAddrRes ) @@ -348,17 +374,17 @@ int CGetAddrInfo::Finish() { std::list lpTryAddrs; bool bFound = false; - for( struct addrinfo *pRes = m_pAddrRes; pRes; pRes = pRes->ai_next ) + for( struct addrinfo * pRes = m_pAddrRes; pRes; pRes = pRes->ai_next ) { // pass through the list building out a lean list of candidates to try. AI_CONFIGADDR doesn't always seem to work #ifdef __sun - if(( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP && pRes->ai_protocol != IPPROTO_IP ) ) + if( (pRes->ai_socktype != SOCK_STREAM) || (pRes->ai_protocol != IPPROTO_TCP && pRes->ai_protocol != IPPROTO_IP) ) #else - if(( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP ) ) + if( (pRes->ai_socktype != SOCK_STREAM) || (pRes->ai_protocol != IPPROTO_TCP) ) #endif /* __sun work around broken impl of getaddrinfo */ continue; - if(( m_csSockAddr.GetAFRequire() != CSSockAddr::RAF_ANY ) && ( pRes->ai_family != m_csSockAddr.GetAFRequire() ) ) + if( (m_csSockAddr.GetAFRequire() != CSSockAddr::RAF_ANY) && (pRes->ai_family != m_csSockAddr.GetAFRequire()) ) continue; // they requested a special type, so be certain we woop past anything unwanted lpTryAddrs.push_back( pRes ); } @@ -372,7 +398,7 @@ int CGetAddrInfo::Finish() if( m_pSock ) m_pSock->SetIPv6( false ); m_csSockAddr.SetIPv6( false ); - struct sockaddr_in *pTmp = ( struct sockaddr_in * )pRes->ai_addr; + struct sockaddr_in * pTmp = ( struct sockaddr_in * )pRes->ai_addr; memcpy( m_csSockAddr.GetAddr(), &( pTmp->sin_addr ), sizeof( *( m_csSockAddr.GetAddr() ) ) ); if( m_pSock && m_pSock->GetConState() == Csock::CST_DESTDNS && m_pSock->GetType() == Csock::OUTBOUND ) { @@ -390,7 +416,7 @@ int CGetAddrInfo::Finish() if( m_pSock ) m_pSock->SetIPv6( true ); m_csSockAddr.SetIPv6( true ); - struct sockaddr_in6 *pTmp = ( struct sockaddr_in6 * )pRes->ai_addr; + struct sockaddr_in6 * pTmp = ( struct sockaddr_in6 * )pRes->ai_addr; memcpy( m_csSockAddr.GetAddr6(), &( pTmp->sin6_addr ), sizeof( *( m_csSockAddr.GetAddr6() ) ) ); if( m_pSock && m_pSock->GetConState() == Csock::CST_DESTDNS && m_pSock->GetType() == Csock::OUTBOUND ) { @@ -404,7 +430,7 @@ int CGetAddrInfo::Finish() } #endif /* HAVE_IPV6 */ - it++; // increment the iterator her so we know if its the last element or not + ++it; // increment the iterator her so we know if its the last element or not if( bTryConnect && it != lpTryAddrs.end() ) { @@ -431,7 +457,7 @@ int CGetAddrInfo::Finish() return( ETIMEDOUT ); } -int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr ) +int GetAddrInfo( const CS_STRING & sHostname, Csock * pSock, CSSockAddr & csSockAddr ) { #ifdef USE_GETHOSTBYNAME if( pSock ) @@ -449,7 +475,7 @@ int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockA #endif /* USE_GETHOSTBYNAME */ } -int Csock::ConvertAddress( const struct sockaddr_storage * pAddr, socklen_t iAddrLen, CS_STRING & sIP, u_short * piPort ) +int Csock::ConvertAddress( const struct sockaddr_storage * pAddr, socklen_t iAddrLen, CS_STRING & sIP, uint16_t * piPort ) { char szHostname[NI_MAXHOST]; char szServ[NI_MAXSERV]; @@ -458,7 +484,7 @@ int Csock::ConvertAddress( const struct sockaddr_storage * pAddr, socklen_t iAdd { sIP = szHostname; if( piPort ) - *piPort = ( u_short )atoi( szServ ); + *piPort = (uint16_t)atoi( szServ ); } return( iRet ); } @@ -516,9 +542,13 @@ bool InitSSL( ECompType eCompressionType ) #ifndef _WIN32 if( access( "/dev/urandom", R_OK ) == 0 ) + { RAND_load_file( "/dev/urandom", 1024 ); + } else if( access( "/dev/random", R_OK ) == 0 ) + { RAND_load_file( "/dev/random", 1024 ); + } else { CS_DEBUG( "Unable to locate entropy location! Tried /dev/urandom and /dev/random" ); @@ -594,15 +624,15 @@ static const char * CS_StrError( int iErrno, char * pszBuff, size_t uBuffLen ) return( CS_UNKNOWN_ERROR ); } -void __Perror( const CS_STRING & s, const char *pszFile, unsigned int iLineNo ) +void __Perror( const CS_STRING & s, const char * pszFile, u_int iLineNo ) { char szBuff[0xff]; std::cerr << s << "(" << pszFile << ":" << iLineNo << "): " << CS_StrError( GetSockError(), szBuff, 0xff ) << endl; } -unsigned long long millitime() +uint64_t millitime() { - unsigned long long iTime = 0; + uint64_t iTime = 0; #ifdef _WIN32 struct timeb tm; ftime( &tm ); @@ -611,8 +641,8 @@ unsigned long long millitime() #else struct timeval tv; gettimeofday( &tv, NULL ); - iTime = ( unsigned long long )tv.tv_sec * 1000; - iTime += (( unsigned long long )tv.tv_usec / 1000 ); + iTime = ( uint64_t )tv.tv_sec * 1000; + iTime += (( uint64_t )tv.tv_usec / 1000 ); #endif /* _WIN32 */ return( iTime ); } @@ -642,23 +672,24 @@ void CCron::run( timeval & tNow ) if( !timerisset( &tNow ) ) gettimeofday( &tNow, NULL ); - if(( m_bActive ) && ( !timercmp( &tNow, &m_tTime, < ) || m_bRunOnNextCall ) ) + if( m_bActive && (!timercmp( &tNow, &m_tTime, < ) || m_bRunOnNextCall) ) { m_bRunOnNextCall = false; // Setting this here because RunJob() could set it back to true RunJob(); - if(( m_iMaxCycles > 0 ) && ( ++m_iCycles >= m_iMaxCycles ) ) + if( m_iMaxCycles > 0 && ++m_iCycles >= m_iMaxCycles ) m_bActive = false; else timeradd( &tNow, &m_tTimeSequence, &m_tTime ); } } -void CCron::StartMaxCycles( double fTimeSequence, u_int iMaxCycles ) +void CCron::StartMaxCycles( double dTimeSequence, u_int iMaxCycles ) { timeval tNow; - m_tTimeSequence.tv_sec = (time_t) fTimeSequence; - m_tTimeSequence.tv_usec = (suseconds_t) ((fTimeSequence - (double) (time_t) fTimeSequence) * 1000000); + m_tTimeSequence.tv_sec = (time_t) dTimeSequence; + // this could be done with modf(), but we're avoiding bringing in libm just for the one function. + m_tTimeSequence.tv_usec = (suseconds_t) ((dTimeSequence - (double) ((time_t) dTimeSequence)) * 1000000); gettimeofday( &tNow, NULL ); timeradd( &tNow, &m_tTimeSequence, &m_tTime ); m_iMaxCycles = iMaxCycles; @@ -673,9 +704,9 @@ void CCron::StartMaxCycles( const timeval& tTimeSequence, u_int iMaxCycles ) m_iMaxCycles = iMaxCycles; } -void CCron::Start( double fTimeSequence ) +void CCron::Start( double dTimeSequence ) { - StartMaxCycles( fTimeSequence, 0 ); + StartMaxCycles( dTimeSequence, 0 ); } void CCron::Start( const timeval& tTimeSequence ) @@ -786,15 +817,17 @@ void CSockCommon::Cron() for( vector::size_type a = 0; a < m_vcCrons.size(); a++ ) { - CCron *pcCron = m_vcCrons[a]; + CCron * pcCron = m_vcCrons[a]; if( !pcCron->isValid() ) { CS_Delete( pcCron ); m_vcCrons.erase( m_vcCrons.begin() + a-- ); - } + } else + { pcCron->run( tNow ); + } } } @@ -805,9 +838,9 @@ void CSockCommon::AddCron( CCron * pcCron ) void CSockCommon::DelCron( const CS_STRING & sName, bool bDeleteAll, bool bCaseSensitive ) { - for( u_int a = 0; a < m_vcCrons.size(); a++ ) + for( size_t a = 0; a < m_vcCrons.size(); ++a ) { - int ( *Cmp )( const char *, const char * ) = ( bCaseSensitive ? strcmp : strcasecmp ); + int (*Cmp)(const char *, const char *) = ( bCaseSensitive ? strcmp : strcasecmp ); if( Cmp( m_vcCrons[a]->GetName().c_str(), sName.c_str() ) == 0 ) { m_vcCrons[a]->Stop(); @@ -829,9 +862,9 @@ void CSockCommon::DelCron( u_int iPos ) } } -void CSockCommon::DelCronByAddr( CCron *pcCron ) +void CSockCommon::DelCronByAddr( CCron * pcCron ) { - for( u_int a = 0; a < m_vcCrons.size(); a++ ) + for( size_t a = 0; a < m_vcCrons.size(); ++a ) { if( m_vcCrons[a] == pcCron ) { @@ -851,7 +884,7 @@ Csock::Csock( int iTimeout ) : CSockCommon() Init( "", 0, iTimeout ); } -Csock::Csock( const CS_STRING & sHostname, u_short iport, int iTimeout ) : CSockCommon() +Csock::Csock( const CS_STRING & sHostname, uint16_t iport, int iTimeout ) : CSockCommon() { #ifdef HAVE_LIBSSL m_pCerVerifyCB = NULL; @@ -860,7 +893,7 @@ Csock::Csock( const CS_STRING & sHostname, u_short iport, int iTimeout ) : CSock } // override this for accept sockets -Csock *Csock::GetSockObj( const CS_STRING & sHostname, u_short iPort ) +Csock *Csock::GetSockObj( const CS_STRING & sHostname, uint16_t iPort ) { return( NULL ); } @@ -905,9 +938,11 @@ void Csock::CloseSocksFD() CS_CLOSE( m_iReadSock ); if( m_iWriteSock != CS_INVALID_SOCK ) CS_CLOSE( m_iWriteSock ); - } + } else if( m_iReadSock != CS_INVALID_SOCK ) + { CS_CLOSE( m_iReadSock ); + } m_iReadSock = CS_INVALID_SOCK; m_iWriteSock = CS_INVALID_SOCK; @@ -1016,41 +1051,38 @@ Csock & Csock::operator<<( ostream & ( *io )( ostream & ) ) return( *this ); } -Csock & Csock::operator<<( int i ) +Csock & Csock::operator<<( int32_t i ) { stringstream s; s << i; Write( s.str() ); return( *this ); } -Csock & Csock::operator<<( unsigned int i ) + +Csock & Csock::operator<<( uint32_t i ) { stringstream s; s << i; Write( s.str() ); return( *this ); } -Csock & Csock::operator<<( long i ) + +Csock & Csock::operator<<( int64_t i ) { stringstream s; s << i; Write( s.str() ); return( *this ); } -Csock & Csock::operator<<( unsigned long i ) -{ - stringstream s; - s << i; - Write( s.str() ); - return( *this ); -} -Csock & Csock::operator<<( unsigned long long i ) + +Csock & Csock::operator<<( uint64_t i ) { stringstream s; s << i; Write( s.str() ); return( *this ); } + Csock & Csock::operator<<( float i ) { stringstream s; @@ -1058,6 +1090,7 @@ Csock & Csock::operator<<( float i ) Write( s.str() ); return( *this ); } + Csock & Csock::operator<<( double i ) { stringstream s; @@ -1069,8 +1102,7 @@ Csock & Csock::operator<<( double i ) bool Csock::Connect() { if( m_bSkipConnect ) - { - // this was already called, so skipping now. this is to allow easy pass through + { // this was already called, so skipping now. this is to allow easy pass through if( m_eConState != CST_OK ) { m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK ); @@ -1122,7 +1154,7 @@ bool Csock::Connect() } -bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u_int iTimeout, bool bDetach ) +bool Csock::Listen( uint16_t iPort, int iMaxConns, const CS_STRING & sBindHost, u_int iTimeout, bool bDetach ) { m_iConnType = LISTENER; m_iTimeout = iTimeout; @@ -1166,15 +1198,19 @@ bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u } #ifdef HAVE_IPV6 -#ifdef _WIN32 -# ifndef IPPROTO_IPV6 -# define IPPROTO_IPV6 41 /* define for apps with _WIN32_WINNT < 0x0501 (XP) */ -# endif /* !IPPROTO_IPV6 */ +# ifdef _WIN32 +# ifndef IPPROTO_IPV6 +# define IPPROTO_IPV6 41 /* define for apps with _WIN32_WINNT < 0x0501 (XP) */ +# endif /* !IPPROTO_IPV6 */ +# ifndef IPV6_V6ONLY +# define IPV6_V6ONLY 27 +# endif /* check for IPV6_V6ONLY support at runtime */ OSVERSIONINFOW lvi = { sizeof( OSVERSIONINFOW ), 0 }; if( ::GetVersionExW( &lvi ) && lvi.dwMajorVersion >= 6 ) // IPV6_V6ONLY is supported on Windows Vista or later. { -#endif /* _WIN32 */ +# endif /* _WIN32 */ +# ifdef IPV6_V6ONLY if( GetIPv6() ) { // per RFC3493#5.3 @@ -1182,16 +1218,17 @@ bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u if( setsockopt( m_iReadSock, IPPROTO_IPV6, IPV6_V6ONLY, ( char * )&on, sizeof( on ) ) != 0 ) PERROR( "IPV6_V6ONLY" ); } -#ifdef _WIN32 +# endif /* IPV6_V6ONLY */ +# ifdef _WIN32 } -#endif /* _WIN32 */ +# endif /* _WIN32 */ #endif /* HAVE_IPV6 */ m_address.SinFamily(); m_address.SinPort( iPort ); if( !GetIPv6() ) { - if( bind( m_iReadSock, ( struct sockaddr * ) m_address.GetSockAddr(), m_address.GetSockAddrLen() ) == -1 ) + if( bind( m_iReadSock, (struct sockaddr *) m_address.GetSockAddr(), m_address.GetSockAddrLen() ) == -1 ) { CallSockError( GetSockError() ); return( false ); @@ -1200,7 +1237,7 @@ bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u #ifdef HAVE_IPV6 else { - if( bind( m_iReadSock, ( struct sockaddr * ) m_address.GetSockAddr6(), m_address.GetSockAddrLen6() ) == -1 ) + if( bind( m_iReadSock, (struct sockaddr *) m_address.GetSockAddr6(), m_address.GetSockAddrLen6() ) == -1 ) { CallSockError( GetSockError() ); return( false ); @@ -1230,7 +1267,7 @@ bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u return( true ); } -cs_sock_t Csock::Accept( CS_STRING & sHost, u_short & iRPort ) +cs_sock_t Csock::Accept( CS_STRING & sHost, uint16_t & iRPort ) { cs_sock_t iSock = CS_INVALID_SOCK; struct sockaddr_storage cAddr; @@ -1304,51 +1341,49 @@ bool Csock::SSLClientSetup() switch( m_iMethod ) { - case SSL3: - m_ssl_ctx = SSL_CTX_new( SSLv3_client_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... SSLv3_client_method failed!" ); - return( false ); - } - break; - case TLS1: - m_ssl_ctx = SSL_CTX_new( TLSv1_client_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... TLSv1_client_method failed!" ); - return( false ); - } - break; - case SSL2: + case SSL3: + m_ssl_ctx = SSL_CTX_new( SSLv3_client_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... SSLv3_client_method failed!" ); + return( false ); + } + break; + case TLS1: + m_ssl_ctx = SSL_CTX_new( TLSv1_client_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... TLSv1_client_method failed!" ); + return( false ); + } + break; + case SSL2: #ifndef OPENSSL_NO_SSL2 - m_ssl_ctx = SSL_CTX_new( SSLv2_client_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... SSLv2_client_method failed!" ); - return( false ); - } - break; + m_ssl_ctx = SSL_CTX_new( SSLv2_client_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... SSLv2_client_method failed!" ); + return( false ); + } + break; #endif /* Fall through if SSL2 is disabled */ - case SSL23: - default: - m_ssl_ctx = SSL_CTX_new( SSLv23_client_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... SSLv23_client_method failed!" ); - return( false ); - } - break; + case SSL23: + default: + m_ssl_ctx = SSL_CTX_new( SSLv23_client_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... SSLv23_client_method failed!" ); + return( false ); + } + break; } - SSL_CTX_set_default_verify_paths( m_ssl_ctx ); if( !m_sPemFile.empty() ) - { - // are we sending a client cerificate ? - SSL_CTX_set_default_passwd_cb( m_ssl_ctx, PemPassCB ); + { // are we sending a client cerificate ? + SSL_CTX_set_default_passwd_cb( m_ssl_ctx, _PemPassCB ); SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, ( void * )this ); // @@ -1372,7 +1407,7 @@ bool Csock::SSLClientSetup() 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_verify( m_ssl, SSL_VERIFY_PEER, ( m_pCerVerifyCB ? m_pCerVerifyCB : _CertVerifyCB ) ); SSL_set_ex_data( m_ssl, GetCsockClassIdx(), this ); SSLFinishSetup( m_ssl ); @@ -1402,49 +1437,48 @@ bool Csock::SSLServerSetup() switch( m_iMethod ) { - case SSL3: - m_ssl_ctx = SSL_CTX_new( SSLv3_server_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... SSLv3_server_method failed!" ); - return( false ); - } - break; - - case TLS1: - m_ssl_ctx = SSL_CTX_new( TLSv1_server_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... TLSv1_server_method failed!" ); - return( false ); - } - break; + case SSL3: + m_ssl_ctx = SSL_CTX_new( SSLv3_server_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... SSLv3_server_method failed!" ); + return( false ); + } + break; + case TLS1: + m_ssl_ctx = SSL_CTX_new( TLSv1_server_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... TLSv1_server_method failed!" ); + return( false ); + } + break; #ifndef OPENSSL_NO_SSL2 - case SSL2: - m_ssl_ctx = SSL_CTX_new( SSLv2_server_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... SSLv2_server_method failed!" ); - return( false ); - } - break; + case SSL2: + m_ssl_ctx = SSL_CTX_new( SSLv2_server_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... SSLv2_server_method failed!" ); + return( false ); + } + break; #endif /* Fall through if SSL2 is disabled */ - case SSL23: - default: - m_ssl_ctx = SSL_CTX_new( SSLv23_server_method() ); - if( !m_ssl_ctx ) - { - CS_DEBUG( "WARNING: MakeConnection .... SSLv23_server_method failed!" ); - return( false ); - } - break; + case SSL23: + default: + m_ssl_ctx = SSL_CTX_new( SSLv23_server_method() ); + if( !m_ssl_ctx ) + { + CS_DEBUG( "WARNING: MakeConnection .... SSLv23_server_method failed!" ); + return( false ); + } + break; } SSL_CTX_set_default_verify_paths( m_ssl_ctx ); // set the pemfile password - SSL_CTX_set_default_passwd_cb( m_ssl_ctx, PemPassCB ); + SSL_CTX_set_default_passwd_cb( m_ssl_ctx, _PemPassCB ); SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, ( void * )this ); if( m_sPemFile.empty() || access( m_sPemFile.c_str(), R_OK ) != 0 ) @@ -1516,7 +1550,7 @@ bool Csock::SSLServerSetup() SSL_set_accept_state( m_ssl ); if( m_iRequireClientCertFlags ) { - SSL_set_verify( m_ssl, m_iRequireClientCertFlags, ( m_pCerVerifyCB ? m_pCerVerifyCB : CertVerifyCB ) ); + SSL_set_verify( m_ssl, m_iRequireClientCertFlags, ( m_pCerVerifyCB ? m_pCerVerifyCB : _CertVerifyCB ) ); SSL_set_ex_data( m_ssl, GetCsockClassIdx(), this ); } @@ -1564,9 +1598,11 @@ bool Csock::ConnectSSL() bPass = true; } #endif /* _WIN32 */ - } + } else + { bPass = true; + } if( m_eConState != CST_OK ) m_eConState = CST_OK; @@ -1576,7 +1612,7 @@ bool Csock::ConnectSSL() #endif /* HAVE_LIBSSL */ } -bool Csock::AllowWrite( unsigned long long & iNOW ) const +bool Csock::AllowWrite( uint64_t & iNOW ) const { if( m_iMaxBytes > 0 && m_iMaxMilliSeconds > 0 ) { @@ -1585,7 +1621,7 @@ bool Csock::AllowWrite( unsigned long long & iNOW ) const if( m_iLastSend < m_iMaxBytes ) return( true ); // allow sending if our out buffer was less than what we can send - if(( iNOW - m_iLastSendTime ) < m_iMaxMilliSeconds ) + if( (iNOW - m_iLastSendTime) < m_iMaxMilliSeconds ) return( false ); } return( true ); @@ -1602,7 +1638,7 @@ bool Csock::Write( const char *data, size_t len ) return( true ); // rate shaping - u_long iBytesToSend = 0; + size_t iBytesToSend = 0; #ifdef HAVE_LIBSSL if( m_bUseSSL && m_sSSLBuffer.empty() && !m_bsslEstablished ) @@ -1614,7 +1650,7 @@ bool Csock::Write( const char *data, size_t len ) #endif /* HAVE_LIBSSL */ if( m_iMaxBytes > 0 && m_iMaxMilliSeconds > 0 ) { - unsigned long long iNOW = millitime(); + uint64_t iNOW = millitime(); // figure out the shaping here // if NOW - m_iLastSendTime > m_iMaxMilliSeconds then send a full length of ( iBytesToSend ) if(( iNOW - m_iLastSendTime ) > m_iMaxMilliSeconds ) @@ -1622,7 +1658,6 @@ bool Csock::Write( const char *data, size_t len ) m_iLastSendTime = iNOW; iBytesToSend = m_iMaxBytes; m_iLastSend = 0; - } else // otherwise send m_iMaxBytes - m_iLastSend iBytesToSend = m_iMaxBytes - m_iLastSend; @@ -1637,10 +1672,11 @@ bool Csock::Write( const char *data, size_t len ) // so, are we ready to send anything ? if( iBytesToSend == 0 ) return( true ); - } else + { iBytesToSend = m_sSend.length(); + } #ifdef HAVE_LIBSSL if( m_bUseSSL ) @@ -1665,30 +1701,30 @@ bool Csock::Write( const char *data, size_t len ) switch( SSL_get_error( m_ssl, iErr ) ) { - case SSL_ERROR_NONE: - m_bsslEstablished = true; - // all ok - break; + case SSL_ERROR_NONE: + m_bsslEstablished = true; + // all ok + break; - case SSL_ERROR_ZERO_RETURN: - { - // weird closer alert - return( false ); - } + case SSL_ERROR_ZERO_RETURN: + { + // weird closer alert + return( false ); + } - case SSL_ERROR_WANT_READ: - // retry - break; + case SSL_ERROR_WANT_READ: + // retry + break; - case SSL_ERROR_WANT_WRITE: - // retry - break; + case SSL_ERROR_WANT_WRITE: + // retry + break; - case SSL_ERROR_SSL: - { - SSLErrors( __FILE__, __LINE__ ); - return( false ); - } + case SSL_ERROR_SSL: + { + SSLErrors( __FILE__, __LINE__ ); + return( false ); + } } if( iErr > 0 ) @@ -1700,7 +1736,7 @@ bool Csock::Write( const char *data, size_t len ) if( TMO_WRITE & GetTimeoutType() ) ResetTimer(); - m_iBytesWritten += ( unsigned long long )iErr; + m_iBytesWritten += ( uint64_t )iErr; } return( true ); @@ -1732,7 +1768,7 @@ bool Csock::Write( const char *data, size_t len ) m_sSend.erase( 0, bytes ); if( TMO_WRITE & GetTimeoutType() ) ResetTimer(); // reset the timer on successful write - m_iBytesWritten += ( unsigned long long )bytes; + m_iBytesWritten += ( uint64_t )bytes; } return( true ); @@ -1801,7 +1837,7 @@ cs_ssize_t Csock::Read( char *data, size_t len ) } if( bytes > 0 ) // becareful not to add negative bytes :P - m_iBytesRead += ( unsigned long long )bytes; + m_iBytesRead += ( uint64_t )bytes; return( bytes ); } @@ -1951,15 +1987,15 @@ void Csock::PushBuff( const char *data, size_t len, bool bStartAtZero ) m_sbuffer.erase( 0, iFind + 1 ); // erase past the newline ReadLine( sBuff ); iStartPos = 0; // reset this back to 0, since we need to look for the next newline here. - - } + } else + { break; + } } if( m_iMaxStoredBufferLength > 0 && m_sbuffer.length() > m_iMaxStoredBufferLength ) ReachedMaxBuffer(); // call the max read buffer event - } CS_STRING & Csock::GetInternalReadBuffer() { return( m_sbuffer ); } @@ -1972,34 +2008,34 @@ const CS_STRING & Csock::GetSockName() const { return( m_sSockName ); } void Csock::SetSockName( const CS_STRING & sName ) { m_sSockName = sName; } const CS_STRING & Csock::GetHostName() const { return( m_shostname ); } void Csock::SetHostName( const CS_STRING & sHostname ) { m_shostname = sHostname; } -unsigned long long Csock::GetStartTime() const { return( m_iStartTime ); } +uint64_t Csock::GetStartTime() const { return( m_iStartTime ); } void Csock::ResetStartTime() { m_iStartTime = 0; } -unsigned long long Csock::GetBytesRead() const { return( m_iBytesRead ); } +uint64_t Csock::GetBytesRead() const { return( m_iBytesRead ); } void Csock::ResetBytesRead() { m_iBytesRead = 0; } -unsigned long long Csock::GetBytesWritten() const { return( m_iBytesWritten ); } +uint64_t Csock::GetBytesWritten() const { return( m_iBytesWritten ); } void Csock::ResetBytesWritten() { m_iBytesWritten = 0; } -double Csock::GetAvgRead( unsigned long long iSample ) +double Csock::GetAvgRead( uint64_t iSample ) { - unsigned long long iDifference = ( millitime() - m_iStartTime ); + uint64_t iDifference = ( millitime() - m_iStartTime ); if( m_iBytesRead == 0 || iSample > iDifference ) - return(( double )m_iBytesRead ); + return( (double)m_iBytesRead ); - return((( double )m_iBytesRead / (( double )iDifference / ( double )iSample ) ) ); + return( ((double)m_iBytesRead / ((double)iDifference / (double)iSample)) ); } -double Csock::GetAvgWrite( unsigned long long iSample ) +double Csock::GetAvgWrite( uint64_t iSample ) { - unsigned long long iDifference = ( millitime() - m_iStartTime ); + uint64_t iDifference = ( millitime() - m_iStartTime ); if( m_iBytesWritten == 0 || iSample > iDifference ) - return(( double )m_iBytesWritten ); + return( (double)m_iBytesWritten ); - return((( double )m_iBytesWritten / (( double )iDifference / ( double )iSample ) ) ); + return( ((double)m_iBytesWritten / ((double)iDifference / (double)iSample)) ); } -u_short Csock::GetRemotePort() +uint16_t Csock::GetRemotePort() { if( m_iRemotePort > 0 ) return( m_iRemotePort ); @@ -2007,7 +2043,7 @@ u_short Csock::GetRemotePort() return( m_iRemotePort ); } -u_short Csock::GetLocalPort() +uint16_t Csock::GetLocalPort() { if( m_iLocalPort > 0 ) return( m_iLocalPort ); @@ -2015,8 +2051,8 @@ u_short Csock::GetLocalPort() return( m_iLocalPort ); } -u_short Csock::GetPort() { return( m_uPort ); } -void Csock::SetPort( u_short iPort ) { m_uPort = iPort; } +uint16_t Csock::GetPort() { return( m_uPort ); } +void Csock::SetPort( uint16_t iPort ) { m_uPort = iPort; } void Csock::Close( ECloseType eCloseType ) { m_eCloseType = eCloseType; @@ -2043,29 +2079,6 @@ const CS_STRING & Csock::GetPemLocation() { return( m_sPemFile ); } void Csock::SetPemPass( const CS_STRING & sPassword ) { m_sPemPass = sPassword; } const CS_STRING & Csock::GetPemPass() const { return( m_sPemPass ); } -int Csock::PemPassCB( char *buf, int size, int rwflag, void *pcSocket ) -{ - Csock *pSock = ( Csock * )pcSocket; - const CS_STRING & sPassword = pSock->GetPemPass(); - memset( buf, '\0', size ); - strncpy( buf, sPassword.c_str(), size ); - buf[size-1] = '\0'; - return(( int )strlen( buf ) ); -} - -int Csock::CertVerifyCB( int preverify_ok, X509_STORE_CTX *x509_ctx ) -{ - /* - * A small quick example on how to get ahold of the Csock in the data portion of x509_ctx - Csock *pSock = GetCsockFromCTX( x509_ctx ); - assert( pSock ); - cerr << pSock->GetRemoteIP() << endl; - */ - - /* return 1 always for now, probably want to add some code for cert verification */ - return( 1 ); -} - void Csock::SetSSLMethod( int iMethod ) { m_iMethod = iMethod; } int Csock::GetSSLMethod() { return( m_iMethod ); } void Csock::SetSSLObject( SSL *ssl ) { m_ssl = ssl; } @@ -2094,8 +2107,10 @@ bool Csock::ConnectInetd( bool bIsSSL, const CS_STRING & sHostname ) { struct sockaddr_in client; socklen_t clen = sizeof( client ); - if( getpeername( 0, ( struct sockaddr * )&client, &clen ) < 0 ) + if( getpeername( 0, (struct sockaddr *)&client, &clen ) < 0 ) + { m_sSockName = "0.0.0.0:0"; + } else { stringstream s; @@ -2152,11 +2167,11 @@ CS_STRING Csock::GetPeerPubKey() { CS_STRING sKey; - SSL_SESSION *pSession = GetSSLSession(); + SSL_SESSION * pSession = GetSSLSession(); if( pSession && pSession->peer ) { - EVP_PKEY *pKey = X509_get_pubkey( pSession->peer ); + EVP_PKEY * pKey = X509_get_pubkey( pSession->peer ); if( pKey ) { char *hxKey = NULL; @@ -2188,6 +2203,7 @@ CS_STRING Csock::GetPeerPubKey() } return( sKey ); } + long Csock::GetPeerFingerprint( CS_STRING & sFP ) { sFP.clear(); @@ -2195,7 +2211,7 @@ long Csock::GetPeerFingerprint( CS_STRING & sFP ) if( !m_ssl ) return( 0 ); - X509* pCert = GetX509(); + X509 * pCert = GetX509(); // Inspired by charybdis if( pCert ) @@ -2211,7 +2227,7 @@ long Csock::GetPeerFingerprint( CS_STRING & sFP ) return( SSL_get_verify_result( m_ssl ) ); } -unsigned int Csock::GetRequireClientCertFlags() { return( m_iRequireClientCertFlags ); } +u_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 ); } #endif /* HAVE_LIBSSL */ @@ -2219,14 +2235,14 @@ void Csock::SetRequiresClientCert( bool bRequiresCert ) { m_iRequireClientCertFl void Csock::SetParentSockName( const CS_STRING & sParentName ) { m_sParentName = sParentName; } const CS_STRING & Csock::GetParentSockName() { return( m_sParentName ); } -void Csock::SetRate( u_int iBytes, unsigned long long iMilliseconds ) +void Csock::SetRate( u_int iBytes, uint64_t iMilliseconds ) { m_iMaxBytes = iBytes; m_iMaxMilliSeconds = iMilliseconds; } u_int Csock::GetRateBytes() { return( m_iMaxBytes ); } -unsigned long long Csock::GetRateTime() { return( m_iMaxMilliSeconds ); } +uint64_t Csock::GetRateTime() { return( m_iMaxMilliSeconds ); } void Csock::EnableReadLine() { m_bEnableReadLine = true; } @@ -2441,7 +2457,7 @@ int Csock::DNSLookup( EDNSLType eDNSLType ) return( ETIMEDOUT ); } if( m_eConState != CST_OK ) - m_eConState = (( eDNSLType == DNS_VHOST ) ? CST_BINDVHOST : CST_CONNECT ); + m_eConState = ( (eDNSLType == DNS_VHOST) ? CST_BINDVHOST : CST_CONNECT ); m_iDNSTryCount = 0; return( 0 ); } @@ -2529,18 +2545,18 @@ cs_sock_t Csock::CreateSocket( bool bListen ) if( bListen ) { const int on = 1; - - if( setsockopt( iRet, SOL_SOCKET, SO_REUSEADDR, ( char * )&on, sizeof( on ) ) != 0 ) + if( setsockopt( iRet, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof( on ) ) != 0 ) PERROR( "SO_REUSEADDR" ); } } else + { PERROR( "socket" ); - + } return( iRet ); } -void Csock::Init( const CS_STRING & sHostname, u_short uPort, int iTimeout ) +void Csock::Init( const CS_STRING & sHostname, uint16_t uPort, int iTimeout ) { #ifdef HAVE_LIBSSL m_ssl = NULL; @@ -2616,7 +2632,7 @@ void CSocketManager::Cleanup() clear(); } -Csock * CSocketManager::GetSockObj( const CS_STRING & sHostname, u_short uPort, int iTimeout ) +Csock * CSocketManager::GetSockObj( const CS_STRING & sHostname, uint16_t uPort, int iTimeout ) { return( new Csock( sHostname, uPort, iTimeout ) ); } @@ -2659,7 +2675,7 @@ void CSocketManager::Connect( const CSConnection & cCon, Csock * pcSock ) AddSock( pcSock, cCon.GetSockName() ); } -bool CSocketManager::Listen( const CSListener & cListen, Csock * pcSock, u_short *piRandPort ) +bool CSocketManager::Listen( const CSListener & cListen, Csock * pcSock, uint16_t * piRandPort ) { if( !pcSock ) pcSock = GetSockObj( "", 0 ); @@ -2693,7 +2709,6 @@ bool CSocketManager::Listen( const CSListener & cListen, Csock * pcSock, u_short *piRandPort = 0; bool bDetach = ( cListen.GetDetach() && !piRandPort ); // can't detach if we're waiting for the port to come up right now - if( pcSock->Listen( cListen.GetPort(), cListen.GetMaxConns(), cListen.GetBindHost(), cListen.GetTimeout(), bDetach ) ) { AddSock( pcSock, cListen.GetSockName() ); @@ -2727,10 +2742,9 @@ bool CSocketManager::HasFDs() const void CSocketManager::Loop() { - for( u_int a = 0; a < this->size(); a++ ) + for( size_t a = 0; a < this->size(); ++a ) { - Csock *pcSock = ( *this )[a]; - + Csock * pcSock = this->at( a ); if( pcSock->GetType() != Csock::OUTBOUND || pcSock->GetConState() == Csock::CST_OK ) continue; if( pcSock->GetConState() == Csock::CST_DNS ) @@ -2831,43 +2845,42 @@ void CSocketManager::Loop() switch( bytes ) { - case Csock::READ_EOF: - { - DelSockByAddr( pcSock ); - break; + case Csock::READ_EOF: + { + DelSockByAddr( pcSock ); + break; + } + + case Csock::READ_ERR: + { + pcSock->CallSockError( GetSockError() ); + DelSockByAddr( pcSock ); + break; + } + + case Csock::READ_EAGAIN: + break; + + case Csock::READ_CONNREFUSED: + pcSock->ConnectionRefused(); + DelSockByAddr( pcSock ); + break; + + case Csock::READ_TIMEDOUT: + pcSock->Timeout(); + DelSockByAddr( pcSock ); + break; + + default: + { + if( Csock::TMO_READ & pcSock->GetTimeoutType() ) + pcSock->ResetTimer(); // reset the timeout timer + + pcSock->ReadData( cBuff(), bytes ); // Call ReadData() before PushBuff() so that it is called before the ReadLine() event - LD 07/18/05 + pcSock->PushBuff( cBuff(), bytes ); + break; + } } - - case Csock::READ_ERR: - { - pcSock->CallSockError( GetSockError() ); - DelSockByAddr( pcSock ); - break; - } - - case Csock::READ_EAGAIN: - break; - - case Csock::READ_CONNREFUSED: - pcSock->ConnectionRefused(); - DelSockByAddr( pcSock ); - break; - - case Csock::READ_TIMEDOUT: - pcSock->Timeout(); - DelSockByAddr( pcSock ); - break; - - default: - { - if( Csock::TMO_READ & pcSock->GetTimeoutType() ) - pcSock->ResetTimer(); // reset the timeout timer - - pcSock->ReadData( cBuff(), bytes ); // Call ReadData() before PushBuff() so that it is called before the ReadLine() event - LD 07/18/05 - pcSock->PushBuff( cBuff(), bytes ); - break; - } - } - } else if( iErrno == SELECT_ERROR ) { @@ -2886,17 +2899,17 @@ void CSocketManager::Loop() break; } - unsigned long long iMilliNow = millitime(); - if(( iMilliNow - m_iCallTimeouts ) >= 1000 ) + uint64_t iMilliNow = millitime(); + if( (iMilliNow - m_iCallTimeouts) >= 1000 ) { m_iCallTimeouts = iMilliNow; // call timeout on all the sockets that recieved no data - for( unsigned int i = 0; i < this->size(); i++ ) + for( size_t i = 0; i < this->size(); ++i ) { - if(( *this )[i]->GetConState() != Csock::CST_OK ) + if( this->at( i )->GetConState() != Csock::CST_OK ) continue; - if(( *this )[i]->CheckTimeout(( time_t )( iMilliNow / 1000 ) ) ) + if( this->at( i )->CheckTimeout( (time_t) (iMilliNow / 1000) ) ) DelSock( i-- ); } } @@ -2904,7 +2917,7 @@ void CSocketManager::Loop() Cron(); } -void CSocketManager::DynamicSelectLoop( u_long iLowerBounds, u_long iUpperBounds, time_t iMaxResolution ) +void CSocketManager::DynamicSelectLoop( uint64_t iLowerBounds, uint64_t iUpperBounds, time_t iMaxResolution ) { SetSelectTimeout( iLowerBounds ); if( m_errno == SELECT_TIMEOUT ) @@ -2916,7 +2929,7 @@ void CSocketManager::DynamicSelectLoop( u_long iLowerBounds, u_long iUpperBounds tMaxResolution.tv_usec = 0; gettimeofday( &tNow, NULL ); timeval tSelectTimeout = GetDynamicSleepTime( tNow, tMaxResolution ); - u_long iSelectTimeout = tSelectTimeout.tv_sec * 1000000 + tSelectTimeout.tv_usec; + uint64_t iSelectTimeout = tSelectTimeout.tv_sec * 1000000 + tSelectTimeout.tv_usec; iSelectTimeout = std::max( iLowerBounds, iSelectTimeout ); iSelectTimeout = std::min( iSelectTimeout, iUpperBounds ); if( iLowerBounds != iSelectTimeout ) @@ -2925,29 +2938,29 @@ void CSocketManager::DynamicSelectLoop( u_long iLowerBounds, u_long iUpperBounds Loop(); } -void CSocketManager::AddSock( Csock *pcSock, const CS_STRING & sSockName ) +void CSocketManager::AddSock( Csock * pcSock, const CS_STRING & sSockName ) { pcSock->SetSockName( sSockName ); this->push_back( pcSock ); } -Csock * CSocketManager::FindSockByRemotePort( u_short iPort ) +Csock * CSocketManager::FindSockByRemotePort( uint16_t iPort ) { - for( unsigned int i = 0; i < this->size(); i++ ) + for( size_t i = 0; i < this->size(); ++i ) { - if(( *this )[i]->GetRemotePort() == iPort ) - return(( *this )[i] ); + if( this->at( i )->GetRemotePort() == iPort ) + return( this->at( i ) ); } - return( NULL ); } -Csock * CSocketManager::FindSockByLocalPort( u_short iPort ) +Csock * CSocketManager::FindSockByLocalPort( uint16_t iPort ) { - for( unsigned int i = 0; i < this->size(); i++ ) - if(( *this )[i]->GetLocalPort() == iPort ) - return(( *this )[i] ); - + for( size_t i = 0; i < this->size(); ++i ) + { + if( this->at( i )->GetLocalPort() == iPort ) + return( this->at( i ) ); + } return( NULL ); } @@ -2956,55 +2969,58 @@ Csock * CSocketManager::FindSockByName( const CS_STRING & sName ) std::vector::iterator it; std::vector::iterator it_end = this->end(); for( it = this->begin(); it != it_end; it++ ) - if(( *it )->GetSockName() == sName ) + { + if( (*it)->GetSockName() == sName ) return( *it ); - + } return( NULL ); } Csock * CSocketManager::FindSockByFD( cs_sock_t iFD ) { - for( unsigned int i = 0; i < this->size(); i++ ) - if(( *this )[i]->GetRSock() == iFD || ( *this )[i]->GetWSock() == iFD ) - return(( *this )[i] ); - + for( size_t i = 0; i < this->size(); ++i ) + { + if( this->at( i )->GetRSock() == iFD || this->at( i )->GetWSock() == iFD ) + return( this->at( i ) ); + } return( NULL ); } std::vector CSocketManager::FindSocksByName( const CS_STRING & sName ) { std::vector vpSocks; - - for( unsigned int i = 0; i < this->size(); i++ ) - if(( *this )[i]->GetSockName() == sName ) - vpSocks.push_back(( *this )[i] ); - + for( size_t i = 0; i < this->size(); ++i ) + { + if( this->at( i )->GetSockName() == sName ) + vpSocks.push_back( this->at( i ) ); + } return( vpSocks ); } std::vector CSocketManager::FindSocksByRemoteHost( const CS_STRING & sHostname ) { std::vector vpSocks; - - for( unsigned int i = 0; i < this->size(); i++ ) - if(( *this )[i]->GetHostName() == sHostname ) - vpSocks.push_back(( *this )[i] ); - + for( size_t i = 0; i < this->size(); ++i ) + { + if( this->at( i )->GetHostName() == sHostname ) + vpSocks.push_back( this->at( i ) ); + } return( vpSocks ); } -void CSocketManager::DelSockByAddr( Csock *pcSock ) +void CSocketManager::DelSockByAddr( Csock * pcSock ) { - for( u_int a = 0; a < this->size(); a++ ) + for( size_t a = 0; a < this->size(); ++a ) { - if( pcSock == ( *this )[a] ) + if( pcSock == this->at( a ) ) { DelSock( a ); return; } } } -void CSocketManager::DelSock( u_int iPos ) + +void CSocketManager::DelSock( size_t iPos ) { if( iPos >= this->size() ) { @@ -3012,7 +3028,7 @@ void CSocketManager::DelSock( u_int iPos ) return; } - Csock * pSock = ( *this )[iPos]; + Csock * pSock = this->at( iPos ); if( pSock->GetCloseType() != Csock::CLT_DEREFERENCE ) { @@ -3027,7 +3043,7 @@ void CSocketManager::DelSock( u_int iPos ) this->erase( this->begin() + iPos ); } -bool CSocketManager::SwapSockByIdx( Csock *pNewSock, u_long iOrginalSockIdx ) +bool CSocketManager::SwapSockByIdx( Csock * pNewSock, size_t iOrginalSockIdx ) { if( iOrginalSockIdx >= this->size() ) { @@ -3035,44 +3051,44 @@ bool CSocketManager::SwapSockByIdx( Csock *pNewSock, u_long iOrginalSockIdx ) return( false ); } - Csock *pSock = ( *this )[iOrginalSockIdx]; + Csock * pSock = this->at( iOrginalSockIdx ); pNewSock->Copy( *pSock ); pSock->Dereference(); - ( *this )[iOrginalSockIdx] = ( Csock * )pNewSock; - this->push_back(( Csock * )pSock ); // this allows it to get cleaned up + this->at( iOrginalSockIdx ) = (Csock *)pNewSock; + this->push_back( (Csock *)pSock ); // this allows it to get cleaned up return( true ); } -bool CSocketManager::SwapSockByAddr( Csock *pNewSock, Csock *pOrigSock ) +bool CSocketManager::SwapSockByAddr( Csock * pNewSock, Csock * pOrigSock ) { - for( u_long a = 0; a < this->size(); a++ ) + for( size_t a = 0; a < this->size(); ++a ) { - if(( *this )[a] == pOrigSock ) + if( this->at( a ) == pOrigSock ) return( SwapSockByIdx( pNewSock, a ) ); } return( false ); } -unsigned long long CSocketManager::GetBytesRead() const +uint64_t CSocketManager::GetBytesRead() const { // Start with the total bytes read from destroyed sockets - unsigned long long iRet = m_iBytesRead; + uint64_t iRet = m_iBytesRead; // Add in the outstanding bytes read from active sockets - for( u_int a = 0; a < this->size(); a++ ) - iRet += ( *this )[a]->GetBytesRead(); + for( size_t a = 0; a < this->size(); ++a ) + iRet += this->at( a )->GetBytesRead(); return( iRet ); } -unsigned long long CSocketManager::GetBytesWritten() const +uint64_t CSocketManager::GetBytesWritten() const { // Start with the total bytes written to destroyed sockets - unsigned long long iRet = m_iBytesWritten; + uint64_t iRet = m_iBytesWritten; // Add in the outstanding bytes written to active sockets - for( u_int a = 0; a < this->size(); a++ ) - iRet += ( *this )[a]->GetBytesWritten(); + for( size_t a = 0; a < this->size(); ++a ) + iRet += this->at( a )->GetBytesWritten(); return( iRet ); } @@ -3085,6 +3101,7 @@ void CSocketManager::FDSetCheck( int iFd, std::map< int, short > & miiReadyFds, else miiReadyFds[iFd] = eType; } + bool CSocketManager::FDHasCheck( int iFd, std::map< int, short > & miiReadyFds, ECheckType eType ) { std::map< int, short >::iterator it = miiReadyFds.find( iFd ); @@ -3121,9 +3138,9 @@ int CSocketManager::Select( std::map< int, short > & miiReadyFds, struct timeval for( uCurrPoll = 0; uCurrPoll < uMaxFD; ++uCurrPoll ) { short iEvents = 0; - if(( pFDs[uCurrPoll].revents & ( POLLIN|POLLERR|POLLHUP|POLLNVAL ) ) ) + if( pFDs[uCurrPoll].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL) ) iEvents |= ECT_Read; - if(( pFDs[uCurrPoll].revents & POLLOUT ) ) + if( pFDs[uCurrPoll].revents & POLLOUT ) iEvents |= ECT_Write; std::map< int, short >::iterator it = miiReadyFds.find( pFDs[uCurrPoll].fd ); if( it != miiReadyFds.end() ) @@ -3154,7 +3171,9 @@ int CSocketManager::Select( std::map< int, short > & miiReadyFds, struct timeval int iRet = select( iHighestFD + 1, &rfds, ( bHasWrite ? &wfds : NULL ), NULL, tvtimeout ); if( iRet <= 0 ) + { miiReadyFds.clear(); + } else { for( std::map< int, short >::iterator it = miiReadyFds.begin(); it != miiReadyFds.end(); ++it ) @@ -3176,17 +3195,17 @@ void CSocketManager::Select( std::map & mpeSocks ) struct timeval tv; std::map< int, short > miiReadyFds; - tv.tv_sec = m_iSelectWait / 1000000; - tv.tv_usec = m_iSelectWait % 1000000; + tv.tv_sec = (time_t) (m_iSelectWait / 1000000); + tv.tv_usec = (time_t) (m_iSelectWait % 1000000); u_int iQuickReset = 1000; if( m_iSelectWait == 0 ) iQuickReset = 0; bool bHasAvailSocks = false; - unsigned long long iNOW = 0; - for( unsigned int i = 0; i < this->size(); i++ ) + uint64_t iNOW = 0; + for( size_t i = 0; i < this->size(); ++i ) { - Csock *pcSock = ( *this )[i]; + Csock * pcSock = this->at( i ); Csock::ECloseType eCloseType = pcSock->GetCloseType(); @@ -3196,7 +3215,9 @@ void CSocketManager::Select( std::map & mpeSocks ) continue; } else + { pcSock->Cron(); // call the Cron handler here + } cs_sock_t & iRSock = pcSock->GetRSock(); cs_sock_t & iWSock = pcSock->GetWSock(); @@ -3303,7 +3324,7 @@ void CSocketManager::Select( std::map & mpeSocks ) if( pcSock->GetSSL() && pcSock->GetType() != Csock::LISTENER ) { - if(( pcSock->GetPending() > 0 ) && ( !pcSock->IsReadPaused() ) ) + if( pcSock->GetPending() > 0 && !pcSock->IsReadPaused() ) SelectSock( mpeSocks, SUCCESS, pcSock ); } } @@ -3332,9 +3353,9 @@ void CSocketManager::Select( std::map & mpeSocks ) m_errno = SUCCESS; #ifdef HAVE_C_ARES // run through ares channels and process timeouts - for( u_long uSock = 0; uSock < this->size(); ++uSock ) + for( size_t uSock = 0; uSock < this->size(); ++uSock ) { - Csock *pcSock = this->at( uSock ); + Csock * pcSock = this->at( uSock ); ares_channel pChannel = pcSock->GetAresChannel(); if( pChannel ) ares_process_fd( pChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD ); @@ -3344,7 +3365,7 @@ void CSocketManager::Select( std::map & mpeSocks ) return; } - if(( iSel == -1 ) && ( errno == EINTR ) ) + if( iSel == -1 && errno == EINTR ) { if( mpeSocks.empty() ) m_errno = SELECT_TRYAGAIN; @@ -3352,7 +3373,7 @@ void CSocketManager::Select( std::map & mpeSocks ) m_errno = SUCCESS; return; - } + } else if( iSel == -1 ) { if( mpeSocks.empty() ) @@ -3370,9 +3391,9 @@ void CSocketManager::Select( std::map & mpeSocks ) CheckFDs( miiReadyFds ); // find out wich one is ready - for( unsigned int i = 0; i < this->size(); i++ ) + for( size_t i = 0; i < this->size(); ++i ) { - Csock *pcSock = ( *this )[i]; + Csock * pcSock = this->at( i ); #ifdef HAVE_C_ARES ares_channel pChannel = pcSock->GetAresChannel(); @@ -3407,22 +3428,23 @@ void CSocketManager::Select( std::map & mpeSocks ) if( iSel > 0 ) { iErrno = SUCCESS; - if(( !pcSock->GetWriteBuffer().empty() ) && ( pcSock->IsConnected() ) ) - { - // write whats in the socks send buffer + if( !pcSock->GetWriteBuffer().empty() && pcSock->IsConnected() ) + { // write whats in the socks send buffer if( !pcSock->Write( "" ) ) { // write failed, sock died :( iErrno = SELECT_ERROR; } } - } + } else + { iErrno = SELECT_ERROR; + } SelectSock( mpeSocks, iErrno, pcSock ); - } + } else if( FDHasCheck( iRSock, miiReadyFds, ECT_Read ) ) { if( iSel > 0 ) @@ -3431,11 +3453,13 @@ void CSocketManager::Select( std::map & mpeSocks ) iErrno = SELECT_ERROR; if( pcSock->GetType() != Csock::LISTENER ) + { SelectSock( mpeSocks, iErrno, pcSock ); + } else // someone is coming in! { CS_STRING sHost; - u_short port; + uint16_t port; cs_sock_t inSock = pcSock->Accept( sHost, port ); if( inSock != CS_INVALID_SOCK ) @@ -3444,7 +3468,7 @@ void CSocketManager::Select( std::map & mpeSocks ) pcSock->ResetTimer(); // let them now it got dinged // if we have a new sock, then add it - Csock *NewpcSock = ( Csock * )pcSock->GetSockObj( sHost, port ); + Csock * NewpcSock = ( Csock * )pcSock->GetSockObj( sHost, port ); if( !NewpcSock ) NewpcSock = GetSockObj( sHost, port ); @@ -3478,13 +3502,16 @@ void CSocketManager::Select( std::map & mpeSocks ) std::stringstream s; s << sHost << ":" << port; AddSock( NewpcSock, s.str() ); - - } + } else + { AddSock( NewpcSock, NewpcSock->GetSockName() ); - } + } + } else + { CS_Delete( NewpcSock ); + } } #ifdef _WIN32 else if( GetSockError() != WSAEWOULDBLOCK ) @@ -3514,8 +3541,7 @@ timeval CSocketManager::GetDynamicSleepTime( const timeval& tNow, const timeval& std::vector::const_iterator it; // This is safe, because we don't modify the vector. std::vector::const_iterator it_end = this->end(); - - for( it = this->begin(); it != it_end; it++ ) + for( it = this->begin(); it != it_end; ++it ) { Csock* pSock = *it; @@ -3534,13 +3560,13 @@ timeval CSocketManager::GetDynamicSleepTime( const timeval& tNow, const timeval& const std::vector & vCrons = pSock->GetCrons(); std::vector::const_iterator cit; std::vector::const_iterator cit_end = vCrons.end(); - for( cit = vCrons.begin(); cit != cit_end; cit++ ) - MinimizeTime( tNextRunTime, ( *cit )->GetNextRun() ); + for( cit = vCrons.begin(); cit != cit_end; ++cit ) + MinimizeTime( tNextRunTime, (*cit)->GetNextRun() ); } std::vector::const_iterator cit; std::vector::const_iterator cit_end = m_vcCrons.end(); - for( cit = m_vcCrons.begin(); cit != cit_end; cit++ ) - MinimizeTime( tNextRunTime, ( *cit )->GetNextRun() ); + for( cit = m_vcCrons.begin(); cit != cit_end; ++cit ) + MinimizeTime( tNextRunTime, (*cit)->GetNextRun() ); timeval tReturnValue; if( timercmp( &tNextRunTime, &tNow, < ) )