1 //
2 // Copyright 2018 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "src/core/xds/xds_client/xds_api.h"
18
19 #include "google/protobuf/struct.upb.h"
20 #include "src/core/util/json/json.h"
21 #include "src/core/util/upb_utils.h"
22 #include "upb/base/string_view.h"
23 #include "upb/mem/arena.hpp"
24
25 namespace grpc_core {
26
27 namespace {
28
29 void PopulateMetadataValue(google_protobuf_Value* value_pb, const Json& value,
30 upb_Arena* arena);
31
PopulateListValue(google_protobuf_ListValue * list_value,const Json::Array & values,upb_Arena * arena)32 void PopulateListValue(google_protobuf_ListValue* list_value,
33 const Json::Array& values, upb_Arena* arena) {
34 for (const auto& value : values) {
35 auto* value_pb = google_protobuf_ListValue_add_values(list_value, arena);
36 PopulateMetadataValue(value_pb, value, arena);
37 }
38 }
39
PopulateMetadata(google_protobuf_Struct * metadata_pb,const Json::Object & metadata,upb_Arena * arena)40 void PopulateMetadata(google_protobuf_Struct* metadata_pb,
41 const Json::Object& metadata, upb_Arena* arena) {
42 for (const auto& p : metadata) {
43 google_protobuf_Value* value = google_protobuf_Value_new(arena);
44 PopulateMetadataValue(value, p.second, arena);
45 google_protobuf_Struct_fields_set(
46 metadata_pb, StdStringToUpbString(p.first), value, arena);
47 }
48 }
49
PopulateMetadataValue(google_protobuf_Value * value_pb,const Json & value,upb_Arena * arena)50 void PopulateMetadataValue(google_protobuf_Value* value_pb, const Json& value,
51 upb_Arena* arena) {
52 switch (value.type()) {
53 case Json::Type::kNull:
54 google_protobuf_Value_set_null_value(value_pb, 0);
55 break;
56 case Json::Type::kNumber:
57 google_protobuf_Value_set_number_value(
58 value_pb, strtod(value.string().c_str(), nullptr));
59 break;
60 case Json::Type::kString:
61 google_protobuf_Value_set_string_value(
62 value_pb, StdStringToUpbString(value.string()));
63 break;
64 case Json::Type::kBoolean:
65 google_protobuf_Value_set_bool_value(value_pb, value.boolean());
66 break;
67 case Json::Type::kObject: {
68 google_protobuf_Struct* struct_value =
69 google_protobuf_Value_mutable_struct_value(value_pb, arena);
70 PopulateMetadata(struct_value, value.object(), arena);
71 break;
72 }
73 case Json::Type::kArray: {
74 google_protobuf_ListValue* list_value =
75 google_protobuf_Value_mutable_list_value(value_pb, arena);
76 PopulateListValue(list_value, value.array(), arena);
77 break;
78 }
79 }
80 }
81
82 } // namespace
83
PopulateXdsNode(const XdsBootstrap::Node * node,absl::string_view user_agent_name,absl::string_view user_agent_version,envoy_config_core_v3_Node * node_msg,upb_Arena * arena)84 void PopulateXdsNode(const XdsBootstrap::Node* node,
85 absl::string_view user_agent_name,
86 absl::string_view user_agent_version,
87 envoy_config_core_v3_Node* node_msg, upb_Arena* arena) {
88 if (node != nullptr) {
89 if (!node->id().empty()) {
90 envoy_config_core_v3_Node_set_id(node_msg,
91 StdStringToUpbString(node->id()));
92 }
93 if (!node->cluster().empty()) {
94 envoy_config_core_v3_Node_set_cluster(
95 node_msg, StdStringToUpbString(node->cluster()));
96 }
97 if (!node->metadata().empty()) {
98 google_protobuf_Struct* metadata =
99 envoy_config_core_v3_Node_mutable_metadata(node_msg, arena);
100 PopulateMetadata(metadata, node->metadata(), arena);
101 }
102 if (!node->locality_region().empty() || !node->locality_zone().empty() ||
103 !node->locality_sub_zone().empty()) {
104 envoy_config_core_v3_Locality* locality =
105 envoy_config_core_v3_Node_mutable_locality(node_msg, arena);
106 if (!node->locality_region().empty()) {
107 envoy_config_core_v3_Locality_set_region(
108 locality, StdStringToUpbString(node->locality_region()));
109 }
110 if (!node->locality_zone().empty()) {
111 envoy_config_core_v3_Locality_set_zone(
112 locality, StdStringToUpbString(node->locality_zone()));
113 }
114 if (!node->locality_sub_zone().empty()) {
115 envoy_config_core_v3_Locality_set_sub_zone(
116 locality, StdStringToUpbString(node->locality_sub_zone()));
117 }
118 }
119 }
120 envoy_config_core_v3_Node_set_user_agent_name(
121 node_msg, StdStringToUpbString(user_agent_name));
122 envoy_config_core_v3_Node_set_user_agent_version(
123 node_msg, StdStringToUpbString(user_agent_version));
124 envoy_config_core_v3_Node_add_client_features(
125 node_msg,
126 upb_StringView_FromString("envoy.lb.does_not_support_overprovisioning"),
127 arena);
128 }
129
130 } // namespace grpc_core
131