00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #pragma once
00019
00020 #include "../pch.h"
00021
00022 #include <stdio.h>
00023 #include <sstream>
00024 #include "goodies.h"
00025 #include "../db/jsobj.h"
00026 #include "../db/cmdline.h"
00027
00028 namespace mongo {
00029
00030 const int SOCK_FAMILY_UNKNOWN_ERROR=13078;
00031 string getAddrInfoStrError(int code);
00032
00033 #if defined(_WIN32)
00034
00035 typedef short sa_family_t;
00036 typedef int socklen_t;
00037 inline int getLastError() { return WSAGetLastError(); }
00038 inline void disableNagle(int sock) {
00039 int x = 1;
00040 if ( setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &x, sizeof(x)) )
00041 out() << "ERROR: disableNagle failed" << endl;
00042 if ( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &x, sizeof(x)) )
00043 out() << "ERROR: SO_KEEPALIVE failed" << endl;
00044 }
00045 inline void prebindOptions( int sock ) { }
00046
00047
00048 struct sockaddr_un {
00049 short sun_family;
00050 char sun_path[108];
00051 };
00052
00053 #else
00054
00055 extern CmdLine cmdLine;
00056
00057 }
00058
00059 #include <sys/socket.h>
00060 #include <sys/types.h>
00061 #include <sys/socket.h>
00062 #include <sys/un.h>
00063 #include <netinet/in.h>
00064 #include <netinet/tcp.h>
00065 #include <arpa/inet.h>
00066 #include <errno.h>
00067 #include <netdb.h>
00068 #ifdef __openbsd__
00069 # include <sys/uio.h>
00070 #endif
00071
00072 #ifndef AI_ADDRCONFIG
00073 # define AI_ADDRCONFIG 0
00074 #endif
00075
00076 namespace mongo {
00077
00078 inline void closesocket(int s) {
00079 close(s);
00080 }
00081 const int INVALID_SOCKET = -1;
00082 typedef int SOCKET;
00083
00084 inline void disableNagle(int sock) {
00085 int x = 1;
00086
00087 #ifdef SOL_TCP
00088 int level = SOL_TCP;
00089 #else
00090 int level = SOL_SOCKET;
00091 #endif
00092
00093 if ( setsockopt(sock, level, TCP_NODELAY, (char *) &x, sizeof(x)) )
00094 log() << "ERROR: disableNagle failed: " << errnoWithDescription() << endl;
00095
00096 #ifdef SO_KEEPALIVE
00097 if ( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &x, sizeof(x)) )
00098 log() << "ERROR: SO_KEEPALIVE failed: " << errnoWithDescription() << endl;
00099 #endif
00100
00101 }
00102 inline void prebindOptions( int sock ) {
00103 DEV log() << "doing prebind option" << endl;
00104 int x = 1;
00105 if ( setsockopt( sock , SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0 )
00106 out() << "Failed to set socket opt, SO_REUSEADDR" << endl;
00107 }
00108
00109
00110 #endif
00111
00112 inline string makeUnixSockPath(int port) {
00113 return cmdLine.socket + "/mongodb-" + BSONObjBuilder::numStr(port) + ".sock";
00114 }
00115
00116 inline void setSockTimeouts(int sock, double secs) {
00117 struct timeval tv;
00118 tv.tv_sec = (int)secs;
00119 tv.tv_usec = (int)((long long)(secs*1000*1000) % (1000*1000));
00120 bool report = logLevel > 3;
00121 DEV report = true;
00122 bool ok = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv) ) == 0;
00123 if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
00124 ok = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof(tv) ) == 0;
00125 DEV if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
00126 }
00127
00128
00129
00130 string hostbyname(const char *hostname);
00131
00132 void enableIPv6(bool state=true);
00133 bool IPv6Enabled();
00134
00135 struct SockAddr {
00136 SockAddr() {
00137 addressSize = sizeof(sa);
00138 memset(&sa, 0, sizeof(sa));
00139 sa.ss_family = AF_UNSPEC;
00140 }
00141 SockAddr(int sourcePort);
00142 SockAddr(const char *ip, int port);
00143
00144 template <typename T>
00145 T& as() { return *(T*)(&sa); }
00146 template <typename T>
00147 const T& as() const { return *(const T*)(&sa); }
00148
00149 string toString(bool includePort=true) const {
00150 string out = getAddr();
00151 if (includePort && getType() != AF_UNIX && getType() != AF_UNSPEC)
00152 out += ':' + BSONObjBuilder::numStr(getPort());
00153 return out;
00154 }
00155
00156
00157 sa_family_t getType() const {
00158 return sa.ss_family;
00159 }
00160
00161 unsigned getPort() const {
00162 switch (getType()) {
00163 case AF_INET: return ntohs(as<sockaddr_in>().sin_port);
00164 case AF_INET6: return ntohs(as<sockaddr_in6>().sin6_port);
00165 case AF_UNIX: return 0;
00166 case AF_UNSPEC: return 0;
00167 default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return 0;
00168 }
00169 }
00170
00171 string getAddr() const {
00172 switch (getType()) {
00173 case AF_INET:
00174 case AF_INET6: {
00175 const int buflen=128;
00176 char buffer[buflen];
00177 int ret = getnameinfo(raw(), addressSize, buffer, buflen, NULL, 0, NI_NUMERICHOST);
00178 massert(13082, getAddrInfoStrError(ret), ret == 0);
00179 return buffer;
00180 }
00181
00182 case AF_UNIX: return (addressSize > 2 ? as<sockaddr_un>().sun_path : "anonymous unix socket");
00183 case AF_UNSPEC: return "(NONE)";
00184 default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return "";
00185 }
00186 }
00187
00188 bool isLocalHost() const;
00189
00190 bool operator==(const SockAddr& r) const {
00191 if (getType() != r.getType())
00192 return false;
00193
00194 if (getPort() != r.getPort())
00195 return false;
00196
00197 switch (getType()) {
00198 case AF_INET: return as<sockaddr_in>().sin_addr.s_addr == r.as<sockaddr_in>().sin_addr.s_addr;
00199 case AF_INET6: return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, r.as<sockaddr_in6>().sin6_addr.s6_addr, sizeof(in6_addr)) == 0;
00200 case AF_UNIX: return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) == 0;
00201 case AF_UNSPEC: return true;
00202 default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false);
00203 }
00204 }
00205 bool operator!=(const SockAddr& r) const {
00206 return !(*this == r);
00207 }
00208 bool operator<(const SockAddr& r) const {
00209 if (getType() < r.getType())
00210 return true;
00211 else if (getType() > r.getType())
00212 return false;
00213
00214 if (getPort() < r.getPort())
00215 return true;
00216 else if (getPort() > r.getPort())
00217 return false;
00218
00219 switch (getType()) {
00220 case AF_INET: return as<sockaddr_in>().sin_addr.s_addr < r.as<sockaddr_in>().sin_addr.s_addr;
00221 case AF_INET6: return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, r.as<sockaddr_in6>().sin6_addr.s6_addr, sizeof(in6_addr)) < 0;
00222 case AF_UNIX: return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) < 0;
00223 case AF_UNSPEC: return false;
00224 default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false);
00225 }
00226 }
00227
00228 const sockaddr* raw() const {return (sockaddr*)&sa;}
00229 sockaddr* raw() {return (sockaddr*)&sa;}
00230
00231 socklen_t addressSize;
00232 private:
00233 struct sockaddr_storage sa;
00234 };
00235
00236 extern SockAddr unknownAddress;
00237
00238 const int MaxMTU = 16384;
00239
00240 inline string getHostName() {
00241 char buf[256];
00242 int ec = gethostname(buf, 127);
00243 if ( ec || *buf == 0 ) {
00244 log() << "can't get this server's hostname " << errnoWithDescription() << endl;
00245 return "";
00246 }
00247 return buf;
00248 }
00249
00250 string getHostNameCached();
00251
00252 class ListeningSockets {
00253 public:
00254 ListeningSockets()
00255 : _mutex("ListeningSockets")
00256 , _sockets( new set<int>() )
00257 , _socketPaths( new set<string>() )
00258 { }
00259 void add( int sock ) {
00260 scoped_lock lk( _mutex );
00261 _sockets->insert( sock );
00262 }
00263 void addPath( string path ) {
00264 scoped_lock lk( _mutex );
00265 _socketPaths->insert( path );
00266 }
00267 void remove( int sock ) {
00268 scoped_lock lk( _mutex );
00269 _sockets->erase( sock );
00270 }
00271 void closeAll() {
00272 set<int>* sockets;
00273 set<string>* paths;
00274
00275 {
00276 scoped_lock lk( _mutex );
00277 sockets = _sockets;
00278 _sockets = new set<int>();
00279 paths = _socketPaths;
00280 _socketPaths = new set<string>();
00281 }
00282
00283 for ( set<int>::iterator i=sockets->begin(); i!=sockets->end(); i++ ) {
00284 int sock = *i;
00285 log() << "closing listening socket: " << sock << endl;
00286 closesocket( sock );
00287 }
00288
00289 for ( set<string>::iterator i=paths->begin(); i!=paths->end(); i++ ) {
00290 string path = *i;
00291 log() << "removing socket file: " << path << endl;
00292 ::remove( path.c_str() );
00293 }
00294 }
00295 static ListeningSockets* get();
00296 private:
00297 mongo::mutex _mutex;
00298 set<int>* _sockets;
00299 set<string>* _socketPaths;
00300 static ListeningSockets* _instance;
00301 };
00302
00303 }