fake_handshaker_server.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
19 
20 #include <memory>
21 #include <sstream>
22 #include <string>
23 
24 #include <grpc/grpc.h>
25 #include <grpc/support/log.h>
29 #include <grpcpp/server.h>
30 #include <grpcpp/server_builder.h>
31 #include <grpcpp/server_context.h>
32 
33 #include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
34 #include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
35 #include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
36 
37 // Fake handshake messages.
38 constexpr char kClientInitFrame[] = "ClientInit";
39 constexpr char kServerFrame[] = "ServerInitAndFinished";
40 constexpr char kClientFinishFrame[] = "ClientFinished";
41 // Error messages.
42 constexpr char kInvalidFrameError[] = "Invalid input frame.";
43 constexpr char kWrongStateError[] = "Wrong handshake state.";
44 
45 namespace grpc {
46 namespace gcp {
47 
48 // FakeHandshakeService implements a fake handshaker service using a fake key
49 // exchange protocol. The fake key exchange protocol is a 3-message protocol:
50 // - Client first sends ClientInit message to Server.
51 // - Server then sends ServerInitAndFinished message back to Client.
52 // - Client finally sends ClientFinished message to Server.
53 // This fake handshaker service is intended for ALTS integration testing without
54 // relying on real ALTS handshaker service inside GCE.
55 // It is thread-safe.
56 class FakeHandshakerService : public HandshakerService::Service {
57  public:
58  explicit FakeHandshakerService(int expected_max_concurrent_rpcs)
59  : expected_max_concurrent_rpcs_(expected_max_concurrent_rpcs) {}
60 
62  ServerContext* /*server_context*/,
64  ConcurrentRpcsCheck concurrent_rpcs_check(this);
65  Status status;
67  HandshakerReq request;
68  HandshakerResp response;
69  gpr_log(GPR_DEBUG, "Start a new handshake.");
70  while (stream->Read(&request)) {
72  if (!status.ok()) return WriteErrorResponse(stream, status);
73  stream->Write(response);
74  if (context.state == COMPLETED) return Status::OK;
75  request.Clear();
76  }
77  return Status::OK;
78  }
79 
80  private:
81  // HandshakeState is used by fake handshaker server to keep track of client's
82  // handshake status. In the beginning of a handshake, the state is INITIAL.
83  // If start_client or start_server request is called, the state becomes at
84  // least STARTED. When the handshaker server produces the first fame, the
85  // state becomes SENT. After the handshaker server processes the final frame
86  // from the peer, the state becomes COMPLETED.
88 
90  bool is_client = true;
92  };
93 
95  const HandshakerReq& request,
96  HandshakerResp* response) {
97  GPR_ASSERT(context != nullptr && response != nullptr);
98  response->Clear();
99  if (request.has_client_start()) {
100  gpr_log(GPR_DEBUG, "Process client start request.");
101  return ProcessClientStart(context, request.client_start(), response);
102  } else if (request.has_server_start()) {
103  gpr_log(GPR_DEBUG, "Process server start request.");
104  return ProcessServerStart(context, request.server_start(), response);
105  } else if (request.has_next()) {
106  gpr_log(GPR_DEBUG, "Process next request.");
107  return ProcessNext(context, request.next(), response);
108  }
109  return Status(StatusCode::INVALID_ARGUMENT, "Request is empty.");
110  }
111 
113  const StartClientHandshakeReq& request,
114  HandshakerResp* response) {
115  GPR_ASSERT(context != nullptr && response != nullptr);
116  // Checks request.
117  if (context->state != INITIAL) {
119  }
120  if (request.application_protocols_size() == 0) {
122  "At least one application protocol needed.");
123  }
124  if (request.record_protocols_size() == 0) {
126  "At least one record protocol needed.");
127  }
128  // Sets response.
129  response->set_out_frames(kClientInitFrame);
130  response->set_bytes_consumed(0);
131  response->mutable_status()->set_code(StatusCode::OK);
132  // Updates handshaker context.
133  context->is_client = true;
134  context->state = SENT;
135  return Status::OK;
136  }
137 
139  const StartServerHandshakeReq& request,
140  HandshakerResp* response) {
141  GPR_ASSERT(context != nullptr && response != nullptr);
142  // Checks request.
143  if (context->state != INITIAL) {
145  }
146  if (request.application_protocols_size() == 0) {
148  "At least one application protocol needed.");
149  }
150  if (request.handshake_parameters().empty()) {
152  "At least one set of handshake parameters needed.");
153  }
154  // Sets response.
155  if (request.in_bytes().empty()) {
156  // start_server request does not have in_bytes.
157  response->set_bytes_consumed(0);
158  context->state = STARTED;
159  } else {
160  // start_server request has in_bytes.
161  if (request.in_bytes() == kClientInitFrame) {
162  response->set_out_frames(kServerFrame);
163  response->set_bytes_consumed(strlen(kClientInitFrame));
164  context->state = SENT;
165  } else {
167  }
168  }
169  response->mutable_status()->set_code(StatusCode::OK);
170  context->is_client = false;
171  return Status::OK;
172  }
173 
175  const NextHandshakeMessageReq& request,
176  HandshakerResp* response) {
177  GPR_ASSERT(context != nullptr && response != nullptr);
178  if (context->is_client) {
179  // Processes next request on client side.
180  if (context->state != SENT) {
182  }
183  if (request.in_bytes() != kServerFrame) {
185  }
186  response->set_out_frames(kClientFinishFrame);
187  response->set_bytes_consumed(strlen(kServerFrame));
188  context->state = COMPLETED;
189  } else {
190  // Processes next request on server side.
191  HandshakeState current_state = context->state;
192  if (current_state == STARTED) {
193  if (request.in_bytes() != kClientInitFrame) {
195  }
196  response->set_out_frames(kServerFrame);
197  response->set_bytes_consumed(strlen(kClientInitFrame));
198  context->state = SENT;
199  } else if (current_state == SENT) {
200  // Client finish frame may be sent along with the first payload from the
201  // client, handshaker only consumes the client finish frame.
202  if (request.in_bytes().substr(0, strlen(kClientFinishFrame)) !=
205  }
206  response->set_bytes_consumed(strlen(kClientFinishFrame));
207  context->state = COMPLETED;
208  } else {
210  }
211  }
212  // At this point, processing next request succeeded.
213  response->mutable_status()->set_code(StatusCode::OK);
214  if (context->state == COMPLETED) {
215  *response->mutable_result() = GetHandshakerResult();
216  }
217  return Status::OK;
218  }
219 
222  const Status& status) {
223  GPR_ASSERT(!status.ok());
224  HandshakerResp response;
225  response.mutable_status()->set_code(status.error_code());
226  response.mutable_status()->set_details(status.error_message());
227  stream->Write(response);
228  return status;
229  }
230 
231  HandshakerResult GetHandshakerResult() {
232  HandshakerResult result;
233  result.set_application_protocol("grpc");
234  result.set_record_protocol("ALTSRP_GCM_AES128_REKEY");
235  result.mutable_peer_identity()->set_service_account("peer_identity");
236  result.mutable_local_identity()->set_service_account("local_identity");
237  string key(1024, '\0');
238  result.set_key_data(key);
239  result.set_max_frame_size(16384);
240  result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2);
241  result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1);
242  result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2);
243  result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_minor(1);
244  return result;
245  }
246 
248  public:
250  : parent_(parent) {
251  if (parent->expected_max_concurrent_rpcs_ > 0) {
254  if (++parent->concurrent_rpcs_ >
257  "FakeHandshakerService:%p concurrent_rpcs_:%d "
258  "expected_max_concurrent_rpcs:%d",
259  parent, parent->concurrent_rpcs_,
261  abort();
262  }
263  }
264  }
265 
271  }
272  }
273 
274  private:
276  };
277 
281 };
282 
283 std::unique_ptr<grpc::Service> CreateFakeHandshakerService(
284  int expected_max_concurrent_rpcs) {
285  return std::unique_ptr<grpc::Service>{
286  new grpc::gcp::FakeHandshakerService(expected_max_concurrent_rpcs)};
287 }
288 
289 } // namespace gcp
290 } // namespace grpc
grpc::gcp::FakeHandshakerService::ConcurrentRpcsCheck::ConcurrentRpcsCheck
ConcurrentRpcsCheck(FakeHandshakerService *parent)
Definition: fake_handshaker_server.cc:249
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
grpc::status
auto status
Definition: cpp/client/credentials_test.cc:200
grpc::gcp::FakeHandshakerService::expected_max_concurrent_rpcs_mu_
grpc::internal::Mutex expected_max_concurrent_rpcs_mu_
Definition: fake_handshaker_server.cc:278
kInvalidFrameError
constexpr char kInvalidFrameError[]
Definition: fake_handshaker_server.cc:42
grpc::gcp::CreateFakeHandshakerService
std::unique_ptr< grpc::Service > CreateFakeHandshakerService(int expected_max_concurrent_rpcs)
Definition: fake_handshaker_server.cc:283
grpc::ServerContext
Definition: grpcpp/impl/codegen/server_context.h:566
log.h
grpc::gcp::FakeHandshakerService::SENT
@ SENT
Definition: fake_handshaker_server.cc:87
grpc::internal::Mutex
Definition: include/grpcpp/impl/codegen/sync.h:59
grpc
Definition: grpcpp/alarm.h:33
grpc::gcp::FakeHandshakerService::HandshakerContext::is_client
bool is_client
Definition: fake_handshaker_server.cc:90
benchmark.request
request
Definition: benchmark.py:77
grpc::ServerReaderWriter
Definition: grpcpp/impl/codegen/sync_stream.h:786
fake_handshaker_server.h
grpc::gcp::FakeHandshakerService::FakeHandshakerService
FakeHandshakerService(int expected_max_concurrent_rpcs)
Definition: fake_handshaker_server.cc:58
grpc::gcp::FakeHandshakerService::INITIAL
@ INITIAL
Definition: fake_handshaker_server.cc:87
grpc::gcp::FakeHandshakerService::ProcessClientStart
Status ProcessClientStart(HandshakerContext *context, const StartClientHandshakeReq &request, HandshakerResp *response)
Definition: fake_handshaker_server.cc:112
grpc::internal::MutexLock
Definition: include/grpcpp/impl/codegen/sync.h:86
grpc::gcp::FakeHandshakerService::concurrent_rpcs_
int concurrent_rpcs_
Definition: fake_handshaker_server.cc:279
grpc.StatusCode.FAILED_PRECONDITION
tuple FAILED_PRECONDITION
Definition: src/python/grpcio/grpc/__init__.py:272
grpc::gcp::FakeHandshakerService::WriteErrorResponse
Status WriteErrorResponse(ServerReaderWriter< HandshakerResp, HandshakerReq > *stream, const Status &status)
Definition: fake_handshaker_server.cc:220
grpc::gcp::FakeHandshakerService::ConcurrentRpcsCheck
Definition: fake_handshaker_server.cc:247
sync.h
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
grpc.StatusCode.OK
tuple OK
Definition: src/python/grpcio/grpc/__init__.py:260
grpc.StatusCode.UNKNOWN
tuple UNKNOWN
Definition: src/python/grpcio/grpc/__init__.py:262
grpc::gcp::FakeHandshakerService::ConcurrentRpcsCheck::parent_
FakeHandshakerService * parent_
Definition: fake_handshaker_server.cc:275
grpc::gcp::FakeHandshakerService::expected_max_concurrent_rpcs_
const int expected_max_concurrent_rpcs_
Definition: fake_handshaker_server.cc:280
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
grpc::gcp::FakeHandshakerService::COMPLETED
@ COMPLETED
Definition: fake_handshaker_server.cc:87
grpc.h
grpc::gcp::FakeHandshakerService::ConcurrentRpcsCheck::~ConcurrentRpcsCheck
~ConcurrentRpcsCheck()
Definition: fake_handshaker_server.cc:266
grpc::Status::OK
static const Status & OK
An OK pre-defined instance.
Definition: include/grpcpp/impl/codegen/status.h:113
grpc::gcp::FakeHandshakerService::GetHandshakerResult
HandshakerResult GetHandshakerResult()
Definition: fake_handshaker_server.cc:231
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
kClientInitFrame
constexpr char kClientInitFrame[]
Definition: fake_handshaker_server.cc:38
run_xds_tests.gcp
gcp
Definition: run_xds_tests.py:3210
server_credentials.h
grpc::gcp::FakeHandshakerService::DoHandshake
Status DoHandshake(ServerContext *, ServerReaderWriter< HandshakerResp, HandshakerReq > *stream) override
Definition: fake_handshaker_server.cc:61
key
const char * key
Definition: hpack_parser_table.cc:164
async_stream.h
server_context.h
asyncio_get_stats.response
response
Definition: asyncio_get_stats.py:28
grpc::protobuf::util::Status
GRPC_CUSTOM_UTIL_STATUS Status
Definition: include/grpcpp/impl/codegen/config_protobuf.h:93
grpc::gcp::FakeHandshakerService
Definition: fake_handshaker_server.cc:56
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
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
kWrongStateError
constexpr char kWrongStateError[]
Definition: fake_handshaker_server.cc:43
grpc::gcp::FakeHandshakerService::STARTED
@ STARTED
Definition: fake_handshaker_server.cc:87
grpc::gcp::FakeHandshakerService::ProcessNext
Status ProcessNext(HandshakerContext *context, const NextHandshakeMessageReq &request, HandshakerResp *response)
Definition: fake_handshaker_server.cc:174
grpc::gcp::FakeHandshakerService::HandshakeState
HandshakeState
Definition: fake_handshaker_server.cc:87
GPR_DEBUG
#define GPR_DEBUG
Definition: include/grpc/impl/codegen/log.h:55
grpc::gcp::FakeHandshakerService::ProcessRequest
Status ProcessRequest(HandshakerContext *context, const HandshakerReq &request, HandshakerResp *response)
Definition: fake_handshaker_server.cc:94
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
kClientFinishFrame
constexpr char kClientFinishFrame[]
Definition: fake_handshaker_server.cc:40
kServerFrame
constexpr char kServerFrame[]
Definition: fake_handshaker_server.cc:39
server.h
grpc::gcp::FakeHandshakerService::HandshakerContext
Definition: fake_handshaker_server.cc:89
grpc::gcp::FakeHandshakerService::ProcessServerStart
Status ProcessServerStart(HandshakerContext *context, const StartServerHandshakeReq &request, HandshakerResp *response)
Definition: fake_handshaker_server.cc:138
server_builder.h
stream
voidpf stream
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:22