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 Implementation of the Snap Communicator class.
22 : *
23 : * This class wraps the C poll() interface in a C++ object with many types
24 : * of objects:
25 : *
26 : * \li Server Connections; for software that want to offer a port to
27 : * which clients can connect to; the server will call accept()
28 : * once a new client connection is ready; this results in a
29 : * Server/Client connection object
30 : * \li Client Connections; for software that want to connect to
31 : * a server; these expect the IP address and port to connect to
32 : * \li Server/Client Connections; for the server when it accepts a new
33 : * connection; in this case the server gets a socket from accept()
34 : * and creates one of these objects to handle the connection
35 : *
36 : * Using the poll() function is the easiest and allows us to listen
37 : * on pretty much any number of sockets (on my server it is limited
38 : * at 16,768 and frankly over 1,000 we probably will start to have
39 : * real slowness issues on small VPN servers.)
40 : */
41 :
42 : // self
43 : //
44 : #include "eventdispatcher/pipe_connection.h"
45 :
46 : #include "eventdispatcher/exception.h"
47 :
48 :
49 : // C++ lib
50 : //
51 : #include <iostream>
52 :
53 :
54 : // C lib
55 : //
56 : #include <unistd.h>
57 : #include <sys/socket.h>
58 :
59 :
60 : // last include
61 : //
62 : #include <snapdev/poison.h>
63 :
64 :
65 :
66 : namespace ed
67 : {
68 :
69 :
70 :
71 : /** \brief Initializes the pipe connection.
72 : *
73 : * This function creates pipes to quickly communicate between two
74 : * processes created with a fork() or fork() + execve().
75 : *
76 : * The function supports three types of pipes:
77 : *
78 : * * PIPE_BIDIRECTIONAL
79 : *
80 : * Create Unix sockets that can be used to send and receive messages
81 : * between two processes.
82 : *
83 : * * PIPE_CHILD_INPUT
84 : *
85 : * A pipe for the input stream of a child. This type of pipe is to
86 : * be used as a replacement to the stdin of a child process. This is
87 : * used in the cppprocess library when creating a fork() + execve()
88 : * process.
89 : *
90 : * * PIPE_CHILD_OUTPUT
91 : *
92 : * A pipe for the output stream and error stream of a child. This
93 : * type of pipe is to be used as a replacement to the stdout and
94 : * stderr of a child process. This is used in the cppprocess when
95 : * creating a fork() + execve() process.
96 : *
97 : * To save file descriptors (1 or 2), it is suggested that you
98 : * call the forked() function once you called fork(). It will
99 : * take care of closing the descriptors used by the other side
100 : * (those you do not need on your side).
101 : *
102 : * \warning
103 : * The file descriptors are opened in a non-blocking state. However, they
104 : * are not closed when you call fork() since they are to be used across
105 : * processes. If you want to do a fork() + execve(), duplicating the
106 : * necessary file descriptors and then call close().
107 : *
108 : * \warning
109 : * You need to create a new pipe_connection each time you want to create
110 : * a new child with fork(). If you want to create a a new process with
111 : * fork() + execve(), you want to create three pipe_connection, one per
112 : * stream (stdin, stdout, stderr). You can always create more if necessary
113 : * in your situation.
114 : *
115 : * \exception event_dispatcher_initialization_error
116 : * This exception is raised if the pipes (socketpair, pipe) cannot be
117 : * created.
118 : *
119 : * \param[in] type The type of pipe to create.
120 : *
121 : * \sa forked()
122 : */
123 9 : pipe_connection::pipe_connection(pipe_t type)
124 : : f_type(type)
125 9 : , f_parent(getpid())
126 : {
127 9 : switch(type)
128 : {
129 0 : case pipe_t::PIPE_BIDIRECTIONAL:
130 0 : if(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, f_socket) != 0)
131 : {
132 : // pipe could not be created
133 0 : throw event_dispatcher_initialization_error("somehow the AF_LOCAL pipes used for a two way pipe connection could not be created.");
134 : }
135 0 : break;
136 :
137 3 : case pipe_t::PIPE_CHILD_INPUT:
138 3 : if(pipe(f_socket) != 0)
139 : {
140 : // pipe could not be created
141 0 : throw event_dispatcher_initialization_error("somehow the FIFO pipes used for a one way pipe (child input) connection could not be created.");
142 : }
143 3 : std::swap(f_socket[0], f_socket[1]);
144 3 : break;
145 :
146 6 : case pipe_t::PIPE_CHILD_OUTPUT:
147 6 : if(pipe(f_socket) != 0)
148 : {
149 : // pipe could not be created
150 0 : throw event_dispatcher_initialization_error("somehow the FIFO pipes used for a one way pipe (child output) connection could not be created.");
151 : }
152 6 : break;
153 :
154 : }
155 9 : }
156 :
157 :
158 : /** \brief Make sure to close the pipes.
159 : *
160 : * The destructor ensures that the pipes get closed.
161 : *
162 : * They may already have been closed if a broken pipe was detected.
163 : *
164 : * \sa close()
165 : */
166 18 : pipe_connection::~pipe_connection()
167 : {
168 9 : close();
169 9 : }
170 :
171 :
172 : /** \brief Get the type of pipe connections.
173 : *
174 : * This function returns the type of this connection, as specified
175 : * on the contructor.
176 : *
177 : * \return The type of the pipe.
178 : */
179 0 : pipe_t pipe_connection::type() const
180 : {
181 0 : return f_type;
182 : }
183 :
184 :
185 : /** \brief Read data from this pipe connection.
186 : *
187 : * This function reads up to count bytes from this pipe connection.
188 : *
189 : * The function makes sure to use the correct socket for the calling
190 : * process (i.e. depending on whether this is the parent or child.)
191 : *
192 : * Just like the system read(2) function, errno is set to the error
193 : * that happened when the function returns -1.
194 : *
195 : * The function returns an error (-1, errno = EBAD) if you try to
196 : * read from a read-only stream.
197 : *
198 : * \param[in] buf A pointer to a buffer of data.
199 : * \param[in] count The number of bytes to read from the pipe connection.
200 : *
201 : * \return The number of bytes read from this pipe socket, or -1 on errors.
202 : *
203 : * \sa write()
204 : */
205 5 : ssize_t pipe_connection::read(void * buf, size_t count)
206 : {
207 5 : if(f_parent == getpid())
208 : {
209 5 : if(f_type == pipe_t::PIPE_CHILD_INPUT)
210 : {
211 0 : errno = EBADF;
212 0 : return -1;
213 : }
214 : }
215 : else
216 : {
217 0 : if(f_type == pipe_t::PIPE_CHILD_OUTPUT)
218 : {
219 0 : errno = EBADF;
220 0 : return -1;
221 : }
222 : }
223 :
224 5 : int const s(get_socket());
225 5 : if(s == -1)
226 : {
227 0 : errno = EBADF;
228 0 : return -1;
229 : }
230 5 : return ::read(s, buf, count);
231 : }
232 :
233 :
234 : /** \brief Write data to this pipe connection.
235 : *
236 : * This function writes count bytes to this pipe connection.
237 : *
238 : * The function makes sure to use the correct socket for the calling
239 : * process (i.e. depending on whether this is the parent or child.)
240 : *
241 : * Just like the system write(2) function, errno is set to the error
242 : * that happened when the function returns -1.
243 : *
244 : * The function returns an error (-1, errno = EBAD) if you try to
245 : * write to a read-only stream.
246 : *
247 : * \param[in] buf A pointer to a buffer of data.
248 : * \param[in] count The number of bytes to write to the pipe connection.
249 : *
250 : * \return The number of bytes written to this pipe socket, or -1 on errors.
251 : *
252 : * \sa read()
253 : */
254 3 : ssize_t pipe_connection::write(void const * buf, size_t count)
255 : {
256 3 : if(f_parent == getpid())
257 : {
258 3 : if(f_type == pipe_t::PIPE_CHILD_OUTPUT)
259 : {
260 0 : errno = EBADF;
261 0 : return -1;
262 : }
263 : }
264 : else
265 : {
266 0 : if(f_type == pipe_t::PIPE_CHILD_INPUT)
267 : {
268 0 : errno = EBADF;
269 0 : return -1;
270 : }
271 : }
272 :
273 3 : int const s(get_socket());
274 3 : if(s == -1)
275 : {
276 0 : errno = EBADF;
277 0 : return -1;
278 : }
279 3 : if(buf != nullptr && count > 0)
280 : {
281 3 : return ::write(s, buf, count);
282 : }
283 0 : return 0;
284 : }
285 :
286 :
287 : /** \brief Close the other side sockets.
288 : *
289 : * This function closes the sockets not used by this side of the pipe.
290 : * This is useful to clean up file descriptors that we otherwise endup
291 : * to never use until this object is destroyed.
292 : *
293 : * Make sure to call this function only after you called the fork()
294 : * function. Calling this too early (before the fork() call) would
295 : * mean that you'd end up closing the file descriptors of the other
296 : * side before the other side received the socket information.
297 : *
298 : * The function can safely be called multiple times.
299 : *
300 : * \note
301 : * To close both sides, call the close() function.
302 : *
303 : * \sa close()
304 : */
305 7 : void pipe_connection::forked()
306 : {
307 7 : int const idx(f_parent == getpid() ? 1 : 0);
308 7 : if(f_socket[idx] != -1)
309 : {
310 7 : ::close(f_socket[idx]);
311 7 : f_socket[idx] = -1;
312 : }
313 7 : }
314 :
315 :
316 : /** \brief Close the sockets.
317 : *
318 : * This function closes the pair of sockets managed by this
319 : * pipe connection object.
320 : *
321 : * After this call, the pipe connection is closed and cannot be
322 : * used anymore. The read and write functions will return immediately
323 : * if called.
324 : *
325 : * The function can safely be called multiple times. It is also safe
326 : * to call the forked() function and then the close() function.
327 : *
328 : * \sa forked()
329 : */
330 18 : void pipe_connection::close()
331 : {
332 18 : if(f_socket[0] != -1)
333 : {
334 9 : ::close(f_socket[0]);
335 9 : f_socket[0] = -1;
336 : }
337 :
338 18 : if(f_socket[1] != -1)
339 : {
340 2 : ::close(f_socket[1]);
341 2 : f_socket[1] = -1;
342 : }
343 18 : }
344 :
345 :
346 : /** \brief This function returns the pipe of the other side.
347 : *
348 : * In some cases, it can be practical to find out the socket from the other
349 : * side of the pipe. This function returns that other socket.
350 : *
351 : * \note
352 : * The main reason for this function is to be able to extract the other
353 : * socket and create the necessary input/output/error stream in a child
354 : * process and close it.
355 : *
356 : * \return A pipe descriptor to listen on with poll().
357 : */
358 9 : int pipe_connection::get_other_socket() const
359 : {
360 9 : if(f_parent == getpid())
361 : {
362 9 : return f_socket[1];
363 : }
364 :
365 0 : return f_socket[0];
366 : }
367 :
368 :
369 : /** \brief Pipe connections accept reads.
370 : *
371 : * This function returns true meaning that the pipe connection can be
372 : * used to read data.
373 : *
374 : * \return true since a pipe connection is a reader.
375 : */
376 13 : bool pipe_connection::is_reader() const
377 : {
378 13 : if(f_parent == getpid())
379 : {
380 13 : if(f_type == pipe_t::PIPE_CHILD_INPUT)
381 : {
382 3 : return false;
383 : }
384 : }
385 : else
386 : {
387 0 : if(f_type == pipe_t::PIPE_CHILD_OUTPUT)
388 : {
389 0 : return false;
390 : }
391 : }
392 :
393 10 : return true;
394 : }
395 :
396 :
397 : /** \brief This function returns the pipe we want to listen on.
398 : *
399 : * This function returns the file descriptor of one of the two
400 : * sockets. The parent process returns the descriptor of socket
401 : * number 0. The child process returns the descriptor of socket
402 : * number 1.
403 : *
404 : * \note
405 : * If the close() function was called, this function returns -1.
406 : *
407 : * \return A pipe descriptor to listen on with poll().
408 : */
409 48 : int pipe_connection::get_socket() const
410 : {
411 48 : if(f_parent == getpid())
412 : {
413 48 : return f_socket[0];
414 : }
415 :
416 0 : return f_socket[1];
417 : }
418 :
419 :
420 : /** \var pipe_t::PIPE_BIDIRECTIONAL
421 : * \brief Used to create a bidirectional pipe.
422 : *
423 : * The pipe is bidirectional. You can read and write to it.
424 : */
425 :
426 :
427 : /** \var pipe_t::PIPE_CHILD_INPUT
428 : * \brief Used to create an input stream for a child.
429 : *
430 : * This type defines a pipe where the parent writes to the pipe and the
431 : * child reads from the pipe.
432 : */
433 :
434 :
435 : /** \var pipe_t::PIPE_CHILD_OUTPUT
436 : * \brief Used to create an output stream for a child.
437 : *
438 : * This type defines a pipe where the parent reads from the pipe and the
439 : * child writes to the pipe.
440 : */
441 :
442 :
443 :
444 6 : } // namespace ed
445 : // vim: ts=4 sw=4 et
|