MongoDB  2.5.0
sock.h
1 // @file sock.h
2 
3 /* Copyright 2009 10gen Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include "mongo/pch.h"
21 
22 #include <stdio.h>
23 
24 #ifndef _WIN32
25 
26 #include <sys/socket.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/un.h>
30 #include <errno.h>
31 
32 #ifdef __openbsd__
33 # include <sys/uio.h>
34 #endif
35 
36 #endif // not _WIN32
37 
38 #ifdef MONGO_SSL
39 #include <openssl/ssl.h>
40 #endif
41 
42 #include "mongo/platform/compiler.h"
43 
44 namespace mongo {
45 
46  class SSLManagerInterface;
47 
48  const int SOCK_FAMILY_UNKNOWN_ERROR=13078;
49 
50  void disableNagle(int sock);
51 
52 #if defined(_WIN32)
53 
54  typedef short sa_family_t;
55  typedef int socklen_t;
56 
57  // This won't actually be used on windows
58  struct sockaddr_un {
59  short sun_family;
60  char sun_path[108]; // length from unix header
61  };
62 
63 #else // _WIN32
64 
65  inline void closesocket(int s) { close(s); }
66  const int INVALID_SOCKET = -1;
67  typedef int SOCKET;
68 
69 #endif // _WIN32
70 
71  string makeUnixSockPath(int port);
72 
73  // If an ip address is passed in, just return that. If a hostname is passed
74  // in, look up its ip and return that. Returns "" on failure.
75  string hostbyname(const char *hostname);
76 
77  void enableIPv6(bool state=true);
78  bool IPv6Enabled();
79  void setSockTimeouts(int sock, double secs);
80 
84  struct SockAddr {
85  SockAddr() {
86  addressSize = sizeof(sa);
87  memset(&sa, 0, sizeof(sa));
88  sa.ss_family = AF_UNSPEC;
89  }
90  SockAddr(int sourcePort); /* listener side */
91  SockAddr(const char *ip, int port); /* EndPoint (remote) side, or if you want to specify which interface locally */
92 
93  template <typename T> T& as() { return *(T*)(&sa); }
94  template <typename T> const T& as() const { return *(const T*)(&sa); }
95 
96  string toString(bool includePort=true) const;
97 
101  sa_family_t getType() const;
102 
103  unsigned getPort() const;
104 
105  string getAddr() const;
106 
107  bool isLocalHost() const;
108 
109  bool operator==(const SockAddr& r) const;
110 
111  bool operator!=(const SockAddr& r) const;
112 
113  bool operator<(const SockAddr& r) const;
114 
115  const sockaddr* raw() const {return (sockaddr*)&sa;}
116  sockaddr* raw() {return (sockaddr*)&sa;}
117 
118  socklen_t addressSize;
119  private:
120  struct sockaddr_storage sa;
121  };
122 
123  extern SockAddr unknownAddress; // ( "0.0.0.0", 0 )
124 
126  string getHostName();
127 
130  string getHostNameCached();
131 
132  string prettyHostName();
133 
137  class SocketException : public DBException {
138  public:
139  const enum Type { CLOSED , RECV_ERROR , SEND_ERROR, RECV_TIMEOUT, SEND_TIMEOUT, FAILED_STATE, CONNECT_ERROR } _type;
140 
141  SocketException( Type t , const std::string& server , int code = 9001 , const std::string& extra="" )
142  : DBException( (string)"socket exception [" + _getStringType( t ) + "] for " + server, code ),
143  _type(t),
144  _server(server),
145  _extra(extra)
146  {}
147 
148  virtual ~SocketException() throw() {}
149 
150  bool shouldPrint() const { return _type != CLOSED; }
151  virtual string toString() const;
152  virtual const std::string* server() const { return &_server; }
153  private:
154 
155  // TODO: Allow exceptions better control over their messages
156  static string _getStringType( Type t ){
157  switch (t) {
158  case CLOSED: return "CLOSED";
159  case RECV_ERROR: return "RECV_ERROR";
160  case SEND_ERROR: return "SEND_ERROR";
161  case RECV_TIMEOUT: return "RECV_TIMEOUT";
162  case SEND_TIMEOUT: return "SEND_TIMEOUT";
163  case FAILED_STATE: return "FAILED_STATE";
164  case CONNECT_ERROR: return "CONNECT_ERROR";
165  default: return "UNKNOWN"; // should never happen
166  }
167  }
168 
169  string _server;
170  string _extra;
171  };
172 
173 
178  class Socket : boost::noncopyable {
179  public:
180 
181  static const int errorPollIntervalSecs;
182 
183  Socket(int sock, const SockAddr& farEnd);
184 
191  Socket(double so_timeout = 0, int logLevel = 0 );
192 
193  ~Socket();
194 
195  bool connect(SockAddr& farEnd);
196  void close();
197 
198  void send( const char * data , int len, const char *context );
199  void send( const vector< pair< char *, int > > &data, const char *context );
200 
201  // recv len or throw SocketException
202  void recv( char * data , int len );
203  int unsafe_recv( char *buf, int max );
204 
205  int getLogLevel() const { return _logLevel; }
206  void setLogLevel( int ll ) { _logLevel = ll; }
207 
208  SockAddr remoteAddr() const { return _remote; }
209  string remoteString() const { return _remote.toString(); }
210  unsigned remotePort() const { return _remote.getPort(); }
211 
212  void clearCounters() { _bytesIn = 0; _bytesOut = 0; }
213  long long getBytesIn() const { return _bytesIn; }
214  long long getBytesOut() const { return _bytesOut; }
215 
216  void setTimeout( double secs );
217  bool isStillConnected();
218 
219 #ifdef MONGO_SSL
220 
221  void secure( SSLManagerInterface* ssl );
222 
223  void secureAccepted( SSLManagerInterface* ssl );
224 #endif
225 
232  void doSSLHandshake();
233 
237  uint64_t getSockCreationMicroSec() const {
238  return _fdCreationMicroSec;
239  }
240 
241  private:
242  void _init();
243 
245  void _send( const vector< pair< char *, int > > &data, const char *context );
246 
248  int _send( const char * data , int len );
249 
251  int _recv( char * buf , int max );
252 
253  void _handleRecvError(int ret, int len, int* retries);
254  MONGO_COMPILER_NORETURN void _handleSendError(int ret, const char* context);
255 
256  int _fd;
257  uint64_t _fdCreationMicroSec;
258  SockAddr _remote;
259  double _timeout;
260 
261  long long _bytesIn;
262  long long _bytesOut;
263  time_t _lastValidityCheckAtSecs;
264 
265 #ifdef MONGO_SSL
266  SSL* _ssl;
267  SSLManagerInterface* _sslManager;
268 #endif
269  int _logLevel; // passed to log() when logging errors
270 
271  };
272 
273 
274 } // namespace mongo