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