diff options
Diffstat (limited to 'Sockets/SocketHandler.cpp')
-rw-r--r-- | Sockets/SocketHandler.cpp | 1422 |
1 files changed, 0 insertions, 1422 deletions
diff --git a/Sockets/SocketHandler.cpp b/Sockets/SocketHandler.cpp deleted file mode 100644 index c563aac..0000000 --- a/Sockets/SocketHandler.cpp +++ /dev/null @@ -1,1422 +0,0 @@ -/** \file SocketHandler.cpp - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004-2007 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#ifdef _WIN32 -#ifdef _MSC_VER -#pragma warning(disable:4786) -#endif -#endif -#include <stdlib.h> -#include <errno.h> - -#include "SocketHandler.h" -#include "UdpSocket.h" -#include "ResolvSocket.h" -#include "ResolvServer.h" -#include "TcpSocket.h" -#include "Mutex.h" -#include "Utility.h" -#include "SocketAddress.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -#ifdef _DEBUG -#define DEB(x) x; fflush(stderr); -#else -#define DEB(x) -#endif - - -SocketHandler::SocketHandler(StdLog *p) -:m_stdlog(p) -,m_mutex(m_mutex) -,m_b_use_mutex(false) -,m_maxsock(0) -,m_preverror(-1) -,m_errcnt(0) -,m_tlast(0) -#ifdef ENABLE_SOCKS4 -,m_socks4_host(0) -,m_socks4_port(0) -,m_bTryDirect(false) -#endif -#ifdef ENABLE_RESOLVER -,m_resolv_id(0) -,m_resolver(NULL) -#endif -#ifdef ENABLE_POOL -,m_b_enable_pool(false) -#endif -#ifdef ENABLE_TRIGGERS -,m_next_trigger_id(0) -#endif -#ifdef ENABLE_DETACH -,m_slave(false) -#endif -{ - FD_ZERO(&m_rfds); - FD_ZERO(&m_wfds); - FD_ZERO(&m_efds); -} - - -SocketHandler::SocketHandler(Mutex& mutex,StdLog *p) -:m_stdlog(p) -,m_mutex(mutex) -,m_b_use_mutex(true) -,m_maxsock(0) -,m_preverror(-1) -,m_errcnt(0) -,m_tlast(0) -#ifdef ENABLE_SOCKS4 -,m_socks4_host(0) -,m_socks4_port(0) -,m_bTryDirect(false) -#endif -#ifdef ENABLE_RESOLVER -,m_resolv_id(0) -,m_resolver(NULL) -#endif -#ifdef ENABLE_POOL -,m_b_enable_pool(false) -#endif -#ifdef ENABLE_TRIGGERS -,m_next_trigger_id(0) -#endif -#ifdef ENABLE_DETACH -,m_slave(false) -#endif -{ - m_mutex.Lock(); - FD_ZERO(&m_rfds); - FD_ZERO(&m_wfds); - FD_ZERO(&m_efds); -} - - -SocketHandler::~SocketHandler() -{ -#ifdef ENABLE_RESOLVER - if (m_resolver) - { - m_resolver -> Quit(); - } -#endif - { - while (m_sockets.size()) - { -DEB( fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());) - socket_m::iterator it = m_sockets.begin(); - Socket *p = it -> second; - if (p) - { -DEB( fprintf(stderr, " fd %d\n", p -> GetSocket());) - p -> Close(); -DEB( fprintf(stderr, " fd closed %d\n", p -> GetSocket());) -// p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!! - // MinionSocket breaks, calling MinderHandler methods in OnDelete - - // MinderHandler is already gone when that happens... - - // only delete socket when controlled - // ie master sockethandler can delete non-detached sockets - // and a slave sockethandler can only delete a detach socket - if (p -> DeleteByHandler() -#ifdef ENABLE_DETACH - && !(m_slave ^ p -> IsDetached()) -#endif - ) - { - p -> SetErasedByHandler(); - delete p; - } - m_sockets.erase(it); - } - else - { - m_sockets.erase(it); - } -DEB( fprintf(stderr, "next\n");) - } -DEB( fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());) - } -#ifdef ENABLE_RESOLVER - if (m_resolver) - { - delete m_resolver; - } -#endif - if (m_b_use_mutex) - { - m_mutex.Unlock(); - } -} - - -Mutex& SocketHandler::GetMutex() const -{ - return m_mutex; -} - - -#ifdef ENABLE_DETACH -void SocketHandler::SetSlave(bool x) -{ - m_slave = x; -} - - -bool SocketHandler::IsSlave() -{ - return m_slave; -} -#endif - - -void SocketHandler::RegStdLog(StdLog *log) -{ - m_stdlog = log; -} - - -void SocketHandler::LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t) -{ - if (m_stdlog) - { - m_stdlog -> error(this, p, user_text, err, sys_err, t); - } -} - - -void SocketHandler::Add(Socket *p) -{ - if (p -> GetSocket() == INVALID_SOCKET) - { - LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING); - if (p -> CloseAndDelete()) - { - m_delete.push_back(p); - } - return; - } - if (m_add.find(p -> GetSocket()) != m_add.end()) - { - LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL); - m_delete.push_back(p); - return; - } - m_add[p -> GetSocket()] = p; -} - - -void SocketHandler::Get(SOCKET s,bool& r,bool& w,bool& e) -{ - if (s >= 0) - { - r = FD_ISSET(s, &m_rfds) ? true : false; - w = FD_ISSET(s, &m_wfds) ? true : false; - e = FD_ISSET(s, &m_efds) ? true : false; - } -} - - -void SocketHandler::Set(SOCKET s,bool bRead,bool bWrite,bool bException) -{ -DEB( fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");) - if (s >= 0) - { - if (bRead) - { - if (!FD_ISSET(s, &m_rfds)) - { - FD_SET(s, &m_rfds); - } - } - else - { - FD_CLR(s, &m_rfds); - } - if (bWrite) - { - if (!FD_ISSET(s, &m_wfds)) - { - FD_SET(s, &m_wfds); - } - } - else - { - FD_CLR(s, &m_wfds); - } - if (bException) - { - if (!FD_ISSET(s, &m_efds)) - { - FD_SET(s, &m_efds); - } - } - else - { - FD_CLR(s, &m_efds); - } - } -} - - -int SocketHandler::Select(long sec,long usec) -{ - struct timeval tv; - tv.tv_sec = sec; - tv.tv_usec = usec; - return Select(&tv); -} - - -int SocketHandler::Select() -{ - if (m_fds_callonconnect.size() || -#ifdef ENABLE_DETACH - (!m_slave && m_fds_detach.size()) || -#endif - m_fds_timeout.size() || - m_fds_retry.size() || - m_fds_close.size() || - m_fds_erase.size()) - { - return Select(0, 200000); - } - return Select(NULL); -} - - -int SocketHandler::Select(struct timeval *tsel) -{ - size_t ignore = 0; - while (m_add.size() > ignore) - { - if (m_sockets.size() >= FD_SETSIZE) - { - LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING); - break; - } - socket_m::iterator it = m_add.begin(); - SOCKET s = it -> first; - Socket *p = it -> second; -DEB( fprintf(stderr, "Trying to add fd %d, m_add.size() %d, ignore %d\n", (int)s, (int)m_add.size(), (int)ignore);) - // - if (m_sockets.find(p -> GetSocket()) != m_sockets.end()) - { - LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL); - // %! it's a dup, don't add to delete queue, just ignore it - m_delete.push_back(p); - m_add.erase(it); -// ignore++; - continue; - } - if (!p -> CloseAndDelete()) - { - StreamSocket *scp = dynamic_cast<StreamSocket *>(p); - if (scp && scp -> Connecting()) // 'Open' called before adding socket - { - Set(s,false,true); - } - else - { - TcpSocket *tcp = dynamic_cast<TcpSocket *>(p); - bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false; - if (p -> IsDisableRead()) - { - Set(s, false, bWrite); - } - else - { - Set(s, true, bWrite); - } - } - m_maxsock = (s > m_maxsock) ? s : m_maxsock; - } - else - { - LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING); - } - // only add to m_fds (process fd_set events) if - // slave handler and detached/detaching socket - // master handler and non-detached socket -#ifdef ENABLE_DETACH - if (!(m_slave ^ p -> IsDetach())) -#endif - { - m_fds.push_back(s); - } - m_sockets[s] = p; - // - m_add.erase(it); - } -#ifdef MACOSX - fd_set rfds; - fd_set wfds; - fd_set efds; - FD_COPY(&m_rfds, &rfds); - FD_COPY(&m_wfds, &wfds); - FD_COPY(&m_efds, &efds); -#else - fd_set rfds = m_rfds; - fd_set wfds = m_wfds; - fd_set efds = m_efds; -#endif - int n; - if (m_b_use_mutex) - { - m_mutex.Unlock(); - n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel); - m_mutex.Lock(); - } - else - { - n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel); - } - if (n == -1) - { - /* - EBADF An invalid file descriptor was given in one of the sets. - EINTR A non blocked signal was caught. - EINVAL n is negative. Or struct timeval contains bad time values (<0). - ENOMEM select was unable to allocate memory for internal tables. - */ - if (Errno != m_preverror || m_errcnt++ % 10000 == 0) - { - LogError(NULL, "select", Errno, StrError(Errno)); -DEB( fprintf(stderr, "m_maxsock: %d\n", m_maxsock); - fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" : - Errno == EINTR ? "EINTR" : - Errno == EBADF ? "EBADF" : - Errno == ENOMEM ? "ENOMEM" : "<another>"); - // test bad fd - for (SOCKET i = 0; i <= m_maxsock; i++) - { - bool t = false; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&efds); - if (FD_ISSET(i, &m_rfds)) - { - FD_SET(i, &rfds); - t = true; - } - if (FD_ISSET(i, &m_wfds)) - { - FD_SET(i, &wfds); - t = true; - } - if (FD_ISSET(i, &m_efds)) - { - FD_SET(i, &efds); - t = true; - } - if (t && m_sockets.find(i) == m_sockets.end()) - { - fprintf(stderr, "Bad fd in fd_set: %d\n", i); - } - } -) // DEB - m_preverror = Errno; - } - /// \todo rebuild fd_set's from active sockets list (m_sockets) here - } - else - if (!n) - { - m_preverror = -1; - } - else - if (n > 0) - { - for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++) - { - SOCKET i = *it2; - if (FD_ISSET(i, &rfds)) - { - socket_m::iterator itmp = m_sockets.find(i); - if (itmp != m_sockets.end()) // found - { - Socket *p = itmp -> second; - // new SSL negotiate method -#ifdef HAVE_OPENSSL - if (p -> IsSSLNegotiate()) - { - p -> SSLNegotiate(); - } - else -#endif - { - p -> OnRead(); - } - } - else - { - LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - n--; - } - if (FD_ISSET(i, &wfds)) - { - socket_m::iterator itmp = m_sockets.find(i); - if (itmp != m_sockets.end()) // found - { - Socket *p = itmp -> second; - // new SSL negotiate method -#ifdef HAVE_OPENSSL - if (p -> IsSSLNegotiate()) - { - p -> SSLNegotiate(); - } - else -#endif - { - p -> OnWrite(); - } - } - else - { - LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - n--; - } - if (FD_ISSET(i, &efds)) - { - socket_m::iterator itmp = m_sockets.find(i); - if (itmp != m_sockets.end()) // found - { - Socket *p = itmp -> second; - p -> OnException(); - } - else - { - LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - n--; - } - } // m_fds loop - m_preverror = -1; - } // if (n > 0) - - // check CallOnConnect - EVENT - if (m_fds_callonconnect.size()) - { - socket_v tmp = m_fds_callonconnect; - for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) - { - Socket *p = NULL; - { - socket_m::iterator itmp = m_sockets.find(*it); - if (itmp != m_sockets.end()) // found - { - p = itmp -> second; - } - else - { - LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - } - if (p) - { -// if (p -> CallOnConnect() && p -> Ready() ) - { - p -> SetConnected(); // moved here from inside if (tcp) check below -#ifdef HAVE_OPENSSL - if (p -> IsSSL()) // SSL Enabled socket - p -> OnSSLConnect(); - else -#endif -#ifdef ENABLE_SOCKS4 - if (p -> Socks4()) - p -> OnSocks4Connect(); - else -#endif - { - TcpSocket *tcp = dynamic_cast<TcpSocket *>(p); - if (tcp) - { - if (tcp -> GetOutputLength()) - { - p -> OnWrite(); - } - } -#ifdef ENABLE_RECONNECT - if (tcp && tcp -> IsReconnect()) - p -> OnReconnect(); - else -#endif - { -// LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO); - p -> OnConnect(); - } - } -// p -> SetCallOnConnect( false ); - AddList(p -> GetSocket(), LIST_CALLONCONNECT, false); - } - } - } - } -#ifdef ENABLE_DETACH - // check detach of socket if master handler - EVENT - if (!m_slave && m_fds_detach.size()) - { - // %! why not using tmp list here??!? - for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++) - { - Socket *p = NULL; - { - socket_m::iterator itmp = m_sockets.find(*it); - if (itmp != m_sockets.end()) // found - { - p = itmp -> second; - } - else - { - LogError(NULL, "GetSocket/handler/5", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - } - if (p) - { -// if (p -> IsDetach()) - { - Set(p -> GetSocket(), false, false, false); - // After DetachSocket(), all calls to Handler() will return a reference - // to the new slave SocketHandler running in the new thread. - p -> DetachSocket(); - // Adding the file descriptor to m_fds_erase will now also remove the - // socket from the detach queue - tnx knightmad - m_fds_erase.push_back(p -> GetSocket()); - } - } - } - } -#endif - // check Connecting - connection timeout - conditional event - if (m_fds_timeout.size()) - { - time_t tnow = time(NULL); - if (tnow != m_tlast) - { - socket_v tmp = m_fds_timeout; -DEB( fprintf(stderr, "Checking %d socket(s) for timeout\n", tmp.size());) - for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) - { - Socket *p = NULL; - { - socket_m::iterator itmp = m_sockets.find(*it); - if (itmp != m_sockets.end()) // found - { - p = itmp -> second; - } - else - { - itmp = m_add.find(*it); - if (itmp != m_add.end()) - { - p = itmp -> second; - } - else - { - LogError(NULL, "GetSocket/handler/6", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - } - } - if (p) - { - if (p -> Timeout(tnow)) - { - StreamSocket *scp = dynamic_cast<StreamSocket *>(p); - if (scp && scp -> Connecting()) - p -> OnConnectTimeout(); - else - p -> OnTimeout(); - p -> SetTimeout(0); - } - } - } - m_tlast = tnow; - } // tnow != tlast - } - // check retry client connect - EVENT - if (m_fds_retry.size()) - { - socket_v tmp = m_fds_retry; - for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) - { - Socket *p = NULL; - { - socket_m::iterator itmp = m_sockets.find(*it); - if (itmp != m_sockets.end()) // found - { - p = itmp -> second; - } - else - { - LogError(NULL, "GetSocket/handler/7", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - } - if (p) - { -// if (p -> RetryClientConnect()) - { - TcpSocket *tcp = dynamic_cast<TcpSocket *>(p); - SOCKET nn = *it; //(*it3).first; - tcp -> SetRetryClientConnect(false); -DEB( fprintf(stderr, "Close() before retry client connect\n");) - p -> Close(); // removes from m_fds_retry - std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress(); - if (ad.get()) - { - tcp -> Open(*ad); - } - else - { - LogError(p, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR); - } - Add(p); - m_fds_erase.push_back(nn); - } - } - } - } - // check close and delete - conditional event - if (m_fds_close.size()) - { - socket_v tmp = m_fds_close; -DEB( fprintf(stderr, "m_fds_close.size() == %d\n", (int)m_fds_close.size());) - for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++) - { - Socket *p = NULL; - { - socket_m::iterator itmp = m_sockets.find(*it); - if (itmp != m_sockets.end()) // found - { - p = itmp -> second; - } - else - { - itmp = m_add.find(*it); - if (itmp != m_add.end()) - { - p = itmp -> second; - } - else - { - LogError(NULL, "GetSocket/handler/8", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING); - } - } - } - if (p) - { -// if (p -> CloseAndDelete() ) - { - TcpSocket *tcp = dynamic_cast<TcpSocket *>(p); - // new graceful tcp - flush and close timeout 5s - if (tcp && p -> IsConnected() && tcp -> GetFlushBeforeClose() && -#ifdef HAVE_OPENSSL - !tcp -> IsSSL() && -#endif - p -> TimeSinceClose() < 5) - { -DEB( fprintf(stderr, " close(1)\n");) - if (tcp -> GetOutputLength()) - { - LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Sending all data before closing", LOG_LEVEL_INFO); - } - else // shutdown write when output buffer is empty - if (!(tcp -> GetShutdown() & SHUT_WR)) - { - SOCKET nn = *it; - if (nn != INVALID_SOCKET && shutdown(nn, SHUT_WR) == -1) - { - LogError(p, "graceful shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR); - } - tcp -> SetShutdown(SHUT_WR); - } - } - else -#ifdef ENABLE_RECONNECT - if (tcp && p -> IsConnected() && tcp -> Reconnect()) - { - SOCKET nn = *it; //(*it3).first; -DEB( fprintf(stderr, " close(2) fd %d\n", nn);) - p -> SetCloseAndDelete(false); - tcp -> SetIsReconnect(); - p -> SetConnected(false); -DEB( fprintf(stderr, "Close() before reconnect\n");) - p -> Close(); // dispose of old file descriptor (Open creates a new) - p -> OnDisconnect(); - std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress(); - if (ad.get()) - { - tcp -> Open(*ad); - } - else - { - LogError(p, "Reconnect", 0, "no address", LOG_LEVEL_ERROR); - } - tcp -> ResetConnectionRetries(); - Add(p); - m_fds_erase.push_back(nn); - } - else -#endif - { - SOCKET nn = *it; //(*it3).first; -DEB( fprintf(stderr, " close(3) fd %d GetSocket() %d\n", nn, p -> GetSocket());) - if (tcp && p -> IsConnected() && tcp -> GetOutputLength()) - { - LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Closing socket while data still left to send", LOG_LEVEL_WARNING); - } -#ifdef ENABLE_POOL - if (p -> Retain() && !p -> Lost()) - { - PoolSocket *p2 = new PoolSocket(*this, p); - p2 -> SetDeleteByHandler(); - Add(p2); - // - p -> SetCloseAndDelete(false); // added - remove from m_fds_close - } - else -#endif // ENABLE_POOL - { - Set(p -> GetSocket(),false,false,false); -DEB( fprintf(stderr, "Close() before OnDelete\n");) - p -> Close(); - } - p -> OnDelete(); - if (p -> DeleteByHandler()) - { - p -> SetErasedByHandler(); - } - m_fds_erase.push_back(nn); - } - } - } - } - } - - // check erased sockets - bool check_max_fd = false; - while (m_fds_erase.size()) - { - socket_v::iterator it = m_fds_erase.begin(); - SOCKET nn = *it; -#ifdef ENABLE_DETACH - { - for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++) - { - if (*it == nn) - { - m_fds_detach.erase(it); - break; - } - } - } -#endif - { - for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++) - { - if (*it == nn) - { - m_fds.erase(it); - break; - } - } - } - { - socket_m::iterator it = m_sockets.find(nn); - if (it != m_sockets.end()) - { - Socket *p = it -> second; - /* Sometimes a SocketThread class can finish its run before the master - sockethandler gets here. In that case, the SocketThread has set the - 'ErasedByHandler' flag on the socket which will make us end up with a - double delete on the socket instance. - The fix is to make sure that the master sockethandler only can delete - non-detached sockets, and a slave sockethandler only can delete - detach sockets. */ - if (p -> ErasedByHandler() -#ifdef ENABLE_DETACH - && !(m_slave ^ p -> IsDetached()) -#endif - ) - { -#ifdef ENABLE_TRIGGERS - bool again = false; - do - { - again = false; - for (std::map<int, Socket *>::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++) - { - int id = it -> first; - Socket *src = it -> second; - if (src == p) - { - for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++) - { - Socket *dst = it -> first; - if (Valid(dst)) - { - dst -> OnCancelled(id); - } - } - m_trigger_src.erase(m_trigger_src.find(id)); - m_trigger_dst.erase(m_trigger_dst.find(id)); - again = true; - break; - } - } - } while (again); -#endif - delete p; - } - m_sockets.erase(it); - } - } - m_fds_erase.erase(it); - check_max_fd = true; - } - // calculate max file descriptor for select() call - if (check_max_fd) - { - m_maxsock = 0; - for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++) - { - SOCKET s = *it; - m_maxsock = s > m_maxsock ? s : m_maxsock; - } - } - // remove Add's that fizzed - while (m_delete.size()) - { - std::list<Socket *>::iterator it = m_delete.begin(); - Socket *p = *it; - p -> OnDelete(); - m_delete.erase(it); - if (p -> DeleteByHandler() -#ifdef ENABLE_DETACH - && !(m_slave ^ p -> IsDetached()) -#endif - ) - { - p -> SetErasedByHandler(); -#ifdef ENABLE_TRIGGERS - bool again = false; - do - { - again = false; - for (std::map<int, Socket *>::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++) - { - int id = it -> first; - Socket *src = it -> second; - if (src == p) - { - for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++) - { - Socket *dst = it -> first; - if (Valid(dst)) - { - dst -> OnCancelled(id); - } - } - m_trigger_src.erase(m_trigger_src.find(id)); - m_trigger_dst.erase(m_trigger_dst.find(id)); - again = true; - break; - } - } - } while (again); -#endif - delete p; - } - } - return n; -} - - -#ifdef ENABLE_RESOLVER -bool SocketHandler::Resolving(Socket *p0) -{ - std::map<Socket *, bool>::iterator it = m_resolve_q.find(p0); - return it != m_resolve_q.end(); -} -#endif - - -bool SocketHandler::Valid(Socket *p0) -{ - for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++) - { - Socket *p = it -> second; - if (p0 == p) - return true; - } - return false; -} - - -bool SocketHandler::OkToAccept(Socket *) -{ - return true; -} - - -size_t SocketHandler::GetCount() -{ -/* -printf(" m_sockets : %d\n", m_sockets.size()); -printf(" m_add : %d\n", m_add.size()); -printf(" m_delete : %d\n", m_delete.size()); -*/ - return m_sockets.size() + m_add.size() + m_delete.size(); -} - - -#ifdef ENABLE_SOCKS4 -void SocketHandler::SetSocks4Host(ipaddr_t a) -{ - m_socks4_host = a; -} - - -void SocketHandler::SetSocks4Host(const std::string& host) -{ - Utility::u2ip(host, m_socks4_host); -} - - -void SocketHandler::SetSocks4Port(port_t port) -{ - m_socks4_port = port; -} - - -void SocketHandler::SetSocks4Userid(const std::string& id) -{ - m_socks4_userid = id; -} -#endif - - -#ifdef ENABLE_RESOLVER -int SocketHandler::Resolve(Socket *p,const std::string& host,port_t port) -{ - // check cache - ResolvSocket *resolv = new ResolvSocket(*this, p, host, port); - resolv -> SetId(++m_resolv_id); - resolv -> SetDeleteByHandler(); - ipaddr_t local; - Utility::u2ip("127.0.0.1", local); - if (!resolv -> Open(local, m_resolver_port)) - { - LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); - } - Add(resolv); - m_resolve_q[p] = true; -DEB( fprintf(stderr, " *** Resolve '%s:%d' id#%d m_resolve_q size: %d p: %p\n", host.c_str(), port, resolv -> GetId(), m_resolve_q.size(), p);) - return resolv -> GetId(); -} - - -#ifdef ENABLE_IPV6 -int SocketHandler::Resolve6(Socket *p,const std::string& host,port_t port) -{ - // check cache - ResolvSocket *resolv = new ResolvSocket(*this, p, host, port, true); - resolv -> SetId(++m_resolv_id); - resolv -> SetDeleteByHandler(); - ipaddr_t local; - Utility::u2ip("127.0.0.1", local); - if (!resolv -> Open(local, m_resolver_port)) - { - LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); - } - Add(resolv); - m_resolve_q[p] = true; - return resolv -> GetId(); -} -#endif - - -int SocketHandler::Resolve(Socket *p,ipaddr_t a) -{ - // check cache - ResolvSocket *resolv = new ResolvSocket(*this, p, a); - resolv -> SetId(++m_resolv_id); - resolv -> SetDeleteByHandler(); - ipaddr_t local; - Utility::u2ip("127.0.0.1", local); - if (!resolv -> Open(local, m_resolver_port)) - { - LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); - } - Add(resolv); - m_resolve_q[p] = true; - return resolv -> GetId(); -} - - -#ifdef ENABLE_IPV6 -int SocketHandler::Resolve(Socket *p,in6_addr& a) -{ - // check cache - ResolvSocket *resolv = new ResolvSocket(*this, p, a); - resolv -> SetId(++m_resolv_id); - resolv -> SetDeleteByHandler(); - ipaddr_t local; - Utility::u2ip("127.0.0.1", local); - if (!resolv -> Open(local, m_resolver_port)) - { - LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL); - } - Add(resolv); - m_resolve_q[p] = true; - return resolv -> GetId(); -} -#endif - - -void SocketHandler::EnableResolver(port_t port) -{ - if (!m_resolver) - { - m_resolver_port = port; - m_resolver = new ResolvServer(port); - } -} - - -bool SocketHandler::ResolverReady() -{ - return m_resolver ? m_resolver -> Ready() : false; -} -#endif // ENABLE_RESOLVER - - -#ifdef ENABLE_SOCKS4 -void SocketHandler::SetSocks4TryDirect(bool x) -{ - m_bTryDirect = x; -} - - -ipaddr_t SocketHandler::GetSocks4Host() -{ - return m_socks4_host; -} - - -port_t SocketHandler::GetSocks4Port() -{ - return m_socks4_port; -} - - -const std::string& SocketHandler::GetSocks4Userid() -{ - return m_socks4_userid; -} - - -bool SocketHandler::Socks4TryDirect() -{ - return m_bTryDirect; -} -#endif - - -#ifdef ENABLE_RESOLVER -bool SocketHandler::ResolverEnabled() -{ - return m_resolver ? true : false; -} - - -port_t SocketHandler::GetResolverPort() -{ - return m_resolver_port; -} -#endif // ENABLE_RESOLVER - - -#ifdef ENABLE_POOL -ISocketHandler::PoolSocket *SocketHandler::FindConnection(int type,const std::string& protocol,SocketAddress& ad) -{ - for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end() && m_sockets.size(); it++) - { - PoolSocket *pools = dynamic_cast<PoolSocket *>(it -> second); - if (pools) - { - if (pools -> GetSocketType() == type && - pools -> GetSocketProtocol() == protocol && -// %! pools -> GetClientRemoteAddress() && - *pools -> GetClientRemoteAddress() == ad) - { - m_sockets.erase(it); - pools -> SetRetain(); // avoid Close in Socket destructor - return pools; // Caller is responsible that this socket is deleted - } - } - } - return NULL; -} - - -void SocketHandler::EnablePool(bool x) -{ - m_b_enable_pool = x; -} - - -bool SocketHandler::PoolEnabled() -{ - return m_b_enable_pool; -} -#endif - - -void SocketHandler::Remove(Socket *p) -{ -#ifdef ENABLE_RESOLVER - std::map<Socket *, bool>::iterator it4 = m_resolve_q.find(p); - if (it4 != m_resolve_q.end()) - m_resolve_q.erase(it4); -#endif - if (p -> ErasedByHandler()) - { - return; - } - for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++) - { - if (it -> second == p) - { - LogError(p, "Remove", -1, "Socket destructor called while still in use", LOG_LEVEL_WARNING); - m_sockets.erase(it); - return; - } - } - for (socket_m::iterator it2 = m_add.begin(); it2 != m_add.end(); it2++) - { - if ((*it2).second == p) - { - LogError(p, "Remove", -2, "Socket destructor called while still in use", LOG_LEVEL_WARNING); - m_add.erase(it2); - return; - } - } - for (std::list<Socket *>::iterator it3 = m_delete.begin(); it3 != m_delete.end(); it3++) - { - if (*it3 == p) - { - LogError(p, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING); - m_delete.erase(it3); - return; - } - } -} - - -void SocketHandler::CheckSanity() -{ - CheckList(m_fds, "active sockets"); // active sockets - CheckList(m_fds_erase, "sockets to be erased"); // should always be empty anyway - CheckList(m_fds_callonconnect, "checklist CallOnConnect"); -#ifdef ENABLE_DETACH - CheckList(m_fds_detach, "checklist Detach"); -#endif - CheckList(m_fds_timeout, "checklist Timeout"); - CheckList(m_fds_retry, "checklist retry client connect"); - CheckList(m_fds_close, "checklist close and delete"); -} - - -void SocketHandler::CheckList(socket_v& ref,const std::string& listname) -{ - for (socket_v::iterator it = ref.begin(); it != ref.end(); it++) - { - SOCKET s = *it; - if (m_sockets.find(s) != m_sockets.end()) - continue; - if (m_add.find(s) != m_add.end()) - continue; - bool found = false; - for (std::list<Socket *>::iterator it = m_delete.begin(); it != m_delete.end(); it++) - { - Socket *p = *it; - if (p -> GetSocket() == s) - { - found = true; - break; - } - } - if (!found) - { - fprintf(stderr, "CheckList failed for \"%s\": fd %d\n", listname.c_str(), s); - } - } -} - - -void SocketHandler::AddList(SOCKET s,list_t which_one,bool add) -{ - if (s == INVALID_SOCKET) - { -DEB( fprintf(stderr, "AddList: invalid_socket\n");) - return; - } - socket_v& ref = - (which_one == LIST_CALLONCONNECT) ? m_fds_callonconnect : -#ifdef ENABLE_DETACH - (which_one == LIST_DETACH) ? m_fds_detach : -#endif - (which_one == LIST_TIMEOUT) ? m_fds_timeout : - (which_one == LIST_RETRY) ? m_fds_retry : - (which_one == LIST_CLOSE) ? m_fds_close : m_fds_close; - if (add) - { -#ifdef ENABLE_DETACH -DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" : - (which_one == LIST_DETACH) ? "Detach" : - (which_one == LIST_TIMEOUT) ? "Timeout" : - (which_one == LIST_RETRY) ? "Retry" : - (which_one == LIST_CLOSE) ? "Close" : "<undef>", - add ? "Add" : "Remove");) -#else -DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" : - (which_one == LIST_TIMEOUT) ? "Timeout" : - (which_one == LIST_RETRY) ? "Retry" : - (which_one == LIST_CLOSE) ? "Close" : "<undef>", - add ? "Add" : "Remove");) -#endif - } - if (add) - { - for (socket_v::iterator it = ref.begin(); it != ref.end(); it++) - { - if (*it == s) // already there - { - return; - } - } - ref.push_back(s); - return; - } - // remove - for (socket_v::iterator it = ref.begin(); it != ref.end(); it++) - { - if (*it == s) - { - ref.erase(it); - break; - } - } -//DEB( fprintf(stderr, "/AddList\n");) -} - - -#ifdef ENABLE_TRIGGERS -int SocketHandler::TriggerID(Socket *src) -{ - int id = m_next_trigger_id++; - m_trigger_src[id] = src; - return id; -} - - -bool SocketHandler::Subscribe(int id, Socket *dst) -{ - if (m_trigger_src.find(id) != m_trigger_src.end()) - { - std::map<Socket *, bool>::iterator it = m_trigger_dst[id].find(dst); - if (it != m_trigger_dst[id].end()) - { - m_trigger_dst[id][dst] = true; - return true; - } - LogError(dst, "Subscribe", id, "Already subscribed", LOG_LEVEL_INFO); - return false; - } - LogError(dst, "Subscribe", id, "Trigger id not found", LOG_LEVEL_INFO); - return false; -} - - -bool SocketHandler::Unsubscribe(int id, Socket *dst) -{ - if (m_trigger_src.find(id) != m_trigger_src.end()) - { - std::map<Socket *, bool>::iterator it = m_trigger_dst[id].find(dst); - if (it != m_trigger_dst[id].end()) - { - m_trigger_dst[id].erase(it); - return true; - } - LogError(dst, "Unsubscribe", id, "Not subscribed", LOG_LEVEL_INFO); - return false; - } - LogError(dst, "Unsubscribe", id, "Trigger id not found", LOG_LEVEL_INFO); - return false; -} - - -void SocketHandler::Trigger(int id, Socket::TriggerData& data, bool erase) -{ - if (m_trigger_src.find(id) != m_trigger_src.end()) - { - data.SetSource( m_trigger_src[id] ); - for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++) - { - Socket *dst = it -> first; - if (Valid(dst)) - { - dst -> OnTrigger(id, data); - } - } - if (erase) - { - m_trigger_src.erase(m_trigger_src.find(id)); - m_trigger_dst.erase(m_trigger_dst.find(id)); - } - } - else - { - LogError(NULL, "Trigger", id, "Trigger id not found", LOG_LEVEL_INFO); - } -} -#endif // ENABLE_TRIGGERS - - -#ifdef SOCKETS_NAMESPACE -} -#endif - |