istio_echo_server_lib.cc
Go to the documentation of this file.
1 //
2 // Copyright 2022 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 
18 
19 #include <thread>
20 
21 #include "absl/strings/str_cat.h"
22 #include "absl/strings/str_format.h"
23 #include "absl/strings/str_split.h"
24 #include "absl/synchronization/blocking_counter.h"
25 
26 #include <grpcpp/client_context.h>
27 #include <grpcpp/grpcpp.h>
28 
30 #include "src/proto/grpc/testing/istio_echo.pb.h"
31 
32 using proto::EchoRequest;
33 using proto::EchoResponse;
34 using proto::EchoTestService;
35 using proto::ForwardEchoRequest;
36 using proto::ForwardEchoResponse;
37 
38 namespace grpc {
39 namespace testing {
40 namespace {
41 
42 const absl::string_view kRequestIdField = "x-request-id";
43 // const absl::string_view kServiceVersionField = "ServiceVersion";
44 // const absl::string_view kServicePortField = "ServicePort";
45 const absl::string_view kStatusCodeField = "StatusCode";
46 // const absl::string_view kUrlField = "URL";
47 const absl::string_view kHostField = "Host";
48 const absl::string_view kHostnameField = "Hostname";
49 // const absl::string_view kMethodField = "Method";
50 const absl::string_view kRequestHeader = "RequestHeader";
51 // const absl::string_view kResponseHeader = "ResponseHeader";
52 // const absl::string_view kClusterField = "Cluster";
53 // const absl::string_view kIstioVersionField = "IstioVersion";
54 const absl::string_view kIpField = "IP"; // The Requester’s IP Address.
55 
56 absl::string_view StringRefToStringView(const string_ref& r) {
57  return absl::string_view(r.data(), r.size());
58 }
59 
60 struct EchoCall {
62  proto::EchoResponse response;
64 };
65 
66 } // namespace
67 
68 EchoTestServiceImpl::EchoTestServiceImpl(std::string hostname,
69  std::string forwarding_address)
70  : hostname_(std::move(hostname)),
71  forwarding_address_(std::move(forwarding_address)) {
72  forwarding_stub_ = EchoTestService::NewStub(
74 }
75 
76 Status EchoTestServiceImpl::Echo(ServerContext* context,
77  const EchoRequest* request,
78  EchoResponse* response) {
79  std::string s;
80  absl::StrAppend(&s, kHostField, "=",
81  StringRefToStringView(context->ExperimentalGetAuthority()),
82  "\n");
83  const std::multimap<string_ref, string_ref> metadata =
84  context->client_metadata();
85  for (const auto& kv : metadata) {
86  // Skip all binary headers.
87  if (kv.first.ends_with("-bin")) {
88  continue;
89  }
90  absl::StrAppend(&s, kRequestHeader, "=", StringRefToStringView(kv.first),
91  ":", StringRefToStringView(kv.second), "\n");
92  }
93  absl::string_view host;
95  std::string peer = context->peer();
96  grpc_core::SplitHostPort(peer, &host, &port);
97  // This is not a complete list, but also not all fields are used. May
98  // need to add/remove fields later, if required by tests. Only keep the
99  // fields needed for now.
100  //
101  // absl::StrAppend(&s,kServiceVersionField,"=",this->version_,"\n");
102  // absl::StrAppend(&s,kServicePortField,"=",this->port_,"\n");
103  // absl::StrAppend(&s,kClusterField,"=",this->cluster_,"\n");
104  // absl::StrAppend(&s,kIstioVersionField,"=",this->istio_version_,"\n");
105  absl::StrAppend(&s, kIpField, "=", host, "\n");
106  absl::StrAppend(&s, kStatusCodeField, "=", std::to_string(200), "\n");
107  absl::StrAppend(&s, kHostnameField, "=", this->hostname_, "\n");
108  absl::StrAppend(&s, "Echo=", request->message(), "\n");
109  response->set_message(s);
110  gpr_log(GPR_INFO, "Echo response:\n%s", s.c_str());
111  return Status::OK;
112 }
113 
114 Status EchoTestServiceImpl::ForwardEcho(ServerContext* context,
115  const ForwardEchoRequest* request,
116  ForwardEchoResponse* response) {
117  std::string raw_url = request->url();
118  size_t colon = raw_url.find_first_of(':');
119  std::string scheme;
120  if (colon == std::string::npos) {
121  return Status(
123  absl::StrFormat("No protocol configured for url %s", raw_url));
124  }
125  scheme = raw_url.substr(0, colon);
126  std::shared_ptr<Channel> channel;
127  if (scheme == "xds") {
128  // We can optionally add support for TLS creds, but we are primarily
129  // concerned with proxyless-grpc here.
130  gpr_log(GPR_INFO, "Creating channel to %s using xDS Creds",
131  raw_url.c_str());
132  channel =
134  } else if (scheme == "grpc") {
135  // We don't really want to test this but the istio test infrastructure needs
136  // this to be supported. If we ever decide to add support for this properly,
137  // we would need to add support for TLS creds here.
138  absl::string_view address = absl::StripPrefix(raw_url, "grpc://");
139  gpr_log(GPR_INFO, "Creating channel to %s", std::string(address).c_str());
141  } else {
142  gpr_log(GPR_INFO, "Protocol %s not supported. Forwarding to %s",
143  scheme.c_str(), forwarding_address_.c_str());
144  ClientContext forwarding_ctx;
145  forwarding_ctx.set_deadline(context->deadline());
146  return forwarding_stub_->ForwardEcho(&forwarding_ctx, *request, response);
147  }
148  auto stub = EchoTestService::NewStub(channel);
149  auto count = request->count() == 0 ? 1 : request->count();
150  // Calculate the amount of time to sleep after each call.
151  std::chrono::duration<double> duration_per_query =
152  std::chrono::nanoseconds::zero();
153  if (request->qps() > 0) {
154  duration_per_query =
155  std::chrono::nanoseconds(std::chrono::seconds(1)) / request->qps();
156  }
157  std::vector<EchoCall> calls(count);
158  EchoRequest echo_request;
159  echo_request.set_message(request->message());
161  for (int i = 0; i < count; ++i) {
162  calls[i].context.AddMetadata(std::string(kRequestIdField),
163  std::to_string(i));
164  for (const auto& header : request->headers()) {
165  if (header.key() != kHostField) {
166  calls[i].context.AddMetadata(header.key(), header.value());
167  }
168  }
171  std::chrono::microseconds(request->timeout_micros());
172  calls[i].context.set_deadline(deadline);
173  stub->async()->Echo(&calls[i].context, &echo_request, &calls[i].response,
174  [&, index = i](Status s) {
175  calls[index].status = s;
176  counter.DecrementCount();
177  });
178  std::this_thread::sleep_for(duration_per_query);
179  }
180  // Wait for all calls to be done.
181  counter.Wait();
182  for (int i = 0; i < count; ++i) {
183  if (calls[i].status.ok()) {
184  std::string body;
185  // The test infrastructure might expect the entire struct instead of
186  // just the message.
187  absl::StrAppend(&body, absl::StrFormat("[%d] grpcecho.Echo(%s)\n", i,
188  request->message()));
189  auto contents =
190  absl::StrSplit(calls[i].response.message(), '\n', absl::SkipEmpty());
191  for (const auto& line : contents) {
192  absl::StrAppend(&body, absl::StrFormat("[%d body] %s\n", i, line));
193  }
194  response->add_output(body);
195  gpr_log(GPR_INFO, "Forward Echo response:%d\n%s", i, body.c_str());
196  } else {
197  gpr_log(GPR_ERROR, "RPC %d failed %d: %s", i,
198  calls[i].status.error_code(),
199  calls[i].status.error_message().c_str());
200  response->clear_output();
201  return calls[i].status;
202  }
203  }
204  return Status::OK;
205 }
206 
207 } // namespace testing
208 } // namespace grpc
absl::StrSplit
strings_internal::Splitter< typename strings_internal::SelectDelimiter< Delimiter >::type, AllowEmpty, absl::string_view > StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d)
Definition: abseil-cpp/absl/strings/str_split.h:499
absl::time_internal::cctz::seconds
std::chrono::duration< std::int_fast64_t > seconds
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h:40
grpc::ClientContext::peer
std::string peer() const
Definition: client_context.cc:174
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
testing
Definition: aws_request_signer_test.cc:25
grpc::status
auto status
Definition: cpp/client/credentials_test.cc:200
calls
static fling_call calls[100001]
Definition: test/core/memory_usage/client.cc:57
now
static double now(void)
Definition: test/core/fling/client.cc:130
grpc::ServerContext
Definition: grpcpp/impl/codegen/server_context.h:566
hostname_
std::string hostname_
Definition: istio_echo_server_test.cc:71
absl::StrAppend
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: abseil-cpp/absl/strings/str_cat.cc:193
metadata
Definition: cq_verifier.cc:48
absl::StrFormat
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:338
grpc
Definition: grpcpp/alarm.h:33
absl::time_internal::cctz::time_point
std::chrono::time_point< std::chrono::system_clock, D > time_point
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h:39
benchmark.request
request
Definition: benchmark.py:77
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
grpc::ClientContext::set_deadline
void set_deadline(const T &deadline)
Definition: grpcpp/impl/codegen/client_context.h:274
grpc_core::SplitHostPort
bool SplitHostPort(absl::string_view name, absl::string_view *host, absl::string_view *port)
Definition: host_port.cc:88
absl::StripPrefix
ABSL_MUST_USE_RESULT absl::string_view StripPrefix(absl::string_view str, absl::string_view prefix)
Definition: abseil-cpp/absl/strings/strip.h:73
async_greeter_client.stub
stub
Definition: hellostreamingworld/async_greeter_client.py:26
channel
wrapped_grpc_channel * channel
Definition: src/php/ext/grpc/call.h:33
absl::SkipEmpty
Definition: abseil-cpp/absl/strings/str_split.h:347
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
fling_call::status
grpc_status_code status
Definition: test/core/memory_usage/client.cc:50
header
struct absl::base_internal::@2940::AllocList::Header header
response
proto::EchoResponse response
Definition: istio_echo_server_lib.cc:62
counter
static int counter
Definition: abseil-cpp/absl/flags/reflection_test.cc:131
absl::BlockingCounter
Definition: abseil-cpp/absl/synchronization/blocking_counter.h:63
grpcpp.h
grpc::testing::EchoTestServiceImpl::forwarding_stub_
std::unique_ptr< proto::EchoTestService::Stub > forwarding_stub_
Definition: istio_echo_server_lib.h:40
grpc::Status::OK
static const Status & OK
An OK pre-defined instance.
Definition: include/grpcpp/impl/codegen/status.h:113
host_port.h
grpc::CreateChannel
std::shared_ptr< Channel > CreateChannel(const grpc::string &target, const std::shared_ptr< ChannelCredentials > &creds)
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc::ClientContext
Definition: grpcpp/impl/codegen/client_context.h:195
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
istio_echo_server_lib.h
contents
string_view contents
Definition: elf.cc:597
client_context.h
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
grpc::ClientContext::deadline
std::chrono::system_clock::time_point deadline() const
Return the deadline for the client call.
Definition: grpcpp/impl/codegen/client_context.h:294
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
fix_build_deps.r
r
Definition: fix_build_deps.py:491
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
string_view
absl::string_view string_view
Definition: attr.cc:22
grpc::protobuf::util::Status
GRPC_CUSTOM_UTIL_STATUS Status
Definition: include/grpcpp/impl/codegen/config_protobuf.h:93
regen-readme.line
line
Definition: regen-readme.py:30
grpc::XdsCredentials
std::shared_ptr< ChannelCredentials > XdsCredentials(const std::shared_ptr< ChannelCredentials > &fallback_creds)
Builds XDS Credentials.
Definition: cpp/client/xds_credentials.cc:30
grpc.StatusCode.INVALID_ARGUMENT
tuple INVALID_ARGUMENT
Definition: src/python/grpcio/grpc/__init__.py:263
grpc::Status
Definition: include/grpcpp/impl/codegen/status.h:35
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
grpc::InsecureChannelCredentials
std::shared_ptr< ChannelCredentials > InsecureChannelCredentials()
Credentials for an unencrypted, unauthenticated channel.
Definition: cpp/client/insecure_credentials.cc:69
forwarding_address_
std::string forwarding_address_
Definition: istio_echo_server_test.cc:72
to_string
static bool to_string(zval *from)
Definition: protobuf/php/ext/google/protobuf/convert.c:333
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:22