Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / resolver / google_c2p / google_c2p_resolver.cc
index 424115d..a430e7a 100644 (file)
 
 #include <grpc/support/port_platform.h>
 
+#include <random>
+
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/xds/xds_client.h"
 #include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
 #include "src/core/lib/http/httpcli.h"
 #include "src/core/lib/iomgr/polling_entity.h"
 #include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
@@ -47,21 +50,21 @@ class GoogleCloud2ProdResolver : public Resolver {
     void Orphan() override;
 
    private:
-    static void OnHttpRequestDone(void* arg, grpc_error* error);
+    static void OnHttpRequestDone(void* arg, grpc_error_handle error);
 
     // Calls OnDone() if not already called.  Releases a ref.
-    void MaybeCallOnDone(grpc_error* error);
+    void MaybeCallOnDone(grpc_error_handle error);
 
     // If error is not GRPC_ERROR_NONE, then it's not safe to look at response.
     virtual void OnDone(GoogleCloud2ProdResolver* resolver,
                         const grpc_http_response* response,
-                        grpc_error* error) = 0;
+                        grpc_error_handle error) = 0;
 
     RefCountedPtr<GoogleCloud2ProdResolver> resolver_;
     grpc_httpcli_context context_;
     grpc_httpcli_response response_;
     grpc_closure on_done_;
-    Atomic<bool> on_done_called_{false};
+    std::atomic<bool> on_done_called_{false};
   };
 
   // A metadata server query to get the zone.
@@ -72,7 +75,8 @@ class GoogleCloud2ProdResolver : public Resolver {
 
    private:
     void OnDone(GoogleCloud2ProdResolver* resolver,
-                const grpc_http_response* response, grpc_error* error) override;
+                const grpc_http_response* response,
+                grpc_error_handle error) override;
   };
 
   // A metadata server query to get the IPv6 address.
@@ -83,7 +87,8 @@ class GoogleCloud2ProdResolver : public Resolver {
 
    private:
     void OnDone(GoogleCloud2ProdResolver* resolver,
-                const grpc_http_response* response, grpc_error* error) override;
+                const grpc_http_response* response,
+                grpc_error_handle error) override;
   };
 
   void ZoneQueryDone(std::string zone);
@@ -127,7 +132,6 @@ GoogleCloud2ProdResolver::MetadataQuery::MetadataQuery(
   grpc_httpcli_get(&context_, pollent, resource_quota, &request,
                    ExecCtx::Get()->Now() + 10000,  // 10s timeout
                    &on_done_, &response_);
-  grpc_resource_quota_unref_internal(resource_quota);
 }
 
 GoogleCloud2ProdResolver::MetadataQuery::~MetadataQuery() {
@@ -142,16 +146,17 @@ void GoogleCloud2ProdResolver::MetadataQuery::Orphan() {
 }
 
 void GoogleCloud2ProdResolver::MetadataQuery::OnHttpRequestDone(
-    void* arg, grpc_error* error) {
+    void* arg, grpc_error_handle error) {
   auto* self = static_cast<MetadataQuery*>(arg);
   self->MaybeCallOnDone(GRPC_ERROR_REF(error));
 }
 
 void GoogleCloud2ProdResolver::MetadataQuery::MaybeCallOnDone(
-    grpc_error* error) {
+    grpc_error_handle error) {
   bool expected = false;
-  if (!on_done_called_.CompareExchangeStrong(
-          &expected, true, MemoryOrder::RELAXED, MemoryOrder::RELAXED)) {
+  if (!on_done_called_.compare_exchange_strong(expected, true,
+                                               std::memory_order_relaxed,
+                                               std::memory_order_relaxed)) {
     // We've already called OnDone(), so just clean up.
     GRPC_ERROR_UNREF(error);
     Unref();
@@ -179,10 +184,10 @@ GoogleCloud2ProdResolver::ZoneQuery::ZoneQuery(
 
 void GoogleCloud2ProdResolver::ZoneQuery::OnDone(
     GoogleCloud2ProdResolver* resolver, const grpc_http_response* response,
-    grpc_error* error) {
+    grpc_error_handle error) {
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR, "error fetching zone from metadata server: %s",
-            grpc_error_string(error));
+            grpc_error_std_string(error).c_str());
   }
   std::string zone;
   if (error == GRPC_ERROR_NONE && response->status == 200) {
@@ -192,7 +197,7 @@ void GoogleCloud2ProdResolver::ZoneQuery::OnDone(
       gpr_log(GPR_ERROR, "could not parse zone from metadata server: %s",
               std::string(body).c_str());
     } else {
-      zone = std::string(body.substr(i));
+      zone = std::string(body.substr(i + 1));
     }
   }
   resolver->ZoneQueryDone(std::move(zone));
@@ -212,10 +217,10 @@ GoogleCloud2ProdResolver::IPv6Query::IPv6Query(
 
 void GoogleCloud2ProdResolver::IPv6Query::OnDone(
     GoogleCloud2ProdResolver* resolver, const grpc_http_response* response,
-    grpc_error* error) {
+    grpc_error_handle error) {
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR, "error fetching IPv6 address from metadata server: %s",
-            grpc_error_string(error));
+            grpc_error_std_string(error).c_str());
   }
   resolver->IPv6QueryDone(error == GRPC_ERROR_NONE && response->status == 200);
   GRPC_ERROR_UNREF(error);
@@ -294,8 +299,11 @@ void GoogleCloud2ProdResolver::IPv6QueryDone(bool ipv6_supported) {
 
 void GoogleCloud2ProdResolver::StartXdsResolver() {
   // Construct bootstrap JSON.
+  std::random_device rd;
+  std::mt19937 mt(rd());
+  std::uniform_int_distribution<uint64_t> dist(1, UINT64_MAX);
   Json::Object node = {
-      {"id", "C2P"},
+      {"id", absl::StrCat("C2P-", dist(mt))},
   };
   if (!zone_->empty()) {
     node["locality"] = Json::Object{
@@ -307,17 +315,25 @@ void GoogleCloud2ProdResolver::StartXdsResolver() {
         {"TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE", true},
     };
   }
+  // Allow the TD server uri to be overridden for testing purposes.
+  UniquePtr<char> override_server(
+      gpr_getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"));
+  const char* server_uri =
+      override_server != nullptr && strlen(override_server.get()) > 0
+          ? override_server.get()
+          : "directpath-pa.googleapis.com";
   Json bootstrap = Json::Object{
       {"xds_servers",
        Json::Array{
            Json::Object{
-               {"server_uri", "directpath-trafficdirector.googleapis.com"},
+               {"server_uri", server_uri},
                {"channel_creds",
                 Json::Array{
                     Json::Object{
                         {"type", "google_default"},
                     },
                 }},
+               {"server_features", Json::Array{"xds_v3"}},
            },
        }},
       {"node", std::move(node)},
@@ -353,8 +369,14 @@ class GoogleCloud2ProdResolverFactory : public ResolverFactory {
 }  // namespace
 
 void GoogleCloud2ProdResolverInit() {
-  ResolverRegistry::Builder::RegisterResolverFactory(
-      absl::make_unique<GoogleCloud2ProdResolverFactory>());
+  // TODO(roth): Remove env var protection once this code is proven stable.
+  UniquePtr<char> value(gpr_getenv("GRPC_EXPERIMENTAL_GOOGLE_C2P_RESOLVER"));
+  bool parsed_value;
+  bool parse_succeeded = gpr_parse_bool_value(value.get(), &parsed_value);
+  if (parse_succeeded && parsed_value) {
+    ResolverRegistry::Builder::RegisterResolverFactory(
+        absl::make_unique<GoogleCloud2ProdResolverFactory>());
+  }
 }
 
 void GoogleCloud2ProdResolverShutdown() {}