![]() |
ListenSocket< X > Class Template ReferenceBinds incoming port number to new Socket class X.
More...
|
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 | |
ListenSocket & | operator= (const ListenSocket &) |
Private Attributes | |
int | m_depth |
X * | m_creator |
bool | m_bHasCreate |
Definition at line 61 of file ListenSocket.h.
ListenSocket< X >::ListenSocket | ( | ISocketHandler & | h, | |
bool | use_creator = true | |||
) | [inline] |
Constructor.
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 }
ListenSocket< X >::~ListenSocket | ( | ) | [inline] |
ListenSocket< X >::ListenSocket | ( | const ListenSocket< X > & | s | ) | [inline, protected] |
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 }
int ListenSocket< X >::Bind | ( | port_t | port, | |
int | depth = 20 | |||
) | [inline] |
Bind and listen to any interface.
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 }
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 }
int ListenSocket< X >::Bind | ( | port_t | port, | |
const std::string & | protocol, | |||
int | depth = 20 | |||
) | [inline] |
Bind and listen to any interface, with optional protocol.
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 }
int ListenSocket< X >::Bind | ( | const std::string & | intf, | |
port_t | port, | |||
int | depth = 20 | |||
) | [inline] |
Bind and listen to specific interface.
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 }
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.
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 }
int ListenSocket< X >::Bind | ( | ipaddr_t | a, | |
port_t | port, | |||
int | depth = 20 | |||
) | [inline] |
Bind and listen to ipv4 interface.
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 }
int ListenSocket< X >::Bind | ( | ipaddr_t | a, | |
port_t | port, | |||
const std::string & | protocol, | |||
int | depth | |||
) | [inline] |
Bind and listen to ipv4 interface.
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 }
int ListenSocket< X >::Bind | ( | SocketAddress & | ad, | |
const std::string & | protocol, | |||
int | depth | |||
) | [inline] |
Bind and listen to network interface.
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 }
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 }
int ListenSocket< X >::GetDepth | ( | ) | [inline] |
Return listen queue depth.
Definition at line 318 of file ListenSocket.h.
00319 { 00320 return m_depth; 00321 }
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 }
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.
bool ListenSocket< X >::HasCreator | ( | ) | [inline] |
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.
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 }
ListenSocket& ListenSocket< X >::operator= | ( | const ListenSocket< X > & | ) | [inline, private] |
int ListenSocket< X >::m_depth [private] |
Definition at line 500 of file ListenSocket.h.
X* ListenSocket< X >::m_creator [private] |
Definition at line 501 of file ListenSocket.h.
bool ListenSocket< X >::m_bHasCreate [private] |
Definition at line 502 of file ListenSocket.h.