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