this should fix all the ipv4/ipv6 issues, tested it on fbsd and linux

git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@999 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
imaginos
2008-04-01 00:22:43 +00:00
parent a89fa4618d
commit 493d515490
2 changed files with 100 additions and 344 deletions
+25 -88
View File
@@ -28,7 +28,7 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* $Revision: 1.184 $
* $Revision: 1.189 $
*/
// note to compile with win32 need to link to winsock2, using gcc its -lws2_32
@@ -83,7 +83,7 @@
#include <set>
#include <map>
#include "main.h"
#include "main.h" // require this as a general rule, most projects have a defines.h or the like
#ifndef CS_STRING
# ifdef _HAS_CSTRING_
@@ -219,6 +219,24 @@ private:
};
class Csock;
/**
* @brief this function is a wrapper around gethostbyname and getaddrinfo (for ipv6)
*
* in the event this code is using ipv6, it calls getaddrinfo, and it tries to start the connection on each iteration
* in the linked list returned by getaddrinfo. if pSock is not NULL the following behavior happens.
* - if pSock is a listener, or if the connect state is in a bind vhost state (to be used with bind) AI_PASSIVE is sent to getaddrinfo
* - if pSock is an outbound connection, AI_ADDRCONFIG and the connection is started from within this function.
* getaddrinfo might return multiple (possibly invalid depending on system configuration) ip addresses, so connect needs to try them all.
* A classic example of this is a hostname that resolves to both ipv4 and ipv6 ip's. You still need to call Connect (and ConnectSSL) to finish
* up the connection state
* - NOTE ... Once threading is reimplemented, this function will spin off a thread to resolve and return EAGAIN until its done.
*
* @param sHostname the host to resolve
* @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
* @return 0 on success, otherwise an error. EAGAIN if this needs to be called again at a later time, ETIMEDOUT if no host is found
*/
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
@@ -230,83 +248,6 @@ Csock *GetCsockFromCTX( X509_STORE_CTX *pCTX );
#endif /* HAVE_LIBSSL */
#if defined( _REENTRANT ) && defined( _USE_THREADED_DNS )
#define ___DO_THREADS
#include <pthread.h>
#ifndef PTHREAD_MUTEX_FAST_NP
#define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL
#endif /* PTHREAD_MUTEX_FAST_NP */
class CSMutex
{
public:
CSMutex ();
virtual ~CSMutex();
int lock() { return( pthread_mutex_lock( &m_mutex ) ); }
int unlock() { return( pthread_mutex_unlock( &m_mutex ) ); }
int trylock() { return( pthread_mutex_trylock( &m_mutex ) ); }
private:
pthread_mutex_t m_mutex;
pthread_mutexattr_t m_mattrib;
};
class CSThread
{
public:
CSThread() { m_eStatus = WAITING; }
virtual ~CSThread() {}
enum EStatus
{
WAITING = 1,
RUNNING = 2,
FINISHED = 3
};
bool start();
void wait();
virtual void run() = 0;
static void *start_thread( void *args );
EStatus Status() { return( m_eStatus ); }
void SetStatus( EStatus e ) { m_eStatus = e; }
int lock() { return( m_mutex.lock() ); }
int unlock() { return( m_mutex.unlock() ); }
int cancel() { return( pthread_cancel( m_ppth ) ); }
private:
pthread_t m_ppth;
EStatus m_eStatus;
CSMutex m_mutex;
};
class CDNSResolver : public CSThread
{
public:
CDNSResolver() : CSThread() { m_bSuccess = false; }
virtual ~CDNSResolver() {}
//! returns imediatly, from here out check if IsCompleted() returns true before looking at ANY of the data
void Lookup( const CS_STRING & sHostname );
virtual void run();
//! true if dns entry was successfuly found
bool Suceeded() const { return( m_bSuccess ); }
//! true if task is finished, this function is thread safe
bool IsCompleted();
CSSockAddr * GetSockAddr() { return( &m_cSockAddr ); }
private:
bool m_bSuccess;
CS_STRING m_sHostname;
CSSockAddr m_cSockAddr;
};
#endif /* ___DO_THREADS */
const u_int CS_BLOCKSIZE = 4096;
template <class T> inline void CS_Delete( T * & p ) { if( p ) { delete p; p = NULL; } }
@@ -521,7 +462,7 @@ public:
CST_START = 0,
CST_DNS = CST_START,
CST_BINDVHOST = 1,
CST_VHOSTDNS = 2,
CST_DESTDNS = 2,
CST_CONNECT = 3,
CST_OK = 4
};
@@ -1002,6 +943,8 @@ public:
//! returns a const reference to the crons associated to this socket
const std::vector<CCron *> & GetCrons() const { return( m_vcCrons ); }
void SetSkipConnect( bool b ) { m_bSkipConnect = b; }
private:
//! making private for safety
Csock( const Csock & cCopy ) {}
@@ -1019,7 +962,7 @@ private:
unsigned int m_iMaxBytes, m_iLastSend, m_iMaxStoredBufferLength, m_iTimeoutType;
CSSockAddr m_address, m_bindhost;
bool m_bIsIPv6;
bool m_bIsIPv6, m_bSkipConnect;
time_t m_iLastCheckTimeoutTime;
#ifdef HAVE_LIBSSL
@@ -1047,10 +990,6 @@ private:
CS_STRING m_sBindHost;
u_int m_iCurBindCount, m_iDNSTryCount;
#ifdef ___DO_THREADS
CDNSResolver m_pResolver;
#endif /* ___DO_THREADS */
};
/**
@@ -1428,7 +1367,7 @@ public:
}
}
if ( pcSock->GetConState() == T::CST_VHOSTDNS )
if ( pcSock->GetConState() == T::CST_DESTDNS )
{
if ( pcSock->DNSLookup( T::DNS_DEST ) == ETIMEDOUT )
{
@@ -1438,7 +1377,6 @@ public:
}
}
if ( pcSock->GetConState() == T::CST_CONNECT )
{
if ( !pcSock->Connect( pcSock->GetBindHost(), true ) )
@@ -1451,7 +1389,6 @@ public:
DelSock( a-- );
continue;
}
#ifdef HAVE_LIBSSL
if ( pcSock->GetSSL() )
{