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 ()
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 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 list.
socket_m m_add
 Sockets to be added to sockets list.
std::list< Socket * > m_delete
 Sockets to be deleted (failed when Add).

Private Member Functions

void Remove (Socket *)
 Remove socket from socket map, used by Socket class.
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
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.
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_connecting
 checklist Connecting
socket_v m_fds_retry
 checklist retry client connect
socket_v m_fds_close
 checklist close and delete

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 :ISocketHandler(p)
00060 ,m_maxsock(0)
00061 ,m_preverror(-1)
00062 ,m_errcnt(0)
00063 #ifdef ENABLE_SOCKS4
00064 ,m_socks4_host(0)
00065 ,m_socks4_port(0)
00066 ,m_bTryDirect(false)
00067 #endif
00068 #ifdef ENABLE_RESOLVER
00069 ,m_resolv_id(0)
00070 ,m_resolver(NULL)
00071 #endif
00072 #ifdef ENABLE_POOL
00073 ,m_b_enable_pool(false)
00074 #endif
00075 {
00076         FD_ZERO(&m_rfds);
00077         FD_ZERO(&m_wfds);
00078         FD_ZERO(&m_efds);
00079 }

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

SocketHandler threadsafe constructor.

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

Definition at line 82 of file SocketHandler.cpp.

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

00083 :ISocketHandler(mutex, p)
00084 ,m_maxsock(0)
00085 ,m_preverror(-1)
00086 ,m_errcnt(0)
00087 #ifdef ENABLE_SOCKS4
00088 ,m_socks4_host(0)
00089 ,m_socks4_port(0)
00090 ,m_bTryDirect(false)
00091 #endif
00092 #ifdef ENABLE_RESOLVER
00093 ,m_resolv_id(0)
00094 ,m_resolver(NULL)
00095 #endif
00096 #ifdef ENABLE_POOL
00097 ,m_b_enable_pool(false)
00098 #endif
00099 {
00100         m_mutex.Lock();
00101         FD_ZERO(&m_rfds);
00102         FD_ZERO(&m_wfds);
00103         FD_ZERO(&m_efds);
00104 }

SocketHandler::~SocketHandler (  ) 

Definition at line 107 of file SocketHandler.cpp.

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

00108 {
00109 #ifdef ENABLE_RESOLVER
00110         if (m_resolver)
00111         {
00112                 m_resolver -> Quit();
00113         }
00114 #endif
00115         {
00116                 while (m_sockets.size())
00117                 {
00118 DEB(                    fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", m_sockets.size());)
00119                         socket_m::iterator it = m_sockets.begin();
00120                         Socket *p = it -> second;
00121                         if (p)
00122                         {
00123 DEB(                            fprintf(stderr, "  fd %d\n", p -> GetSocket());)
00124                                 p -> Close();
00125 DEB(                            fprintf(stderr, "  fd closed %d\n", p -> GetSocket());)
00126 //                              p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!!
00127                                 // MinionSocket breaks, calling MinderHandler methods in OnDelete -
00128                                 // MinderHandler is already gone when that happens...
00129 
00130                                 // only delete socket when controlled
00131                                 // ie master sockethandler can delete non-detached sockets
00132                                 // and a slave sockethandler can only delete a detach socket
00133                                 if (p -> DeleteByHandler()
00134 #ifdef ENABLE_DETACH
00135                                         && !(m_slave ^ p -> IsDetached()) 
00136 #endif
00137                                         )
00138                                 {
00139                                         p -> SetErasedByHandler();
00140                                         delete p;
00141                                 }
00142                                 m_sockets.erase(it);
00143                         }
00144                         else
00145                         {
00146                                 m_sockets.erase(it);
00147                         }
00148 DEB(                    fprintf(stderr, "next\n");)
00149                 }
00150 DEB(            fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", m_sockets.size());)
00151         }
00152 #ifdef ENABLE_RESOLVER
00153         if (m_resolver)
00154         {
00155                 delete m_resolver;
00156         }
00157 #endif
00158         if (m_b_use_mutex)
00159         {
00160                 m_mutex.Unlock();
00161         }
00162 }


Member Function Documentation

void SocketHandler::Add ( Socket  )  [virtual]

Add socket instance to socket map.

Removal is always automatic.

Implements ISocketHandler.

Reimplemented in EventHandler.

Definition at line 165 of file SocketHandler.cpp.

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

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

00166 {
00167         if (p -> GetSocket() == INVALID_SOCKET)
00168         {
00169                 LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING);
00170                 if (p -> CloseAndDelete())
00171                 {
00172                         m_delete.push_back(p);
00173                 }
00174                 return;
00175         }
00176         if (m_add.find(p -> GetSocket()) != m_add.end())
00177         {
00178                 LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL);
00179                 m_delete.push_back(p);
00180                 return;
00181         }
00182         m_add[p -> GetSocket()] = p;
00183 }

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

Remove socket from socket map, used by Socket class.

Implements ISocketHandler.

Definition at line 1105 of file SocketHandler.cpp.

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

01106 {
01107         if (p -> ErasedByHandler())
01108         {
01109                 return;
01110         }
01111         for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
01112         {
01113                 if (it -> second == p)
01114                 {
01115                         LogError(p, "Remove", -1, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
01116                         m_sockets.erase(it);
01117                         return;
01118                 }
01119         }
01120         for (socket_m::iterator it2 = m_add.begin(); it2 != m_add.end(); it2++)
01121         {
01122                 if ((*it2).second == p)
01123                 {
01124                         LogError(p, "Remove", -2, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
01125                         m_add.erase(it2);
01126                         return;
01127                 }
01128         }
01129         for (std::list<Socket *>::iterator it3 = m_delete.begin(); it3 != m_delete.end(); it3++)
01130         {
01131                 if (*it3 == p)
01132                 {
01133                         LogError(p, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
01134                         m_delete.erase(it3);
01135                         return;
01136                 }
01137         }
01138 }

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

References m_efds, m_rfds, and m_wfds.

00187 {
00188         if (s >= 0)
00189         {
00190                 r = FD_ISSET(s, &m_rfds) ? true : false;
00191                 w = FD_ISSET(s, &m_wfds) ? true : false;
00192                 e = FD_ISSET(s, &m_efds) ? true : false;
00193         }
00194 }

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

References DEB, m_efds, m_rfds, and m_wfds.

Referenced by Select().

00198 {
00199 DEB(fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");)
00200         if (s >= 0)
00201         {
00202                 if (bRead)
00203                 {
00204                         if (!FD_ISSET(s, &m_rfds))
00205                         {
00206                                 FD_SET(s, &m_rfds);
00207                         }
00208                 }
00209                 else
00210                 {
00211                         FD_CLR(s, &m_rfds);
00212                 }
00213                 if (bWrite)
00214                 {
00215                         if (!FD_ISSET(s, &m_wfds))
00216                         {
00217                                 FD_SET(s, &m_wfds);
00218                         }
00219                 }
00220                 else
00221                 {
00222                         FD_CLR(s, &m_wfds);
00223                 }
00224                 if (bException)
00225                 {
00226                         if (!FD_ISSET(s, &m_efds))
00227                         {
00228                                 FD_SET(s, &m_efds);
00229                         }
00230                 }
00231                 else
00232                 {
00233                         FD_CLR(s, &m_efds);
00234                 }
00235         }
00236 }

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

Wait for events, generate callbacks.

Implements ISocketHandler.

Definition at line 239 of file SocketHandler.cpp.

References Select().

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

00240 {
00241         struct timeval tv;
00242         tv.tv_sec = sec;
00243         tv.tv_usec = usec;
00244         return Select(&tv);
00245 }

int SocketHandler::Select (  )  [virtual]

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

Implements ISocketHandler.

Definition at line 248 of file SocketHandler.cpp.

References m_fds_callonconnect, m_fds_close, m_fds_connecting, m_fds_detach, m_fds_erase, m_fds_retry, and ISocketHandler::m_slave.

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

00249 {
00250         if (m_fds_callonconnect.size() ||
00251 #ifdef ENABLE_DETACH
00252                 (!m_slave && m_fds_detach.size()) ||
00253 #endif
00254                 m_fds_connecting.size() ||
00255                 m_fds_retry.size() ||
00256                 m_fds_close.size() ||
00257                 m_fds_erase.size())
00258         {
00259                 return Select(0, 200000);
00260         }
00261         return Select(NULL);
00262 }

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

Wait for events, generate callbacks.

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

Todo:
state reason why connect failed

Todo:
state reason why connect failed

Implements ISocketHandler.

Definition at line 265 of file SocketHandler.cpp.

References Add(), DEB, ENABLE_DETACH, Errno, HAVE_OPENSSL, INVALID_SOCKET, Mutex::Lock, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, ISocketHandler::LogError(), m_add, ISocketHandler::m_b_use_mutex, m_delete, m_efds, m_errcnt, m_fds, m_fds_callonconnect, m_fds_close, m_fds_connecting, m_fds_detach, m_fds_erase, m_fds_retry, m_maxsock, ISocketHandler::m_mutex, m_preverror, m_rfds, ISocketHandler::m_slave, m_sockets, m_wfds, Set(), StrError, and Mutex::Unlock().

00266 {
00267         size_t ignore = 0;
00268         while (m_add.size() > ignore)
00269         {
00270                 if (m_sockets.size() >= FD_SETSIZE)
00271                 {
00272                         LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING);
00273                         break;
00274                 }
00275                 socket_m::iterator it = m_add.begin();
00276                 SOCKET s = it -> first;
00277                 Socket *p = it -> second;
00278 DEB(fprintf(stderr, "Trying to add fd %d,  m_add.size() %d,  ignore %d\n", s, m_add.size(), ignore);)
00279                 //
00280                 if (m_sockets.find(p -> GetSocket()) != m_sockets.end())
00281                 {
00282                         LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL);
00283                         // %! it's a dup, don't add to delete queue, just ignore it
00284 //                      m_delete.push_back(p);
00285 //                      m_add.erase(it);
00286                         ignore++;
00287                         continue;
00288                 }
00289                 if (!p -> CloseAndDelete())
00290                 {
00291                         if (p -> Connecting()) // 'Open' called before adding socket
00292                         {
00293                                 Set(s,false,true);
00294                         }
00295                         else
00296                         {
00297                                 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00298                                 bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false;
00299                                 if (p -> IsDisableRead())
00300                                 {
00301                                         Set(s, false, bWrite);
00302                                 }
00303                                 else
00304                                 {
00305                                         Set(s, true, bWrite);
00306                                 }
00307                         }
00308                         m_maxsock = (s > m_maxsock) ? s : m_maxsock;
00309                 }
00310                 else
00311                 {
00312                         LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING);
00313                 }
00314                 // only add to m_fds (process fd_set events) if
00315                 //  slave handler and detached/detaching socket
00316                 //  master handler and non-detached socket
00317 #ifdef ENABLE_DETACH
00318                 if (!(m_slave ^ p -> IsDetach()))
00319 #endif
00320                 {
00321                         m_fds.push_back(s);
00322                 }
00323                 m_sockets[s] = p;
00324                 //
00325                 m_add.erase(it);
00326         }
00327 #ifdef MACOSX
00328         fd_set rfds;
00329         fd_set wfds;
00330         fd_set efds;
00331         FD_COPY(&m_rfds, &rfds);
00332         FD_COPY(&m_wfds, &wfds);
00333         FD_COPY(&m_efds, &efds);
00334 #else
00335         fd_set rfds = m_rfds;
00336         fd_set wfds = m_wfds;
00337         fd_set efds = m_efds;
00338 #endif
00339         int n;
00340         if (m_b_use_mutex)
00341         {
00342                 m_mutex.Unlock();
00343                 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
00344                 m_mutex.Lock();
00345         }
00346         else
00347         {
00348                 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
00349         }
00350         if (n == -1)
00351         {
00352                 /*
00353                         EBADF  An invalid file descriptor was given in one of the sets.
00354                         EINTR  A non blocked signal was caught.
00355                         EINVAL n is negative. Or struct timeval contains bad time values (<0).
00356                         ENOMEM select was unable to allocate memory for internal tables.
00357                 */
00358                 if (Errno != m_preverror || m_errcnt++ % 10000 == 0)
00359                 {
00360                         LogError(NULL, "select", Errno, StrError(Errno));
00361 DEB(                    fprintf(stderr, "m_maxsock: %d\n", m_maxsock);
00362                         fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" :
00363                                 Errno == EINTR ? "EINTR" :
00364                                 Errno == EBADF ? "EBADF" :
00365                                 Errno == ENOMEM ? "ENOMEM" : "<another>");
00366                         // test bad fd
00367                         for (SOCKET i = 0; i <= m_maxsock; i++)
00368                         {
00369                                 bool t = false;
00370                                 FD_ZERO(&rfds);
00371                                 FD_ZERO(&wfds);
00372                                 FD_ZERO(&efds);
00373                                 if (FD_ISSET(i, &m_rfds))
00374                                 {
00375                                         FD_SET(i, &rfds);
00376                                         t = true;
00377                                 }
00378                                 if (FD_ISSET(i, &m_wfds))
00379                                 {
00380                                         FD_SET(i, &wfds);
00381                                         t = true;
00382                                 }
00383                                 if (FD_ISSET(i, &m_efds))
00384                                 {
00385                                         FD_SET(i, &efds);
00386                                         t = true;
00387                                 }
00388                                 if (t && m_sockets.find(i) == m_sockets.end())
00389                                 {
00390                                         fprintf(stderr, "Bad fd in fd_set: %d\n", i);
00391                                 }
00392                         }
00393 ) // DEB
00394                         m_preverror = Errno;
00395                 }
00397         }
00398         else
00399         if (!n)
00400         {
00401                 m_preverror = -1;
00402         }
00403         else
00404         if (n > 0)
00405         {
00406                 for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++)
00407                 {
00408                         SOCKET i = *it2;
00409                         if (FD_ISSET(i, &rfds))
00410                         {
00411                                 socket_m::iterator itmp = m_sockets.find(i);
00412                                 if (itmp != m_sockets.end()) // found
00413                                 {
00414                                         Socket *p = itmp -> second;
00415                                         // new SSL negotiate method
00416 #ifdef HAVE_OPENSSL
00417                                         if (p -> IsSSLNegotiate())
00418                                         {
00419                                                 p -> SSLNegotiate();
00420                                         }
00421                                         else
00422 #endif
00423                                         {
00424                                                 p -> OnRead();
00425                                         }
00426                                 }
00427                                 else
00428                                 {
00429                                         LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00430                                 }
00431                                 n--;
00432                         }
00433                         if (FD_ISSET(i, &wfds))
00434                         {
00435                                 socket_m::iterator itmp = m_sockets.find(i);
00436                                 if (itmp != m_sockets.end()) // found
00437                                 {
00438                                         Socket *p = itmp -> second;
00439                                         // new SSL negotiate method
00440 #ifdef HAVE_OPENSSL
00441                                         if (p -> IsSSLNegotiate())
00442                                         {
00443                                                 p -> SSLNegotiate();
00444                                         }
00445                                         else
00446 #endif
00447                                         {
00448                                                 p -> OnWrite();
00449                                         }
00450                                 }
00451                                 else
00452                                 {
00453                                         LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00454                                 }
00455                                 n--;
00456                         }
00457                         if (FD_ISSET(i, &efds))
00458                         {
00459                                 socket_m::iterator itmp = m_sockets.find(i);
00460                                 if (itmp != m_sockets.end()) // found
00461                                 {
00462                                         Socket *p = itmp -> second;
00463                                         p -> OnException();
00464                                 }
00465                                 else
00466                                 {
00467                                         LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00468                                 }
00469                                 n--;
00470                         }
00471                 } // m_fds loop
00472                 m_preverror = -1;
00473         } // if (n > 0)
00474 
00475         // check CallOnConnect
00476         if (m_fds_callonconnect.size())
00477         {
00478                 socket_v tmp = m_fds_callonconnect;
00479                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00480                 {
00481                         Socket *p = NULL;
00482                         {
00483                                 socket_m::iterator itmp = m_sockets.find(*it);
00484                                 if (itmp != m_sockets.end()) // found
00485                                 {
00486                                         p = itmp -> second;
00487                                 }
00488                                 else
00489                                 {
00490                                         LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00491                                 }
00492                         }
00493                         if (p)
00494                         {
00495                                 if (p -> CallOnConnect() && p -> Ready() )
00496                                 {
00497                                         p -> SetConnected(); // moved here from inside if (tcp) check below
00498 #ifdef HAVE_OPENSSL
00499                                         if (p -> IsSSL()) // SSL Enabled socket
00500                                                 p -> OnSSLConnect();
00501                                         else
00502 #endif
00503 #ifdef ENABLE_SOCKS4
00504                                         if (p -> Socks4())
00505                                                 p -> OnSocks4Connect();
00506                                         else
00507 #endif
00508                                         {
00509                                                 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00510                                                 if (tcp)
00511                                                 {
00512                                                         if (tcp -> GetOutputLength())
00513                                                         {
00514                                                                 p -> OnWrite();
00515                                                         }
00516                                                 }
00517 #ifdef ENABLE_RECONNECT
00518                                                 if (tcp && tcp -> IsReconnect())
00519                                                         p -> OnReconnect();
00520                                                 else
00521 #endif
00522                                                 {
00523 //                                                      LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO);
00524                                                         p -> OnConnect();
00525                                                 }
00526                                         }
00527                                         p -> SetCallOnConnect( false );
00528                                 }
00529                         }
00530                 }
00531         }
00532 #ifdef ENABLE_DETACH
00533         if (!m_slave && m_fds_detach.size())
00534         {
00535                 for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
00536                 {
00537                         Socket *p = NULL;
00538                         {
00539                                 socket_m::iterator itmp = m_sockets.find(*it);
00540                                 if (itmp != m_sockets.end()) // found
00541                                 {
00542                                         p = itmp -> second;
00543                                 }
00544                                 else
00545                                 {
00546                                         LogError(NULL, "GetSocket/handler/5", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00547                                 }
00548                         }
00549                         if (p)
00550                         {
00551                                 if (p -> IsDetach())
00552                                 {
00553                                         Set(p -> GetSocket(), false, false, false);
00554                                         // After DetachSocket(), all calls to Handler() will return a reference
00555                                         // to the new slave SocketHandler running in the new thread.
00556                                         p -> DetachSocket();
00557                                         // Adding the file descriptor to m_fds_erase will now also remove the
00558                                         // socket from the detach queue - tnx knightmad
00559                                         m_fds_erase.push_back(p -> GetSocket());
00560                                 }
00561                         }
00562                 }
00563         }
00564 #endif
00565         // check Connecting - connection timeout
00566         if (m_fds_connecting.size())
00567         {
00568                 socket_v tmp = m_fds_connecting;
00569                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00570                 {
00571                         Socket *p = NULL;
00572                         {
00573                                 socket_m::iterator itmp = m_sockets.find(*it);
00574                                 if (itmp != m_sockets.end()) // found
00575                                 {
00576                                         p = itmp -> second;
00577                                 }
00578                                 else
00579                                 {
00580                                         itmp = m_add.find(*it);
00581                                         if (itmp != m_add.end())
00582                                         {
00583                                                 p = itmp -> second;
00584                                         }
00585                                         else
00586                                         {
00587                                                 LogError(NULL, "GetSocket/handler/6", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00588                                         }
00589                                 }
00590                         }
00591                         if (p)
00592                         {
00593                                 if (p -> Connecting() && p -> GetConnectTime() >= p -> GetConnectTimeout() )
00594                                 {
00595                                         LogError(p, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
00596 #ifdef ENABLE_SOCKS4
00597                                         if (p -> Socks4())
00598                                         {
00599                                                 p -> OnSocks4ConnectFailed();
00600                                                 // retry direct connection
00601                                         }
00602                                         else
00603 #endif
00604                                         if (p -> GetConnectionRetry() == -1 ||
00605                                                 (p -> GetConnectionRetry() && p -> GetConnectionRetries() < p -> GetConnectionRetry()) )
00606                                         {
00607                                                 p -> IncreaseConnectionRetries();
00608                                                 // ask socket via OnConnectRetry callback if we should continue trying
00609                                                 if (p -> OnConnectRetry())
00610                                                 {
00611                                                         p -> SetRetryClientConnect();
00612                                                 }
00613                                                 else
00614                                                 {
00615                                                         p -> SetCloseAndDelete( true );
00617                                                         p -> OnConnectFailed();
00618                                                 }
00619                                         }
00620                                         else
00621                                         {
00622                                                 p -> SetCloseAndDelete(true);
00624                                                 p -> OnConnectFailed();
00625                                         }
00626                                         //
00627                                         p -> SetConnecting(false);
00628                                 }
00629                         }
00630                 }
00631         }
00632         // check retry client connect
00633         if (m_fds_retry.size())
00634         {
00635                 socket_v tmp = m_fds_retry;
00636                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00637                 {
00638                         Socket *p = NULL;
00639                         {
00640                                 socket_m::iterator itmp = m_sockets.find(*it);
00641                                 if (itmp != m_sockets.end()) // found
00642                                 {
00643                                         p = itmp -> second;
00644                                 }
00645                                 else
00646                                 {
00647                                         LogError(NULL, "GetSocket/handler/7", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00648                                 }
00649                         }
00650                         if (p)
00651                         {
00652                                 if (p -> RetryClientConnect())
00653                                 {
00654                                         TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00655                                         SOCKET nn = *it; //(*it3).first;
00656                                         p -> SetRetryClientConnect(false);
00657 DEB(    fprintf(stderr, "Close() before retry client connect\n");)
00658                                         p -> Close(); // removes from m_fds_retry
00659                                         std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
00660                                         if (ad.get())
00661                                         {
00662                                                 tcp -> Open(*ad);
00663                                         }
00664                                         else
00665                                         {
00666                                                 LogError(p, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR);
00667                                         }
00668                                         Add(p);
00669                                         m_fds_erase.push_back(nn);
00670                                 }
00671                         }
00672                 }
00673         }
00674         // check close and delete
00675         if (m_fds_close.size())
00676         {
00677                 socket_v tmp = m_fds_close;
00678 DEB(fprintf(stderr, "m_fds_close.size() == %d\n", m_fds_close.size());)
00679                 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
00680                 {
00681                         Socket *p = NULL;
00682                         {
00683                                 socket_m::iterator itmp = m_sockets.find(*it);
00684                                 if (itmp != m_sockets.end()) // found
00685                                 {
00686                                         p = itmp -> second;
00687                                 }
00688                                 else
00689                                 {
00690                                         itmp = m_add.find(*it);
00691                                         if (itmp != m_add.end())
00692                                         {
00693                                                 p = itmp -> second;
00694                                         }
00695                                         else
00696                                         {
00697                                                 LogError(NULL, "GetSocket/handler/8", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
00698                                         }
00699                                 }
00700                         }
00701                         if (p)
00702                         {
00703                                 if (p -> CloseAndDelete() )
00704                                 {
00705                                         TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
00706                                         // new graceful tcp - flush and close timeout 5s
00707                                         if (tcp && p -> IsConnected() && tcp -> GetFlushBeforeClose() && 
00708 #ifdef HAVE_OPENSSL
00709                                                 !tcp -> IsSSL() && 
00710 #endif
00711                                                 p -> TimeSinceClose() < 5)
00712                                         {
00713 DEB(fprintf(stderr, " close(1)\n");)
00714                                                 if (tcp -> GetOutputLength())
00715                                                 {
00716                                                         LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Sending all data before closing", LOG_LEVEL_INFO);
00717                                                 }
00718                                                 else // shutdown write when output buffer is empty
00719                                                 if (!(p -> GetShutdown() & SHUT_WR))
00720                                                 {
00721                                                         SOCKET nn = *it;
00722                                                         if (nn != INVALID_SOCKET && shutdown(nn, SHUT_WR) == -1)
00723                                                         {
00724                                                                 LogError(p, "graceful shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00725                                                         }
00726                                                         p -> SetShutdown(SHUT_WR);
00727                                                 }
00728                                         }
00729                                         else
00730 #ifdef ENABLE_RECONNECT
00731                                         if (tcp && p -> IsConnected() && tcp -> Reconnect())
00732                                         {
00733                                                 SOCKET nn = *it; //(*it3).first;
00734 DEB(fprintf(stderr, " close(2) fd %d\n", nn);)
00735                                                 p -> SetCloseAndDelete(false);
00736                                                 tcp -> SetIsReconnect();
00737                                                 p -> SetConnected(false);
00738 DEB(    fprintf(stderr, "Close() before reconnect\n");)
00739                                                 p -> Close(); // dispose of old file descriptor (Open creates a new)
00740                                                 p -> OnDisconnect();
00741                                                 std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
00742                                                 if (ad.get())
00743                                                 {
00744                                                         tcp -> Open(*ad);
00745                                                 }
00746                                                 else
00747                                                 {
00748                                                         LogError(p, "Reconnect", 0, "no address", LOG_LEVEL_ERROR);
00749                                                 }
00750                                                 tcp -> ResetConnectionRetries();
00751                                                 Add(p);
00752                                                 m_fds_erase.push_back(nn);
00753                                         }
00754                                         else
00755 #endif
00756                                         {
00757                                                 SOCKET nn = *it; //(*it3).first;
00758 DEB(fprintf(stderr, " close(3) fd %d GetSocket() %d\n", nn, p -> GetSocket());)
00759                                                 if (tcp && p -> IsConnected() && tcp -> GetOutputLength())
00760                                                 {
00761                                                         LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Closing socket while data still left to send", LOG_LEVEL_WARNING);
00762                                                 }
00763 #ifdef ENABLE_POOL
00764                                                 if (p -> Retain() && !p -> Lost())
00765                                                 {
00766                                                         PoolSocket *p2 = new PoolSocket(*this, p);
00767                                                         p2 -> SetDeleteByHandler();
00768                                                         Add(p2);
00769                                                         //
00770                                                         p -> SetCloseAndDelete(false); // added - remove from m_fds_close
00771                                                 }
00772                                                 else
00773 #endif // ENABLE_POOL
00774                                                 {
00775                                                         Set(p -> GetSocket(),false,false,false);
00776 DEB(    fprintf(stderr, "Close() before OnDelete\n");)
00777                                                         p -> Close();
00778                                                 }
00779                                                 p -> OnDelete();
00780                                                 if (p -> DeleteByHandler())
00781                                                 {
00782                                                         p -> SetErasedByHandler();
00783                                                 }
00784                                                 m_fds_erase.push_back(nn);
00785                                         }
00786                                 }
00787                         }
00788                 }
00789         }
00790 
00791         // check erased sockets
00792         bool check_max_fd = false;
00793         while (m_fds_erase.size())
00794         {
00795                 socket_v::iterator it = m_fds_erase.begin();
00796                 SOCKET nn = *it;
00797 #ifdef ENABLE_DETACH
00798                 {
00799                         for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
00800                         {
00801                                 if (*it == nn)
00802                                 {
00803                                         m_fds_detach.erase(it);
00804                                         break;
00805                                 }
00806                         }
00807                 }
00808 #endif
00809                 {
00810                         for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
00811                         {
00812                                 if (*it == nn)
00813                                 {
00814                                         m_fds.erase(it);
00815                                         break;
00816                                 }
00817                         }
00818                 }
00819                 {
00820                         socket_m::iterator it = m_sockets.find(nn);
00821                         if (it != m_sockets.end())
00822                         {
00823                                 Socket *p = it -> second;
00824                                 /* Sometimes a SocketThread class can finish its run before the master
00825                                    sockethandler gets here. In that case, the SocketThread has set the
00826                                    'ErasedByHandler' flag on the socket which will make us end up with a
00827                                    double delete on the socket instance. 
00828                                    The fix is to make sure that the master sockethandler only can delete
00829                                    non-detached sockets, and a slave sockethandler only can delete
00830                                    detach sockets. */
00831                                 if (p -> ErasedByHandler()
00832 #ifdef ENABLE_DETACH
00833                                         && !(m_slave ^ p -> IsDetached()) 
00834 #endif
00835                                         )
00836                                 {
00837                                         delete p;
00838                                 }
00839                                 m_sockets.erase(it);
00840                         }
00841                 }
00842                 m_fds_erase.erase(it);
00843                 check_max_fd = true;
00844         }
00845         // calculate max file descriptor for select() call
00846         if (check_max_fd)
00847         {
00848                 m_maxsock = 0;
00849                 for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
00850                 {
00851                         SOCKET s = *it;
00852                         m_maxsock = s > m_maxsock ? s : m_maxsock;
00853                 }
00854         }
00855         // remove Add's that fizzed
00856         while (m_delete.size())
00857         {
00858                 std::list<Socket *>::iterator it = m_delete.begin();
00859                 Socket *p = *it;
00860                 p -> OnDelete();
00861                 m_delete.erase(it);
00862                 if (p -> DeleteByHandler()
00863 #ifdef ENABLE_DETACH
00864                         && !(m_slave ^ p -> IsDetached()) 
00865 #endif
00866                         )
00867                 {
00868                         p -> SetErasedByHandler();
00869                         delete p;
00870                 }
00871         }
00872         return n;
00873 }

bool SocketHandler::Valid ( Socket  )  [virtual]

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

Implements ISocketHandler.

Definition at line 876 of file SocketHandler.cpp.

References m_sockets.

Referenced by EventHandler::CheckEvents().

00877 {
00878         for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
00879         {
00880                 Socket *p = it -> second;
00881                 if (p0 == p)
00882                         return true;
00883         }
00884         return false;
00885 }

size_t SocketHandler::GetCount (  )  [virtual]

Return number of sockets handled by this handler.

Implements ISocketHandler.

Definition at line 894 of file SocketHandler.cpp.

References m_add, m_delete, and m_sockets.

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

00895 {
00896         return m_sockets.size() + m_add.size() + m_delete.size();
00897 }

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

00889 {
00890         return true;
00891 }

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

References DEB, ENABLE_DETACH, INVALID_SOCKET, LIST_CALLONCONNECT, LIST_CLOSE, LIST_CONNECTING, LIST_DETACH, LIST_RETRY, m_fds_callonconnect, m_fds_close, m_fds_connecting, m_fds_detach, and m_fds_retry.

01183 {
01184         if (s == INVALID_SOCKET)
01185         {
01186                 return;
01187         }
01188         socket_v& ref =
01189                 (which_one == LIST_CALLONCONNECT) ? m_fds_callonconnect :
01190 #ifdef ENABLE_DETACH
01191                 (which_one == LIST_DETACH) ? m_fds_detach :
01192 #endif
01193                 (which_one == LIST_CONNECTING) ? m_fds_connecting :
01194                 (which_one == LIST_RETRY) ? m_fds_retry :
01195                 (which_one == LIST_CLOSE) ? m_fds_close : m_fds_close;
01196 #ifdef ENABLE_DETACH
01197 DEB(
01198 fprintf(stderr, "%5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
01199         (which_one == LIST_DETACH) ? "Detach" :
01200         (which_one == LIST_CONNECTING) ? "Connecting" :
01201         (which_one == LIST_RETRY) ? "Retry" :
01202         (which_one == LIST_CLOSE) ? "Close" : "<undef>",
01203         add ? "Add" : "Remove");
01204 )
01205 #else
01206 DEB(
01207 fprintf(stderr, "%5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
01208         (which_one == LIST_CONNECTING) ? "Connecting" :
01209         (which_one == LIST_RETRY) ? "Retry" :
01210         (which_one == LIST_CLOSE) ? "Close" : "<undef>",
01211         add ? "Add" : "Remove");
01212 )
01213 #endif
01214         if (add)
01215         {
01216                 for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
01217                 {
01218                         if (*it == s)
01219                         {
01220                                 ref.erase(it);
01221                                 break;
01222                         }
01223                 }
01224                 ref.push_back(s);
01225                 return;
01226         }
01227         // remove
01228         for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
01229         {
01230                 if (*it == s)
01231                 {
01232                         ref.erase(it);
01233                         break;
01234                 }
01235         }
01236 DEB(    fprintf(stderr, "/AddList\n");)
01237 }

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

Find available open connection (used by connection pool).

Reimplemented from ISocketHandler.

Definition at line 1070 of file SocketHandler.cpp.

References m_sockets.

01071 {
01072         for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end() && m_sockets.size(); it++)
01073         {
01074                 PoolSocket *pools = dynamic_cast<PoolSocket *>(it -> second);
01075                 if (pools)
01076                 {
01077                         if (pools -> GetSocketType() == type &&
01078                             pools -> GetSocketProtocol() == protocol &&
01079 // %!                       pools -> GetClientRemoteAddress() &&
01080                             *pools -> GetClientRemoteAddress() == ad)
01081                         {
01082                                 m_sockets.erase(it);
01083                                 pools -> SetRetain(); // avoid Close in Socket destructor
01084                                 return pools; // Caller is responsible that this socket is deleted
01085                         }
01086                 }
01087         }
01088         return NULL;
01089 }

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

Enable connection pool (by default disabled).

Reimplemented from ISocketHandler.

Definition at line 1092 of file SocketHandler.cpp.

References m_b_enable_pool.

01093 {
01094         m_b_enable_pool = x;
01095 }

bool SocketHandler::PoolEnabled (  )  [virtual]

Check pool status.

Returns:
true if connection pool is enabled

Reimplemented from ISocketHandler.

Definition at line 1098 of file SocketHandler.cpp.

References m_b_enable_pool.

01099 { 
01100         return m_b_enable_pool; 
01101 }

void SocketHandler::SetSocks4Host ( ipaddr_t   )  [virtual]

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

Reimplemented from ISocketHandler.

Definition at line 901 of file SocketHandler.cpp.

References m_socks4_host.

00902 {
00903         m_socks4_host = a;
00904 }

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

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

Reimplemented from ISocketHandler.

Definition at line 907 of file SocketHandler.cpp.

References m_socks4_host, and Utility::u2ip().

00908 {
00909         Utility::u2ip(host, m_socks4_host);
00910 }

void SocketHandler::SetSocks4Port ( port_t   )  [virtual]

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

Reimplemented from ISocketHandler.

Definition at line 913 of file SocketHandler.cpp.

References m_socks4_port.

00914 {
00915         m_socks4_port = port;
00916 }

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

Set optional socks4 userid.

Reimplemented from ISocketHandler.

Definition at line 919 of file SocketHandler.cpp.

References m_socks4_userid.

00920 {
00921         m_socks4_userid = id;
00922 }

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

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

Reimplemented from ISocketHandler.

Definition at line 1024 of file SocketHandler.cpp.

References m_bTryDirect.

01025 {
01026         m_bTryDirect = x;
01027 }

ipaddr_t SocketHandler::GetSocks4Host (  )  [virtual]

Get socks4 server ip.

Returns:
socks4 server ip

Reimplemented from ISocketHandler.

Definition at line 1030 of file SocketHandler.cpp.

References m_socks4_host.

01031 {
01032         return m_socks4_host;
01033 }

port_t SocketHandler::GetSocks4Port (  )  [virtual]

Get socks4 port number.

Returns:
socks4 port number

Reimplemented from ISocketHandler.

Definition at line 1036 of file SocketHandler.cpp.

References m_socks4_port.

01037 {
01038         return m_socks4_port;
01039 }

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

Get socks4 userid (optional).

Returns:
socks4 userid

Implements ISocketHandler.

Definition at line 1042 of file SocketHandler.cpp.

References m_socks4_userid.

01043 {
01044         return m_socks4_userid;
01045 }

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

Reimplemented from ISocketHandler.

Definition at line 1048 of file SocketHandler.cpp.

References m_bTryDirect.

01049 {
01050         return m_bTryDirect;
01051 }

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

Enable asynchronous DNS.

Parameters:
port Listen port of asynchronous dns server

Reimplemented from ISocketHandler.

Definition at line 1006 of file SocketHandler.cpp.

References m_resolver, and m_resolver_port.

01007 {
01008         if (!m_resolver)
01009         {
01010                 m_resolver_port = port;
01011                 m_resolver = new ResolvServer(port);
01012         }
01013 }

bool SocketHandler::ResolverEnabled (  )  [virtual]

Check resolver status.

Returns:
true if resolver is enabled

Reimplemented from ISocketHandler.

Definition at line 1056 of file SocketHandler.cpp.

References m_resolver.

01057 { 
01058         return m_resolver ? true : false; 
01059 }

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

Reimplemented from ISocketHandler.

Definition at line 927 of file SocketHandler.cpp.

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

00928 {
00929         // check cache
00930         ResolvSocket *resolv = new ResolvSocket(*this, p);
00931         resolv -> SetId(++m_resolv_id);
00932         resolv -> SetHost(host);
00933         resolv -> SetPort(port);
00934         resolv -> SetDeleteByHandler();
00935         ipaddr_t local;
00936         Utility::u2ip("127.0.0.1", local);
00937         if (!resolv -> Open(local, m_resolver_port))
00938         {
00939                 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
00940         }
00941         Add(resolv);
00942         return m_resolv_id;
00943 }

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

Do a reverse dns lookup.

Reimplemented from ISocketHandler.

Definition at line 968 of file SocketHandler.cpp.

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

00969 {
00970         // check cache
00971         ResolvSocket *resolv = new ResolvSocket(*this, p);
00972         resolv -> SetId(++m_resolv_id);
00973         resolv -> SetAddress(a);
00974         resolv -> SetDeleteByHandler();
00975         ipaddr_t local;
00976         Utility::u2ip("127.0.0.1", local);
00977         if (!resolv -> Open(local, m_resolver_port))
00978         {
00979                 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
00980         }
00981         Add(resolv);
00982         return m_resolv_id;
00983 }

port_t SocketHandler::GetResolverPort (  )  [virtual]

Get listen port of asynchronous dns server.

Reimplemented from ISocketHandler.

Definition at line 1062 of file SocketHandler.cpp.

References m_resolver_port.

01063 { 
01064         return m_resolver_port; 
01065 }

bool SocketHandler::ResolverReady (  )  [virtual]

Resolver thread ready for queries.

Reimplemented from ISocketHandler.

Definition at line 1016 of file SocketHandler.cpp.

References m_resolver.

01017 {
01018         return m_resolver ? m_resolver -> Ready() : false;
01019 }

void SocketHandler::CheckSanity (  ) 

Sanity check of those accursed lists.

Definition at line 1141 of file SocketHandler.cpp.

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

01142 {
01143         CheckList(m_fds, "active sockets"); // active sockets
01144         CheckList(m_fds_erase, "sockets to be erased"); // should always be empty anyway
01145         CheckList(m_fds_callonconnect, "checklist CallOnConnect");
01146 #ifdef ENABLE_DETACH
01147         CheckList(m_fds_detach, "checklist Detach");
01148 #endif
01149         CheckList(m_fds_connecting, "checklist Connecting");
01150         CheckList(m_fds_retry, "checklist retry client connect");
01151         CheckList(m_fds_close, "checklist close and delete");
01152 }

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

Used by CheckSanity.

Definition at line 1155 of file SocketHandler.cpp.

References m_add, m_delete, and m_sockets.

Referenced by CheckSanity().

01156 {
01157         for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
01158         {
01159                 SOCKET s = *it;
01160                 if (m_sockets.find(s) != m_sockets.end())
01161                         continue;
01162                 if (m_add.find(s) != m_add.end())
01163                         continue;
01164                 bool found = false;
01165                 for (std::list<Socket *>::iterator it = m_delete.begin(); it != m_delete.end(); it++)
01166                 {
01167                         Socket *p = *it;
01168                         if (p -> GetSocket() == s)
01169                         {
01170                                 found = true;
01171                                 break;
01172                         }
01173                 }
01174                 if (!found)
01175                 {
01176                         fprintf(stderr, "CheckList failed for \"%s\": fd %d\n", listname.c_str(), s);
01177                 }
01178         }
01179 }


Member Data Documentation

Sockets to be added to sockets list.

Definition at line 169 of file SocketHandler.h.

Referenced by Add(), CheckList(), MinderHandler::Count(), MinderHandler::FindMinion(), GetCount(), Remove(), and Select().

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

Sockets to be deleted (failed when Add).

Definition at line 170 of file SocketHandler.h.

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

Highest file descriptor + 1 in active sockets list.

Definition at line 174 of file SocketHandler.h.

Referenced by Select().

fd_set SocketHandler::m_rfds [private]

file descriptor set monitored for read events

Definition at line 175 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 176 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 177 of file SocketHandler.h.

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

debug select() error

Definition at line 178 of file SocketHandler.h.

Referenced by Select().

int SocketHandler::m_errcnt [private]

Definition at line 179 of file SocketHandler.h.

Referenced by Select().

Socks4 server host ip.

Definition at line 181 of file SocketHandler.h.

Referenced by GetSocks4Host(), and SetSocks4Host().

Socks4 server port number.

Definition at line 182 of file SocketHandler.h.

Referenced by GetSocks4Port(), and SetSocks4Port().

std::string SocketHandler::m_socks4_userid [private]

Socks4 userid.

Definition at line 183 of file SocketHandler.h.

Referenced by GetSocks4Userid(), and SetSocks4Userid().

Try direct connection if socks4 server fails.

Definition at line 184 of file SocketHandler.h.

Referenced by SetSocks4TryDirect(), and Socks4TryDirect().

Resolver id counter.

Definition at line 187 of file SocketHandler.h.

Referenced by Resolve().

Resolver thread pointer.

Definition at line 188 of file SocketHandler.h.

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

Resolver listen port.

Definition at line 189 of file SocketHandler.h.

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

Connection pool enabled if true.

Definition at line 192 of file SocketHandler.h.

Referenced by EnablePool(), and PoolEnabled().

Active file descriptor list.

Definition at line 194 of file SocketHandler.h.

Referenced by CheckSanity(), and Select().

File descriptors that are to be erased from m_sockets.

Definition at line 195 of file SocketHandler.h.

Referenced by CheckSanity(), and Select().

checklist CallOnConnect

Definition at line 196 of file SocketHandler.h.

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

checklist Detach

Definition at line 198 of file SocketHandler.h.

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

checklist Connecting

Definition at line 200 of file SocketHandler.h.

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

checklist retry client connect

Definition at line 201 of file SocketHandler.h.

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

checklist close and delete

Definition at line 202 of file SocketHandler.h.

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


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