Imported Upstream version 1.27.0
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / xds / xds_bootstrap.cc
index 533b62a..5824391 100644 (file)
@@ -58,23 +58,23 @@ XdsBootstrap::XdsBootstrap(grpc_slice contents, grpc_error** error)
     return;
   }
   InlinedVector<grpc_error*, 1> error_list;
-  bool seen_xds_server = false;
+  bool seen_xds_servers = false;
   bool seen_node = false;
   for (grpc_json* child = tree_->child; child != nullptr; child = child->next) {
     if (child->key == nullptr) {
       error_list.push_back(
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
-    } else if (strcmp(child->key, "xds_server") == 0) {
-      if (child->type != GRPC_JSON_OBJECT) {
+    } else if (strcmp(child->key, "xds_servers") == 0) {
+      if (child->type != GRPC_JSON_ARRAY) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "\"xds_server\" field is not an object"));
+            "\"xds_servers\" field is not an array"));
       }
-      if (seen_xds_server) {
+      if (seen_xds_servers) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-            "duplicate \"xds_server\" field"));
+            "duplicate \"xds_servers\" field"));
       }
-      seen_xds_server = true;
-      grpc_error* parse_error = ParseXdsServer(child);
+      seen_xds_servers = true;
+      grpc_error* parse_error = ParseXdsServerList(child);
       if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
     } else if (strcmp(child->key, "node") == 0) {
       if (child->type != GRPC_JSON_OBJECT) {
@@ -90,9 +90,9 @@ XdsBootstrap::XdsBootstrap(grpc_slice contents, grpc_error** error)
       if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
     }
   }
-  if (!seen_xds_server) {
+  if (!seen_xds_servers) {
     error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-        "\"xds_server\" field not present"));
+        "\"xds_servers\" field not present"));
   }
   *error = GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing xds bootstrap file",
                                          &error_list);
@@ -103,9 +103,33 @@ XdsBootstrap::~XdsBootstrap() {
   grpc_slice_unref_internal(contents_);
 }
 
-grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) {
+grpc_error* XdsBootstrap::ParseXdsServerList(grpc_json* json) {
   InlinedVector<grpc_error*, 1> error_list;
-  server_uri_ = nullptr;
+  size_t idx = 0;
+  for (grpc_json *child = json->child; child != nullptr;
+       child = child->next, ++idx) {
+    if (child->key != nullptr) {
+      char* msg;
+      gpr_asprintf(&msg, "array element %" PRIuPTR " key is not null", idx);
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
+    }
+    if (child->type != GRPC_JSON_OBJECT) {
+      char* msg;
+      gpr_asprintf(&msg, "array element %" PRIuPTR " is not an object", idx);
+      error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
+    } else {
+      grpc_error* parse_error = ParseXdsServer(child, idx);
+      if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
+    }
+  }
+  return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"xds_servers\" array",
+                                       &error_list);
+}
+
+grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json, size_t idx) {
+  InlinedVector<grpc_error*, 1> error_list;
+  servers_.emplace_back();
+  XdsServer& server = servers_[servers_.size() - 1];
   bool seen_channel_creds = false;
   for (grpc_json* child = json->child; child != nullptr; child = child->next) {
     if (child->key == nullptr) {
@@ -116,11 +140,11 @@ grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
             "\"server_uri\" field is not a string"));
       }
-      if (server_uri_ != nullptr) {
+      if (server.server_uri != nullptr) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
             "duplicate \"server_uri\" field"));
       }
-      server_uri_ = child->value;
+      server.server_uri = child->value;
     } else if (strcmp(child->key, "channel_creds") == 0) {
       if (child->type != GRPC_JSON_ARRAY) {
         error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@@ -131,19 +155,29 @@ grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) {
             "duplicate \"channel_creds\" field"));
       }
       seen_channel_creds = true;
-      grpc_error* parse_error = ParseChannelCredsArray(child);
+      grpc_error* parse_error = ParseChannelCredsArray(child, &server);
       if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
     }
   }
-  if (server_uri_ == nullptr) {
+  if (server.server_uri == nullptr) {
     error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
         "\"server_uri\" field not present"));
   }
-  return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"xds_server\" object",
-                                       &error_list);
+  // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
+  // string is not static in this case.
+  if (error_list.empty()) return GRPC_ERROR_NONE;
+  char* msg;
+  gpr_asprintf(&msg, "errors parsing index %" PRIuPTR, idx);
+  grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+  gpr_free(msg);
+  for (size_t i = 0; i < error_list.size(); ++i) {
+    error = grpc_error_add_child(error, error_list[i]);
+  }
+  return error;
 }
 
-grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) {
+grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json,
+                                                 XdsServer* server) {
   InlinedVector<grpc_error*, 1> error_list;
   size_t idx = 0;
   for (grpc_json *child = json->child; child != nullptr;
@@ -158,7 +192,7 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) {
       gpr_asprintf(&msg, "array element %" PRIuPTR " is not an object", idx);
       error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
     } else {
-      grpc_error* parse_error = ParseChannelCreds(child, idx);
+      grpc_error* parse_error = ParseChannelCreds(child, idx, server);
       if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
     }
   }
@@ -166,7 +200,8 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) {
                                        &error_list);
 }
 
-grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx) {
+grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx,
+                                            XdsServer* server) {
   InlinedVector<grpc_error*, 1> error_list;
   ChannelCreds channel_creds;
   for (grpc_json* child = json->child; child != nullptr; child = child->next) {
@@ -195,7 +230,9 @@ grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx) {
       channel_creds.config = child;
     }
   }
-  if (channel_creds.type != nullptr) channel_creds_.push_back(channel_creds);
+  if (channel_creds.type != nullptr) {
+    server->channel_creds.push_back(channel_creds);
+  }
   // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
   // string is not static in this case.
   if (error_list.empty()) return GRPC_ERROR_NONE;