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 :
43 : // self
44 : //
45 : #include "eventdispatcher/fd_connection.h"
46 :
47 :
48 : // C lib
49 : //
50 : #include <unistd.h>
51 :
52 :
53 : // last include
54 : //
55 : #include <snapdev/poison.h>
56 :
57 :
58 :
59 : namespace ed
60 : {
61 :
62 :
63 :
64 : /** \brief Initializes the file descriptor connection.
65 : *
66 : * This function creates a connection based on an existing file descriptor.
67 : * This is a class used to handle existing pipes or socket (opposed to other
68 : * implementations which create a pipe, open a socket, etc.) It is especially
69 : * useful if you want to listen to stdin and stdout. Use the `fileno()`
70 : * function to get the file descriptor and create a `snap_fd_connection`
71 : * object what that descriptor.
72 : *
73 : * The mode parameter defines how you are to use the file descriptor. In
74 : * other words, a socket that is read/write could be added to two different
75 : * `snap_fd_connection` objects: one to read and one to write, instead of
76 : * a single read/write object.
77 : *
78 : * Note that although you can say it's only going to be used in READ or
79 : * in WRITE mode, in all cases, make sure that the file is readable before
80 : * specifying READ or RW, and make sure that the file is writable before
81 : * specifying WRITE or RW.
82 : *
83 : * \note
84 : * It is important to note that the lifetime of the file desriptor is
85 : * not managed by this object. You are responsible for the descriptor to
86 : * stay valid as long as the connection is added to the snap_communicator
87 : * list of connections. If you want to close the connection, please first
88 : * remove the connection from the snap_communicator, destroy the connection,
89 : * then close the file descriptor.
90 : *
91 : * \note
92 : * It is possible to pass -1 (or any negative number) as the file
93 : * descriptor. In that case it is interpreted as "not a valid
94 : * file descriptor."
95 : *
96 : * \warning
97 : * If you are to use a read() or a write() that may block, make sure to
98 : * first set your file descriptor in non-blocking mode. If that's not
99 : * possible, then make sure to read or write only one byte at a time.
100 : * The loop will be slower, but you will avoid blocks which would
101 : * prevent the rest of the software from getting their own events.
102 : *
103 : * \param[in] fd The file descriptor to handle.
104 : * \param[in] mode The mode this descriptor is to be used by the connection.
105 : */
106 0 : fd_connection::fd_connection(int fd, mode_t mode)
107 : : f_fd(fd)
108 0 : , f_mode(mode)
109 : {
110 0 : }
111 :
112 :
113 : /** \brief Used to close the file descriptor.
114 : *
115 : * This function closes the file descript of this connection.
116 : *
117 : * The function is not called automatically as we mention in the
118 : * constructor, the function cannot just close the file descriptor
119 : * on its own so it is up to you to call this function or not.
120 : * It is not mandatory.
121 : *
122 : * The function does not verify to know whether the file descriptor
123 : * was already closed outside of this function. Although it is safe
124 : * to call this function multiple times, if you close the file
125 : * descriptor with other means, then calling this function may
126 : * end up closing another file...
127 : */
128 0 : void fd_connection::close()
129 : {
130 0 : if(f_fd != -1)
131 : {
132 0 : ::close(f_fd);
133 0 : f_fd = -1;
134 : }
135 0 : }
136 :
137 :
138 : /** \brief Used to mark the file descriptor as closed.
139 : *
140 : * This function marks the file descriptor as closed. Whether it is,
141 : * is your own concern. This is used to avoid a double close in
142 : * case some other function ends up calling close() and yet you
143 : * somehow closed the file descriptor (i.e. fclose(f) will do that
144 : * on you...)
145 : *
146 : * \code
147 : * ...
148 : * fclose(f);
149 : * // tell connection that we've close the connection fd
150 : * c->mark_closed();
151 : * ...
152 : * \endcode
153 : *
154 : * Note that if you do not have any other copy of the file descriptor
155 : * and you call mark_closed() instead of close(), you will leak that
156 : * file descriptor.
157 : */
158 0 : void fd_connection::mark_closed()
159 : {
160 0 : f_fd = -1;
161 0 : }
162 :
163 :
164 : /** \brief Check whether this connection is a reader.
165 : *
166 : * If you created this file descriptor connection as a reader, then this
167 : * function returns true.
168 : *
169 : * A reader has a mode of FD_MODE_READ or FD_MODE_RW.
170 : *
171 : * \return true if the connection is considered to be a reader.
172 : */
173 0 : bool fd_connection::is_reader() const
174 : {
175 0 : return f_mode != mode_t::FD_MODE_WRITE && get_socket() != -1;
176 : }
177 :
178 :
179 : /** \brief Check whether this connection is a writer.
180 : *
181 : * If you created this file descriptor connection as a writer, then this
182 : * function returns true.
183 : *
184 : * A writer has a mode of FD_MODE_WRITE or FD_MODE_RW.
185 : *
186 : * \return true if the connection is considered to be a writer.
187 : */
188 0 : bool fd_connection::is_writer() const
189 : {
190 0 : return f_mode != mode_t::FD_MODE_READ && get_socket() != -1;
191 : }
192 :
193 :
194 : /** \brief Return the file descriptor ("socket").
195 : *
196 : * This function returns the file descriptor specified in the constructor.
197 : *
198 : * The current naming convention comes from the fact that the library
199 : * was first created for sockets.
200 : *
201 : * \return The connection file descriptor.
202 : */
203 0 : int fd_connection::get_socket() const
204 : {
205 0 : return f_fd;
206 : }
207 :
208 :
209 : /** \brief Read up data from the file descriptor.
210 : *
211 : * This function attempts to read up to \p count bytes of data from
212 : * this file descriptor. If that works to some extend, then the
213 : * data read will be saved in \p buf and the function returns
214 : * the number of bytes read.
215 : *
216 : * If no data can be read, the function may return -1 or 0.
217 : *
218 : * The file descriptor must be a reader or the function will always fail.
219 : *
220 : * \param[in] buf The buffer where the data read is saved.
221 : * \param[in] count The maximum number of bytes to read at once.
222 : */
223 0 : ssize_t fd_connection::read(void * buf, size_t count)
224 : {
225 : // WARNING: We MUST call the fd_connection version of the is_writer(),
226 : // because the fd_buffer_connection::is_writer() also checks
227 : // the f_output buffer which has unwanted side effects
228 : //
229 0 : if(!fd_connection::is_reader())
230 : {
231 0 : errno = EBADF;
232 0 : return -1;
233 : }
234 :
235 0 : return ::read(f_fd, buf, count);
236 : }
237 :
238 :
239 : /** \brief Write buffer data to the file descriptor.
240 : *
241 : * This function writes \p count bytes of data from \p buf to
242 : * the file descriptor attached to this connection.
243 : *
244 : * If the file descriptor is closed, then an error occurs and
245 : * the function returns -1.
246 : *
247 : * \note
248 : * If you setup the file descriptor in non-blocking mode, then the
249 : * function will return early if it cannot cache or immediately
250 : * send the specified data.
251 : *
252 : * \param[in] buf A pointer to a buffer of data to write to the file.
253 : * \param[in] count The number of bytes to write to the file.
254 : *
255 : * \return The number of bytes written to the file.
256 : */
257 0 : ssize_t fd_connection::write(void const * buf, size_t count)
258 : {
259 : // WARNING: We MUST call the fd_connection version of the is_writer(),
260 : // because the fd_buffer_connection::is_writer() also checks
261 : // the f_output buffer which has unwanted side effects
262 : //
263 0 : if(!fd_connection::is_writer())
264 : {
265 0 : errno = EBADF;
266 0 : return -1;
267 : }
268 :
269 0 : return ::write(f_fd, buf, count);
270 : }
271 :
272 :
273 :
274 : } // namespace ed
275 : // vim: ts=4 sw=4 et
|