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 Handle an AF_UNIX socket as a server.
22 : *
23 : * This class is used to listen on a stream oriented connection using an
24 : * AF_UNIX type of socket.
25 : */
26 :
27 : // to get the POLLRDHUP definition
28 : //#ifndef _GNU_SOURCE
29 : //#define _GNU_SOURCE
30 : //#endif
31 :
32 :
33 : // self
34 : //
35 : #include "eventdispatcher/local_stream_server_connection.h"
36 :
37 : #include "eventdispatcher/exception.h"
38 : #include "eventdispatcher/local_stream_client_connection.h"
39 :
40 :
41 : // snaplogger lib
42 : //
43 : #include <snaplogger/message.h>
44 :
45 :
46 : // snapdev lib
47 : //
48 : //#include <snapdev/not_reached.h>
49 :
50 :
51 : // C++ lib
52 : //
53 : //#include <cstring>
54 :
55 :
56 : // C lib
57 : //
58 : #include <fcntl.h>
59 : #include <sys/stat.h>
60 :
61 :
62 : // last include
63 : //
64 : #include <snapdev/poison.h>
65 :
66 :
67 :
68 : namespace ed
69 : {
70 :
71 :
72 :
73 : /** \brief Initialize the local stream server.
74 : *
75 : * The server constructor creates a socket, binds it, and then listen to it.
76 : *
77 : * \todo
78 : * Fix docs.
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 : * \note
99 : * The code here handles the file based sockets by attempting to delete
100 : * the file if it already exists. If you create services that could end
101 : * up using the exact same socket name, then it could be an issue. If
102 : * not then the code will do exactly what you expects. That being said.
103 : * If you want to increase your chance of proper clean up of a Unix
104 : * socket file, you would have to create a parent process which deletes
105 : * the file whenever the child dies. Then it can either restart the child
106 : * (on a crash) or just quit.
107 : *
108 : * \exception event_dispatcher_runtime_error
109 : * This exception is raised if the socket cannot be created, bound to
110 : * the specified Unix address, or listen() fails on the socket.
111 : *
112 : * \param[in] u The Unix address to listen on.
113 : * \param[in] max_connections The number of connections to keep in the listen queue.
114 : * \param[in] force_reuse_addr Whether to allow the deletion of a file
115 : * before the bind() call.
116 : * \param[in] close_on_exec Whether to close the server & client sockets
117 : * on an execve().
118 : */
119 1 : local_stream_server_connection::local_stream_server_connection(
120 : addr::unix const & address
121 : , int max_connections
122 : , bool force_reuse_addr
123 1 : , bool close_on_exec)
124 : : f_address(address)
125 : , f_max_connections(max_connections)
126 1 : , f_close_on_exec(close_on_exec)
127 : {
128 1 : if(f_max_connections < 5)
129 : {
130 0 : f_max_connections = 5;
131 : }
132 1 : else if(f_max_connections > 1000)
133 : {
134 0 : f_max_connections = 1000;
135 : }
136 :
137 1 : sockaddr_un un;
138 1 : f_address.get_un(un);
139 2 : f_socket.reset(socket(
140 1 : un.sun_family
141 : , SOCK_STREAM | SOCK_NONBLOCK | (close_on_exec ? SOCK_CLOEXEC : 0)
142 : , 0));
143 1 : if(f_socket == nullptr)
144 : {
145 0 : int const e(errno);
146 0 : SNAP_LOG_ERROR
147 0 : << "socket() failed creating a socket descriptor (errno: "
148 0 : << std::to_string(e)
149 : << " -- "
150 0 : << strerror(e)
151 : << "); cannot listen on address \""
152 0 : << f_address.to_uri()
153 : << "\"."
154 : << SNAP_LOG_SEND;
155 0 : throw event_dispatcher_runtime_error("could not create socket for AF_UNIX server");
156 : }
157 :
158 1 : if(f_address.is_unnamed())
159 : {
160 : // for an unnamed socket, we do not bind at all the user is
161 : // responsible for knowing where to read and where to write
162 : //
163 0 : return;
164 : }
165 :
166 1 : int r(-1);
167 1 : if(f_address.is_file())
168 : {
169 : // a Unix file socket must create a new socket file to prove unicity
170 : // if the file already exists, even if it isn't used, the bind() call
171 : // will fail; if the file exists and the force_reuse_addr is true this
172 : // this function attempts to delete the file if it is a socket and we
173 : // can't connect to it (i.e. "lost file")
174 : //
175 1 : struct stat st = {};
176 1 : if(stat(un.sun_path, &st) == 0)
177 : {
178 0 : if(!S_ISSOCK(st.st_mode))
179 : {
180 0 : SNAP_LOG_ERROR
181 0 : << "file \""
182 : << un.sun_path
183 : << "\" is not a socket; cannot listen on address \""
184 0 : << f_address.to_uri()
185 : << "\"."
186 : << SNAP_LOG_SEND;
187 0 : throw event_dispatcher_runtime_error("file already exists and it is not a socket, can't create an AF_UNIX server");
188 : }
189 :
190 0 : bool available(false);
191 0 : if(force_reuse_addr)
192 : {
193 : try
194 : {
195 0 : local_stream_client_connection test_connection(f_address);
196 : }
197 0 : catch(event_dispatcher_runtime_error const & e)
198 : {
199 : // note: in Linux we can distinguish between a full
200 : // backlog (EAGAIN) and a disconnected socket
201 : // (ECONNREFUSED); we should not set available
202 : // to true on EAGAIN...
203 : //
204 0 : available = true;
205 : }
206 : }
207 0 : if(!available)
208 : {
209 0 : SNAP_LOG_ERROR
210 0 : << "file socket \""
211 : << un.sun_path
212 : << "\" already in use (errno: "
213 0 : << std::to_string(EADDRINUSE)
214 : << " -- "
215 0 : << strerror(EADDRINUSE)
216 : << "); cannot listen on address \""
217 0 : << f_address.to_uri()
218 : << "\"."
219 : << SNAP_LOG_SEND;
220 0 : throw event_dispatcher_runtime_error("socket already exists, can't create an AF_UNIX server");
221 : }
222 :
223 0 : r = f_address.unlink();
224 0 : if(r != 0
225 0 : && errno != ENOENT)
226 : {
227 0 : SNAP_LOG_ERROR
228 0 : << "not able to delete file socket \""
229 : << un.sun_path
230 : << "\"; socket already in use (errno: "
231 0 : << std::to_string(EADDRINUSE)
232 : << " -- "
233 0 : << strerror(EADDRINUSE)
234 : << "); cannot listen on address \""
235 0 : << f_address.to_uri()
236 : << "\"."
237 : << SNAP_LOG_SEND;
238 0 : throw event_dispatcher_runtime_error("could not unlink socket to reuse it as an AF_UNIX server");
239 : }
240 : }
241 2 : r = bind(
242 2 : f_socket.get()
243 : , reinterpret_cast<sockaddr const *>(&un)
244 : , sizeof(struct sockaddr_un));
245 : }
246 : else
247 : {
248 : // we want to limit the size because otherwise it would include
249 : // the '\0's after the specified name
250 : //
251 0 : std::size_t const size(sizeof(un.sun_family)
252 : + 1 // for the '\0' in sun_path[0]
253 0 : + strlen(un.sun_path + 1));
254 0 : r = bind(
255 0 : f_socket.get()
256 : , reinterpret_cast<sockaddr const *>(&un)
257 : , size);
258 : }
259 :
260 1 : if(r < 0)
261 : {
262 : throw event_dispatcher_runtime_error(
263 : "could not bind the socket to \""
264 0 : + f_address.to_uri()
265 0 : + "\"");
266 : }
267 :
268 : // start listening, we expect the caller to then call accept() to
269 : // acquire connections
270 : //
271 1 : if(listen(f_socket.get(), f_max_connections) < 0)
272 : {
273 : throw event_dispatcher_runtime_error(
274 : "could not listen to the socket bound to \""
275 0 : + f_address.to_uri()
276 0 : + "\"");
277 : }
278 : }
279 :
280 :
281 : /** \brief Clean up the server socket.
282 : *
283 : * This function deletes the socket file if this service used such a socket.
284 : *
285 : * \note
286 : * If the server crashes, that delete may not happen. In order to allow
287 : * for a restart, calling the constructor and setting the force_reuse_addr
288 : * to true is what will generally work best.
289 : */
290 2 : local_stream_server_connection::~local_stream_server_connection()
291 : {
292 1 : f_address.unlink();
293 1 : }
294 :
295 :
296 : /** \brief Check whether this connection is a listener.
297 : *
298 : * This function already returns true since a server is a listener.
299 : * This allows us to have our process_accept() function called instead
300 : * of the process_read().
301 : *
302 : * \return Always true since this is a listening server.
303 : */
304 10 : bool local_stream_server_connection::is_listener() const
305 : {
306 10 : return true;
307 : }
308 :
309 :
310 : /** \brief Retrieve the socket descriptor.
311 : *
312 : * This function returns the socket descriptor. It can be used to
313 : * tweak things on the socket such as making it non-blocking or
314 : * directly accessing the data.
315 : *
316 : * \return The socket descriptor.
317 : */
318 19 : int local_stream_server_connection::get_socket() const
319 : {
320 19 : return f_socket.get();
321 : }
322 :
323 :
324 : /** \brief Retrieve the maximum number of connections.
325 : *
326 : * This function returns the maximum number of connections that can
327 : * be accepted by the socket. This was set by the constructor and
328 : * it cannot be changed later.
329 : *
330 : * \return The maximum number of incoming connections.
331 : */
332 0 : int local_stream_server_connection::get_max_connections() const
333 : {
334 0 : return f_max_connections;
335 : }
336 :
337 :
338 : /** \brief Retrieve one new connection.
339 : *
340 : * This function will wait until a new connection arrives and returns a
341 : * new bio_client object for each new connection.
342 : *
343 : * If the socket is made non-blocking then the function may return without
344 : * a bio_client object (i.e. a null pointer instead.)
345 : *
346 : * \return A file descriptor representing the new connection socket.
347 : */
348 1 : snap::raii_fd_t local_stream_server_connection::accept()
349 : {
350 1 : struct sockaddr_un un;
351 1 : socklen_t len(sizeof(un));
352 : snap::raii_fd_t r(::accept(
353 2 : f_socket.get()
354 : , reinterpret_cast<sockaddr *>(&un)
355 2 : , &len));
356 1 : if(r == nullptr)
357 : {
358 0 : throw event_dispatcher_runtime_error("failed accepting a new AF_UNIX client");
359 : }
360 :
361 : // force a close on execve() to avoid sharing the socket in child
362 : // processes
363 : //
364 1 : if(f_close_on_exec)
365 : {
366 : // if this call fails, we ignore the error, but still log the event
367 : //
368 1 : if(fcntl(r.get(), F_SETFD, FD_CLOEXEC) != 0)
369 : {
370 0 : SNAP_LOG_WARNING
371 : << "::accept(): an error occurred trying"
372 0 : " to mark accepted AF_UNIX socket with FD_CLOEXEC."
373 : << SNAP_LOG_SEND;
374 : }
375 : }
376 :
377 1 : return r;
378 : }
379 :
380 :
381 : /** \brief Return the current state of the close-on-exec flag.
382 : *
383 : * This function returns the current state of the close-on-exec flag. This
384 : * is the flag as defined in the contructor or by the set_close_on_exec()
385 : * function. It does not represent the status of the server socket nor
386 : * of the clients that were accept()'ed by this class.
387 : *
388 : * It will, however, be used whenever the accept() is called in the future.
389 : *
390 : * \return The current status of the close-on-exec flag.
391 : */
392 0 : bool local_stream_server_connection::get_close_on_exec() const
393 : {
394 0 : return f_close_on_exec;
395 : }
396 :
397 :
398 : /** \brief Change the close-on-exec flag for future accept() calls.
399 : *
400 : * This function allows you to change the close-on-exec flag after
401 : * you created a Unix server. This means you may say that the server
402 : * needs to be closed, but not the connections or vice versa.
403 : *
404 : * \param[in] yes Whether the close-on-exec will be set on sockets
405 : * returned by the accept() function.
406 : */
407 0 : void local_stream_server_connection::set_close_on_exec(bool yes)
408 : {
409 0 : f_close_on_exec = yes;
410 0 : }
411 :
412 :
413 : /** \brief Retrieve the server IP address.
414 : *
415 : * This function returns the IP address used to bind the socket. This
416 : * is the address clients have to use to connect to the server unless
417 : * the address was set to all zeroes (0.0.0.0) in which case any user
418 : * can connect.
419 : *
420 : * The IP address cannot be changed.
421 : *
422 : * \return The server IP address.
423 : */
424 0 : addr::unix local_stream_server_connection::get_addr() const
425 : {
426 0 : return f_address;
427 : }
428 :
429 :
430 :
431 :
432 :
433 6 : } // namespace ed
434 : // vim: ts=4 sw=4 et
|