|
17 | 17 | #include "Firestore/core/src/firebase/firestore/remote/grpc_connection.h"
|
18 | 18 |
|
19 | 19 | #include <algorithm>
|
| 20 | +#include <mutex> // NOLINT(build/c++11) |
20 | 21 | #include <string>
|
21 | 22 | #include <utility>
|
22 | 23 |
|
@@ -66,15 +67,51 @@ struct HostConfig {
|
66 | 67 | bool use_insecure_channel = false;
|
67 | 68 | };
|
68 | 69 |
|
69 |
| -using ConfigByHost = std::unordered_map<std::string, HostConfig>; |
| 70 | +class HostConfigMap { |
| 71 | + using ConfigByHost = std::unordered_map<std::string, HostConfig>; |
| 72 | + using Guard = std::lock_guard<std::mutex>; |
| 73 | + |
| 74 | + public: |
| 75 | + const HostConfig* _Nullable find(const std::string& host) const { |
| 76 | + Guard guard{mutex_}; |
| 77 | + auto iter = map_.find(host); |
| 78 | + if (iter == map_.end()) { |
| 79 | + return nullptr; |
| 80 | + } else { |
| 81 | + return &(iter->second); |
| 82 | + } |
| 83 | + } |
70 | 84 |
|
71 |
| -ConfigByHost& Config() { |
72 |
| - static ConfigByHost config_by_host_; |
73 |
| - return config_by_host_; |
74 |
| -} |
| 85 | + void UseTestCertificate(const std::string& host, |
| 86 | + const Path& certificate_path, |
| 87 | + const std::string& target_name) { |
| 88 | + HARD_ASSERT(!host.empty(), "Empty host name"); |
| 89 | + HARD_ASSERT(!certificate_path.native_value().empty(), |
| 90 | + "Empty path to test certificate"); |
| 91 | + HARD_ASSERT(!target_name.empty(), "Empty SSL target name"); |
| 92 | + |
| 93 | + Guard guard(mutex_); |
| 94 | + HostConfig& host_config = map_[host]; |
| 95 | + host_config.certificate_path = certificate_path; |
| 96 | + host_config.target_name = target_name; |
| 97 | + } |
| 98 | + |
| 99 | + void UseInsecureChannel(const std::string& host) { |
| 100 | + HARD_ASSERT(!host.empty(), "Empty host name"); |
| 101 | + |
| 102 | + Guard guard(mutex_); |
| 103 | + HostConfig& host_config = map_[host]; |
| 104 | + host_config.use_insecure_channel = true; |
| 105 | + } |
| 106 | + |
| 107 | + private: |
| 108 | + ConfigByHost map_; |
| 109 | + mutable std::mutex mutex_; |
| 110 | +}; |
75 | 111 |
|
76 |
| -bool HasSpecialConfig(const std::string& host) { |
77 |
| - return Config().find(host) != Config().end(); |
| 112 | +HostConfigMap& Config() { |
| 113 | + static HostConfigMap config_by_host_; |
| 114 | + return config_by_host_; |
78 | 115 | }
|
79 | 116 |
|
80 | 117 | } // namespace
|
@@ -144,22 +181,21 @@ void GrpcConnection::EnsureActiveStub() {
|
144 | 181 | std::shared_ptr<grpc::Channel> GrpcConnection::CreateChannel() const {
|
145 | 182 | const std::string& host = database_info_->host();
|
146 | 183 |
|
147 |
| - if (!HasSpecialConfig(host)) { |
| 184 | + const HostConfig* host_config = Config().find(host); |
| 185 | + if (!host_config) { |
148 | 186 | std::string root_certificate = LoadGrpcRootCertificate();
|
149 | 187 | return grpc::CreateChannel(host, CreateSslCredentials(root_certificate));
|
150 | 188 | }
|
151 | 189 |
|
152 |
| - const HostConfig& host_config = Config()[host]; |
153 |
| - |
154 | 190 | // For the case when `Settings.sslEnabled == false`.
|
155 |
| - if (host_config.use_insecure_channel) { |
| 191 | + if (host_config->use_insecure_channel) { |
156 | 192 | return grpc::CreateChannel(host, grpc::InsecureChannelCredentials());
|
157 | 193 | }
|
158 | 194 |
|
159 | 195 | // For tests only
|
160 | 196 | grpc::ChannelArguments args;
|
161 |
| - args.SetSslTargetNameOverride(host_config.target_name); |
162 |
| - Path path = host_config.certificate_path; |
| 197 | + args.SetSslTargetNameOverride(host_config->target_name); |
| 198 | + Path path = host_config->certificate_path; |
163 | 199 | StatusOr<std::string> test_certificate = ReadFile(path);
|
164 | 200 | HARD_ASSERT(test_certificate.ok(),
|
165 | 201 | StringFormat("Unable to open root certificates at file path %s",
|
@@ -241,21 +277,11 @@ void GrpcConnection::Unregister(GrpcCall* call) {
|
241 | 277 | const std::string& host,
|
242 | 278 | const Path& certificate_path,
|
243 | 279 | const std::string& target_name) {
|
244 |
| - HARD_ASSERT(!host.empty(), "Empty host name"); |
245 |
| - HARD_ASSERT(!certificate_path.native_value().empty(), |
246 |
| - "Empty path to test certificate"); |
247 |
| - HARD_ASSERT(!target_name.empty(), "Empty SSL target name"); |
248 |
| - |
249 |
| - HostConfig& host_config = Config()[host]; |
250 |
| - host_config.certificate_path = certificate_path; |
251 |
| - host_config.target_name = target_name; |
| 280 | + Config().UseTestCertificate(host, certificate_path, target_name); |
252 | 281 | }
|
253 | 282 |
|
254 | 283 | /*static*/ void GrpcConnection::UseInsecureChannel(const std::string& host) {
|
255 |
| - HARD_ASSERT(!host.empty(), "Empty host name"); |
256 |
| - |
257 |
| - HostConfig& host_config = Config()[host]; |
258 |
| - host_config.use_insecure_channel = true; |
| 284 | + Config().UseInsecureChannel(host); |
259 | 285 | }
|
260 | 286 |
|
261 | 287 | } // namespace remote
|
|
0 commit comments