diff --git a/include/znc/Socket.h b/include/znc/Socket.h index 9ad3cdb7..51abf162 100644 --- a/include/znc/Socket.h +++ b/include/znc/Socket.h @@ -131,6 +131,7 @@ public: void Connect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout = 60, bool bSSL = false, const CString& sBindHost = "", CZNCSock *pcSock = NULL); unsigned int GetAnonConnectionCount(const CString &sIP) const; + void DelSockByAddr(Csock* pcSock) override; private: void FinishConnect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout, bool bSSL, const CString& sBindHost, CZNCSock *pcSock); diff --git a/src/Socket.cpp b/src/Socket.cpp index 6870e492..7c7fba50 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -349,12 +349,16 @@ CSockManager::CSockManager() { CSockManager::~CSockManager() { } +// It's here to not break ABI of 1.6; in 1.7 this should be a data member of CSockManager. +static std::map g_InFlightDnsSockets; + void CSockManager::Connect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout, bool bSSL, const CString& sBindHost, CZNCSock *pcSock) { + g_InFlightDnsSockets[pcSock] = false; if (pcSock) { pcSock->SetHostToVerifySSL(sHostname); } #ifdef HAVE_THREADED_DNS - DEBUG("TDNS: initiating resolving of [" << sHostname << "] and bindhost [" << sBindHost << "]"); + DEBUG("TDNS: initiating resolving of [" << sHostname << "] and bindhost [" << sBindHost << "] for [" << sSockName << "]"); TDNSTask* task = new TDNSTask; task->sHostname = sHostname; task->iPort = iPort; @@ -380,6 +384,18 @@ void CSockManager::Connect(const CString& sHostname, u_short iPort, const CStrin } void CSockManager::FinishConnect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout, bool bSSL, const CString& sBindHost, CZNCSock *pcSock) { + auto it = g_InFlightDnsSockets.find(pcSock); + if (it != g_InFlightDnsSockets.end()) { + bool bSocketDeletedAlready = it->second; + g_InFlightDnsSockets.erase(it); + if (bSocketDeletedAlready) { + DEBUG("TDNS: Socket [" << sSockName << "] is deleted already, not proceeding with connection"); + return; + } + } else { + // impossible + } + CSConnection C(sHostname, iPort, iTimeout); C.SetSockName(sSockName); @@ -396,6 +412,15 @@ void CSockManager::FinishConnect(const CString& sHostname, u_short iPort, const TSocketManager::Connect(C, pcSock); } +void CSockManager::DelSockByAddr(Csock* pcSock) { + auto it = g_InFlightDnsSockets.find(pcSock); + if (it != g_InFlightDnsSockets.end()) { + // Then socket is resolving its DNS. When that finishes, let it silently die without crash. + it->second = true; + } + TSocketManager::DelSockByAddr(pcSock); +} + /////////////////// CSocket /////////////////// CSocket::CSocket(CModule* pModule) : CZNCSock() {