Logo
~Sockets~
~Examples~
~Contact~


SocketHandler Class Reference
[Basic sockets]

Socket container class, event generator. More...

#include <SocketHandler.h>

Inheritance diagram for SocketHandler:

Inheritance graph
[legend]
Collaboration diagram for SocketHandler:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 SocketHandler (StdLog *log=NULL)
 SocketHandler constructor.
 SocketHandler (Mutex &mutex, StdLog *log=NULL)
 SocketHandler threadsafe constructor.
 ~SocketHandler ()
MutexGetMutex () 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.
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 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.
Mutexm_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.
void Remove (Socket *)
 Remove socket from socket map, used by Socket class.

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.
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 55 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 59 of file SocketHandler.h.


Constructor & Destructor Documentation

SocketHandler::SocketHandler ( StdLog log = NULL  ) 

SocketHandler constructor.

Parameters:
log Optional log class pointer

Definition at line 58 of file SocketHandler.cpp.

References m_efds, m_rfds, and m_wfds.

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 }

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

SocketHandler threadsafe constructor.

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

Definition at line 91 of file SocketHandler.cpp.

References Mutex::Lock, m_efds, m_mutex, m_rfds, and m_wfds.

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 }

SocketHandler::~SocketHandler (  ) 

Definition at line 125 of file SocketHandler.cpp.

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

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 }


Member Function Documentation

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

Get mutex reference for threadsafe operations.

Implements ISocketHandler.

Definition at line 183 of file SocketHandler.cpp.

References m_mutex.

00184 {
00185         return m_mutex; 
00186 }

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

Register StdLog object for error callback.

Parameters:
log Pointer to log class

Implements ISocketHandler.

Definition at line 203 of file SocketHandler.cpp.

References m_stdlog.

00204 {
00205         m_stdlog = log;
00206 }

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 209 of file SocketHandler.cpp.

References m_stdlog.

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

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

void SocketHandler::Add ( Socket  )  [virtual]

Add socket instance to socket map.

Removal is always automatic.

Implements ISocketHandler.

Reimplemented in EventHandler.

Definition at line 218 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().

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 }

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 239 of file SocketHandler.cpp.

References m_efds, m_rfds, and m_wfds.

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 }

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 250 of file SocketHandler.cpp.

References DEB, m_efds, m_rfds, and m_wfds.

Referenced by Select().

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 }

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

Wait for events, generate callbacks.

Implements ISocketHandler.

Definition at line 292 of file SocketHandler.cpp.

References Select().

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

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

int SocketHandler::Select (  )  [virtual]

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

Implements ISocketHandler.

Definition at line 301 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().

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 }

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 318 of file SocketHandler.cpp.

References Add(), AddList(), DEB, ENABLE_DETACH, Errno, HAVE_OPENSSL, INVALID_SOCKET, LIST_CALLONCONNECT, Mutex::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, Mutex::Unlock(), and Valid().

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 }

bool SocketHandler::Valid ( Socket  )  [virtual]

Check that a socket really is handled by this socket handler.

Implements ISocketHandler.

Definition at line 966 of file SocketHandler.cpp.

References m_sockets.

Referenced by AddList(), EventHandler::CheckEvents(), and Select().

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 }

size_t SocketHandler::GetCount (  )  [virtual]

Return number of sockets handled by this handler.

Implements ISocketHandler.

Definition at line 984 of file SocketHandler.cpp.

References m_add, m_delete, and m_sockets.

Referenced by Socket::SocketThread::Run().

00985 {
00986         return m_sockets.size() + m_add.size() + m_delete.size();
00987 }

bool SocketHandler::OkToAccept ( Socket p  )  [virtual]

Override and return false to deny all incoming connections.

Parameters:
p ListenSocket class pointer (use GetPort to identify which one)

Implements ISocketHandler.

Definition at line 978 of file SocketHandler.cpp.

00979 {
00980         return true;
00981 }

void SocketHandler::AddList ( SOCKET  s,
list_t  which_one,
bool  add 
) [virtual]

Called by Socket when a socket changes state.

Implements ISocketHandler.

Definition at line 1265 of file SocketHandler.cpp.

References DEB, ENABLE_DETACH, INVALID_SOCKET, LIST_CALLONCONNECT, LIST_CLOSE, LIST_DETACH, LIST_RETRY, LIST_TIMEOUT, LOG_LEVEL_INFO, LogError(), m_fds_callonconnect, m_fds_close, m_fds_detach, m_fds_retry, m_fds_timeout, and Valid().

Referenced by Select().

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 }

ISocketHandler::PoolSocket * SocketHandler::FindConnection ( int  type,
const std::string &  protocol,
SocketAddress  
) [virtual]

Find available open connection (used by connection pool).

Implements ISocketHandler.

Definition at line 1153 of file SocketHandler.cpp.

References m_sockets.

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 }

void SocketHandler::EnablePool ( bool  x = true  )  [virtual]

Enable connection pool (by default disabled).

Implements ISocketHandler.

Definition at line 1175 of file SocketHandler.cpp.

References m_b_enable_pool.

01176 {
01177         m_b_enable_pool = x;
01178 }

bool SocketHandler::PoolEnabled (  )  [virtual]

Check pool status.

Returns:
true if connection pool is enabled

Implements ISocketHandler.

Definition at line 1181 of file SocketHandler.cpp.

References m_b_enable_pool.

01182 { 
01183         return m_b_enable_pool; 
01184 }

void SocketHandler::SetSocks4Host ( ipaddr_t   )  [virtual]

Set socks4 server ip that all new tcp sockets should use.

Implements ISocketHandler.

Definition at line 991 of file SocketHandler.cpp.

References m_socks4_host.

00992 {
00993         m_socks4_host = a;
00994 }

void SocketHandler::SetSocks4Host ( const std::string &   )  [virtual]

Set socks4 server hostname that all new tcp sockets should use.

Implements ISocketHandler.

Definition at line 997 of file SocketHandler.cpp.

References m_socks4_host, and Utility::u2ip().

00998 {
00999         Utility::u2ip(host, m_socks4_host);
01000 }

void SocketHandler::SetSocks4Port ( port_t   )  [virtual]

Set socks4 server port number that all new tcp sockets should use.

Implements ISocketHandler.

Definition at line 1003 of file SocketHandler.cpp.

References m_socks4_port.

01004 {
01005         m_socks4_port = port;
01006 }

void SocketHandler::SetSocks4Userid ( const std::string &   )  [virtual]

Set optional socks4 userid.

Implements ISocketHandler.

Definition at line 1009 of file SocketHandler.cpp.

References m_socks4_userid.

01010 {
01011         m_socks4_userid = id;
01012 }

void SocketHandler::SetSocks4TryDirect ( bool  x = true  )  [virtual]

If connection to socks4 server fails, immediately try direct connection to final host.

Implements ISocketHandler.

Definition at line 1107 of file SocketHandler.cpp.

References m_bTryDirect.

01108 {
01109         m_bTryDirect = x;
01110 }

ipaddr_t SocketHandler::GetSocks4Host (  )  [virtual]

Get socks4 server ip.

Returns:
socks4 server ip

Implements ISocketHandler.

Definition at line 1113 of file SocketHandler.cpp.

References m_socks4_host.

01114 {
01115         return m_socks4_host;
01116 }

port_t SocketHandler::GetSocks4Port (  )  [virtual]

Get socks4 port number.

Returns:
socks4 port number

Implements ISocketHandler.

Definition at line 1119 of file SocketHandler.cpp.

References m_socks4_port.

01120 {
01121         return m_socks4_port;
01122 }

const std::string & SocketHandler::GetSocks4Userid (  )  [virtual]

Get socks4 userid (optional).

Returns:
socks4 userid

Implements ISocketHandler.

Definition at line 1125 of file SocketHandler.cpp.

References m_socks4_userid.

01126 {
01127         return m_socks4_userid;
01128 }

bool SocketHandler::Socks4TryDirect (  )  [virtual]

Check status of socks4 try direct flag.

Returns:
true if direct connection should be tried if connection to socks4 server fails

Implements ISocketHandler.

Definition at line 1131 of file SocketHandler.cpp.

References m_bTryDirect.

01132 {
01133         return m_bTryDirect;
01134 }

void SocketHandler::EnableResolver ( port_t  port = 16667  )  [virtual]

Enable asynchronous DNS.

Parameters:
port Listen port of asynchronous dns server

Implements ISocketHandler.

Definition at line 1089 of file SocketHandler.cpp.

References m_resolver, and m_resolver_port.

01090 {
01091         if (!m_resolver)
01092         {
01093                 m_resolver_port = port;
01094                 m_resolver = new ResolvServer(port);
01095         }
01096 }

bool SocketHandler::ResolverEnabled (  )  [virtual]

Check resolver status.

Returns:
true if resolver is enabled

Implements ISocketHandler.

Definition at line 1139 of file SocketHandler.cpp.

References m_resolver.

01140 { 
01141         return m_resolver ? true : false; 
01142 }

int SocketHandler::Resolve ( Socket ,
const std::string &  host,
port_t  port 
) [virtual]

Queue a dns request.

Parameters:
host Hostname to be resolved
port Port number will be echoed in Socket::OnResolved callback

Implements ISocketHandler.

Definition at line 1017 of file SocketHandler.cpp.

References Add(), LOG_LEVEL_FATAL, LogError(), m_resolv_id, m_resolver_port, and Utility::u2ip().

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 }

int SocketHandler::Resolve ( Socket ,
ipaddr_t  a 
) [virtual]

Do a reverse dns lookup.

Implements ISocketHandler.

Definition at line 1053 of file SocketHandler.cpp.

References Add(), LOG_LEVEL_FATAL, LogError(), m_resolv_id, m_resolver_port, and Utility::u2ip().

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 }

port_t SocketHandler::GetResolverPort (  )  [virtual]

Get listen port of asynchronous dns server.

Implements ISocketHandler.

Definition at line 1145 of file SocketHandler.cpp.

References m_resolver_port.

01146 { 
01147         return m_resolver_port; 
01148 }

bool SocketHandler::ResolverReady (  )  [virtual]

Resolver thread ready for queries.

Implements ISocketHandler.

Definition at line 1099 of file SocketHandler.cpp.

References m_resolver.

01100 {
01101         return m_resolver ? m_resolver -> Ready() : false;
01102 }

void SocketHandler::SetSlave ( bool  x = true  )  [virtual]

Indicates that the handler runs under SocketThread.

Implements ISocketHandler.

Definition at line 190 of file SocketHandler.cpp.

References m_slave.

Referenced by Socket::SocketThread::Run().

00191 {
00192         m_slave = x;
00193 }

bool SocketHandler::IsSlave (  )  [virtual]

Indicates that the handler runs under SocketThread.

Implements ISocketHandler.

Definition at line 196 of file SocketHandler.cpp.

References m_slave.

00197 {
00198         return m_slave;
00199 }

void SocketHandler::CheckSanity (  ) 

Sanity check of those accursed lists.

Definition at line 1224 of file SocketHandler.cpp.

References CheckList(), m_fds, m_fds_callonconnect, m_fds_close, m_fds_detach, m_fds_erase, m_fds_retry, and m_fds_timeout.

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 }

void SocketHandler::CheckList ( socket_v ,
const std::string &   
) [private]

Used by CheckSanity.

Definition at line 1238 of file SocketHandler.cpp.

References m_add, m_delete, and m_sockets.

Referenced by CheckSanity().

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 }

void SocketHandler::Remove ( Socket  )  [private, virtual]

Remove socket from socket map, used by Socket class.

Implements ISocketHandler.

Definition at line 1188 of file SocketHandler.cpp.

References LOG_LEVEL_WARNING, LogError(), m_add, m_delete, and m_sockets.

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 }


Member Data Documentation

Active sockets map.

Definition at line 203 of file SocketHandler.h.

Referenced by CheckList(), FindConnection(), GetCount(), Remove(), Select(), Valid(), and ~SocketHandler().

Sockets to be added to sockets map.

Definition at line 204 of file SocketHandler.h.

Referenced by Add(), CheckList(), GetCount(), Remove(), and Select().

std::list<Socket *> SocketHandler::m_delete [protected]

Sockets to be deleted (failed when Add).

Definition at line 205 of file SocketHandler.h.

Referenced by Add(), CheckList(), GetCount(), Remove(), and Select().

Registered log class, or NULL.

Definition at line 208 of file SocketHandler.h.

Referenced by LogError(), and RegStdLog().

Thread safety mutex.

Definition at line 209 of file SocketHandler.h.

Referenced by GetMutex(), Select(), SocketHandler(), and ~SocketHandler().

bool SocketHandler::m_b_use_mutex [protected]

Mutex correctly initialized.

Definition at line 210 of file SocketHandler.h.

Referenced by Select(), and ~SocketHandler().

Highest file descriptor + 1 in active sockets list.

Definition at line 216 of file SocketHandler.h.

Referenced by Select().

fd_set SocketHandler::m_rfds [private]

file descriptor set monitored for read events

Definition at line 217 of file SocketHandler.h.

Referenced by Get(), Select(), Set(), and SocketHandler().

fd_set SocketHandler::m_wfds [private]

file descriptor set monitored for write events

Definition at line 218 of file SocketHandler.h.

Referenced by Get(), Select(), Set(), and SocketHandler().

fd_set SocketHandler::m_efds [private]

file descriptor set monitored for exceptions

Definition at line 219 of file SocketHandler.h.

Referenced by Get(), Select(), Set(), and SocketHandler().

debug select() error

Definition at line 220 of file SocketHandler.h.

Referenced by Select().

int SocketHandler::m_errcnt [private]

debug select() error

Definition at line 221 of file SocketHandler.h.

Referenced by Select().

time_t SocketHandler::m_tlast [private]

timeout control

Definition at line 222 of file SocketHandler.h.

Referenced by Select().

Active file descriptor list.

Definition at line 225 of file SocketHandler.h.

Referenced by CheckSanity(), and Select().

File descriptors that are to be erased from m_sockets.

Definition at line 226 of file SocketHandler.h.

Referenced by CheckSanity(), and Select().

checklist CallOnConnect

Definition at line 227 of file SocketHandler.h.

Referenced by AddList(), CheckSanity(), and Select().

checklist Detach

Definition at line 229 of file SocketHandler.h.

Referenced by AddList(), CheckSanity(), and Select().

checklist timeout

Definition at line 231 of file SocketHandler.h.

Referenced by AddList(), CheckSanity(), and Select().

checklist retry client connect

Definition at line 232 of file SocketHandler.h.

Referenced by AddList(), CheckSanity(), and Select().

checklist close and delete

Definition at line 233 of file SocketHandler.h.

Referenced by AddList(), CheckSanity(), and Select().

Socks4 server host ip.

Definition at line 236 of file SocketHandler.h.

Referenced by GetSocks4Host(), and SetSocks4Host().

Socks4 server port number.

Definition at line 237 of file SocketHandler.h.

Referenced by GetSocks4Port(), and SetSocks4Port().

std::string SocketHandler::m_socks4_userid [private]

Socks4 userid.

Definition at line 238 of file SocketHandler.h.

Referenced by GetSocks4Userid(), and SetSocks4Userid().

Try direct connection if socks4 server fails.

Definition at line 239 of file SocketHandler.h.

Referenced by SetSocks4TryDirect(), and Socks4TryDirect().

Resolver id counter.

Definition at line 242 of file SocketHandler.h.

Referenced by Resolve().

Resolver thread pointer.

Definition at line 243 of file SocketHandler.h.

Referenced by EnableResolver(), ResolverEnabled(), ResolverReady(), and ~SocketHandler().

Resolver listen port.

Definition at line 244 of file SocketHandler.h.

Referenced by EnableResolver(), GetResolverPort(), and Resolve().

Connection pool enabled if true.

Definition at line 247 of file SocketHandler.h.

Referenced by EnablePool(), and PoolEnabled().

bool SocketHandler::m_slave [private]

Indicates that this is a ISocketHandler run in SocketThread.

Definition at line 255 of file SocketHandler.h.

Referenced by IsSlave(), Select(), SetSlave(), and ~SocketHandler().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4