Logo
~Sockets~
~Examples~
~Contact~


SocketHandler Class Reference
[Basic sockets]

Socket container class, event generator. More...

#include <SocketHandler.h>

Inheritance diagram for SocketHandler:
Collaboration diagram for SocketHandler:

List of all members.


Public Member Functions

 SocketHandler (StdLog *log=NULL)
 SocketHandler constructor.
 SocketHandler (IMutex &mutex, StdLog *log=NULL)
 SocketHandler threadsafe constructor.
 ~SocketHandler ()
IMutexGetMutex () const
 Get mutex reference for threadsafe operations.
void RegStdLog (StdLog *log)
 Register StdLog object for error callback.
void LogError (Socket *p, const std::string &user_text, int err, const std::string &sys_err, loglevel_t t=LOG_LEVEL_WARNING)
 Log error to log class for print out / storage.
void Add (Socket *)
 Add socket instance to socket map.
void Get (SOCKET s, bool &r, bool &w, bool &e)
 Get status of read/write/exception file descriptor set for a socket.
void Set (SOCKET s, bool bRead, bool bWrite, bool bException=true)
 Set read/write/exception file descriptor sets (fd_set).
int Select (long sec, long usec)
 Wait for events, generate callbacks.
int Select ()
 This method will not return until an event has been detected.
int Select (struct timeval *tsel)
 Wait for events, generate callbacks.
bool Valid (Socket *)
 Check that a socket really is handled by this socket handler.
size_t GetCount ()
 Return number of sockets handled by this handler.
bool OkToAccept (Socket *p)
 Override and return false to deny all incoming connections.
void AddList (SOCKET s, list_t which_one, bool add)
 Called by Socket when a socket changes state.
ISocketHandler::PoolSocketFindConnection (int type, const std::string &protocol, SocketAddress &)
 Find available open connection (used by connection pool).
void EnablePool (bool x=true)
 Enable connection pool (by default disabled).
bool PoolEnabled ()
 Check pool status.
void SetSocks4Host (ipaddr_t)
 Set socks4 server ip that all new tcp sockets should use.
void SetSocks4Host (const std::string &)
 Set socks4 server hostname that all new tcp sockets should use.
void SetSocks4Port (port_t)
 Set socks4 server port number that all new tcp sockets should use.
void SetSocks4Userid (const std::string &)
 Set optional socks4 userid.
void SetSocks4TryDirect (bool x=true)
 If connection to socks4 server fails, immediately try direct connection to final host.
ipaddr_t GetSocks4Host ()
 Get socks4 server ip.
port_t GetSocks4Port ()
 Get socks4 port number.
const std::string & GetSocks4Userid ()
 Get socks4 userid (optional).
bool Socks4TryDirect ()
 Check status of socks4 try direct flag.
void EnableResolver (port_t port=16667)
 Enable asynchronous DNS.
bool ResolverEnabled ()
 Check resolver status.
int Resolve (Socket *, const std::string &host, port_t port)
 Queue a dns request.
int Resolve (Socket *, ipaddr_t a)
 Do a reverse dns lookup.
port_t GetResolverPort ()
 Get listen port of asynchronous dns server.
bool ResolverReady ()
 Resolver thread ready for queries.
bool Resolving (Socket *)
 Returns true if the socket is waiting for a resolve event.
void SetSlave (bool x=true)
 Indicates that the handler runs under SocketThread.
bool IsSlave ()
 Indicates that the handler runs under SocketThread.
void CheckSanity ()
 Sanity check of those accursed lists.

Protected Types

typedef std::map< SOCKET,
Socket * > 
socket_m
 Map type for holding file descriptors/socket object pointers.

Protected Member Functions

void Remove (Socket *)
 Remove socket from socket map, used by Socket class.

Protected Attributes

socket_m m_sockets
 Active sockets map.
socket_m m_add
 Sockets to be added to sockets map.
std::list< Socket * > m_delete
 Sockets to be deleted (failed when Add).
StdLogm_stdlog
 Registered log class, or NULL.
IMutexm_mutex
 Thread safety mutex.
bool m_b_use_mutex
 Mutex correctly initialized.

Private Member Functions

void CheckList (socket_v &, const std::string &)
 Used by CheckSanity.

Private Attributes

SOCKET m_maxsock
 Highest file descriptor + 1 in active sockets list.
fd_set m_rfds
 file descriptor set monitored for read events
fd_set m_wfds
 file descriptor set monitored for write events
fd_set m_efds
 file descriptor set monitored for exceptions
int m_preverror
 debug select() error
int m_errcnt
 debug select() error
time_t m_tlast
 timeout control
socket_v m_fds
 Active file descriptor list.
socket_v m_fds_erase
 File descriptors that are to be erased from m_sockets.
socket_v m_fds_callonconnect
 checklist CallOnConnect
socket_v m_fds_detach
 checklist Detach
socket_v m_fds_timeout
 checklist timeout
socket_v m_fds_retry
 checklist retry client connect
socket_v m_fds_close
 checklist close and delete
ipaddr_t m_socks4_host
 Socks4 server host ip.
port_t m_socks4_port
 Socks4 server port number.
std::string m_socks4_userid
 Socks4 userid.
bool m_bTryDirect
 Try direct connection if socks4 server fails.
int m_resolv_id
 Resolver id counter.
ResolvServerm_resolver
 Resolver thread pointer.
port_t m_resolver_port
 Resolver listen port.
std::map< Socket *, bool > m_resolve_q
 resolve queue
bool m_b_enable_pool
 Connection pool enabled if true.
bool m_slave
 Indicates that this is a ISocketHandler run in SocketThread.

Detailed Description

Socket container class, event generator.

Definition at line 53 of file SocketHandler.h.


Member Typedef Documentation

typedef std::map<SOCKET,Socket *> SocketHandler::socket_m [protected]

Map type for holding file descriptors/socket object pointers.

Definition at line 57 of file SocketHandler.h.


Constructor & Destructor Documentation

SocketHandler::SocketHandler ( StdLog log = NULL  ) 

SocketHandler constructor.

Parameters:
log Optional log class pointer

Definition at line 59 of file SocketHandler.cpp.

References m_efds, m_rfds, and m_wfds.

00060 :m_stdlog(p)
00061 ,m_mutex(m_mutex)
00062 ,m_b_use_mutex(false)
00063 ,m_maxsock(0)
00064 ,m_preverror(-1)
00065 ,m_errcnt(0)
00066 ,m_tlast(0)
00067 #ifdef ENABLE_SOCKS4
00068 ,m_socks4_host(0)
00069 ,m_socks4_port(0)
00070 ,m_bTryDirect(false)
00071 #endif
00072 #ifdef ENABLE_RESOLVER
00073 ,m_resolv_id(0)
00074 ,m_resolver(NULL)
00075 #endif
00076 #ifdef ENABLE_POOL
00077 ,m_b_enable_pool(false)
00078 #endif
00079 #ifdef ENABLE_TRIGGERS
00080 ,m_next_trigger_id(0)
00081 #endif
00082 #ifdef ENABLE_DETACH
00083 ,m_slave(false)
00084 #endif
00085 {
00086         FD_ZERO(&m_rfds);
00087         FD_ZERO(&m_wfds);
00088         FD_ZERO(&m_efds);
00089 }

SocketHandler::SocketHandler ( IMutex mutex,
StdLog log = NULL 
)

SocketHandler threadsafe constructor.

Parameters:
mutex Externally declared mutex variable
log Optional log class pointer

Definition at line 92 of file SocketHandler.cpp.

References IMutex::Lock(), m_efds, m_mutex, m_rfds, and m_wfds.

00093 :m_stdlog(p)
00094 ,m_mutex(mutex)
00095 ,m_b_use_mutex(true)
00096 ,m_maxsock(0)
00097 ,m_preverror(-1)
00098 ,m_errcnt(0)
00099 ,m_tlast(0)
00100 #ifdef ENABLE_SOCKS4
00101 ,m_socks4_host(0)
00102 ,m_socks4_port(0)
00103 ,m_bTryDirect(false)
00104 #endif
00105 #ifdef ENABLE_RESOLVER
00106 ,m_resolv_id(0)
00107 ,m_resolver(NULL)
00108 #endif
00109 #ifdef ENABLE_POOL
00110 ,m_b_enable_pool(false)
00111 #endif
00112 #ifdef ENABLE_TRIGGERS
00113 ,m_next_trigger_id(0)
00114 #endif
00115 #ifdef ENABLE_DETACH
00116 ,m_slave(false)
00117 #endif
00118 {
00119         m_mutex.Lock();
00120         FD_ZERO(&m_rfds);
00121         FD_ZERO(&m_wfds);
00122         FD_ZERO(&m_efds);
00123 }

SocketHandler::~SocketHandler (  ) 

Definition at line 126 of file SocketHandler.cpp.

References DEB, ENABLE_DETACH, ENABLE_RESOLVER, m_b_use_mutex, m_mutex, m_resolver, m_slave, m_sockets, and IMutex::Unlock().

00127 {
00128 #ifdef ENABLE_RESOLVER
00129         if (m_resolver)
00130         {
00131                 m_resolver -> Quit();
00132         }
00133 #endif
00134         {
00135                 while (m_sockets.size())
00136                 {
00137 DEB(                    fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());)
00138                         socket_m::iterator it = m_sockets.begin();
00139                         Socket *p = it -> second;
00140                         if (p)
00141                         {
00142 DEB(                            fprintf(stderr, "  fd %d\n", p -> GetSocket());)
00143                                 p -> Close();
00144 DEB(                            fprintf(stderr, "  fd closed %d\n", p -> GetSocket());)
00145 //                              p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!!
00146                                 // MinionSocket breaks, calling MinderHandler methods in OnDelete -
00147                                 // MinderHandler is already gone when that happens...
00148 
00149                                 // only delete socket when controlled
00150                                 // ie master sockethandler can delete non-detached sockets
00151                                 // and a slave sockethandler can only delete a detach socket
00152                                 if (p -> DeleteByHandler()
00153 #ifdef ENABLE_DETACH
00154                                         && !(m_slave ^ p -> IsDetached()) 
00155 #endif
00156                                         )
00157                                 {
00158                                         p -> SetErasedByHandler();
00159                                         delete p;
00160                                 }
00161                                 m_sockets.erase(it);
00162                         }
00163                         else
00164                         {
00165                                 m_sockets.erase(it);
00166                         }
00167 DEB(                    fprintf(stderr, "next\n");)
00168                 }
00169 DEB(            fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());)
00170         }
00171 #ifdef ENABLE_RESOLVER
00172         if (m_resolver)
00173         {
00174                 delete m_resolver;
00175         }
00176 #endif
00177         if (m_b_use_mutex)
00178         {
00179                 m_mutex.Unlock();
00180         }
00181 }


Member Function Documentation

IMutex & SocketHandler::GetMutex (  )  const [virtual]

Get mutex reference for threadsafe operations.

Implements ISocketHandler.

Definition at line 184 of file SocketHandler.cpp.

References m_mutex.

00185 {
00186         return m_mutex; 
00187 }

void SocketHandler::RegStdLog ( StdLog log  )  [virtual]

Register StdLog object for error callback.

Parameters:
log Pointer to log class

Implements ISocketHandler.

Definition at line 204 of file SocketHandler.cpp.

References m_stdlog.

00205 {
00206         m_stdlog = log;
00207 }

void SocketHandler::LogError ( Socket p,
const std::string &  user_text,
int  err,
const std::string &  sys_err,
loglevel_t  t = LOG_LEVEL_WARNING 
) [virtual]

Log error to log class for print out / storage.

Implements ISocketHandler.

Definition at line 210 of file SocketHandler.cpp.

References m_stdlog.

Referenced by Add(), AddList(), Remove(), Resolve(), and Select().

00211 {
00212         if (m_stdlog)
00213         {
00214                 m_stdlog -> error(this, p, user_text, err, sys_err, t);
00215         }
00216 }

void SocketHandler::Add ( Socket p  )  [virtual]

Add socket instance to socket map.

Removal is always automatic.

Implements ISocketHandler.

Reimplemented in EventHandler.

Definition at line 219 of file SocketHandler.cpp.

References INVALID_SOCKET, LOG_LEVEL_FATAL, LOG_LEVEL_WARNING, LogError(), m_add, and m_delete.

Referenced by EventHandler::Add(), Resolve(), Socket::SocketThread::Run(), ResolvServer::Run(), and Select().

00220 {
00221         if (p -> GetSocket() == INVALID_SOCKET)
00222         {
00223                 LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING);
00224                 if (p -> CloseAndDelete())
00225                 {
00226                         m_delete.push_back(p);
00227                 }
00228                 return;
00229         }
00230         if (m_add.find(p -> GetSocket()) != m_add.end())
00231         {
00232                 LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL);
00233                 m_delete.push_back(p);
00234                 return;
00235         }
00236         m_add[p -> GetSocket()] = p;
00237 }

void SocketHandler::Get ( SOCKET  s,
bool &  r,
bool &  w,
bool &  e 
) [virtual]

Get status of read/write/exception file descriptor set for a socket.

Implements ISocketHandler.

Definition at line 240 of file SocketHandler.cpp.

References m_efds, m_rfds, and m_wfds.

00241 {
00242         if (s >= 0)
00243         {
00244                 r = FD_ISSET(s, &m_rfds) ? true : false;
00245                 w = FD_ISSET(s, &m_wfds) ? true : false;
00246                 e = FD_ISSET(s, &m_efds) ? true : false;
00247         }
00248 }

void SocketHandler::Set ( SOCKET  s,
bool  bRead,
bool  bWrite,
bool  bException = true 
) [virtual]

Set read/write/exception file descriptor sets (fd_set).

Implements ISocketHandler.

Definition at line 251 of file SocketHandler.cpp.

References DEB, m_efds, m_rfds, and m_wfds.

Referenced by Select().

00252 {
00253 DEB(    fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");)
00254         if (s >= 0)
00255         {
00256                 if (bRead)
00257                 {
00258                         if (!FD_ISSET(s, &m_rfds))
00259                         {
00260                                 FD_SET(s, &m_rfds);
00261                         }
00262                 }
00263                 else
00264                 {
00265                         FD_CLR(s, &m_rfds);
00266                 }
00267                 if (bWrite)
00268                 {
00269                         if (!FD_ISSET(s, &m_wfds))
00270                         {
00271                                 FD_SET(s, &m_wfds);
00272                         }
00273                 }
00274                 else
00275                 {
00276                         FD_CLR(s, &m_wfds);
00277                 }
00278                 if (bException)
00279                 {
00280                         if (!FD_ISSET(s, &m_efds))
00281                         {
00282                                 FD_SET(s, &m_efds);
00283                         }
00284                 }
00285                 else
00286                 {
00287                         FD_CLR(s, &m_efds);
00288                 }
00289         }
00290 }

int SocketHandler::Select ( long  sec,
long  usec 
) [virtual]

Wait for events, generate callbacks.

Implements ISocketHandler.

Definition at line 293 of file SocketHandler.cpp.

References Select().

Referenced by Socket::SocketThread::Run(), and ResolvServer::Run().

00294 {
00295         struct timeval tv;
00296         tv.tv_sec = sec;
00297         tv.tv_usec = usec;
00298         return Select(&tv);
00299 }

int SocketHandler::Select (  )  [virtual]

This method will not return until an event has been detected.

Implements ISocketHandler.

Definition at line 302 of file SocketHandler.cpp.

References m_fds_callonconnect, m_fds_close, m_fds_detach, m_fds_erase, m_fds_retry, m_fds_timeout, and m_slave.

Referenced by EventHandler::EventLoop(), and Select().

00303 {
00304         if (m_fds_callonconnect.size() ||
00305 #ifdef ENABLE_DETACH
00306                 (!m_slave && m_fds_detach.size()) ||
00307 #endif
00308                 m_fds_timeout.size() ||
00309                 m_fds_retry.size() ||
00310                 m_fds_close.size() ||
00311                 m_fds_erase.size())
00312         {
00313                 return Select(0, 200000);
00314         }
00315         return Select(NULL);
00316 }

int SocketHandler::Select ( struct timeval *  tsel  )  [virtual]

Wait for events, generate callbacks.

Todo:
rebuild fd_set's from active sockets list (m_sockets) here

Implements ISocketHandler.

Definition at line 319 of file SocketHandler.cpp.

References Add(), AddList(), DEB, ENABLE_DETACH, Errno, INVALID_SOCKET, LIST_CALLONCONNECT, IMutex::Lock(), LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LogError(), m_add, m_b_use_mutex, m_delete, m_efds, m_errcnt, m_fds, m_fds_callonconnect, m_fds_close, m_fds_detach, m_fds_erase, m_fds_retry, m_fds_timeout, m_maxsock, m_mutex, m_preverror, m_rfds, m_slave, m_sockets, m_tlast, m_wfds, Set(), StrError, IMutex::Unlock(), and Valid().

00320 {
00321         size_t ignore = 0;
00322         while (m_add.size() > ignore)
00323         {
00324                 if (m_sockets.size() >= FD_SETSIZE)
00325                 {
00326                         LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING);
00327                         break;
00328                 }
00329                 socket_m::iterator it = m_add.begin();
00330                 SOCKET s = it -> first;
00331                 Socket *p = it -> second;
00332 DEB(            fprintf(stderr, "Trying to add fd %d,  m_add.size() %d,  ignore %d\n", (int)s, (int)m_add.size(), (int)ignore);)
00333                 //
00334                 if (m_sockets.find(p -> GetSocket()) != m_sockets.end())
00335                 {
00336                         LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL);
00337                         // %! it's a dup, don't add to delete queue, just ignore it
00338                         m_delete.push_back(p);
00339                         m_add.erase(it);
00340 //                      ignore++;
00341                         continue;
00342                 }
00343                 if (!p -> CloseAndDelete())
00344                 {
00345                         StreamSocket *scp = dynamic_cast<StreamSocket *>(p);
00346                         if (scp && scp -> Connecting()) // 'Open' called before adding socket
00347                         {
00348                                 Set(s,false,true);
00349                         }
00350                         else
00351                         {
00352                                 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00353                                 bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false;
00354                                 if (p -> IsDisableRead())
00355                                 {
00356                                         Set(s, false, bWrite);
00357                                 }
00358                                 else
00359                                 {
00360                                         Set(s, true, bWrite);
00361                                 }
00362                         }
00363                         m_maxsock = (s > m_maxsock) ? s : m_maxsock;
00364                 }
00365                 else
00366                 {
00367                         LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING);
00368                 }
00369                 // only add to m_fds (process fd_set events) if
00370                 //  slave handler and detached/detaching socket
00371                 //  master handler and non-detached socket
00372 #ifdef ENABLE_DETACH
00373                 if (!(m_slave ^ p -> IsDetach()))
00374 #endif
00375                 {
00376                         m_fds.push_back(s);
00377                 }
00378                 m_sockets[s] = p;
00379                 //
00380                 m_add.erase(it);
00381         }
00382 #ifdef MACOSX
00383         fd_set rfds;
00384         fd_set wfds;
00385         fd_set efds;
00386         FD_COPY(&m_rfds, &rfds);
00387         FD_COPY(&m_wfds, &wfds);
00388         FD_COPY(&m_efds, &efds);
00389 #else
00390         fd_set rfds = m_rfds;
00391         fd_set wfds = m_wfds;
00392         fd_set efds = m_efds;
00393 #endif
00394         int n;
00395         if (m_b_use_mutex)
00396         {
00397                 m_mutex.Unlock();
00398                 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
00399                 m_mutex.Lock();
00400         }
00401         else
00402         {
00403                 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
00404         }
00405         if (n == -1)
00406         {
00407                 /*
00408                         EBADF  An invalid file descriptor was given in one of the sets.
00409                         EINTR  A non blocked signal was caught.
00410                         EINVAL n is negative. Or struct timeval contains bad time values (<0).
00411                         ENOMEM select was unable to allocate memory for internal tables.
00412                 */
00413                 if (Errno != m_preverror || m_errcnt++ % 10000 == 0)
00414                 {
00415                         LogError(NULL, "select", Errno, StrError(Errno));
00416 DEB(                    fprintf(stderr, "m_maxsock: %d\n", m_maxsock);
00417                         fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" :
00418                                 Errno == EINTR ? "EINTR" :
00419                                 Errno == EBADF ? "EBADF" :
00420                                 Errno == ENOMEM ? "ENOMEM" : "<another>");
00421                         // test bad fd
00422                         for (SOCKET i = 0; i <= m_maxsock; i++)
00423                         {
00424                                 bool t = false;
00425                                 FD_ZERO(&rfds);
00426                                 FD_ZERO(&wfds);
00427                                 FD_ZERO(&efds);
00428                                 if (FD_ISSET(i, &m_rfds))
00429                                 {
00430                                         FD_SET(i, &rfds);
00431                                         t = true;
00432                                 }
00433                                 if (FD_ISSET(i, &m_wfds))
00434                                 {
00435                                         FD_SET(i, &wfds);
00436                                         t = true;
00437                                 }
00438                                 if (FD_ISSET(i, &m_efds))
00439                                 {
00440                                         FD_SET(i, &efds);
00441                                         t = true;
00442                                 }
00443                                 if (t && m_sockets.find(i) == m_sockets.end())
00444                                 {
00445                                         fprintf(stderr, "Bad fd in fd_set: %d\n", i);
00446                                 }
00447                         }
00448 ) // DEB
00449                         m_preverror = Errno;
00450                 }
00452         }
00453         else
00454         if (!n)
00455         {
00456                 m_preverror = -1;
00457         }
00458         else
00459         if (n > 0)
00460         {
00461                 for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++)
00462                 {
00463                         SOCKET i = *it2;
00464                         if (FD_ISSET(i, &rfds))
00465                         {
00466                                 socket_m::iterator itmp = m_sockets.find(i);
00467                                 if (itmp != m_sockets.end()) // found
00468                                 {
00469                                         Socket *p = itmp -> second;
00470                                         // new SSL negotiate method
00471 #ifdef HAVE_OPENSSL
00472                                         if (p -> IsSSLNegotiate())
00473                                         {
00474                                                 p -> SSLNegotiate();
00475                                         }
00476                                         else
00477 #endif
00478                                         {
00479                                                 p -> OnRead();
00480                                         }
00481                                 }
00482                                 else
00483                                 {
00484                                         LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00485                                 }
00486                                 n--;
00487                         }
00488                         if (FD_ISSET(i, &wfds))
00489                         {
00490                                 socket_m::iterator itmp = m_sockets.find(i);
00491                                 if (itmp != m_sockets.end()) // found
00492                                 {
00493                                         Socket *p = itmp -> second;
00494                                         // new SSL negotiate method
00495 #ifdef HAVE_OPENSSL
00496                                         if (p -> IsSSLNegotiate())
00497                                         {
00498                                                 p -> SSLNegotiate();
00499                                         }
00500                                         else
00501 #endif
00502                                         {
00503                                                 p -> OnWrite();
00504                                         }
00505                                 }
00506                                 else
00507                                 {
00508                                         LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00509                                 }
00510                                 n--;
00511                         }
00512                         if (FD_ISSET(i, &efds))
00513                         {
00514                                 socket_m::iterator itmp = m_sockets.find(i);
00515                                 if (itmp != m_sockets.end()) // found
00516                                 {
00517                                         Socket *p = itmp -> second;
00518                                         p -> OnException();
00519                                 }
00520                                 else
00521                                 {
00522                                         LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00523                                 }
00524                                 n--;
00525                         }
00526                 } // m_fds loop
00527                 m_preverror = -1;
00528         } // if (n > 0)
00529 
00530         // check CallOnConnect - EVENT
00531         if (m_fds_callonconnect.size())
00532         {
00533                 socket_v tmp = m_fds_callonconnect;
00534                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00535                 {
00536                         Socket *p = NULL;
00537                         {
00538                                 socket_m::iterator itmp = m_sockets.find(*it);
00539                                 if (itmp != m_sockets.end()) // found
00540                                 {
00541                                         p = itmp -> second;
00542                                 }
00543                                 else
00544                                 {
00545                                         LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00546                                 }
00547                         }
00548                         if (p)
00549                         {
00550 //                              if (p -> CallOnConnect() && p -> Ready() )
00551                                 {
00552                                         p -> SetConnected(); // moved here from inside if (tcp) check below
00553 #ifdef HAVE_OPENSSL
00554                                         if (p -> IsSSL()) // SSL Enabled socket
00555                                                 p -> OnSSLConnect();
00556                                         else
00557 #endif
00558 #ifdef ENABLE_SOCKS4
00559                                         if (p -> Socks4())
00560                                                 p -> OnSocks4Connect();
00561                                         else
00562 #endif
00563                                         {
00564                                                 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00565                                                 if (tcp)
00566                                                 {
00567                                                         if (tcp -> GetOutputLength())
00568                                                         {
00569                                                                 p -> OnWrite();
00570                                                         }
00571