PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/include/sockets/ListenSocket.h

https://bitbucket.org/oregon/oregoncore/
C Header | 421 lines | 307 code | 28 blank | 86 comment | 37 complexity | d41f92cbe33fe0b1f8d992487f61bec6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, CC-BY-SA-3.0, BSD-2-Clause
  1. /** \file ListenSocket.h
  2. ** \date 2004-02-13
  3. ** \author grymse@alhem.net
  4. **/
  5. /*
  6. Copyright (C) 2004-2007 Anders Hedstrom
  7. This library is made available under the terms of the GNU GPL.
  8. If you would like to use this library in a closed-source application,
  9. a separate license agreement is available. For information about
  10. the closed-source license agreement for the C++ sockets library,
  11. please visit http://www.alhem.net/Sockets/license.html and/or
  12. email license@alhem.net.
  13. This program is free software; you can redistribute it and/or
  14. modify it under the terms of the GNU General Public License
  15. as published by the Free Software Foundation; either version 2
  16. of the License, or (at your option) any later version.
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. GNU General Public License for more details.
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24. */
  25. #ifndef _SOCKETS_ListenSocket_H
  26. #define _SOCKETS_ListenSocket_H
  27. #include "sockets-config.h"
  28. #ifdef _WIN32
  29. #include <stdlib.h>
  30. #else
  31. #include <errno.h>
  32. #endif
  33. #include "ISocketHandler.h"
  34. #include "Socket.h"
  35. #include "Utility.h"
  36. #include "SctpSocket.h"
  37. #include "Ipv4Address.h"
  38. #include "Ipv6Address.h"
  39. #ifdef ENABLE_EXCEPTIONS
  40. #include "Exception.h"
  41. #endif
  42. #ifdef SOCKETS_NAMESPACE
  43. namespace SOCKETS_NAMESPACE {
  44. #endif
  45. /** Binds incoming port number to new Socket class X.
  46. \ingroup basic */
  47. template <class X>
  48. class ListenSocket : public Socket
  49. {
  50. public:
  51. /** Constructor.
  52. \param h ISocketHandler reference
  53. \param use_creator Optional use of creator (default true) */
  54. ListenSocket(ISocketHandler& h,bool use_creator = true) : Socket(h), m_depth(0), m_creator(NULL)
  55. ,m_bHasCreate(false)
  56. {
  57. if (use_creator)
  58. {
  59. m_creator = new X(h);
  60. Socket *tmp = m_creator -> Create();
  61. if (tmp && dynamic_cast<X *>(tmp))
  62. {
  63. m_bHasCreate = true;
  64. }
  65. if (tmp)
  66. {
  67. delete tmp;
  68. }
  69. }
  70. }
  71. ~ListenSocket() {
  72. if (m_creator)
  73. {
  74. delete m_creator;
  75. }
  76. }
  77. /** Close file descriptor. */
  78. int Close() {
  79. if (GetSocket() != INVALID_SOCKET)
  80. {
  81. closesocket(GetSocket());
  82. }
  83. return 0;
  84. }
  85. /** Bind and listen to any interface.
  86. \param port Port (0 is random)
  87. \param depth Listen queue depth */
  88. int Bind(port_t port,int depth = 20) {
  89. #ifdef ENABLE_IPV6
  90. #ifdef IPPROTO_IPV6
  91. if (IsIpv6())
  92. {
  93. Ipv6Address ad(port);
  94. return Bind(ad, depth);
  95. }
  96. else
  97. #endif
  98. #endif
  99. {
  100. Ipv4Address ad(port);
  101. return Bind(ad, depth);
  102. }
  103. }
  104. int Bind(SocketAddress& ad,int depth) {
  105. #ifdef USE_SCTP
  106. if (dynamic_cast<SctpSocket *>(m_creator))
  107. {
  108. return Bind(ad, "sctp", depth);
  109. }
  110. #endif
  111. return Bind(ad, "tcp", depth);
  112. }
  113. /** Bind and listen to any interface, with optional protocol.
  114. \param port Port (0 is random)
  115. \param protocol Network protocol
  116. \param depth Listen queue depth */
  117. int Bind(port_t port,const std::string& protocol,int depth = 20) {
  118. #ifdef ENABLE_IPV6
  119. #ifdef IPPROTO_IPV6
  120. if (IsIpv6())
  121. {
  122. Ipv6Address ad(port);
  123. return Bind(ad, protocol, depth);
  124. }
  125. else
  126. #endif
  127. #endif
  128. {
  129. Ipv4Address ad(port);
  130. return Bind(ad, protocol, depth);
  131. }
  132. }
  133. /** Bind and listen to specific interface.
  134. \param intf Interface hostname
  135. \param port Port (0 is random)
  136. \param depth Listen queue depth */
  137. int Bind(const std::string& intf,port_t port,int depth = 20) {
  138. #ifdef ENABLE_IPV6
  139. #ifdef IPPROTO_IPV6
  140. if (IsIpv6())
  141. {
  142. Ipv6Address ad(intf, port);
  143. if (ad.IsValid())
  144. {
  145. return Bind(ad, depth);
  146. }
  147. Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
  148. return -1;
  149. }
  150. else
  151. #endif
  152. #endif
  153. {
  154. Ipv4Address ad(intf, port);
  155. if (ad.IsValid())
  156. {
  157. return Bind(ad, depth);
  158. }
  159. Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
  160. return -1;
  161. }
  162. }
  163. /** Bind and listen to specific interface.
  164. \param intf Interface hostname
  165. \param port Port (0 is random)
  166. \param protocol Network protocol
  167. \param depth Listen queue depth */
  168. int Bind(const std::string& intf,port_t port,const std::string& protocol,int depth = 20) {
  169. #ifdef ENABLE_IPV6
  170. #ifdef IPPROTO_IPV6
  171. if (IsIpv6())
  172. {
  173. Ipv6Address ad(intf, port);
  174. if (ad.IsValid())
  175. {
  176. return Bind(ad, protocol, depth);
  177. }
  178. Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
  179. return -1;
  180. }
  181. else
  182. #endif
  183. #endif
  184. {
  185. Ipv4Address ad(intf, port);
  186. if (ad.IsValid())
  187. {
  188. return Bind(ad, protocol, depth);
  189. }
  190. Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
  191. return -1;
  192. }
  193. }
  194. /** Bind and listen to ipv4 interface.
  195. \param a Ipv4 interface address
  196. \param port Port (0 is random)
  197. \param depth Listen queue depth */
  198. int Bind(ipaddr_t a,port_t port,int depth = 20) {
  199. Ipv4Address ad(a, port);
  200. #ifdef USE_SCTP
  201. if (dynamic_cast<SctpSocket *>(m_creator))
  202. {
  203. return Bind(ad, "sctp", depth);
  204. }
  205. #endif
  206. return Bind(ad, "tcp", depth);
  207. }
  208. /** Bind and listen to ipv4 interface.
  209. \param a Ipv4 interface address
  210. \param port Port (0 is random)
  211. \param protocol Network protocol
  212. \param depth Listen queue depth */
  213. int Bind(ipaddr_t a,port_t port,const std::string& protocol,int depth) {
  214. Ipv4Address ad(a, port);
  215. return Bind(ad, protocol, depth);
  216. }
  217. #ifdef ENABLE_IPV6
  218. #ifdef IPPROTO_IPV6
  219. /** Bind and listen to ipv6 interface.
  220. \param a Ipv6 interface address
  221. \param port Port (0 is random)
  222. \param depth Listen queue depth */
  223. int Bind(in6_addr a,port_t port,int depth = 20) {
  224. Ipv6Address ad(a, port);
  225. #ifdef USE_SCTP
  226. if (dynamic_cast<SctpSocket *>(m_creator))
  227. {
  228. return Bind(ad, "sctp", depth);
  229. }
  230. #endif
  231. return Bind(ad, "tcp", depth);
  232. }
  233. /** Bind and listen to ipv6 interface.
  234. \param a Ipv6 interface address
  235. \param port Port (0 is random)
  236. \param protocol Network protocol
  237. \param depth Listen queue depth */
  238. int Bind(in6_addr a,port_t port,const std::string& protocol,int depth) {
  239. Ipv6Address ad(a, port);
  240. return Bind(ad, protocol, depth);
  241. }
  242. #endif
  243. #endif
  244. /** Bind and listen to network interface.
  245. \param ad Interface address
  246. \param protocol Network protocol
  247. \param depth Listen queue depth */
  248. int Bind(SocketAddress& ad,const std::string& protocol,int depth) {
  249. SOCKET s;
  250. if ( (s = CreateSocket(ad.GetFamily(), SOCK_STREAM, protocol)) == INVALID_SOCKET)
  251. {
  252. return -1;
  253. }
  254. if (bind(s, ad, ad) == -1)
  255. {
  256. Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
  257. closesocket(s);
  258. #ifdef ENABLE_EXCEPTIONS
  259. throw Exception("bind() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
  260. #endif
  261. return -1;
  262. }
  263. if (listen(s, depth) == -1)
  264. {
  265. Handler().LogError(this, "listen", Errno, StrError(Errno), LOG_LEVEL_FATAL);
  266. closesocket(s);
  267. #ifdef ENABLE_EXCEPTIONS
  268. throw Exception("listen() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
  269. #endif
  270. return -1;
  271. }
  272. m_depth = depth;
  273. Attach(s);
  274. return 0;
  275. }
  276. /** Return assigned port number. */
  277. port_t GetPort()
  278. {
  279. return GetSockPort();
  280. }
  281. /** Return listen queue depth. */
  282. int GetDepth()
  283. {
  284. return m_depth;
  285. }
  286. /** OnRead on a ListenSocket receives an incoming connection. */
  287. void OnRead()
  288. {
  289. struct sockaddr sa;
  290. socklen_t sa_len = sizeof(struct sockaddr);
  291. SOCKET a_s = accept(GetSocket(), &sa, &sa_len);
  292. if (a_s == INVALID_SOCKET)
  293. {
  294. Handler().LogError(this, "accept", Errno, StrError(Errno), LOG_LEVEL_ERROR);
  295. return;
  296. }
  297. if (!Handler().OkToAccept(this))
  298. {
  299. Handler().LogError(this, "accept", -1, "Not OK to accept", LOG_LEVEL_WARNING);
  300. closesocket(a_s);
  301. return;
  302. }
  303. if (Handler().GetCount() >= FD_SETSIZE)
  304. {
  305. Handler().LogError(this, "accept", (int)Handler().GetCount(), "ISocketHandler fd_set limit reached", LOG_LEVEL_FATAL);
  306. closesocket(a_s);
  307. return;
  308. }
  309. Socket *tmp = m_bHasCreate ? m_creator -> Create() : new X(Handler());
  310. #ifdef ENABLE_IPV6
  311. tmp -> SetIpv6( IsIpv6() );
  312. #endif
  313. tmp -> SetParent(this);
  314. tmp -> Attach(a_s);
  315. tmp -> SetNonblocking(true);
  316. {
  317. #ifdef ENABLE_IPV6
  318. #ifdef IPPROTO_IPV6
  319. if (sa_len == sizeof(struct sockaddr_in6))
  320. {
  321. struct sockaddr_in6 *p = (struct sockaddr_in6 *)&sa;
  322. if (p -> sin6_family == AF_INET6)
  323. {
  324. Ipv6Address ad(p -> sin6_addr,ntohs(p -> sin6_port));
  325. ad.SetFlowinfo(p -> sin6_flowinfo);
  326. #ifndef _WIN32
  327. ad.SetScopeId(p -> sin6_scope_id);
  328. #endif
  329. tmp -> SetRemoteAddress(ad);
  330. }
  331. }
  332. #endif
  333. #endif
  334. if (sa_len == sizeof(struct sockaddr_in))
  335. {
  336. struct sockaddr_in *p = (struct sockaddr_in *)&sa;
  337. if (p -> sin_family == AF_INET)
  338. {
  339. Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
  340. tmp -> SetRemoteAddress(ad);
  341. }
  342. }
  343. }
  344. tmp -> SetConnected(true);
  345. tmp -> Init();
  346. tmp -> SetDeleteByHandler(true);
  347. Handler().Add(tmp);
  348. #ifdef HAVE_OPENSSL
  349. if (tmp -> IsSSL()) // SSL Enabled socket
  350. {
  351. // %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
  352. // %! If that happens and negotiation fails, the 'tmp' instance is
  353. // %! still added to the list of active sockets in the sockethandler.
  354. // %! See bugfix for this in SocketHandler::Select - don't Set rwx
  355. // %! flags if CloseAndDelete() flag is true.
  356. // %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
  357. // %! the Add problem altogether, so ignore the above.
  358. // %! (OnSSLAccept does no longer call SSLNegotiate().)
  359. tmp -> OnSSLAccept();
  360. }
  361. else
  362. #endif
  363. {
  364. tmp -> OnAccept();
  365. }
  366. }
  367. /** Please don't use this method.
  368. "accept()" is handled automatically in the OnRead() method. */
  369. virtual SOCKET Accept(SOCKET socket, struct sockaddr *saptr, socklen_t *lenptr)
  370. {
  371. return accept(socket, saptr, lenptr);
  372. }
  373. bool HasCreator() { return m_bHasCreate; }
  374. void OnOptions(int,int,int,SOCKET) {
  375. SetSoReuseaddr(true);
  376. }
  377. protected:
  378. ListenSocket(const ListenSocket& s) : Socket(s) {}
  379. private:
  380. ListenSocket& operator=(const ListenSocket& ) { return *this; }
  381. int m_depth;
  382. X *m_creator;
  383. bool m_bHasCreate;
  384. };
  385. #ifdef SOCKETS_NAMESPACE
  386. }
  387. #endif
  388. #endif // _SOCKETS_ListenSocket_H