Logo
~Sockets~
~Examples~
~Contact~


ListenSocket< X > Class Template Reference
[Basic sockets]

Binds incoming port number to new Socket class X. More...

#include <ListenSocket.h>

Inheritance diagram for ListenSocket< X >:
Collaboration diagram for ListenSocket< X >:

List of all members.


Public Member Functions

 ListenSocket (ISocketHandler &h, bool use_creator=true)
 Constructor.
 ~ListenSocket ()
int Close ()
 Close file descriptor.
int Bind (port_t port, int depth=20)
 Bind and listen to any interface.
int Bind (SocketAddress &ad, int depth)
int Bind (port_t port, const std::string &protocol, int depth=20)
 Bind and listen to any interface, with optional protocol.
int Bind (const std::string &intf, port_t port, int depth=20)
 Bind and listen to specific interface.
int Bind (const std::string &intf, port_t port, const std::string &protocol, int depth=20)
 Bind and listen to specific interface.
int Bind (ipaddr_t a, port_t port, int depth=20)
 Bind and listen to ipv4 interface.
int Bind (ipaddr_t a, port_t port, const std::string &protocol, int depth)
 Bind and listen to ipv4 interface.
int Bind (SocketAddress &ad, const std::string &protocol, int depth)
 Bind and listen to network interface.
port_t GetPort ()
 Return assigned port number.
int GetDepth ()
 Return listen queue depth.
void OnRead ()
 OnRead on a ListenSocket receives an incoming connection.
virtual SOCKET Accept (SOCKET socket, struct sockaddr *saptr, socklen_t *lenptr)
 Please don't use this method.
bool HasCreator ()
void OnOptions (int, int, int, SOCKET)
 Called when a client socket is created, to set socket options.

Protected Member Functions

 ListenSocket (const ListenSocket &s)

Private Member Functions

ListenSocketoperator= (const ListenSocket &)

Private Attributes

int m_depth
X * m_creator
bool m_bHasCreate

Detailed Description

template<class X>
class ListenSocket< X >

Binds incoming port number to new Socket class X.

Definition at line 61 of file ListenSocket.h.


Constructor & Destructor Documentation

template<class X>
ListenSocket< X >::ListenSocket ( ISocketHandler h,
bool  use_creator = true 
) [inline]

Constructor.

Parameters:
h ISocketHandler reference
use_creator Optional use of creator (default true)

Definition at line 67 of file ListenSocket.h.

00067                                                                 : Socket(h), m_depth(0), m_creator(NULL)
00068         ,m_bHasCreate(false)
00069         {
00070                 if (use_creator)
00071                 {
00072                         m_creator = new X(h);
00073                         Socket *tmp = m_creator -> Create();
00074                         if (tmp && dynamic_cast<X *>(tmp))
00075                         {
00076                                 m_bHasCreate = true;
00077                         }
00078                         if (tmp)
00079                         {
00080                                 delete tmp;
00081                         }
00082                 }
00083         }

template<class X>
ListenSocket< X >::~ListenSocket (  )  [inline]

Definition at line 84 of file ListenSocket.h.

00084                         {
00085                 if (m_creator)
00086                 {
00087                         delete m_creator;
00088                 }
00089         }

template<class X>
ListenSocket< X >::ListenSocket ( const ListenSocket< X > &  s  )  [inline, protected]

Definition at line 497 of file ListenSocket.h.

00497 : Socket(s) {}


Member Function Documentation

template<class X>
int ListenSocket< X >::Close (  )  [inline, virtual]

Close file descriptor.

Reimplemented from Socket.

Definition at line 92 of file ListenSocket.h.

References closesocket, and INVALID_SOCKET.

00092                     {
00093                 if (GetSocket() != INVALID_SOCKET)
00094                 {
00095                         if (closesocket(GetSocket()) == -1)
00096                         {
00097                         }
00098                         else
00099                         {
00100                                 Attach(INVALID_SOCKET);
00101                         }
00102                 }
00103                 return 0;
00104         }

template<class X>
int ListenSocket< X >::Bind ( port_t  port,
int  depth = 20 
) [inline]

Bind and listen to any interface.

Parameters:
port Port (0 is random)
depth Listen queue depth

Definition at line 109 of file ListenSocket.h.

Referenced by ResolvServer::Run().

00109                                              {
00110 #ifdef ENABLE_IPV6
00111 #ifdef IPPROTO_IPV6
00112                 if (IsIpv6())
00113                 {
00114                         Ipv6Address ad(port);
00115                         return Bind(ad, depth);
00116                 }
00117                 else
00118 #endif
00119 #endif
00120                 {
00121                         Ipv4Address ad(port);
00122                         return Bind(ad, depth);
00123                 }
00124         }

template<class X>
int ListenSocket< X >::Bind ( SocketAddress ad,
int  depth 
) [inline]

Definition at line 126 of file ListenSocket.h.

00126                                               {
00127 #ifdef USE_SCTP
00128                 if (dynamic_cast<SctpSocket *>(m_creator))
00129                 {
00130                         return Bind(ad, "sctp", depth);
00131                 }
00132 #endif
00133                 return Bind(ad, "tcp", depth);
00134         }

template<class X>
int ListenSocket< X >::Bind ( port_t  port,
const std::string &  protocol,
int  depth = 20 
) [inline]

Bind and listen to any interface, with optional protocol.

Parameters:
port Port (0 is random)
protocol Network protocol
depth Listen queue depth

Definition at line 140 of file ListenSocket.h.

00140                                                                        {
00141 #ifdef ENABLE_IPV6
00142 #ifdef IPPROTO_IPV6
00143                 if (IsIpv6())
00144                 {
00145                         Ipv6Address ad(port);
00146                         return Bind(ad, protocol, depth);
00147                 }
00148                 else
00149 #endif
00150 #endif
00151                 {
00152                         Ipv4Address ad(port);
00153                         return Bind(ad, protocol, depth);
00154                 }
00155         }

template<class X>
int ListenSocket< X >::Bind ( const std::string &  intf,
port_t  port,
int  depth = 20 
) [inline]

Bind and listen to specific interface.

Parameters:
intf Interface hostname
port Port (0 is random)
depth Listen queue depth

Definition at line 161 of file ListenSocket.h.

References Ipv4Address::IsValid(), and LOG_LEVEL_FATAL.

00161                                                                    {
00162 #ifdef ENABLE_IPV6
00163 #ifdef IPPROTO_IPV6
00164                 if (IsIpv6())
00165                 {
00166                         Ipv6Address ad(intf, port);
00167                         if (ad.IsValid())
00168                         {
00169                                 return Bind(ad, depth);
00170                         }
00171                         Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
00172                         return -1;
00173                 }
00174                 else
00175 #endif
00176 #endif
00177                 {
00178                         Ipv4Address ad(intf, port);
00179                         if (ad.IsValid())
00180                         {
00181                                 return Bind(ad, depth);
00182                         }
00183                         Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
00184                         return -1;
00185                 }
00186         }

template<class X>
int ListenSocket< X >::Bind ( const std::string &  intf,
port_t  port,
const std::string &  protocol,
int  depth = 20 
) [inline]

Bind and listen to specific interface.

Parameters:
intf Interface hostname
port Port (0 is random)
protocol Network protocol
depth Listen queue depth

Definition at line 193 of file ListenSocket.h.

References Ipv4Address::IsValid(), and LOG_LEVEL_FATAL.

00193                                                                                              {
00194 #ifdef ENABLE_IPV6
00195 #ifdef IPPROTO_IPV6
00196                 if (IsIpv6())
00197                 {
00198                         Ipv6Address ad(intf, port);
00199                         if (ad.IsValid())
00200                         {
00201                                 return Bind(ad, protocol, depth);
00202                         }
00203                         Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
00204                         return -1;
00205                 }
00206                 else
00207 #endif
00208 #endif
00209                 {
00210                         Ipv4Address ad(intf, port);
00211                         if (ad.IsValid())
00212                         {
00213                                 return Bind(ad, protocol, depth);
00214                         }
00215                         Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
00216                         return -1;
00217                 }
00218         }

template<class X>
int ListenSocket< X >::Bind ( ipaddr_t  a,
port_t  port,
int  depth = 20 
) [inline]

Bind and listen to ipv4 interface.

Parameters:
a Ipv4 interface address
port Port (0 is random)
depth Listen queue depth

Definition at line 224 of file ListenSocket.h.

00224                                                         {
00225                 Ipv4Address ad(a, port);
00226 #ifdef USE_SCTP
00227                 if (dynamic_cast<SctpSocket *>(m_creator))
00228                 {
00229                         return Bind(ad, "sctp", depth);
00230                 }
00231 #endif
00232                 return Bind(ad, "tcp", depth);
00233         }

template<class X>
int ListenSocket< X >::Bind ( ipaddr_t  a,
port_t  port,
const std::string &  protocol,
int  depth 
) [inline]

Bind and listen to ipv4 interface.

Parameters:
a Ipv4 interface address
port Port (0 is random)
protocol Network protocol
depth Listen queue depth

Definition at line 239 of file ListenSocket.h.

00239                                                                              {
00240                 Ipv4Address ad(a, port);
00241                 return Bind(ad, protocol, depth);
00242         }

template<class X>
int ListenSocket< X >::Bind ( SocketAddress ad,
const std::string &  protocol,
int  depth 
) [inline]

Bind and listen to network interface.

Parameters:
ad Interface address
protocol Network protocol
depth Listen queue depth

Definition at line 276 of file ListenSocket.h.

References closesocket, Errno, SocketAddress::GetFamily(), SocketAddress::GetPort(), INVALID_SOCKET, Utility::l2string(), LOG_LEVEL_FATAL, and StrError.

00276                                                                         {
00277                 SOCKET s;
00278                 if ( (s = CreateSocket(ad.GetFamily(), SOCK_STREAM, protocol)) == INVALID_SOCKET)
00279                 {
00280                         return -1;
00281                 }
00282                 // socket must be nonblocking for async connect
00283                 if (!SetNonblocking(true, s))
00284                 {
00285                         closesocket(s);
00286                         return -1;
00287                 }
00288                 if (bind(s, ad, ad) == -1)
00289                 {
00290                         Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00291                         closesocket(s);
00292 #ifdef ENABLE_EXCEPTIONS
00293                         throw Exception("bind() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
00294 #endif
00295                         return -1;
00296                 }
00297                 if (listen(s, depth) == -1)
00298                 {
00299                         Handler().LogError(this, "listen", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00300                         closesocket(s);
00301 #ifdef ENABLE_EXCEPTIONS
00302                         throw Exception("listen() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
00303 #endif
00304                         return -1;
00305                 }
00306                 m_depth = depth;
00307                 Attach(s);
00308                 return 0;
00309         }

template<class X>
port_t ListenSocket< X >::GetPort (  )  [inline, virtual]

Return assigned port number.

Reimplemented from Socket.

Definition at line 312 of file ListenSocket.h.

00313         {
00314                 return GetSockPort();
00315         }

template<class X>
int ListenSocket< X >::GetDepth (  )  [inline]

Return listen queue depth.

Definition at line 318 of file ListenSocket.h.

00319         {
00320                 return m_depth;
00321         }

template<class X>
void ListenSocket< X >::OnRead (  )  [inline, virtual]

OnRead on a ListenSocket receives an incoming connection.

Reimplemented from Socket.

Definition at line 324 of file ListenSocket.h.

References ISocketHandler::Add(), closesocket, Errno, ISocketHandler::GetMutex(), INVALID_SOCKET, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_WARNING, ISocketHandler::Release(), and StrError.

00325         {
00326                 struct sockaddr sa;
00327                 int max = 10; // process max 10 incoming connection in one call
00328                 while (max--)
00329                 {
00330                         socklen_t sa_len = sizeof(struct sockaddr);
00331                         SOCKET a_s = accept(GetSocket(), &sa, &sa_len);
00332                         if (a_s == INVALID_SOCKET)
00333                         {
00334                                 // EAGAIN or EWOULDBLOCK
00335 #ifdef _WIN32
00336                                 if (Errno != WSAEWOULDBLOCK)
00337 #else
00338                                 if (Errno != EWOULDBLOCK)
00339 #endif
00340                                 {
00341                                         Handler().LogError(this, "accept", Errno, StrError(Errno), LOG_LEVEL_ERROR);
00342                                 }
00343                                 return;
00344                         }
00345                         if (!Handler().OkToAccept(this))
00346                         {
00347                                 Handler().LogError(this, "accept", -1, "Not OK to accept", LOG_LEVEL_WARNING);
00348                                 closesocket(a_s);
00349                                 return;
00350                         }
00351                         if (Handler().GetCount() >= Handler().MaxCount())
00352                         {
00353                                 Handler().LogError(this, "accept", (int)Handler().GetCount(), "ISocketHandler socket limit reached", LOG_LEVEL_FATAL);
00354                                 closesocket(a_s);
00355                                 return;
00356                         }
00357                         //
00358                         Socket *tmp = NULL;
00359                         if (Handler().IsThreaded())
00360                         {
00361                                 ISocketHandler& h = Handler().GetRandomHandler();
00362                                 tmp = new X(h); // %! no support for Create
00363 #ifdef ENABLE_IPV6
00364                                 tmp -> SetIpv6( IsIpv6() );
00365 #endif
00366                                 tmp -> SetParent(this);
00367                                 tmp -> Attach(a_s);
00368                                 tmp -> SetNonblocking(true);
00369 #ifdef ENABLE_IPV6
00370 #ifdef IPPROTO_IPV6
00371                                 if (sa_len == sizeof(struct sockaddr_in6))
00372                                 {
00373                                         if (reinterpret_cast<struct sockaddr_in6&>(sa).sin6_family == AF_INET6)
00374                                         {
00375                                                 Ipv6Address ad(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_addr,
00376                                                         ntohs(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_port));
00377                                                 ad.SetFlowinfo(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_flowinfo);
00378 #ifndef _WIN32
00379                                                 ad.SetScopeId(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_scope_id);
00380 #endif
00381                                                 tmp -> SetRemoteAddress(ad);
00382                                         }
00383                                 }
00384 #endif
00385 #endif
00386                                 if (sa_len == sizeof(struct sockaddr_in))
00387                                 {
00388                                         struct sockaddr_in *p = (struct sockaddr_in *)&sa;
00389                                         if (p -> sin_family == AF_INET)
00390                                         {
00391                                                 Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
00392                                                 tmp -> SetRemoteAddress(ad);
00393                                         }
00394                                 }
00395                                 tmp -> SetConnected(true);
00396                                 tmp -> Init();
00397                                 tmp -> SetDeleteByHandler(true);
00398                                 {
00399                                         Lock lock(h.GetMutex());
00400                                         h.Add(tmp);
00401 #ifdef HAVE_OPENSSL
00402                                         if (tmp -> IsSSL()) // SSL Enabled socket
00403                                         {
00404                                                 // %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
00405                                                 // %! If that happens and negotiation fails, the 'tmp' instance is
00406                                                 // %! still added to the list of active sockets in the sockethandler.
00407                                                 // %! See bugfix for this in SocketHandler::Select - don't Set rwx
00408                                                 // %! flags if CloseAndDelete() flag is true.
00409                                                 // %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
00410                                                 // %! the Add problem altogether, so ignore the above.
00411                                                 // %! (OnSSLAccept does no longer call SSLNegotiate().)
00412                                                 tmp -> OnSSLAccept();
00413                                         }
00414                                         else
00415 #endif
00416                                         {
00417                                                 tmp -> OnAccept();
00418                                         }
00419                                 }
00420                                 h.Release();
00421                         }
00422                         else
00423                         {
00424                                 tmp = m_bHasCreate ? m_creator -> Create() : new X(Handler());
00425 #ifdef ENABLE_IPV6
00426                                 tmp -> SetIpv6( IsIpv6() );
00427 #endif
00428                                 tmp -> SetParent(this);
00429                                 tmp -> Attach(a_s);
00430                                 tmp -> SetNonblocking(true);
00431 #ifdef ENABLE_IPV6
00432 #ifdef IPPROTO_IPV6
00433                                 if (sa_len == sizeof(struct sockaddr_in6))
00434                                 {
00435                                         if (reinterpret_cast<struct sockaddr_in6&>(sa).sin6_family == AF_INET6)
00436                                         {
00437                                                 Ipv6Address ad(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_addr,
00438                                                         ntohs(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_port));
00439                                                 ad.SetFlowinfo(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_flowinfo);
00440 #ifndef _WIN32
00441                                                 ad.SetScopeId(reinterpret_cast<struct sockaddr_in6&>(sa).sin6_scope_id);
00442 #endif
00443                                                 tmp -> SetRemoteAddress(ad);
00444                                         }
00445                                 }
00446 #endif
00447 #endif
00448                                 if (sa_len == sizeof(struct sockaddr_in))
00449                                 {
00450                                         struct sockaddr_in *p = (struct sockaddr_in *)&sa;
00451                                         if (p -> sin_family == AF_INET)
00452                                         {
00453                                                 Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
00454                                                 tmp -> SetRemoteAddress(ad);
00455                                         }
00456                                 }
00457                                 tmp -> SetConnected(true);
00458                                 tmp -> Init();
00459                                 tmp -> SetDeleteByHandler(true);
00460                                 Handler().Add(tmp);
00461 #ifdef HAVE_OPENSSL
00462                                 if (tmp -> IsSSL()) // SSL Enabled socket
00463                                 {
00464                                         // %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
00465                                         // %! If that happens and negotiation fails, the 'tmp' instance is
00466                                         // %! still added to the list of active sockets in the sockethandler.
00467                                         // %! See bugfix for this in SocketHandler::Select - don't Set rwx
00468                                         // %! flags if CloseAndDelete() flag is true.
00469                                         // %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
00470                                         // %! the Add problem altogether, so ignore the above.
00471                                         // %! (OnSSLAccept does no longer call SSLNegotiate().)
00472                                         tmp -> OnSSLAccept();
00473                                 }
00474                                 else
00475 #endif
00476                                 {
00477                                         tmp -> OnAccept();
00478                                 }
00479                         }
00480                 } // while (true)
00481         }

template<class X>
virtual SOCKET ListenSocket< X >::Accept ( SOCKET  socket,
struct sockaddr *  saptr,
socklen_t *  lenptr 
) [inline, virtual]

Please don't use this method.

"accept()" is handled automatically in the OnRead() method.

Definition at line 485 of file ListenSocket.h.

00486         {
00487                 return accept(socket, saptr, lenptr);
00488         }

template<class X>
bool ListenSocket< X >::HasCreator (  )  [inline]

Definition at line 490 of file ListenSocket.h.

00490 { return m_bHasCreate; }

template<class X>
void ListenSocket< X >::OnOptions ( int  family,
int  type,
int  protocol,
SOCKET  s 
) [inline, virtual]

Called when a client socket is created, to set socket options.

Parameters:
family AF_INET, AF_INET6, etc
type SOCK_STREAM, SOCK_DGRAM, etc
protocol Protocol number (tcp, udp, sctp, etc)
s Socket file descriptor

Implements Socket.

Definition at line 492 of file ListenSocket.h.

00492                                            {
00493                 SetSoReuseaddr(true);
00494         }

template<class X>
ListenSocket& ListenSocket< X >::operator= ( const ListenSocket< X > &   )  [inline, private]

Definition at line 499 of file ListenSocket.h.

00499 { return *this; }


Member Data Documentation

template<class X>
int ListenSocket< X >::m_depth [private]

Definition at line 500 of file ListenSocket.h.

template<class X>
X* ListenSocket< X >::m_creator [private]

Definition at line 501 of file ListenSocket.h.

template<class X>
bool ListenSocket< X >::m_bHasCreate [private]

Definition at line 502 of file ListenSocket.h.


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