1 2 /** 3 * Copyright (C) 2018-present MongoDB, Inc. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the Server Side Public License, version 1, 7 * as published by MongoDB, Inc. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * Server Side Public License for more details. 13 * 14 * You should have received a copy of the Server Side Public License 15 * along with this program. If not, see 16 * <http://www.mongodb.com/licensing/server-side-public-license>. 17 * 18 * As a special exception, the copyright holders give permission to link the 19 * code of portions of this program with the OpenSSL library under certain 20 * conditions as described in each individual source file and distribute 21 * linked combinations including the program with the OpenSSL library. You 22 * must comply with the Server Side Public License in all respects for 23 * all of the code used other than as permitted herein. If you modify file(s) 24 * with this exception, you may extend this exception to your version of the 25 * file(s), but you are not obligated to do so. If you do not wish to do so, 26 * delete this exception statement from your version. If you delete this 27 * exception statement from all source files in the program, then also delete 28 * it in the license file. 29 */ 30 31 #pragma once 32 33 #include <memory> 34 #include <sstream> 35 #include <string> 36 #include <vector> 37 38 #include "mongo/base/status_with.h" 39 #include "mongo/base/string_data.h" 40 #include "mongo/bson/util/builder.h" 41 #include "mongo/stdx/mutex.h" 42 #include "mongo/util/assert_util.h" 43 #include "mongo/util/net/hostandport.h" 44 45 namespace mongo { 46 47 class DBClientBase; 48 class MongoURI; 49 50 /** 51 * ConnectionString handles parsing different ways to connect to mongo and determining method 52 * samples: 53 * server 54 * server:port 55 * foo/server:port,server:port SET 56 * 57 * Typical use: 58 * 59 * ConnectionString cs(uassertStatusOK(ConnectionString::parse(url))); 60 * std::string errmsg; 61 * DBClientBase * conn = cs.connect( errmsg ); 62 */ 63 class ConnectionString { 64 public: 65 enum ConnectionType { INVALID, MASTER, SET, CUSTOM, LOCAL }; 66 67 ConnectionString() = default; 68 69 /** 70 * Constructs a connection string representing a replica set. 71 */ 72 static ConnectionString forReplicaSet(StringData setName, std::vector<HostAndPort> servers); 73 74 /** 75 * Constructs a local connection string. 76 */ 77 static ConnectionString forLocal(); 78 79 /** 80 * Creates a MASTER connection string with the specified server. 81 */ 82 explicit ConnectionString(const HostAndPort& server); 83 84 /** 85 * Creates a connection string from an unparsed list of servers, type, and setName. 86 */ 87 ConnectionString(ConnectionType type, const std::string& s, const std::string& setName); 88 89 /** 90 * Creates a connection string from a pre-parsed list of servers, type, and setName. 91 */ 92 ConnectionString(ConnectionType type, 93 std::vector<HostAndPort> servers, 94 const std::string& setName); 95 96 ConnectionString(const std::string& s, ConnectionType connType); 97 isValid()98 bool isValid() const { 99 return _type != INVALID; 100 } 101 toString()102 const std::string& toString() const { 103 return _string; 104 } 105 getSetName()106 const std::string& getSetName() const { 107 return _setName; 108 } 109 getServers()110 const std::vector<HostAndPort>& getServers() const { 111 return _servers; 112 } 113 type()114 ConnectionType type() const { 115 return _type; 116 } 117 118 /** 119 * Returns true if two connection strings match in terms of their type and the exact order of 120 * their hosts. 121 */ 122 bool operator==(const ConnectionString& other) const; 123 bool operator!=(const ConnectionString& other) const; 124 125 std::unique_ptr<DBClientBase> connect(StringData applicationName, 126 std::string& errmsg, 127 double socketTimeout = 0, 128 const MongoURI* uri = nullptr) const; 129 130 static StatusWith<ConnectionString> parse(const std::string& url); 131 132 static std::string typeToString(ConnectionType type); 133 134 // 135 // Allow overriding the default connection behavior 136 // This is needed for some tests, which otherwise would fail because they are unable to contact 137 // the correct servers. 138 // 139 140 class ConnectionHook { 141 public: ~ConnectionHook()142 virtual ~ConnectionHook() {} 143 144 // Returns an alternative connection object for a string 145 virtual std::unique_ptr<DBClientBase> connect(const ConnectionString& c, 146 std::string& errmsg, 147 double socketTimeout) = 0; 148 }; 149 setConnectionHook(ConnectionHook * hook)150 static void setConnectionHook(ConnectionHook* hook) { 151 stdx::lock_guard<stdx::mutex> lk(_connectHookMutex); 152 _connectHook = hook; 153 } 154 getConnectionHook()155 static ConnectionHook* getConnectionHook() { 156 stdx::lock_guard<stdx::mutex> lk(_connectHookMutex); 157 return _connectHook; 158 } 159 160 // Allows ConnectionStrings to be stored more easily in sets/maps 161 bool operator<(const ConnectionString& other) const { 162 return _string < other._string; 163 } 164 165 166 friend std::ostream& operator<<(std::ostream&, const ConnectionString&); 167 friend StringBuilder& operator<<(StringBuilder&, const ConnectionString&); 168 169 private: 170 /** 171 * Creates a SET connection string with the specified set name and servers. 172 */ 173 ConnectionString(StringData setName, std::vector<HostAndPort> servers); 174 175 /** 176 * Creates a connection string with the specified type. Used for creating LOCAL strings. 177 */ 178 explicit ConnectionString(ConnectionType connType); 179 180 void _fillServers(std::string s); 181 void _finishInit(); 182 183 ConnectionType _type{INVALID}; 184 std::vector<HostAndPort> _servers; 185 std::string _string; 186 std::string _setName; 187 188 static stdx::mutex _connectHookMutex; 189 static ConnectionHook* _connectHook; 190 }; 191 192 inline std::ostream& operator<<(std::ostream& ss, const ConnectionString& cs) { 193 ss << cs._string; 194 return ss; 195 } 196 197 inline StringBuilder& operator<<(StringBuilder& sb, const ConnectionString& cs) { 198 sb << cs._string; 199 return sb; 200 } 201 202 } // namespace mongo 203