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