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 Unix stream server-client class.
22 : *
23 : * Whenever a Unix stream server accepts a new connection, it expects the
24 : * accept() function to return a socket descriptor which is used to create
25 : * a local_stream_server_client_connection object. If you want to receive
26 : * data by line, use a buffer. If you want messages, use the message
27 : * version.
28 : */
29 :
30 : // self
31 : //
32 : #include "eventdispatcher/local_stream_server_client_connection.h"
33 :
34 : #include "eventdispatcher/exception.h"
35 :
36 :
37 : // snaplogger lib
38 : //
39 : #include <snaplogger/message.h>
40 :
41 :
42 : // C++ lib
43 : //
44 : #include <cstring>
45 :
46 :
47 : // C lib
48 : //
49 : #include <arpa/inet.h>
50 : #include <netdb.h>
51 :
52 :
53 : // last include
54 : //
55 : #include <snapdev/poison.h>
56 :
57 :
58 :
59 : namespace ed
60 : {
61 :
62 :
63 :
64 : /** \brief Create a client connection created from an accept().
65 : *
66 : * This constructor initializes a client connection from a socket
67 : * that we received from an accept() call.
68 : *
69 : * The destructor will automatically close that socket on destruction.
70 : *
71 : * \param[in] client The client that accept() returned.
72 : */
73 1 : local_stream_server_client_connection::local_stream_server_client_connection(snap::raii_fd_t client)
74 1 : : f_client(std::move(client))
75 : {
76 1 : }
77 :
78 :
79 : /** \brief Read data from the TCP server client socket.
80 : *
81 : * This function reads as much data up to the specified amount
82 : * in \p count. The read data is saved in \p buf.
83 : *
84 : * \param[in,out] buf The buffer where the data gets read.
85 : * \param[in] count The maximum number of bytes to read in buf.
86 : *
87 : * \return The number of bytes read or -1 if an error occurred.
88 : */
89 4 : ssize_t local_stream_server_client_connection::read(void * buf, size_t count)
90 : {
91 4 : if(f_client == nullptr)
92 : {
93 0 : errno = EBADF;
94 0 : return -1;
95 : }
96 4 : return ::read(f_client.get(), reinterpret_cast<char *>(buf), count);
97 : }
98 :
99 :
100 : /** \brief Write data to this connection's socket.
101 : *
102 : * This function writes up to \p count bytes of data from \p buf
103 : * to this connection's socket.
104 : *
105 : * \warning
106 : * This write function may not always write all the data you are
107 : * trying to send to the remote connection. If you want to make
108 : * sure that all your data is written to the other connection,
109 : * you want to instead use the local_stream_server_client_buffer_connection
110 : * which overloads the write() function and saves the data to be
111 : * written to the socket in a buffer. The communicator run
112 : * loop is then responsible for sending all the data.
113 : *
114 : * \param[in] buf The buffer of data to be written to the socket.
115 : * \param[in] count The number of bytes the caller wants to write to the
116 : * connection.
117 : *
118 : * \return The number of bytes written to the socket or -1 if an error occurred.
119 : */
120 1 : ssize_t local_stream_server_client_connection::write(void const * buf, size_t count)
121 : {
122 1 : if(f_client == nullptr)
123 : {
124 0 : errno = EBADF;
125 0 : return -1;
126 : }
127 1 : return ::write(f_client.get(), reinterpret_cast<char const *>(buf), count);
128 : }
129 :
130 :
131 : /** \brief Retrieve the socket of this connection.
132 : *
133 : * This function returns the socket defined in this connection. It is
134 : * the socket that was received through an accept() call.
135 : *
136 : * \return The socket descriptor of this connection.
137 : */
138 29 : int local_stream_server_client_connection::get_socket() const
139 : {
140 29 : if(f_client == nullptr)
141 : {
142 : // client connection was closed
143 : //
144 0 : errno = EBADF;
145 0 : return -1;
146 : }
147 29 : return f_client.get();
148 : }
149 :
150 :
151 : /** \brief Tell that we are always a reader.
152 : *
153 : * This function always returns true meaning that the connection is
154 : * always of a reader. In most cases this is safe because if nothing
155 : * is being written to you then poll() never returns so you do not
156 : * waste much time in have a TCP connection always marked as a
157 : * reader.
158 : *
159 : * \return The events to listen to for this connection.
160 : */
161 7 : bool local_stream_server_client_connection::is_reader() const
162 : {
163 7 : return true;
164 : }
165 :
166 :
167 : /** \brief Close this connection.
168 : *
169 : * This function is most often called on an error to clearly mark it
170 : * as closed. That way other function that attempt to use the socket
171 : * fill automatically fail instead of trying to access another file.
172 : */
173 0 : void local_stream_server_client_connection::close()
174 : {
175 0 : f_client.reset();
176 0 : }
177 :
178 :
179 : /** \brief Retrieve a copy of the client's address.
180 : *
181 : * This function returns a copy of the address of this client connection.
182 : *
183 : * The function may throw an error if the address is (somehow) not
184 : * supported, which is possible in clients that connect to servers
185 : * other than eventdispatcher servers.
186 : *
187 : * \return The Unix address this client is connected to.
188 : */
189 0 : addr::unix local_stream_server_client_connection::get_client_address() const
190 : {
191 : // make sure the address is defined and the socket open
192 : //
193 0 : const_cast<local_stream_server_client_connection *>(this)->define_address();
194 0 : return f_address;
195 : }
196 :
197 :
198 : /** \brief Retrieve the socket address if we have not done so yet.
199 : *
200 : * This function make sure that the f_address and f_length parameters are
201 : * defined. This is done by calling the getsockname() function.
202 : *
203 : * If f_length is still zero, then it is expected that address was not
204 : * yet read.
205 : *
206 : * Note that the function returns -1 if the socket is now -1 (i.e. the
207 : * connection is closed) whether or not the function worked before.
208 : */
209 0 : void local_stream_server_client_connection::define_address()
210 : {
211 0 : int const s(get_socket());
212 0 : if(s == -1)
213 : {
214 0 : errno = EBADF;
215 0 : return;
216 : }
217 :
218 0 : if(!f_address_defined)
219 : {
220 : // address not defined yet, retrieve it with getsockname()
221 : //
222 0 : f_address_defined = true;
223 0 : f_address.set_from_socket(s);
224 : }
225 : }
226 :
227 :
228 :
229 6 : } // namespace ed
230 : // vim: ts=4 sw=4 et
|