Line data Source code
1 : // Copyright (c) 2012-2019 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program; if not, write to the Free Software
18 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : /** \file
21 : * \brief Event dispatch class.
22 : *
23 : * Class used to handle events.
24 : */
25 :
26 : // to get the POLLRDHUP definition
27 : #ifndef _GNU_SOURCE
28 : #define _GNU_SOURCE
29 : #endif
30 :
31 :
32 : // self
33 : //
34 : #include "eventdispatcher/tcp_server.h"
35 :
36 : #include "eventdispatcher/exception.h"
37 :
38 :
39 : // snaplogger lib
40 : //
41 : #include <snaplogger/message.h>
42 :
43 :
44 : // snapdev lib
45 : //
46 : #include <snapdev/not_reached.h>
47 :
48 :
49 : // C lib
50 : //
51 : #include <poll.h>
52 :
53 :
54 : // last include
55 : //
56 : #include <snapdev/poison.h>
57 :
58 :
59 :
60 : namespace ed
61 : {
62 :
63 :
64 :
65 : /** \brief Initialize the server and start listening for connections.
66 : *
67 : * The server constructor creates a socket, binds it, and then listen to it.
68 : *
69 : * By default the server accepts a maximum of \p max_connections (set to
70 : * 0 or less to get the default tcp_server::MAX_CONNECTIONS) in its waiting queue.
71 : * If you use the server and expect a low connection rate, you may want to
72 : * reduce the count to 5. Although some very busy servers use larger numbers.
73 : * This value gets clamped to a minimum of 5 and a maximum of 1,000.
74 : *
75 : * Note that the maximum number of connections is actually limited to
76 : * /proc/sys/net/core/somaxconn connections. This number is generally 128
77 : * in 2016. So the super high limit of 1,000 is anyway going to be ignored
78 : * by the OS.
79 : *
80 : * The address is made non-reusable (which is the default for TCP sockets.)
81 : * It is possible to mark the server address as immediately reusable by
82 : * setting the \p reuse_addr to true.
83 : *
84 : * By default the server is marked as "keepalive". You can turn it off
85 : * using the keepalive() function with false.
86 : *
87 : * \exception tcp_client_server_parameter_error
88 : * This exception is raised if the address parameter is an empty string or
89 : * otherwise an invalid IP address, or if the port is out of range.
90 : *
91 : * \exception tcp_client_server_runtime_error
92 : * This exception is raised if the socket cannot be created, bound to
93 : * the specified IP address and port, or listen() fails on the socket.
94 : *
95 : * \param[in] addr The address to listen on. It may be set to "0.0.0.0".
96 : * \param[in] port The port to listen on.
97 : * \param[in] max_connections The number of connections to keep in the listen queue.
98 : * \param[in] reuse_addr Whether to mark the socket with the SO_REUSEADDR flag.
99 : * \param[in] auto_close Automatically close the client socket in accept and the destructor.
100 : */
101 0 : tcp_server::tcp_server(std::string const & addr, int port, int max_connections, bool reuse_addr, bool auto_close)
102 0 : : f_max_connections(max_connections <= 0 ? MAX_CONNECTIONS : max_connections)
103 : //, f_socket(-1) -- auto-init
104 : , f_port(port)
105 : , f_addr(addr)
106 : //, f_accepted_socket(-1) -- auto-init
107 : //, f_keepalive(true) -- auto-init
108 0 : , f_auto_close(auto_close)
109 : {
110 0 : if(f_addr.empty())
111 : {
112 0 : throw event_dispatcher_invalid_parameter("the address cannot be an empty string.");
113 : }
114 0 : if(f_port < 0 || f_port >= 65536)
115 : {
116 0 : throw event_dispatcher_invalid_parameter("invalid port for a client socket.");
117 : }
118 0 : if(f_max_connections < 5)
119 : {
120 0 : f_max_connections = 5;
121 : }
122 0 : else if(f_max_connections > 1000)
123 : {
124 0 : f_max_connections = 1000;
125 : }
126 :
127 : addrinfo hints;
128 0 : memset(&hints, 0, sizeof(hints));
129 0 : hints.ai_family = AF_UNSPEC;
130 0 : hints.ai_socktype = SOCK_STREAM;
131 0 : hints.ai_protocol = IPPROTO_TCP;
132 0 : std::string port_str(std::to_string(f_port));
133 0 : addrinfo * addrinfo(nullptr);
134 0 : int const r(getaddrinfo(addr.c_str(), port_str.c_str(), &hints, &addrinfo));
135 0 : raii_addrinfo_t addr_info(addrinfo);
136 0 : if(r != 0
137 0 : || addrinfo == nullptr)
138 : {
139 0 : throw event_dispatcher_runtime_error("invalid address or port: \"" + addr + ":" + port_str + "\"");
140 : }
141 :
142 0 : f_socket = socket(addr_info.get()->ai_family, SOCK_STREAM, IPPROTO_TCP);
143 0 : if(f_socket < 0)
144 : {
145 0 : int const e(errno);
146 0 : std::string err("socket() failed to create a socket descriptor (errno: ");
147 0 : err += std::to_string(e);
148 0 : err += " -- ";
149 0 : err += strerror(e);
150 0 : err += ")";
151 0 : throw event_dispatcher_runtime_error("could not create socket for client");
152 : }
153 :
154 : // this should be optional as reusing an address for TCP/IP is not 100% safe
155 0 : if(reuse_addr)
156 : {
157 : // try to mark the socket address as immediately reusable
158 : // if this fails, we ignore the error (TODO log an INFO message)
159 0 : int optval(1);
160 0 : socklen_t const optlen(sizeof(optval));
161 0 : snap::NOTUSED(setsockopt(f_socket, SOL_SOCKET, SO_REUSEADDR, &optval, optlen));
162 : }
163 :
164 0 : if(bind(f_socket, addr_info.get()->ai_addr, addr_info.get()->ai_addrlen) < 0)
165 : {
166 0 : close(f_socket);
167 0 : throw event_dispatcher_runtime_error("could not bind the socket to \"" + f_addr + "\"");
168 : }
169 :
170 : // start listening, we expect the caller to then call accept() to
171 : // acquire connections
172 0 : if(listen(f_socket, f_max_connections) < 0)
173 : {
174 0 : close(f_socket);
175 0 : throw event_dispatcher_runtime_error("could not listen to the socket bound to \"" + f_addr + "\"");
176 : }
177 0 : }
178 :
179 :
180 : /** \brief Clean up the server sockets.
181 : *
182 : * This function ensures that the server sockets get cleaned up.
183 : *
184 : * If the \p auto_close parameter was set to true in the constructor, then
185 : * the last accepter socket gets closed by this function.
186 : *
187 : * \note
188 : * DO NOT use the shutdown() call since we may end up forking and using
189 : * that connection in the child.
190 : */
191 0 : tcp_server::~tcp_server()
192 : {
193 0 : close(f_socket);
194 0 : if(f_auto_close && f_accepted_socket != -1)
195 : {
196 0 : close(f_accepted_socket);
197 : }
198 0 : }
199 :
200 :
201 : /** \brief Retrieve the socket descriptor.
202 : *
203 : * This function returns the socket descriptor. It can be used to
204 : * tweak things on the socket such as making it non-blocking or
205 : * directly accessing the data.
206 : *
207 : * \return The socket descriptor.
208 : */
209 0 : int tcp_server::get_socket() const
210 : {
211 0 : return f_socket;
212 : }
213 :
214 :
215 : /** \brief Retrieve the maximum number of connections.
216 : *
217 : * This function returns the maximum number of connections that can
218 : * be accepted by the socket. This was set by the constructor and
219 : * it cannot be changed later.
220 : *
221 : * \return The maximum number of incoming connections.
222 : */
223 0 : int tcp_server::get_max_connections() const
224 : {
225 0 : return f_max_connections;
226 : }
227 :
228 :
229 : /** \brief Return the server port.
230 : *
231 : * This function returns the port the server was created with. This port
232 : * is exactly what the server currently uses. It cannot be changed.
233 : *
234 : * \return The server port.
235 : */
236 0 : int tcp_server::get_port() const
237 : {
238 0 : return f_port;
239 : }
240 :
241 :
242 : /** \brief Retrieve the server IP address.
243 : *
244 : * This function returns the IP address used to bind the socket. This
245 : * is the address clients have to use to connect to the server unless
246 : * the address was set to all zeroes (0.0.0.0) in which case any user
247 : * can connect.
248 : *
249 : * The IP address cannot be changed.
250 : *
251 : * \return The server IP address.
252 : */
253 0 : std::string tcp_server::get_addr() const
254 : {
255 0 : return f_addr;
256 : }
257 :
258 :
259 : /** \brief Return the current status of the keepalive flag.
260 : *
261 : * This function returns the current status of the keepalive flag. This
262 : * flag is set to true by default (in the constructor.) It can be
263 : * changed with the keepalive() function.
264 : *
265 : * The flag is used to mark new connections with the SO_KEEPALIVE flag.
266 : * This is used whenever a service may take a little to long to answer
267 : * and avoid losing the TCP connection before the answer is sent to
268 : * the client.
269 : *
270 : * \return The current status of the keepalive flag.
271 : */
272 0 : bool tcp_server::get_keepalive() const
273 : {
274 0 : return f_keepalive;
275 : }
276 :
277 :
278 : /** \brief Set the keepalive flag.
279 : *
280 : * This function sets the keepalive flag to either true (i.e. mark connection
281 : * sockets with the SO_KEEPALIVE flag) or false. The default is true (as set
282 : * in the constructor,) because in most cases this is a feature people want.
283 : *
284 : * \param[in] yes Whether to keep new connections alive even when no traffic
285 : * goes through.
286 : */
287 0 : void tcp_server::set_keepalive(bool yes)
288 : {
289 0 : f_keepalive = yes;
290 0 : }
291 :
292 :
293 : /** \brief Accept a connection.
294 : *
295 : * A TCP server accepts incoming connections. This call is a blocking call.
296 : * If no connections are available on the line, then the call blocks until
297 : * a connection becomes available.
298 : *
299 : * To prevent being blocked by this call you can either check the status of
300 : * the file descriptor (use the get_socket() function to retrieve the
301 : * descriptor and use an appropriate wait with 0 as a timeout,) or transform
302 : * the socket in a non-blocking socket (not tested, though.)
303 : *
304 : * This TCP socket implementation is expected to be used in one of two ways:
305 : *
306 : * (1) the main server accepts connections and then fork()'s to handle the
307 : * transaction with the client, in that case we want to set the \p auto_close
308 : * parameter of the constructor to true so the accept() function automatically
309 : * closes the last accepted socket.
310 : *
311 : * (2) the main server keeps a set of connections and handles them alongside
312 : * the main server connection. Although there are limits to what you can do
313 : * in this way, it is very efficient, but this also means the accept() call
314 : * cannot close the last accepted socket since the rest of the software may
315 : * still be working on it.
316 : *
317 : * The function returns a client/server socket. This is the socket one can
318 : * use to communicate with the client that just connected to the server. This
319 : * descriptor can be written to or read from.
320 : *
321 : * This function is the one that applies the keepalive flag to the
322 : * newly accepted socket.
323 : *
324 : * \note
325 : * If you prevent SIGCHLD from stopping your code, you may want to allow it
326 : * when calling this function (that is, if you're interested in getting that
327 : * information immediately, otherwise it is cleaner to always block those
328 : * signals.)
329 : *
330 : * \note
331 : * DO NOT use the shutdown() call since we may end up forking and using
332 : * that connection in the child.
333 : *
334 : * \param[in] max_wait_ms The maximum number of milliseconds to wait for
335 : * a message. If set to -1 (the default), accept() will block
336 : * indefintely.
337 : *
338 : * \return A client socket descriptor or -1 if an error occured, -2 if timeout and max_wait is set.
339 : */
340 0 : int tcp_server::accept( int const max_wait_ms )
341 : {
342 : // auto-close?
343 0 : if(f_auto_close && f_accepted_socket != -1)
344 : {
345 : // if the close is interrupted, make sure we try again otherwise
346 : // we could lose that stream until next restart (this could happen
347 : // if you have SIGCHLD)
348 0 : if(close(f_accepted_socket) == -1)
349 : {
350 0 : if(errno == EINTR)
351 : {
352 0 : close(f_accepted_socket);
353 : }
354 : }
355 : }
356 0 : f_accepted_socket = -1;
357 :
358 0 : if( max_wait_ms > -1 )
359 : {
360 : pollfd fd;
361 0 : fd.events = POLLIN | POLLPRI | POLLRDHUP;
362 0 : fd.fd = f_socket;
363 0 : int const retval(poll(&fd, 1, max_wait_ms));
364 :
365 : // on newer system each input of select() must be a distinct fd_set...
366 : // fd_set s;
367 : //
368 : // FD_ZERO(&s);
369 : //#pragma GCC diagnostic push
370 : //#pragma GCC diagnostic ignored "-Wold-style-cast"
371 : // FD_SET(f_socket, &s);
372 : //#pragma GCC diagnostic pop
373 : //
374 : // struct timeval timeout;
375 : // timeout.tv_sec = max_wait_ms / 1000;
376 : // timeout.tv_usec = (max_wait_ms % 1000) * 1000;
377 : // int const retval = select(f_socket + 1, &s, nullptr, &s, &timeout);
378 :
379 0 : if( retval == -1 )
380 : {
381 : // error
382 : //
383 0 : return -1;
384 : }
385 0 : else if( retval == 0 )
386 : {
387 : // timeout
388 : //
389 0 : return -2;
390 : }
391 : }
392 :
393 : // accept the next connection
394 : //
395 : struct sockaddr_in accepted_addr;
396 0 : socklen_t addr_len(sizeof(accepted_addr));
397 0 : memset(&accepted_addr, 0, sizeof(accepted_addr));
398 0 : f_accepted_socket = ::accept(f_socket, reinterpret_cast<struct sockaddr *>(&accepted_addr), &addr_len);
399 :
400 : // mark the new connection with the SO_KEEPALIVE flag
401 : //
402 0 : if(f_accepted_socket != -1 && f_keepalive)
403 : {
404 : // if this fails, we ignore the error, but still log the event
405 : //
406 0 : int optval(1);
407 0 : socklen_t const optlen(sizeof(optval));
408 0 : if(setsockopt(f_accepted_socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) != 0)
409 : {
410 : SNAP_LOG_WARNING
411 : << "tcp_server::accept(): an error occurred trying to mark"
412 0 : " accepted socket with SO_KEEPALIVE.";
413 : }
414 : }
415 :
416 0 : return f_accepted_socket;
417 : }
418 :
419 :
420 : /** \brief Retrieve the last accepted socket descriptor.
421 : *
422 : * This function returns the last accepted socket descriptor as retrieved by
423 : * accept(). If accept() was never called or failed, then this returns -1.
424 : *
425 : * Note that it is possible that the socket was closed in between in which
426 : * case this value is going to be an invalid socket.
427 : *
428 : * \return The last accepted socket descriptor.
429 : */
430 0 : int tcp_server::get_last_accepted_socket() const
431 : {
432 0 : return f_accepted_socket;
433 : }
434 :
435 :
436 :
437 6 : } // namespace ed
438 : // vim: ts=4 sw=4 et
|