Logo
~Sockets~
~Examples~
~Contact~


SocketHandler.cpp

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2004-2007  Anders Hedstrom
00007 
00008 This library is made available under the terms of the GNU GPL.
00009 
00010 If you would like to use this library in a closed-source application,
00011 a separate license agreement is available. For information about 
00012 the closed-source license agreement for the C++ sockets library,
00013 please visit http://www.alhem.net/Sockets/license.html and/or
00014 email license@alhem.net.
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 */
00030 #ifdef _WIN32
00031 #pragma warning(disable:4786)
00032 #include <stdlib.h>
00033 #else
00034 #include <errno.h>
00035 #endif
00036 
00037 #include "SocketHandler.h"
00038 #include "UdpSocket.h"
00039 #include "ResolvSocket.h"
00040 #include "ResolvServer.h"
00041 #include "TcpSocket.h"
00042 #include "Mutex.h"
00043 #include "Utility.h"
00044 #include "SocketAddress.h"
00045 
00046 #ifdef SOCKETS_NAMESPACE
00047 namespace SOCKETS_NAMESPACE {
00048 #endif
00049 
00050 
00051 #ifdef _DEBUG
00052 #define DEB(x) x; fflush(stderr);
00053 #else
00054 #define DEB(x) 
00055 #endif
00056 
00057 
00058 SocketHandler::SocketHandler(StdLog *p)
00059 :ISocketHandler(p)
00060 ,m_maxsock(0)
00061 ,m_preverror(-1)
00062 ,m_errcnt(0)
00063 #ifdef ENABLE_SOCKS4
00064 ,m_socks4_host(0)
00065 ,m_socks4_port(0)
00066 ,m_bTryDirect(false)
00067 #endif
00068 #ifdef ENABLE_RESOLVER
00069 ,m_resolv_id(0)
00070 ,m_resolver(NULL)
00071 #endif
00072 #ifdef ENABLE_POOL
00073 ,m_b_enable_pool(false)
00074 #endif
00075 {
00076         FD_ZERO(&m_rfds);
00077         FD_ZERO(&m_wfds);
00078         FD_ZERO(&m_efds);
00079 }
00080 
00081 
00082 SocketHandler::SocketHandler(Mutex& mutex,StdLog *p)
00083 :ISocketHandler(mutex, p)
00084 ,m_maxsock(0)
00085 ,m_preverror(-1)
00086 ,m_errcnt(0)
00087 #ifdef ENABLE_SOCKS4
00088 ,m_socks4_host(0)
00089 ,m_socks4_port(0)
00090 ,m_bTryDirect(false)
00091 #endif
00092 #ifdef ENABLE_RESOLVER
00093 ,m_resolv_id(0)
00094 ,m_resolver(NULL)
00095 #endif
00096 #ifdef ENABLE_POOL
00097 ,m_b_enable_pool(false)
00098 #endif
00099 {
00100         m_mutex.Lock();
00101         FD_ZERO(&m_rfds);
00102         FD_ZERO(&m_wfds);
00103         FD_ZERO(&m_efds);
00104 }
00105 
00106 
00107 SocketHandler::~SocketHandler()
00108 {
00109 #ifdef ENABLE_RESOLVER
00110         if (m_resolver)
00111         {
00112                 m_resolver -> Quit();
00113         }
00114 #endif
00115         {
00116                 while (m_sockets.size())
00117                 {
00118 DEB(                    fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", m_sockets.size());)
00119                         socket_m::iterator it = m_sockets.begin();
00120                         Socket *p = it -> second;
00121                         if (p)
00122                         {
00123 DEB(                            fprintf(stderr, "  fd %d\n", p -> GetSocket());)
00124                                 p -> Close();
00125 DEB(                            fprintf(stderr, "  fd closed %d\n", p -> GetSocket());)
00126 //                              p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!!
00127                                 // MinionSocket breaks, calling MinderHandler methods in OnDelete -
00128                                 // MinderHandler is already gone when that happens...
00129 
00130                                 // only delete socket when controlled
00131                                 // ie master sockethandler can delete non-detached sockets
00132                                 // and a slave sockethandler can only delete a detach socket
00133                                 if (p -> DeleteByHandler()
00134 #ifdef ENABLE_DETACH
00135                                         && !(m_slave ^ p -> IsDetached()) 
00136 #endif
00137                                         )
00138                                 {
00139                                         p -> SetErasedByHandler();
00140                                         delete p;
00141                                 }
00142                                 m_sockets.erase(it);
00143                         }
00144                         else
00145                         {
00146                                 m_sockets.erase(it);
00147                         }
00148 DEB(                    fprintf(stderr, "next\n");)
00149                 }
00150 DEB(            fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", m_sockets.size());)
00151         }
00152 #ifdef ENABLE_RESOLVER
00153         if (m_resolver)
00154         {
00155                 delete m_resolver;
00156         }
00157 #endif
00158         if (m_b_use_mutex)
00159         {
00160                 m_mutex.Unlock();
00161         }
00162 }
00163 
00164 
00165 void SocketHandler::Add(Socket *p)
00166 {
00167         if (p -> GetSocket() == INVALID_SOCKET)
00168         {
00169                 LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING);
00170                 if (p -> CloseAndDelete())
00171                 {
00172                         m_delete.push_back(p);
00173                 }
00174                 return;
00175         }
00176         if (m_add.find(p -> GetSocket()) != m_add.end())
00177         {
00178                 LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL);
00179                 m_delete.push_back(p);
00180                 return;
00181         }
00182         m_add[p -> GetSocket()] = p;
00183 }
00184 
00185 
00186 void SocketHandler::Get(SOCKET s,bool& r,bool& w,bool& e)
00187 {
00188         if (s >= 0)
00189         {
00190                 r = FD_ISSET(s, &m_rfds) ? true : false;
00191                 w = FD_ISSET(s, &m_wfds) ? true : false;
00192                 e = FD_ISSET(s, &m_efds) ? true : false;
00193         }
00194 }
00195 
00196 
00197 void SocketHandler::Set(SOCKET s,bool bRead,bool bWrite,bool bException)
00198 {
00199 DEB(fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");)
00200         if (s >= 0)
00201         {
00202                 if (bRead)
00203                 {
00204                         if (!FD_ISSET(s, &m_rfds))
00205                         {
00206                                 FD_SET(s, &m_rfds);
00207                         }
00208                 }
00209                 else
00210                 {
00211                         FD_CLR(s, &m_rfds);
00212                 }
00213                 if (bWrite)
00214                 {
00215                         if (!FD_ISSET(s, &m_wfds))
00216                         {
00217                                 FD_SET(s, &m_wfds);
00218                         }
00219                 }
00220                 else
00221                 {
00222                         FD_CLR(s, &m_wfds);
00223                 }
00224                 if (bException)
00225                 {
00226                         if (!FD_ISSET(s, &m_efds))
00227                         {
00228                                 FD_SET(s, &m_efds);
00229                         }
00230                 }
00231                 else
00232                 {
00233                         FD_CLR(s, &m_efds);
00234                 }
00235         }
00236 }
00237 
00238 
00239 int SocketHandler::Select(long sec,long usec)
00240 {
00241         struct timeval tv;
00242         tv.tv_sec = sec;
00243         tv.tv_usec = usec;
00244         return Select(&tv);
00245 }
00246 
00247 
00248 int SocketHandler::Select()
00249 {
00250         if (m_fds_callonconnect.size() ||
00251 #ifdef ENABLE_DETACH
00252                 (!m_slave && m_fds_detach.size()) ||
00253 #endif
00254                 m_fds_connecting.size() ||
00255                 m_fds_retry.size() ||
00256                 m_fds_close.size() ||
00257                 m_fds_erase.size())
00258         {
00259                 return Select(0, 200000);
00260         }
00261         return Select(NULL);
00262 }
00263 
00264 
00265 int SocketHandler::Select(struct timeval *tsel)
00266 {
00267         size_t ignore = 0;
00268         while (m_add.size() > ignore)
00269         {
00270                 if (m_sockets.size() >= FD_SETSIZE)
00271                 {
00272                         LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING);
00273                         break;
00274                 }
00275                 socket_m::iterator it = m_add.begin();
00276                 SOCKET s = it -> first;
00277                 Socket *p = it -> second;
00278 DEB(fprintf(stderr, "Trying to add fd %d,  m_add.size() %d,  ignore %d\n", s, m_add.size(), ignore);)
00279                 //
00280                 if (m_sockets.find(p -> GetSocket()) != m_sockets.end())
00281                 {
00282                         LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL);
00283                         // %! it's a dup, don't add to delete queue, just ignore it
00284 //                      m_delete.push_back(p);
00285 //                      m_add.erase(it);
00286                         ignore++;
00287                         continue;
00288                 }
00289                 if (!p -> CloseAndDelete())
00290                 {
00291                         if (p -> Connecting()) // 'Open' called before adding socket
00292                         {
00293                                 Set(s,false,true);
00294                         }
00295                         else
00296                         {
00297                                 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00298                                 bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false;
00299                                 if (p -> IsDisableRead())
00300                                 {
00301                                         Set(s, false, bWrite);
00302                                 }
00303                                 else
00304                                 {
00305                                         Set(s, true, bWrite);
00306                                 }
00307                         }
00308                         m_maxsock = (s > m_maxsock) ? s : m_maxsock;
00309                 }
00310                 else
00311                 {
00312                         LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING);
00313                 }
00314                 // only add to m_fds (process fd_set events) if
00315                 //  slave handler and detached/detaching socket
00316                 //  master handler and non-detached socket
00317 #ifdef ENABLE_DETACH
00318                 if (!(m_slave ^ p -> IsDetach()))
00319 #endif
00320                 {
00321                         m_fds.push_back(s);
00322                 }
00323                 m_sockets[s] = p;
00324                 //
00325                 m_add.erase(it);
00326         }
00327 #ifdef MACOSX
00328         fd_set rfds;
00329         fd_set wfds;
00330         fd_set efds;
00331         FD_COPY(&m_rfds, &rfds);
00332         FD_COPY(&m_wfds, &wfds);
00333         FD_COPY(&m_efds, &efds);
00334 #else
00335         fd_set rfds = m_rfds;
00336         fd_set wfds = m_wfds;
00337         fd_set efds = m_efds;
00338 #endif
00339         int n;
00340         if (m_b_use_mutex)
00341         {
00342                 m_mutex.Unlock();
00343                 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
00344                 m_mutex.Lock();
00345         }
00346         else
00347         {
00348                 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
00349         }
00350         if (n == -1)
00351         {
00352                 /*
00353                         EBADF  An invalid file descriptor was given in one of the sets.
00354                         EINTR  A non blocked signal was caught.
00355                         EINVAL n is negative. Or struct timeval contains bad time values (<0).
00356                         ENOMEM select was unable to allocate memory for internal tables.
00357                 */
00358                 if (Errno != m_preverror || m_errcnt++ % 10000 == 0)
00359                 {
00360                         LogError(NULL, "select", Errno, StrError(Errno));
00361 DEB(                    fprintf(stderr, "m_maxsock: %d\n", m_maxsock);
00362                         fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" :
00363                                 Errno == EINTR ? "EINTR" :
00364                                 Errno == EBADF ? "EBADF" :
00365                                 Errno == ENOMEM ? "ENOMEM" : "<another>");
00366                         // test bad fd
00367                         for (SOCKET i = 0; i <= m_maxsock; i++)
00368                         {
00369                                 bool t = false;
00370                                 FD_ZERO(&rfds);
00371                                 FD_ZERO(&wfds);
00372                                 FD_ZERO(&efds);
00373                                 if (FD_ISSET(i, &m_rfds))
00374                                 {
00375                                         FD_SET(i, &rfds);
00376                                         t = true;
00377                                 }
00378                                 if (FD_ISSET(i, &m_wfds))
00379                                 {
00380                                         FD_SET(i, &wfds);
00381                                         t = true;
00382                                 }
00383                                 if (FD_ISSET(i, &m_efds))
00384                                 {
00385                                         FD_SET(i, &efds);
00386                                         t = true;
00387                                 }
00388                                 if (t && m_sockets.find(i) == m_sockets.end())
00389                                 {
00390                                         fprintf(stderr, "Bad fd in fd_set: %d\n", i);
00391                                 }
00392                         }
00393 ) // DEB
00394                         m_preverror = Errno;
00395                 }
00397         }
00398         else
00399         if (!n)
00400         {
00401                 m_preverror = -1;
00402         }
00403         else
00404         if (n > 0)
00405         {
00406                 for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++)
00407                 {
00408                         SOCKET i = *it2;
00409                         if (FD_ISSET(i, &rfds))
00410                         {
00411                                 socket_m::iterator itmp = m_sockets.find(i);
00412                                 if (itmp != m_sockets.end()) // found
00413                                 {
00414                                         Socket *p = itmp -> second;
00415                                         // new SSL negotiate method
00416 #ifdef HAVE_OPENSSL
00417                                         if (p -> IsSSLNegotiate())
00418                                         {
00419                                                 p -> SSLNegotiate();
00420                                         }
00421                                         else
00422 #endif
00423                                         {
00424                                                 p -> OnRead();
00425                                         }
00426                                 }
00427                                 else
00428                                 {
00429                                         LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00430                                 }
00431                                 n--;
00432                         }
00433                         if (FD_ISSET(i, &wfds))
00434                         {
00435                                 socket_m::iterator itmp = m_sockets.find(i);
00436                                 if (itmp != m_sockets.end()) // found
00437                                 {
00438                                         Socket *p = itmp -> second;
00439                                         // new SSL negotiate method
00440 #ifdef HAVE_OPENSSL
00441                                         if (p -> IsSSLNegotiate())
00442                                         {
00443                                                 p -> SSLNegotiate();
00444                                         }
00445                                         else
00446 #endif
00447                                         {
00448                                                 p -> OnWrite();
00449                                         }
00450                                 }
00451                                 else
00452                                 {
00453                                         LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00454                                 }
00455                                 n--;
00456                         }
00457                         if (FD_ISSET(i, &efds))
00458                         {
00459                                 socket_m::iterator itmp = m_sockets.find(i);
00460                                 if (itmp != m_sockets.end()) // found
00461                                 {
00462                                         Socket *p = itmp -> second;
00463                                         p -> OnException();
00464                                 }
00465                                 else
00466                                 {
00467                                         LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00468                                 }
00469                                 n--;
00470                         }
00471                 } // m_fds loop
00472                 m_preverror = -1;
00473         } // if (n > 0)
00474 
00475         // check CallOnConnect
00476         if (m_fds_callonconnect.size())
00477         {
00478                 socket_v tmp = m_fds_callonconnect;
00479                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00480                 {
00481                         Socket *p = NULL;
00482                         {
00483                                 socket_m::iterator itmp = m_sockets.find(*it);
00484                                 if (itmp != m_sockets.end()) // found
00485                                 {
00486                                         p = itmp -> second;
00487                                 }
00488                                 else
00489                                 {
00490                                         LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00491                                 }
00492                         }
00493                         if (p)
00494                         {
00495                                 if (p -> CallOnConnect() && p -> Ready() )
00496                                 {
00497                                         p -> SetConnected(); // moved here from inside if (tcp) check below
00498 #ifdef HAVE_OPENSSL
00499                                         if (p -> IsSSL()) // SSL Enabled socket
00500                                                 p -> OnSSLConnect();
00501                                         else
00502 #endif
00503 #ifdef ENABLE_SOCKS4
00504                                         if (p -> Socks4())
00505                                                 p -> OnSocks4Connect();
00506                                         else
00507 #endif
00508                                         {
00509                                                 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00510                                                 if (tcp)
00511                                                 {
00512                                                         if (tcp -> GetOutputLength())
00513                                                         {
00514                                                                 p -> OnWrite();
00515                                                         }
00516                                                 }
00517 #ifdef ENABLE_RECONNECT
00518                                                 if (tcp && tcp -> IsReconnect())
00519                                                         p -> OnReconnect();
00520                                                 else
00521 #endif
00522                                                 {
00523 //                                                      LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO);
00524                                                         p -> OnConnect();
00525                                                 }
00526                                         }
00527                                         p -> SetCallOnConnect( false );
00528                                 }
00529                         }
00530                 }
00531         }
00532 #ifdef ENABLE_DETACH
00533         if (!m_slave && m_fds_detach.size())
00534         {
00535                 for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
00536                 {
00537                         Socket *p = NULL;
00538                         {
00539                                 socket_m::iterator itmp = m_sockets.find(*it);
00540                                 if (itmp != m_sockets.end()) // found
00541                                 {
00542                                         p = itmp -> second;
00543                                 }
00544                                 else
00545                                 {
00546                                         LogError(NULL, "GetSocket/handler/5", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00547                                 }
00548                         }
00549                         if (p)
00550                         {
00551                                 if (p -> IsDetach())
00552                                 {
00553                                         Set(p -> GetSocket(), false, false, false);
00554                                         // After DetachSocket(), all calls to Handler() will return a reference
00555                                         // to the new slave SocketHandler running in the new thread.
00556                                         p -> DetachSocket();
00557                                         // Adding the file descriptor to m_fds_erase will now also remove the
00558                                         // socket from the detach queue - tnx knightmad
00559                                         m_fds_erase.push_back(p -> GetSocket());
00560                                 }
00561                         }
00562                 }
00563         }
00564 #endif
00565         // check Connecting - connection timeout
00566         if (m_fds_connecting.size())
00567         {
00568                 socket_v tmp = m_fds_connecting;
00569                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00570                 {
00571                         Socket *p = NULL;
00572                         {
00573                                 socket_m::iterator itmp = m_sockets.find(*it);
00574                                 if (itmp != m_sockets.end()) // found
00575                                 {
00576                                         p = itmp -> second;
00577                                 }
00578                                 else
00579                                 {
00580                                         itmp = m_add.find(*it);
00581                                         if (itmp != m_add.end())
00582                                         {
00583                                                 p = itmp -> second;
00584                                         }
00585                                         else
00586                                         {
00587                                                 LogError(NULL, "GetSocket/handler/6", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00588                                         }
00589                                 }
00590                         }
00591                         if (p)
00592                         {
00593                                 if (p -> Connecting() && p -> GetConnectTime() >= p -> GetConnectTimeout() )
00594                                 {
00595                                         LogError(p, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
00596 #ifdef ENABLE_SOCKS4
00597                                         if (p -> Socks4())
00598                                         {
00599                                                 p -> OnSocks4ConnectFailed();
00600                                                 // retry direct connection
00601                                         }
00602                                         else
00603 #endif
00604                                         if (p -> GetConnectionRetry() == -1 ||
00605                                                 (p -> GetConnectionRetry() && p -> GetConnectionRetries() < p -> GetConnectionRetry()) )
00606                                         {
00607                                                 p -> IncreaseConnectionRetries();
00608                                                 // ask socket via OnConnectRetry callback if we should continue trying
00609                                                 if (p -> OnConnectRetry())
00610                                                 {
00611                                                         p -> SetRetryClientConnect();
00612                                                 }
00613                                                 else
00614                                                 {
00615                                                         p -> SetCloseAndDelete( true );
00617                                                         p -> OnConnectFailed();
00618                                                 }
00619                                         }
00620                                         else
00621                                         {
00622                                                 p -> SetCloseAndDelete(true);
00624                                                 p -> OnConnectFailed();
00625                                         }
00626                                         //
00627                                         p -> SetConnecting(false);
00628                                 }
00629                         }
00630                 }
00631         }
00632         // check retry client connect
00633         if (m_fds_retry.size())
00634         {
00635                 socket_v tmp = m_fds_retry;
00636                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00637                 {
00638                         Socket *p = NULL;
00639                         {
00640                                 socket_m::iterator itmp = m_sockets.find(*it);
00641                                 if (itmp != m_sockets.end()) // found
00642                                 {
00643                                         p = itmp -> second;
00644                                 }
00645                                 else
00646                                 {
00647                                         LogError(NULL, "GetSocket/handler/7", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00648                                 }
00649                         }
00650                         if (p)
00651                         {
00652                                 if (p -> RetryClientConnect())
00653                                 {
00654                                         TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00655                                         SOCKET nn = *it; //(*it3).first;
00656                                         p -> SetRetryClientConnect(false);
00657 DEB(    fprintf(stderr, "Close() before retry client connect\n");)
00658                                         p -> Close(); // removes from m_fds_retry
00659                                         std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
00660                                         if (ad.get())
00661                                         {
00662                                                 tcp -> Open(*ad);
00663                                         }
00664                                         else
00665                                         {
00666                                                 LogError(p, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR);
00667                                         }
00668                                         Add(p);
00669                                         m_fds_erase.push_back(nn);
00670                                 }
00671                         }
00672                 }
00673         }
00674         // check close and delete
00675         if (m_fds_close.size())
00676         {
00677                 socket_v tmp = m_fds_close;
00678 DEB(fprintf(stderr, "m_fds_close.size() == %d\n", m_fds_close.size());)
00679                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00680                 {
00681                         Socket *p = NULL;
00682                         {
00683                                 socket_m::iterator itmp = m_sockets.find(*it);
00684                                 if (itmp != m_sockets.end()) // found
00685                                 {
00686                                         p = itmp -> second;
00687                                 }
00688                                 else
00689                                 {
00690                                         itmp = m_add.find(*it);
00691                                         if (itmp != m_add.end())
00692                                         {
00693                                                 p = itmp -> second;
00694                                         }
00695                                         else
00696                                         {
00697                                                 LogError(NULL, "GetSocket/handler/8", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00698                                         }
00699                                 }
00700                         }
00701                         if (p)
00702                         {
00703                                 if (p -> CloseAndDelete() )
00704                                 {
00705                                         TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00706                                         // new graceful tcp - flush and close timeout 5s
00707                                         if (tcp && p -> IsConnected() && tcp -> GetFlushBeforeClose() && 
00708 #ifdef HAVE_OPENSSL
00709                                                 !tcp -> IsSSL() && 
00710 #endif
00711                                                 p -> TimeSinceClose() < 5)
00712                                         {
00713 DEB(fprintf(stderr, " close(1)\n");)
00714                                                 if (tcp -> GetOutputLength())
00715                                                 {
00716                                                         LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Sending all data before closing", LOG_LEVEL_INFO);
00717                                                 }
00718                                                 else // shutdown write when output buffer is empty
00719                                                 if (!(p -> GetShutdown() & SHUT_WR))
00720                                                 {
00721                                                         SOCKET nn = *it;
00722                                                         if (nn != INVALID_SOCKET && shutdown(nn, SHUT_WR) == -1)
00723                                                         {
00724                                                                 LogError(p, "graceful shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00725                                                         }
00726                                                         p -> SetShutdown(SHUT_WR);
00727                                                 }
00728                                         }
00729                                         else
00730 #ifdef ENABLE_RECONNECT
00731                                         if (tcp && p -> IsConnected() && tcp -> Reconnect())
00732                                         {
00733                                                 SOCKET nn = *it; //(*it3).first;
00734 DEB(fprintf(stderr, " close(2) fd %d\n", nn);)
00735                                                 p -> SetCloseAndDelete(false);
00736                                                 tcp -> SetIsReconnect();
00737                                                 p -> SetConnected(false);
00738 DEB(    fprintf(stderr, "Close() before reconnect\n");)
00739                                                 p -> Close(); // dispose of old file descriptor (Open creates a new)
00740                                                 p -> OnDisconnect();
00741                                                 std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
00742                                                 if (ad.get())
00743                                                 {
00744                                                         tcp -> Open(*ad);
00745                                                 }
00746                                                 else
00747                                                 {
00748                                                         LogError(p, "Reconnect", 0, "no address", LOG_LEVEL_ERROR);
00749                                                 }
00750                                                 tcp -> ResetConnectionRetries();
00751                                                 Add(p);
00752                                                 m_fds_erase.push_back(nn);
00753                                         }
00754                                         else
00755 #endif
00756                                         {
00757                                                 SOCKET nn = *it; //(*it3).first;
00758 DEB(fprintf(stderr, " close(3) fd %d GetSocket() %d\n", nn, p -> GetSocket());)
00759                                                 if (tcp && p -> IsConnected() && tcp -> GetOutputLength())
00760                                                 {
00761                                                         LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Closing socket while data still left to send", LOG_LEVEL_WARNING);
00762                                                 }
00763 #ifdef ENABLE_POOL
00764                                                 if (p -> Retain() && !p -> Lost())
00765                                                 {
00766                                                         PoolSocket *p2 = new PoolSocket(*this, p);
00767                                                         p2 -> SetDeleteByHandler();
00768                                                         Add(p2);
00769                                                         //
00770                                                         p -> SetCloseAndDelete(false); // added - remove from m_fds_close
00771                                                 }
00772                                                 else
00773 #endif // ENABLE_POOL
00774                                                 {
00775                                                         Set(p -> GetSocket(),false,false,false);
00776 DEB(    fprintf(stderr, "Close() before OnDelete\n");)
00777                                                         p -> Close();
00778                                                 }
00779                                                 p -> OnDelete();
00780                                                 if (p -> DeleteByHandler())
00781                                                 {
00782                                                         p -> SetErasedByHandler();
00783                                                 }
00784                                                 m_fds_erase.push_back(nn);
00785                                         }
00786                                 }
00787                         }
00788                 }
00789         }
00790 
00791         // check erased sockets
00792         bool check_max_fd = false;
00793         while (m_fds_erase.size())
00794         {
00795                 socket_v::iterator it = m_fds_erase.begin();
00796                 SOCKET nn = *it;
00797 #ifdef ENABLE_DETACH
00798                 {
00799                         for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
00800                         {
00801                                 if (*it == nn)
00802                                 {
00803                                         m_fds_detach.erase(it);
00804                                         break;
00805                                 }
00806                         }
00807                 }
00808 #endif
00809                 {
00810                         for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
00811                         {
00812                                 if (*it == nn)
00813                                 {
00814                                         m_fds.erase(it);
00815                                         break;
00816                                 }
00817                         }
00818                 }
00819                 {
00820                         socket_m::iterator it = m_sockets.find(nn);
00821                         if (it != m_sockets.end())
00822                         {
00823                                 Socket *p = it -> second;
00824                                 /* Sometimes a SocketThread class can finish its run before the master
00825                                    sockethandler gets here. In that case, the SocketThread has set the
00826                                    'ErasedByHandler' flag on the socket which will make us end up with a
00827                                    double delete on the socket instance. 
00828                                    The fix is to make sure that the master sockethandler only can delete
00829                                    non-detached sockets, and a slave sockethandler only can delete
00830                                    detach sockets. */
00831                                 if (p -> ErasedByHandler()
00832 #ifdef ENABLE_DETACH
00833                                         && !(m_slave ^ p -> IsDetached()) 
00834 #endif
00835                                         )
00836                                 {
00837                                         delete p;
00838                                 }
00839                                 m_sockets.erase(it);
00840                         }
00841                 }
00842                 m_fds_erase.erase(it);
00843                 check_max_fd = true;
00844         }
00845         // calculate max file descriptor for select() call
00846         if (check_max_fd)
00847         {
00848                 m_maxsock = 0;
00849                 for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
00850                 {
00851                         SOCKET s = *it;
00852                         m_maxsock = s > m_maxsock ? s : m_maxsock;
00853                 }
00854         }
00855         // remove Add's that fizzed
00856         while (m_delete.size())
00857         {
00858                 std::list<Socket *>::iterator it = m_delete.begin();
00859                 Socket *p = *it;
00860                 p -> OnDelete();
00861                 m_delete.erase(it);
00862                 if (p -> DeleteByHandler()
00863 #ifdef ENABLE_DETACH
00864                         && !(m_slave ^ p -> IsDetached()) 
00865 #endif
00866                         )
00867                 {
00868                         p -> SetErasedByHandler();
00869                         delete p;
00870                 }
00871         }
00872         return n;
00873 }
00874 
00875 
00876 bool SocketHandler::Valid(Socket *p0)
00877 {
00878         for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
00879         {
00880                 Socket *p = it -> second;
00881                 if (p0 == p)
00882                         return true;
00883         }
00884         return false;
00885 }
00886 
00887 
00888 bool SocketHandler::OkToAccept(Socket *)
00889 {
00890         return true;
00891 }
00892 
00893 
00894 size_t SocketHandler::GetCount()
00895 {
00896         return m_sockets.size() + m_add.size() + m_delete.size();
00897 }
00898 
00899 
00900 #ifdef ENABLE_SOCKS4
00901 void SocketHandler::SetSocks4Host(ipaddr_t a)
00902 {
00903         m_socks4_host = a;
00904 }
00905 
00906 
00907 void SocketHandler::SetSocks4Host(const std::string& host)
00908 {
00909         Utility::u2ip(host, m_socks4_host);
00910 }
00911 
00912 
00913 void SocketHandler::SetSocks4Port(port_t port)
00914 {
00915         m_socks4_port = port;
00916 }
00917 
00918 
00919 void SocketHandler::SetSocks4Userid(const std::string& id)
00920 {
00921         m_socks4_userid = id;
00922 }
00923 #endif
00924 
00925 
00926 #ifdef ENABLE_RESOLVER
00927 int SocketHandler::Resolve(Socket *p,const std::string& host,port_t port)
00928 {
00929         // check cache
00930         ResolvSocket *resolv = new ResolvSocket(*this, p);
00931         resolv -> SetId(++m_resolv_id);
00932         resolv -> SetHost(host);
00933         resolv -> SetPort(port);
00934         resolv -> SetDeleteByHandler();
00935         ipaddr_t local;
00936         Utility::u2ip("127.0.0.1", local);
00937         if (!resolv -> Open(local, m_resolver_port))
00938         {
00939                 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
00940         }
00941         Add(resolv);
00942         return m_resolv_id;
00943 }
00944 
00945 
00946 #ifdef ENABLE_IPV6
00947 int SocketHandler::Resolve6(Socket *p,const std::string& host,port_t port)
00948 {
00949         // check cache
00950         ResolvSocket *resolv = new ResolvSocket(*this, p);
00951         resolv -> SetId(++m_resolv_id);
00952         resolv -> SetHost(host);
00953         resolv -> SetPort(port);
00954         resolv -> SetResolveIpv6();
00955         resolv -> SetDeleteByHandler();
00956         ipaddr_t local;
00957         Utility::u2ip("127.0.0.1", local);
00958         if (!resolv -> Open(local, m_resolver_port))
00959         {
00960                 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
00961         }
00962         Add(resolv);
00963         return m_resolv_id;
00964 }
00965 #endif
00966 
00967 
00968 int SocketHandler::Resolve(Socket *p,ipaddr_t a)
00969 {
00970         // check cache
00971         ResolvSocket *resolv = new ResolvSocket(*this, p);
00972         resolv -> SetId(++m_resolv_id);
00973         resolv -> SetAddress(a);
00974         resolv -> SetDeleteByHandler();
00975         ipaddr_t local;
00976         Utility::u2ip("127.0.0.1", local);
00977         if (!resolv -> Open(local, m_resolver_port))
00978         {
00979                 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
00980         }
00981         Add(resolv);
00982         return m_resolv_id;
00983 }
00984 
00985 
00986 #ifdef ENABLE_IPV6
00987 int SocketHandler::Resolve(Socket *p,in6_addr& a)
00988 {
00989         // check cache
00990         ResolvSocket *resolv = new ResolvSocket(*this, p);
00991         resolv -> SetId(++m_resolv_id);
00992         resolv -> SetAddress(a);
00993         resolv -> SetDeleteByHandler();
00994         ipaddr_t local;
00995         Utility::u2ip("127.0.0.1", local);
00996         if (!resolv -> Open(local, m_resolver_port))
00997         {
00998                 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
00999         }
01000         Add(resolv);
01001         return m_resolv_id;
01002 }
01003 #endif
01004 
01005 
01006 void SocketHandler::EnableResolver(port_t port)
01007 {
01008         if (!m_resolver)
01009         {
01010                 m_resolver_port = port;
01011                 m_resolver = new ResolvServer(port);
01012         }
01013 }
01014 
01015 
01016 bool SocketHandler::ResolverReady()
01017 {
01018         return m_resolver ? m_resolver -> Ready() : false;
01019 }
01020 #endif
01021 
01022 
01023 #ifdef ENABLE_SOCKS4
01024 void SocketHandler::SetSocks4TryDirect(bool x)
01025 {
01026         m_bTryDirect = x;
01027 }
01028 
01029 
01030 ipaddr_t SocketHandler::GetSocks4Host()
01031 {
01032         return m_socks4_host;
01033 }
01034 
01035 
01036 port_t SocketHandler::GetSocks4Port()
01037 {
01038         return m_socks4_port;
01039 }
01040 
01041 
01042 const std::string& SocketHandler::GetSocks4Userid()
01043 {
01044         return m_socks4_userid;
01045 }
01046 
01047 
01048 bool SocketHandler::Socks4TryDirect()
01049 {
01050         return m_bTryDirect;
01051 }
01052 #endif
01053 
01054 
01055 #ifdef ENABLE_RESOLVER
01056 bool SocketHandler::ResolverEnabled() 
01057 { 
01058         return m_resolver ? true : false; 
01059 }
01060 
01061 
01062 port_t SocketHandler::GetResolverPort() 
01063 { 
01064         return m_resolver_port; 
01065 }
01066 #endif
01067 
01068 
01069 #ifdef ENABLE_POOL
01070 ISocketHandler::PoolSocket *SocketHandler::FindConnection(int type,const std::string& protocol,SocketAddress& ad)
01071 {
01072         for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end() && m_sockets.size(); it++)
01073         {
01074                 PoolSocket *pools = dynamic_cast<PoolSocket *>(it -> second);
01075                 if (pools)
01076                 {
01077                         if (pools -> GetSocketType() == type &&
01078                             pools -> GetSocketProtocol() == protocol &&
01079 // %!                       pools -> GetClientRemoteAddress() &&
01080                             *pools -> GetClientRemoteAddress() == ad)
01081                         {
01082                                 m_sockets.erase(it);
01083                                 pools -> SetRetain(); // avoid Close in Socket destructor
01084                                 return pools; // Caller is responsible that this socket is deleted
01085                         }
01086                 }
01087         }
01088         return NULL;
01089 }
01090 
01091 
01092 void SocketHandler::EnablePool(bool x)
01093 {
01094         m_b_enable_pool = x;
01095 }
01096 
01097 
01098 bool SocketHandler::PoolEnabled() 
01099 { 
01100         return m_b_enable_pool; 
01101 }
01102 #endif
01103 
01104 
01105 void SocketHandler::Remove(Socket *p)
01106 {
01107         if (p -> ErasedByHandler())
01108         {
01109                 return;
01110         }
01111         for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
01112         {
01113                 if (it -> second == p)
01114                 {
01115                         LogError(p, "Remove", -1, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
01116                         m_sockets.erase(it);
01117                         return;
01118                 }
01119         }
01120         for (socket_m::iterator it2 = m_add.begin(); it2 != m_add.end(); it2++)
01121         {
01122                 if ((*it2).second == p)
01123                 {
01124                         LogError(p, "Remove", -2, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
01125                         m_add.erase(it2);
01126                         return;
01127                 }
01128         }
01129         for (std::list<Socket *>::iterator it3 = m_delete.begin(); it3 != m_delete.end(); it3++)
01130         {
01131                 if (*it3 == p)
01132                 {
01133                         LogError(p, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
01134                         m_delete.erase(it3);
01135                         return;
01136                 }
01137         }
01138 }
01139 
01140 
01141 void SocketHandler::CheckSanity()
01142 {
01143         CheckList(m_fds, "active sockets"); // active sockets
01144         CheckList(m_fds_erase, "sockets to be erased"); // should always be empty anyway
01145         CheckList(m_fds_callonconnect, "checklist CallOnConnect");
01146 #ifdef ENABLE_DETACH
01147         CheckList(m_fds_detach, "checklist Detach");
01148 #endif
01149         CheckList(m_fds_connecting, "checklist Connecting");
01150         CheckList(m_fds_retry, "checklist retry client connect");
01151         CheckList(m_fds_close, "checklist close and delete");
01152 }
01153 
01154 
01155 void SocketHandler::CheckList(socket_v& ref,const std::string& listname)
01156 {
01157         for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
01158         {
01159                 SOCKET s = *it;
01160                 if (m_sockets.find(s) != m_sockets.end())
01161                         continue;
01162                 if (m_add.find(s) != m_add.end())
01163                         continue;
01164                 bool found = false;
01165                 for (std::list<Socket *>::iterator it = m_delete.begin(); it != m_delete.end(); it++)
01166                 {
01167                         Socket *p = *it;
01168                         if (p -> GetSocket() == s)
01169                         {
01170                                 found = true;
01171                                 break;
01172                         }
01173                 }
01174                 if (!found)
01175                 {
01176                         fprintf(stderr, "CheckList failed for \"%s\": fd %d\n", listname.c_str(), s);
01177                 }
01178         }
01179 }
01180 
01181 
01182 void SocketHandler::AddList(SOCKET s,list_t which_one,bool add)
01183 {
01184         if (s == INVALID_SOCKET)
01185         {
01186                 return;
01187         }
01188         socket_v& ref =
01189                 (which_one == LIST_CALLONCONNECT) ? m_fds_callonconnect :
01190 #ifdef ENABLE_DETACH
01191                 (which_one == LIST_DETACH) ? m_fds_detach :
01192 #endif
01193                 (which_one == LIST_CONNECTING) ? m_fds_connecting :
01194                 (which_one == LIST_RETRY) ? m_fds_retry :
01195                 (which_one == LIST_CLOSE) ? m_fds_close : m_fds_close;
01196 #ifdef ENABLE_DETACH
01197 DEB(
01198 fprintf(stderr, "%5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
01199         (which_one == LIST_DETACH) ? "Detach" :
01200         (which_one == LIST_CONNECTING) ? "Connecting" :
01201         (which_one == LIST_RETRY) ? "Retry" :
01202         (which_one == LIST_CLOSE) ? "Close" : "<undef>",
01203         add ? "Add" : "Remove");
01204 )
01205 #else
01206 DEB(
01207 fprintf(stderr, "%5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
01208         (which_one == LIST_CONNECTING) ? "Connecting" :
01209         (which_one == LIST_RETRY) ? "Retry" :
01210         (which_one == LIST_CLOSE) ? "Close" : "<undef>",
01211         add ? "Add" : "Remove");
01212 )
01213 #endif
01214         if (add)
01215         {
01216                 for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
01217                 {
01218                         if (*it == s)
01219                         {
01220                                 ref.erase(it);
01221                                 break;
01222                         }
01223                 }
01224                 ref.push_back(s);
01225                 return;
01226         }
01227         // remove
01228         for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
01229         {
01230                 if (*it == s)
01231                 {
01232                         ref.erase(it);
01233                         break;
01234                 }
01235         }
01236 DEB(    fprintf(stderr, "/AddList\n");)
01237 }
01238 
01239 
01240 #ifdef SOCKETS_NAMESPACE
01241 }
01242 #endif
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4