xapian-core  1.4.25
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 
217  WSAOVERLAPPED overlapped;
218 
223  DWORD calc_read_wait_msecs(double end_time);
224 #endif
225 
226  protected:
231  std::string context;
232 
233  public:
235  RemoteConnection(int fdin_, int fdout_,
236  const std::string & context_ = std::string());
237 
238 #ifdef __WIN32__
239  ~RemoteConnection();
241 #endif
242 
247  bool ready_to_read() const;
248 
266  int sniff_next_message_type(double end_time);
267 
278  int get_message(std::string &result, double end_time);
279 
296  int get_message_chunked(double end_time);
297 
318  int get_message_chunk(std::string &result, size_t at_least,
319  double end_time);
320 
332  int receive_file(const std::string &file, double end_time);
333 
343  void send_message(char type, const std::string & s, double end_time);
344 
354  void send_file(char type, int fd, double end_time);
355 
361  void shutdown();
362 
364  void do_close();
365 };
366 
373  public:
375  OwnedRemoteConnection(int fdin_, int fdout_,
376  const std::string& context_ = std::string())
377  : RemoteConnection(fdin_, fdout_, context_) { }
378 
381  do_close();
382  }
383 };
384 
385 #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)