fixed windows endian include
[anytun.git] / src / syncListenSocket.h
blob9740ecf07dc34e28aa76269e4919a320dbeb967d
1 /*
2 Copyright (C) 2004-2007 Anders Hedstrom
4 This library is made available under the terms of the GNU GPL.
6 If you would like to use this library in a closed-source application,
7 a separate license agreement is available. For information about
8 the closed-source license agreement for the C++ sockets library,
9 please visit http://www.alhem.net/Sockets/license.html and/or
10 email license@alhem.net.
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 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.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #ifndef _SOCKETS_SyncListenSocket_H
27 #define _SOCKETS_SyncListenSocket_H
28 #include "Sockets/sockets-config.h"
30 #ifdef _WIN32
31 #include <stdlib.h>
32 #else
33 #include <errno.h>
34 #endif
36 #include "Sockets/ISocketHandler.h"
37 #include "Sockets/Socket.h"
38 #include "Sockets/Utility.h"
39 #include "Sockets/SctpSocket.h"
40 #include "Sockets/Ipv4Address.h"
41 #include "Sockets/Ipv6Address.h"
42 #ifdef ENABLE_EXCEPTIONS
43 #include "Sockets/Exception.h"
44 #endif
46 #ifdef SOCKETS_NAMESPACE
47 namespace SOCKETS_NAMESPACE {
48 #endif
51 /** Binds incoming port number to new Socket class X.
52 \ingroup basic */
53 template <class X,class Y>
54 class SyncListenSocket : public Socket
56 public:
57 /** Constructor.
58 \param h ISocketHandler reference
59 \param use_creator Optional use of creator (default true) */
60 SyncListenSocket(ISocketHandler& h, Y & y,bool use_creator = true) : Socket(h), m_depth(0), m_creator(NULL),
61 m_bHasCreate(false),y_(y)
63 if (use_creator)
65 m_creator = new X(h,y);
66 Socket *tmp = m_creator -> Create();
67 if (tmp && dynamic_cast<X *>(tmp))
69 m_bHasCreate = true;
71 if (tmp)
73 delete tmp;
77 ~SyncListenSocket() {
78 if (m_creator)
80 delete m_creator;
84 /** Close file descriptor. */
85 int Close() {
86 if (GetSocket() != INVALID_SOCKET)
88 closesocket(GetSocket());
90 return 0;
93 /** Bind and listen to any interface.
94 \param port Port (0 is random)
95 \param depth Listen queue depth */
96 int Bind(port_t port,int depth = 20) {
97 #ifdef ENABLE_IPV6
98 #ifdef IPPROTO_IPV6
99 if (IsIpv6())
101 Ipv6Address ad(port);
102 return Bind(ad, depth);
104 else
105 #endif
106 #endif
108 Ipv4Address ad(port);
109 return Bind(ad, depth);
113 int Bind(SocketAddress& ad,int depth) {
114 #ifdef USE_SCTP
115 if (dynamic_cast<SctpSocket *>(m_creator))
117 return Bind(ad, "sctp", depth);
119 #endif
120 return Bind(ad, "tcp", depth);
123 /** Bind and listen to any interface, with optional protocol.
124 \param port Port (0 is random)
125 \param protocol Network protocol
126 \param depth Listen queue depth */
127 int Bind(port_t port,const std::string& protocol,int depth = 20) {
128 #ifdef ENABLE_IPV6
129 #ifdef IPPROTO_IPV6
130 if (IsIpv6())
132 Ipv6Address ad(port);
133 return Bind(ad, protocol, depth);
135 else
136 #endif
137 #endif
139 Ipv4Address ad(port);
140 return Bind(ad, protocol, depth);
144 /** Bind and listen to specific interface.
145 \param intf Interface hostname
146 \param port Port (0 is random)
147 \param depth Listen queue depth */
148 int Bind(const std::string& intf,port_t port,int depth = 20) {
149 #ifdef ENABLE_IPV6
150 #ifdef IPPROTO_IPV6
151 if (IsIpv6())
153 Ipv6Address ad(intf, port);
154 if (ad.IsValid())
156 return Bind(ad, depth);
158 Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
159 return -1;
161 else
162 #endif
163 #endif
165 Ipv4Address ad(intf, port);
166 if (ad.IsValid())
168 return Bind(ad, depth);
170 Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
171 return -1;
175 /** Bind and listen to specific interface.
176 \param intf Interface hostname
177 \param port Port (0 is random)
178 \param protocol Network protocol
179 \param depth Listen queue depth */
180 int Bind(const std::string& intf,port_t port,const std::string& protocol,int depth = 20) {
181 #ifdef ENABLE_IPV6
182 #ifdef IPPROTO_IPV6
183 if (IsIpv6())
185 Ipv6Address ad(intf, port);
186 if (ad.IsValid())
188 return Bind(ad, protocol, depth);
190 Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
191 return -1;
193 else
194 #endif
195 #endif
197 Ipv4Address ad(intf, port);
198 if (ad.IsValid())
200 return Bind(ad, protocol, depth);
202 Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
203 return -1;
207 /** Bind and listen to ipv4 interface.
208 \param a Ipv4 interface address
209 \param port Port (0 is random)
210 \param depth Listen queue depth */
211 int Bind(ipaddr_t a,port_t port,int depth = 20) {
212 Ipv4Address ad(a, port);
213 #ifdef USE_SCTP
214 if (dynamic_cast<SctpSocket *>(m_creator))
216 return Bind(ad, "sctp", depth);
218 #endif
219 return Bind(ad, "tcp", depth);
221 /** Bind and listen to ipv4 interface.
222 \param a Ipv4 interface address
223 \param port Port (0 is random)
224 \param protocol Network protocol
225 \param depth Listen queue depth */
226 int Bind(ipaddr_t a,port_t port,const std::string& protocol,int depth) {
227 Ipv4Address ad(a, port);
228 return Bind(ad, protocol, depth);
231 #ifdef ENABLE_IPV6
232 #ifdef IPPROTO_IPV6
233 /** Bind and listen to ipv6 interface.
234 \param a Ipv6 interface address
235 \param port Port (0 is random)
236 \param depth Listen queue depth */
237 int Bind(in6_addr a,port_t port,int depth = 20) {
238 Ipv6Address ad(a, port);
239 #ifdef USE_SCTP
240 if (dynamic_cast<SctpSocket *>(m_creator))
242 return Bind(ad, "sctp", depth);
244 #endif
245 return Bind(ad, "tcp", depth);
247 /** Bind and listen to ipv6 interface.
248 \param a Ipv6 interface address
249 \param port Port (0 is random)
250 \param protocol Network protocol
251 \param depth Listen queue depth */
252 int Bind(in6_addr a,port_t port,const std::string& protocol,int depth) {
253 Ipv6Address ad(a, port);
254 return Bind(ad, protocol, depth);
256 #endif
257 #endif
259 /** Bind and listen to network interface.
260 \param ad Interface address
261 \param protocol Network protocol
262 \param depth Listen queue depth */
263 int Bind(SocketAddress& ad,const std::string& protocol,int depth) {
264 SOCKET s;
265 if ( (s = CreateSocket(ad.GetFamily(), SOCK_STREAM, protocol)) == INVALID_SOCKET)
267 return -1;
269 if (bind(s, ad, ad) == -1)
271 Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
272 closesocket(s);
273 #ifdef ENABLE_EXCEPTIONS
274 throw Exception("bind() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
275 #endif
276 return -1;
278 if (listen(s, depth) == -1)
280 Handler().LogError(this, "listen", Errno, StrError(Errno), LOG_LEVEL_FATAL);
281 closesocket(s);
282 #ifdef ENABLE_EXCEPTIONS
283 throw Exception("listen() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
284 #endif
285 return -1;
287 m_depth = depth;
288 Attach(s);
289 return 0;
292 /** Return assigned port number. */
293 port_t GetPort()
295 return GetSockPort();
298 /** Return listen queue depth. */
299 int GetDepth()
301 return m_depth;
304 /** OnRead on a ListenSocket receives an incoming connection. */
305 void OnRead()
307 struct sockaddr sa;
308 socklen_t sa_len = sizeof(struct sockaddr);
309 SOCKET a_s = accept(GetSocket(), &sa, &sa_len);
311 if (a_s == INVALID_SOCKET)
313 Handler().LogError(this, "accept", Errno, StrError(Errno), LOG_LEVEL_ERROR);
314 return;
316 if (!Handler().OkToAccept(this))
318 Handler().LogError(this, "accept", -1, "Not OK to accept", LOG_LEVEL_WARNING);
319 closesocket(a_s);
320 return;
322 if (Handler().GetCount() >= FD_SETSIZE)
324 Handler().LogError(this, "accept", (int)Handler().GetCount(), "ISocketHandler fd_set limit reached", LOG_LEVEL_FATAL);
325 closesocket(a_s);
326 return;
328 Socket *tmp = m_bHasCreate ? m_creator -> Create() : new X(Handler(),y_);
329 #ifdef ENABLE_IPV6
330 tmp -> SetIpv6( IsIpv6() );
331 #endif
332 tmp -> SetParent(this);
333 tmp -> Attach(a_s);
334 tmp -> SetNonblocking(true);
336 #ifdef ENABLE_IPV6
337 #ifdef IPPROTO_IPV6
338 if (sa_len == sizeof(struct sockaddr_in6))
340 struct sockaddr_in6 *p = (struct sockaddr_in6 *)&sa;
341 if (p -> sin6_family == AF_INET6)
343 Ipv6Address ad(p -> sin6_addr,ntohs(p -> sin6_port));
344 ad.SetFlowinfo(p -> sin6_flowinfo);
345 #ifndef _WIN32
346 ad.SetScopeId(p -> sin6_scope_id);
347 #endif
348 tmp -> SetRemoteAddress(ad);
351 #endif
352 #endif
353 if (sa_len == sizeof(struct sockaddr_in))
355 struct sockaddr_in *p = (struct sockaddr_in *)&sa;
356 if (p -> sin_family == AF_INET)
358 Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
359 tmp -> SetRemoteAddress(ad);
363 tmp -> SetConnected(true);
364 tmp -> Init();
365 tmp -> SetDeleteByHandler(true);
366 Handler().Add(tmp);
367 #ifdef HAVE_OPENSSL
368 if (tmp -> IsSSL()) // SSL Enabled socket
370 // %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
371 // %! If that happens and negotiation fails, the 'tmp' instance is
372 // %! still added to the list of active sockets in the sockethandler.
373 // %! See bugfix for this in SocketHandler::Select - don't Set rwx
374 // %! flags if CloseAndDelete() flag is true.
375 // %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
376 // %! the Add problem altogether, so ignore the above.
377 // %! (OnSSLAccept does no longer call SSLNegotiate().)
378 tmp -> OnSSLAccept();
380 else
381 #endif
383 tmp -> OnAccept();
387 /** Please don't use this method.
388 "accept()" is handled automatically in the OnRead() method. */
389 virtual SOCKET Accept(SOCKET socket, struct sockaddr *saptr, socklen_t *lenptr)
391 return accept(socket, saptr, lenptr);
394 bool HasCreator() { return m_bHasCreate; }
396 void OnOptions(int,int,int,SOCKET) {
397 SetSoReuseaddr(true);
400 protected:
401 SyncListenSocket(const SyncListenSocket& s) : Socket(s) {}
402 private:
403 SyncListenSocket& operator=(const SyncListenSocket& ) { return *this; }
404 int m_depth;
405 X *m_creator;
406 bool m_bHasCreate;
407 Y & y_;
412 #ifdef SOCKETS_NAMESPACE
414 #endif
416 #endif // _SOCKETS_SyncListenSocket_H