scriptindex: Fix weird error cases
[xapian.git] / xapian-core / net / remoteconnection.h
blob01d0bb9dbbbc0dfdaa4a235bfdf05bc7579ea3cf
1 /** @file
2 * @brief RemoteConnection class used by the remote backend.
3 */
4 /* Copyright (C) 2006,2007,2008,2010,2011,2014,2015,2019 Olly Betts
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.
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.
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
21 #ifndef XAPIAN_INCLUDED_REMOTECONNECTION_H
22 #define XAPIAN_INCLUDED_REMOTECONNECTION_H
24 #include <cerrno>
25 #include <string>
27 #include "remoteprotocol.h"
28 #include "safenetdb.h" // For EAI_* constants.
29 #include "safeunistd.h"
31 #ifdef __WIN32__
32 # include "safewinsock2.h"
34 # include <xapian/error.h>
36 /** Class to initialise winsock and keep it initialised while we use it.
38 * We need to get WinSock initialised before we use it, and make it clean up
39 * after we've finished using it. This class performs this initialisation when
40 * constructed and cleans up when destructed. Multiple instances of the class
41 * may be instantiated - windows keeps a count of the number of times that
42 * WSAStartup has been successfully called and only performs the actual cleanup
43 * when WSACleanup has been called the same number of times.
45 * Simply ensure that an instance of this class is initialised whenever we're
46 * doing socket handling. This class can be used as a mixin class (just
47 * inherit from it) or instantiated as a class member or local variable).
49 struct WinsockInitializer {
50 WinsockInitializer() {
51 WSADATA wsadata;
52 int wsaerror = WSAStartup(MAKEWORD(2, 2), &wsadata);
53 // FIXME - should we check the returned information in wsadata to check
54 // that we have a version of winsock which is recent enough for us?
56 if (wsaerror != 0) {
57 throw Xapian::NetworkError("Failed to initialize winsock", wsaerror);
61 ~WinsockInitializer() {
62 WSACleanup();
66 /** Get the errno value of the last error to occur due to a socket operation.
68 * This is specific to the calling thread.
70 * This is needed because some platforms (Windows) separate errors due to
71 * socket operations from other errors. On platforms which don't do this,
72 * the return value will be the value of errno.
74 inline int socket_errno() {
75 int wsa_err = WSAGetLastError();
76 switch (wsa_err) {
77 # ifdef EADDRINUSE
78 case WSAEADDRINUSE: return EADDRINUSE;
79 # endif
80 # ifdef ETIMEDOUT
81 case WSAETIMEDOUT: return ETIMEDOUT;
82 # endif
83 # ifdef EINPROGRESS
84 case WSAEINPROGRESS: return EINPROGRESS;
85 # endif
86 default: return wsa_err;
90 /* Newer compilers define these, in which case we map to those already defined
91 * values in socket_errno() above.
93 # ifndef EADDRINUSE
94 # define EADDRINUSE WSAEADDRINUSE
95 # endif
96 # ifndef ETIMEDOUT
97 # define ETIMEDOUT WSAETIMEDOUT
98 # endif
99 # ifndef EINPROGRESS
100 # define EINPROGRESS WSAEINPROGRESS
101 # endif
103 // We must call closesocket() (instead of just close()) under __WIN32__ or
104 // else the socket remains in the CLOSE_WAIT state.
105 # define CLOSESOCKET(S) closesocket(S)
106 #else
107 inline int socket_errno() { return errno; }
109 # define CLOSESOCKET(S) close(S)
110 #endif
112 inline int eai_to_xapian(int e) {
113 // Under WIN32, the EAI_* constants are defined to be WSA_* constants with
114 // roughly equivalent meanings, so we can just let them be handled as any
115 // other WSA_* error codes would be.
116 #ifndef __WIN32__
117 // Ensure they all have the same sign - this switch will fail to compile if
118 // we bitwise-or some 1 and some 2 bits to get 3.
119 #define C(X) ((X) < 0 ? 2 : 1)
120 // Switch on a value there is a case for, to avoid clang warning:
121 // "no case matching constant switch condition '0'"
122 switch (3) {
123 case
124 C(EAI_AGAIN)|
125 C(EAI_BADFLAGS)|
126 C(EAI_FAIL)|
127 C(EAI_FAMILY)|
128 C(EAI_MEMORY)|
129 C(EAI_NONAME)|
130 C(EAI_SERVICE)|
131 C(EAI_SOCKTYPE)|
132 C(EAI_SYSTEM)|
133 #ifdef EAI_ADDRFAMILY
134 // In RFC 2553 but not RFC 3493 or POSIX:
135 C(EAI_ADDRFAMILY)|
136 #endif
137 #ifdef EAI_NODATA
138 // In RFC 2553 but not RFC 3493 or POSIX:
139 C(EAI_NODATA)|
140 #endif
141 #ifdef EAI_OVERFLOW
142 // In RFC 3493 and POSIX but not RFC 2553:
143 C(EAI_OVERFLOW)|
144 #endif
145 0: break;
146 case 3: break;
148 #undef C
150 // EAI_SYSTEM means "look at errno".
151 if (e == EAI_SYSTEM)
152 return errno;
153 // POSIX only says that EAI_* constants are "non-zero". On Linux they are
154 // negative, but allow for them being positive too.
155 if (EAI_FAIL > 0)
156 return -e;
157 #endif
158 return e;
161 /** A RemoteConnection object provides a bidirectional connection to another
162 * RemoteConnection object on a remote machine.
164 * The connection is implemented using a pair of file descriptors. Messages
165 * with a single byte type code and arbitrary data as the contents can be
166 * sent and received.
168 class RemoteConnection {
169 /// Don't allow assignment.
170 void operator=(const RemoteConnection &);
172 /// Don't allow copying.
173 RemoteConnection(const RemoteConnection &);
175 /** The file descriptor used for reading.
177 * If this is -1, the connection is unidirectional and write-only.
178 * If both fdin and fdout are -1, then the connection has been closed.
180 int fdin;
182 /** The file descriptor used for writing.
184 * If this is -1, the connection is unidirectional and read-only.
185 * If both fdin and fdout are -1, then the connection has been closed.
186 * It is valid for fdout to be the same as fdin.
188 int fdout;
190 /// Buffer to hold unprocessed input.
191 std::string buffer;
193 /// Remaining bytes of message data still to come over fdin for a chunked read.
194 off_t chunked_data_left;
196 /** Read until there are at least min_len bytes in buffer.
198 * If for some reason this isn't possible, returns false upon EOF and
199 * otherwise throws NetworkError.
201 * @param min_len Minimum number of bytes required in buffer.
202 * @param end_time If this time is reached, then a timeout
203 * exception will be thrown. If (end_time == 0.0),
204 * then keep trying indefinitely.
206 * @return false on EOF, otherwise true.
208 bool read_at_least(size_t min_len, double end_time);
210 #ifdef __WIN32__
211 /** On Windows we use overlapped IO. We share an overlapped structure
212 * for both reading and writing, as we know that we always wait for
213 * one to finish before starting another (ie, we don't *really* use
214 * overlapped IO - no IO is overlapped - its used only to manage timeouts)
216 WSAOVERLAPPED overlapped;
218 /** Calculate how many milliseconds a read should wait.
220 * This will raise a timeout exception if end_time has already passed.
222 DWORD calc_read_wait_msecs(double end_time);
223 #endif
225 protected:
226 /** The context to report with errors.
228 * Subclasses are allowed to manage this.
230 std::string context;
232 public:
233 /// Constructor.
234 RemoteConnection(int fdin_, int fdout_,
235 const std::string & context_ = std::string());
237 #ifdef __WIN32__
238 /// Destructor
239 ~RemoteConnection();
240 #endif
242 /** See if there is data available to read.
244 * @return true if there is data waiting to be read.
246 bool ready_to_read() const;
248 /** Check what the next message type is.
250 * This must not be called after a call to get_message_chunked() until
251 * get_message_chunk() has returned 0 to indicate the whole message
252 * has been received.
254 * Other than that restriction, this may be called at any time to
255 * determine what the next message waiting to be processed is: it will not
256 * affect subsequent calls which read messages.
258 * @param end_time If this time is reached, then a timeout
259 * exception will be thrown. If
260 * (end_time == 0.0) then the operation will
261 * never timeout.
263 * @return Message type code or -1 for EOF.
265 int sniff_next_message_type(double end_time);
267 /** Read one message from fdin.
269 * @param[out] result Message data.
270 * @param end_time If this time is reached, then a timeout
271 * exception will be thrown. If
272 * (end_time == 0.0) then the operation will
273 * never timeout.
275 * @return Message type code or -1 for EOF.
277 int get_message(std::string &result, double end_time);
279 /** Prepare to read one message from fdin in chunks.
281 * Sometimes a message can be sufficiently large that you don't want to
282 * read it all into memory before processing it. Also, it may be more
283 * efficient to process it as you go.
285 * This method doesn't actually return any message data - call
286 * get_message_chunk() to do that.
288 * @param end_time If this time is reached, then a timeout
289 * exception will be thrown. If
290 * (end_time == 0.0) then the operation will
291 * never timeout.
293 * @return Message type code or -1 for EOF.
295 int get_message_chunked(double end_time);
297 /** Read a chunk of a message from fdin.
299 * You must call get_message_chunked() before calling this method.
301 * @param[in,out] result Message data. This is appended to, so if you
302 * read more than needed the previous time, leave
303 * the excess in result.
304 * @param at_least Return at least this many bytes in result,
305 * unless there isn't enough data left in the
306 * message (in which case all remaining data is
307 * read and 0 is returned).
308 * @param end_time If this time is reached, then a timeout
309 * exception will be thrown. If
310 * (end_time == 0.0) then the operation will
311 * never timeout.
313 * @return 1 if at least at_least bytes are now in result;
314 * -1 on EOF on the connection; 0 for having read
315 * < at_least bytes, but finished the message.
317 int get_message_chunk(std::string &result, size_t at_least,
318 double end_time);
320 /** Save the contents of a message as a file.
322 * @param file Path to file to save the message data into. If
323 * the file exists it will be overwritten.
324 * @param end_time If this time is reached, then a timeout
325 * exception will be thrown. If
326 * (end_time == 0.0) then the operation will
327 * never timeout.
329 * @return Message type code or -1 for EOF.
331 int receive_file(const std::string &file, double end_time);
333 /** Send a message.
335 * @param type Message type code.
336 * @param s Message data.
337 * @param end_time If this time is reached, then a timeout
338 * exception will be thrown. If
339 * (end_time == 0.0) then the operation will
340 * never timeout.
342 void send_message(char type, const std::string & s, double end_time);
344 /** Send the contents of a file as a message.
346 * @param type Message type code.
347 * @param fd File containing the message data.
348 * @param end_time If this time is reached, then a timeout
349 * exception will be thrown. If
350 * (end_time == 0.0) then the operation will
351 * never timeout.
353 void send_file(char type, int fd, double end_time);
355 /** Shutdown the connection.
357 * Sends a shutdown message to the server and waits for it to close its
358 * end of the connection.
360 void shutdown();
362 /** Close the connection. */
363 void do_close();
366 /** RemoteConnection which owns its own fd(s).
368 * The object takes ownership of the fd(s) for the connection and will close
369 * them when it is destroyed.
371 class OwnedRemoteConnection : public RemoteConnection {
372 public:
373 /// Constructor.
374 OwnedRemoteConnection(int fdin_, int fdout_,
375 const std::string& context_ = std::string())
376 : RemoteConnection(fdin_, fdout_, context_) { }
378 /// Destructor.
379 ~OwnedRemoteConnection() {
380 do_close();
384 #endif // XAPIAN_INCLUDED_REMOTECONNECTION_H