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 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 <unistd.h>
52 : #include <sys/socket.h>
53 :
54 :
55 : // last include
56 : //
57 : #include <snapdev/poison.h>
58 :
59 :
60 :
61 :
62 : namespace ed
63 : {
64 :
65 :
66 :
67 : /** \brief Initializes the pipe connection.
68 : *
69 : * This function creates the pipes that are to be used to connect
70 : * two processes (these are actually Unix sockets). These are
71 : * used whenever you fork() so the parent process can very quickly
72 : * communicate with the child process using complex messages just
73 : * like you do between services and Snap Communicator.
74 : *
75 : * \warning
76 : * The sockets are opened in a non-blocking state. However, they are
77 : * not closed when you call fork() since they are to be used across
78 : * processes.
79 : *
80 : * \warning
81 : * You need to create a new snap_pipe_connection each time you want
82 : * to create a new child.
83 : *
84 : * \exception snap_communicator_initialization_error
85 : * This exception is raised if the pipes (socketpair) cannot be created.
86 : */
87 0 : pipe_connection::pipe_connection()
88 : {
89 0 : if(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, f_socket) != 0)
90 : {
91 : // pipe could not be created
92 0 : throw event_dispatcher_initialization_error("somehow the pipes used for a two way pipe connection could not be created.");
93 : }
94 :
95 0 : f_parent = getpid();
96 0 : }
97 :
98 :
99 : /** \brief Make sure to close the pipes.
100 : *
101 : * The destructor ensures that the pipes get closed.
102 : *
103 : * They may already have been closed if a broken pipe was detected.
104 : */
105 0 : pipe_connection::~pipe_connection()
106 : {
107 0 : close();
108 0 : }
109 :
110 :
111 : /** \brief Read data from this pipe connection.
112 : *
113 : * This function reads up to count bytes from this pipe connection.
114 : *
115 : * The function makes sure to use the correct socket for the calling
116 : * process (i.e. depending on whether this is the parent or child.)
117 : *
118 : * Just like the system read(2) function, errno is set to the error
119 : * that happened when the function returns -1.
120 : *
121 : * \param[in] buf A pointer to a buffer of data.
122 : * \param[in] count The number of bytes to read from the pipe connection.
123 : *
124 : * \return The number of bytes read from this pipe socket, or -1 on errors.
125 : */
126 0 : ssize_t pipe_connection::read(void * buf, size_t count)
127 : {
128 0 : int const s(get_socket());
129 0 : if(s == -1)
130 : {
131 0 : errno = EBADF;
132 0 : return -1;
133 : }
134 0 : return ::read(s, buf, count);
135 : }
136 :
137 :
138 : /** \brief Write data to this pipe connection.
139 : *
140 : * This function writes count bytes to this pipe connection.
141 : *
142 : * The function makes sure to use the correct socket for the calling
143 : * process (i.e. depending on whether this is the parent or child.)
144 : *
145 : * Just like the system write(2) function, errno is set to the error
146 : * that happened when the function returns -1.
147 : *
148 : * \param[in] buf A pointer to a buffer of data.
149 : * \param[in] count The number of bytes to write to the pipe connection.
150 : *
151 : * \return The number of bytes written to this pipe socket, or -1 on errors.
152 : */
153 0 : ssize_t pipe_connection::write(void const * buf, size_t count)
154 : {
155 0 : int const s(get_socket());
156 0 : if(s == -1)
157 : {
158 0 : errno = EBADF;
159 0 : return -1;
160 : }
161 0 : if(buf != nullptr && count > 0)
162 : {
163 0 : return ::write(s, buf, count);
164 : }
165 0 : return 0;
166 : }
167 :
168 :
169 : /** \brief Close the sockets.
170 : *
171 : * This function closes the pair of sockets managed by this
172 : * pipe connection object.
173 : *
174 : * After this call, the pipe connection is closed and cannot be
175 : * used anymore. The read and write functions will return immediately
176 : * if called.
177 : */
178 0 : void pipe_connection::close()
179 : {
180 0 : if(f_socket[0] != -1)
181 : {
182 0 : ::close(f_socket[0]);
183 0 : ::close(f_socket[1]);
184 0 : f_socket[0] = -1;
185 0 : f_socket[1] = -1;
186 : }
187 0 : }
188 :
189 :
190 : /** \brief Pipe connections accept reads.
191 : *
192 : * This function returns true meaning that the pipe connection can be
193 : * used to read data.
194 : *
195 : * \return true since a pipe connection is a reader.
196 : */
197 0 : bool pipe_connection::is_reader() const
198 : {
199 0 : return true;
200 : }
201 :
202 :
203 : /** \brief This function returns the pipe we want to listen on.
204 : *
205 : * This function returns the file descriptor of one of the two
206 : * sockets. The parent process returns the descriptor of socket
207 : * number 0. The child process returns the descriptor of socket
208 : * number 1.
209 : *
210 : * \note
211 : * If the close() function was called, this function returns -1.
212 : *
213 : * \return A pipe descriptor to listen on with poll().
214 : */
215 0 : int pipe_connection::get_socket() const
216 : {
217 0 : if(f_parent == getpid())
218 : {
219 0 : return f_socket[0];
220 : }
221 :
222 0 : return f_socket[1];
223 : }
224 :
225 :
226 :
227 :
228 :
229 :
230 :
231 : } // namespace ed
232 : // vim: ts=4 sw=4 et
|