• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The gRPC Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "src/core/resolver/dns/event_engine/service_config_helper.h"
15 
16 #include <grpc/support/port_platform.h>
17 #include <stdlib.h>
18 
19 #include <algorithm>
20 #include <vector>
21 
22 #include "absl/status/statusor.h"
23 #include "absl/strings/string_view.h"
24 #include "src/core/util/gethostname.h"
25 #include "src/core/util/json/json.h"
26 #include "src/core/util/json/json_args.h"
27 #include "src/core/util/json/json_object_loader.h"
28 #include "src/core/util/json/json_reader.h"
29 #include "src/core/util/json/json_writer.h"
30 #include "src/core/util/status_helper.h"
31 
32 namespace grpc_core {
33 
34 namespace {
35 
36 struct ServiceConfigChoice {
37   std::vector<std::string> client_language;
38   int percentage = -1;
39   std::vector<std::string> client_hostname;
40   Json::Object service_config;
41 
JsonLoadergrpc_core::__anon894ddc220111::ServiceConfigChoice42   static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
43     static const auto* loader =
44         JsonObjectLoader<ServiceConfigChoice>()
45             .OptionalField("clientLanguage",
46                            &ServiceConfigChoice::client_language)
47             .OptionalField("percentage", &ServiceConfigChoice::percentage)
48             .OptionalField("clientHostname",
49                            &ServiceConfigChoice::client_hostname)
50             .Field("serviceConfig", &ServiceConfigChoice::service_config)
51             .Finish();
52     return loader;
53   }
54 };
55 
vector_contains(const std::vector<std::string> & v,const std::string & value)56 bool vector_contains(const std::vector<std::string>& v,
57                      const std::string& value) {
58   return std::find(v.begin(), v.end(), value) != v.end();
59 }
60 
61 }  // namespace
62 
ChooseServiceConfig(absl::string_view service_config_json)63 absl::StatusOr<std::string> ChooseServiceConfig(
64     absl::string_view service_config_json) {
65   auto json = JsonParse(service_config_json);
66   GRPC_RETURN_IF_ERROR(json.status());
67   auto choices = LoadFromJson<std::vector<ServiceConfigChoice>>(*json);
68   GRPC_RETURN_IF_ERROR(choices.status());
69   for (const ServiceConfigChoice& choice : *choices) {
70     // Check client language, if specified.
71     if (!choice.client_language.empty() &&
72         !vector_contains(choice.client_language, "c++")) {
73       continue;
74     }
75     // Check client hostname, if specified.
76     if (!choice.client_hostname.empty()) {
77       const char* hostname = grpc_gethostname();
78       if (!vector_contains(choice.client_hostname, hostname)) {
79         continue;
80       }
81     }
82     // Check percentage, if specified.
83     if (choice.percentage != -1) {
84       int random_pct = rand() % 100;
85       if (random_pct > choice.percentage || choice.percentage == 0) {
86         continue;
87       }
88     }
89     return JsonDump(Json::FromObject(choice.service_config));
90   }
91   // No matching service config was found
92   return "";
93 }
94 
95 }  // namespace grpc_core
96