xapian-core  1.4.23
remoteconnection.h
Go to the documentation of this file.
1 
4 /* Copyright (C) 2006,2007,2008,2010,2011,2014,2015,2019 Olly Betts
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 
21 #ifndef XAPIAN_INCLUDED_REMOTECONNECTION_H
22 #define XAPIAN_INCLUDED_REMOTECONNECTION_H
23 
24 #include <cerrno>
25 #include <string>
26 
27 #include "remoteprotocol.h"
28 #include "safenetdb.h" // For EAI_* constants.
29 #include "safeunistd.h"
30 
31 #ifdef __WIN32__
32 # include "safewinsock2.h"
33 
34 # include <xapian/error.h>
35 
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?
55 
56  if (wsaerror != 0) {
57  throw Xapian::NetworkError("Failed to initialize winsock", wsaerror);
58  }
59  }
60 
61  ~WinsockInitializer() {
62  WSACleanup();
63  }
64 };
65 
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;
87  }
88 }
89 
90 /* Newer compilers define these, in which case we map to those already defined
91  * values in socket_errno() above.
92  */
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
102 
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; }
108 
109 # define CLOSESOCKET(S) close(S)
110 #endif
111 
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;
147  }
148 #undef C
149 
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;
159 }
160 
170  void operator=(const RemoteConnection &);
171 
174 
180  int fdin;
181 
188  int fdout;
189 
191  std::string buffer;
192 
195 
208  bool read_at_least(size_t min_len, double end_time);
209 
210 #ifdef __WIN32__
211 
216  WSAOVERLAPPED overlapped;
217 
222  DWORD calc_read_wait_msecs(double end_time);
223 #endif
224 
225  protected:
230  std::string context;
231 
232  public:
234  RemoteConnection(int fdin_, int fdout_,
235  const std::string & context_ = std::string());
236 
237 #ifdef __WIN32__
238  ~RemoteConnection();
240 #endif
241 
246  bool ready_to_read() const;
247 
265  int sniff_next_message_type(double end_time);
266 
277  int get_message(std::string &result, double end_time);
278 
295  int get_message_chunked(double end_time);
296 
317  int get_message_chunk(std::string &result, size_t at_least,
318  double end_time);
319 
331  int receive_file(const std::string &file, double end_time);
332 
342  void send_message(char type, const std::string & s, double end_time);
343 
353  void send_file(char type, int fd, double end_time);
354 
360  void shutdown();
361 
363  void do_close();
364 };
365 
372  public:
374  OwnedRemoteConnection(int fdin_, int fdout_,
375  const std::string& context_ = std::string())
376  : RemoteConnection(fdin_, fdout_, context_) { }
377 
380  do_close();
381  }
382 };
383 
384 #endif // XAPIAN_INCLUDED_REMOTECONNECTION_H
A RemoteConnection object provides a bidirectional connection to another RemoteConnection object on a...
OwnedRemoteConnection(int fdin_, int fdout_, const std::string &context_=std::string())
Constructor.
off_t chunked_data_left
Remaining bytes of message data still to come over fdin for a chunked read.
double end_time(double timeout)
Return the end time for a timeout in timeout seconds.
Definition: realtime.h:95
int eai_to_xapian(int e)
include <netdb.h>, with portability workarounds.
std::string context
The context to report with errors.
Remote protocol version and message numbers.
Hierarchy of classes which Xapian can throw as exceptions.
int fdin
The file descriptor used for reading.
include <winsock2.h> but working around problems.
std::string buffer
Buffer to hold unprocessed input.
RemoteConnection which owns its own fd(s).
~OwnedRemoteConnection()
Destructor.
Indicates a problem communicating with a remote database.
Definition: error.h:803
<unistd.h>, but with compat.
int fdout
The file descriptor used for writing.
int socket_errno()
#define C(X)