Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / src / core / tsi / alts / handshaker / alts_handshaker_client.cc
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  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
22
23 #include <grpc/byte_buffer.h>
24 #include <grpc/support/alloc.h>
25 #include <grpc/support/log.h>
26
27 #include "src/core/lib/slice/slice_internal.h"
28 #include "src/core/lib/surface/call.h"
29 #include "src/core/lib/surface/channel.h"
30 #include "src/core/tsi/alts/handshaker/alts_shared_resource.h"
31 #include "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h"
32 #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
33
34 #define TSI_ALTS_INITIAL_BUFFER_SIZE 256
35
36 const int kHandshakerClientOpNum = 4;
37
38 struct alts_handshaker_client {
39   const alts_handshaker_client_vtable* vtable;
40 };
41
42 typedef struct alts_grpc_handshaker_client {
43   alts_handshaker_client base;
44   alts_tsi_handshaker* handshaker;
45   grpc_call* call;
46   /* A pointer to a function handling the interaction with handshaker service.
47    * That is, it points to grpc_call_start_batch_and_execute when the handshaker
48    * client is used in a non-testing use case and points to a custom function
49    * that validates the data to be sent to handshaker service in a testing use
50    * case. */
51   alts_grpc_caller grpc_caller;
52   /* A callback function provided by gRPC to handle the response returned from
53    * handshaker service. It also serves to bring the control safely back to
54    * application when dedicated CQ and thread are used. */
55   grpc_iomgr_cb_func grpc_cb;
56   /* A gRPC closure to be scheduled when the response from handshaker service
57    * is received. It will be initialized with grpc_cb. */
58   grpc_closure on_handshaker_service_resp_recv;
59   /* Buffers containing information to be sent (or received) to (or from) the
60    * handshaker service. */
61   grpc_byte_buffer* send_buffer;
62   grpc_byte_buffer* recv_buffer;
63   grpc_status_code status;
64   /* Initial metadata to be received from handshaker service. */
65   grpc_metadata_array recv_initial_metadata;
66   /* A callback function provided by an application to be invoked when response
67    * is received from handshaker service. */
68   tsi_handshaker_on_next_done_cb cb;
69   void* user_data;
70   /* ALTS credential options passed in from the caller. */
71   grpc_alts_credentials_options* options;
72   /* target name information to be passed to handshaker service for server
73    * authorization check. */
74   grpc_slice target_name;
75   /* boolean flag indicating if the handshaker client is used at client
76    * (is_client = true) or server (is_client = false) side. */
77   bool is_client;
78   /* a temporary store for data received from handshaker service used to extract
79    * unused data. */
80   grpc_slice recv_bytes;
81   /* a buffer containing data to be sent to the grpc client or server's peer. */
82   unsigned char* buffer;
83   size_t buffer_size;
84 } alts_grpc_handshaker_client;
85
86 static void handshaker_client_send_buffer_destroy(
87     alts_grpc_handshaker_client* client) {
88   GPR_ASSERT(client != nullptr);
89   grpc_byte_buffer_destroy(client->send_buffer);
90   client->send_buffer = nullptr;
91 }
92
93 static bool is_handshake_finished_properly(grpc_gcp_HandshakerResp* resp) {
94   GPR_ASSERT(resp != nullptr);
95   if (grpc_gcp_HandshakerResp_result(resp)) {
96     return true;
97   }
98   return false;
99 }
100
101 void alts_handshaker_client_handle_response(alts_handshaker_client* c,
102                                             bool is_ok) {
103   GPR_ASSERT(c != nullptr);
104   alts_grpc_handshaker_client* client =
105       reinterpret_cast<alts_grpc_handshaker_client*>(c);
106   grpc_byte_buffer* recv_buffer = client->recv_buffer;
107   grpc_status_code status = client->status;
108   tsi_handshaker_on_next_done_cb cb = client->cb;
109   void* user_data = client->user_data;
110   alts_tsi_handshaker* handshaker = client->handshaker;
111
112   /* Invalid input check. */
113   if (cb == nullptr) {
114     gpr_log(GPR_ERROR,
115             "cb is nullptr in alts_tsi_handshaker_handle_response()");
116     return;
117   }
118   if (handshaker == nullptr) {
119     gpr_log(GPR_ERROR,
120             "handshaker is nullptr in alts_tsi_handshaker_handle_response()");
121     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
122     return;
123   }
124   /* TSI handshake has been shutdown. */
125   if (alts_tsi_handshaker_has_shutdown(handshaker)) {
126     gpr_log(GPR_ERROR, "TSI handshake shutdown");
127     cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr);
128     return;
129   }
130   /* Failed grpc call check. */
131   if (!is_ok || status != GRPC_STATUS_OK) {
132     gpr_log(GPR_ERROR, "grpc call made to handshaker service failed");
133     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
134     return;
135   }
136   if (recv_buffer == nullptr) {
137     gpr_log(GPR_ERROR,
138             "recv_buffer is nullptr in alts_tsi_handshaker_handle_response()");
139     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
140     return;
141   }
142   upb::Arena arena;
143   grpc_gcp_HandshakerResp* resp =
144       alts_tsi_utils_deserialize_response(recv_buffer, arena.ptr());
145   grpc_byte_buffer_destroy(client->recv_buffer);
146   client->recv_buffer = nullptr;
147   /* Invalid handshaker response check. */
148   if (resp == nullptr) {
149     gpr_log(GPR_ERROR, "alts_tsi_utils_deserialize_response() failed");
150     cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr);
151     return;
152   }
153   const grpc_gcp_HandshakerStatus* resp_status =
154       grpc_gcp_HandshakerResp_status(resp);
155   if (resp_status == nullptr) {
156     gpr_log(GPR_ERROR, "No status in HandshakerResp");
157     cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr);
158     return;
159   }
160   upb_strview out_frames = grpc_gcp_HandshakerResp_out_frames(resp);
161   unsigned char* bytes_to_send = nullptr;
162   size_t bytes_to_send_size = 0;
163   if (out_frames.size > 0) {
164     bytes_to_send_size = out_frames.size;
165     while (bytes_to_send_size > client->buffer_size) {
166       client->buffer_size *= 2;
167       client->buffer = static_cast<unsigned char*>(
168           gpr_realloc(client->buffer, client->buffer_size));
169     }
170     memcpy(client->buffer, out_frames.data, bytes_to_send_size);
171     bytes_to_send = client->buffer;
172   }
173   tsi_handshaker_result* result = nullptr;
174   if (is_handshake_finished_properly(resp)) {
175     alts_tsi_handshaker_result_create(resp, client->is_client, &result);
176     alts_tsi_handshaker_result_set_unused_bytes(
177         result, &client->recv_bytes,
178         grpc_gcp_HandshakerResp_bytes_consumed(resp));
179   }
180   grpc_status_code code = static_cast<grpc_status_code>(
181       grpc_gcp_HandshakerStatus_code(resp_status));
182   if (code != GRPC_STATUS_OK) {
183     upb_strview details = grpc_gcp_HandshakerStatus_details(resp_status);
184     if (details.size > 0) {
185       char* error_details = (char*)gpr_zalloc(details.size + 1);
186       memcpy(error_details, details.data, details.size);
187       gpr_log(GPR_ERROR, "Error from handshaker service:%s", error_details);
188       gpr_free(error_details);
189     }
190   }
191   cb(alts_tsi_utils_convert_to_tsi_result(code), user_data, bytes_to_send,
192      bytes_to_send_size, result);
193 }
194
195 /**
196  * Populate grpc operation data with the fields of ALTS handshaker client and
197  * make a grpc call.
198  */
199 static tsi_result make_grpc_call(alts_handshaker_client* c, bool is_start) {
200   GPR_ASSERT(c != nullptr);
201   alts_grpc_handshaker_client* client =
202       reinterpret_cast<alts_grpc_handshaker_client*>(c);
203   grpc_op ops[kHandshakerClientOpNum];
204   memset(ops, 0, sizeof(ops));
205   grpc_op* op = ops;
206   if (is_start) {
207     op->op = GRPC_OP_SEND_INITIAL_METADATA;
208     op->data.send_initial_metadata.count = 0;
209     op++;
210     GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
211     op->op = GRPC_OP_RECV_INITIAL_METADATA;
212     op->data.recv_initial_metadata.recv_initial_metadata =
213         &client->recv_initial_metadata;
214     op++;
215     GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
216   }
217   op->op = GRPC_OP_SEND_MESSAGE;
218   op->data.send_message.send_message = client->send_buffer;
219   op++;
220   GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
221   op->op = GRPC_OP_RECV_MESSAGE;
222   op->data.recv_message.recv_message = &client->recv_buffer;
223   op++;
224   GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
225   GPR_ASSERT(client->grpc_caller != nullptr);
226   if (client->grpc_caller(client->call, ops, static_cast<size_t>(op - ops),
227                           &client->on_handshaker_service_resp_recv) !=
228       GRPC_CALL_OK) {
229     gpr_log(GPR_ERROR, "Start batch operation failed");
230     return TSI_INTERNAL_ERROR;
231   }
232   return TSI_OK;
233 }
234
235 /* Serializes a grpc_gcp_HandshakerReq message into a buffer and returns newly
236  * grpc_byte_buffer holding it. */
237 static grpc_byte_buffer* get_serialized_handshaker_req(
238     grpc_gcp_HandshakerReq* req, upb_arena* arena) {
239   size_t buf_length;
240   char* buf = grpc_gcp_HandshakerReq_serialize(req, arena, &buf_length);
241   if (buf == nullptr) {
242     return nullptr;
243   }
244   grpc_slice slice = grpc_slice_from_copied_buffer(buf, buf_length);
245   grpc_byte_buffer* byte_buffer = grpc_raw_byte_buffer_create(&slice, 1);
246   grpc_slice_unref_internal(slice);
247   return byte_buffer;
248 }
249
250 /* Create and populate a client_start handshaker request, then serialize it. */
251 static grpc_byte_buffer* get_serialized_start_client(
252     alts_handshaker_client* c) {
253   GPR_ASSERT(c != nullptr);
254   alts_grpc_handshaker_client* client =
255       reinterpret_cast<alts_grpc_handshaker_client*>(c);
256   upb::Arena arena;
257   grpc_gcp_HandshakerReq* req = grpc_gcp_HandshakerReq_new(arena.ptr());
258   grpc_gcp_StartClientHandshakeReq* start_client =
259       grpc_gcp_HandshakerReq_mutable_client_start(req, arena.ptr());
260   grpc_gcp_StartClientHandshakeReq_set_handshake_security_protocol(
261       start_client, grpc_gcp_ALTS);
262   grpc_gcp_StartClientHandshakeReq_add_application_protocols(
263       start_client, upb_strview_makez(ALTS_APPLICATION_PROTOCOL), arena.ptr());
264   grpc_gcp_StartClientHandshakeReq_add_record_protocols(
265       start_client, upb_strview_makez(ALTS_RECORD_PROTOCOL), arena.ptr());
266   grpc_gcp_RpcProtocolVersions* client_version =
267       grpc_gcp_StartClientHandshakeReq_mutable_rpc_versions(start_client,
268                                                             arena.ptr());
269   grpc_gcp_RpcProtocolVersions_assign_from_struct(
270       client_version, arena.ptr(), &client->options->rpc_versions);
271   grpc_gcp_StartClientHandshakeReq_set_target_name(
272       start_client,
273       upb_strview_make(reinterpret_cast<const char*>(
274                            GRPC_SLICE_START_PTR(client->target_name)),
275                        GRPC_SLICE_LENGTH(client->target_name)));
276   target_service_account* ptr =
277       (reinterpret_cast<grpc_alts_credentials_client_options*>(client->options))
278           ->target_account_list_head;
279   while (ptr != nullptr) {
280     grpc_gcp_Identity* target_identity =
281         grpc_gcp_StartClientHandshakeReq_add_target_identities(start_client,
282                                                                arena.ptr());
283     grpc_gcp_Identity_set_service_account(target_identity,
284                                           upb_strview_makez(ptr->data));
285     ptr = ptr->next;
286   }
287   return get_serialized_handshaker_req(req, arena.ptr());
288 }
289
290 static tsi_result handshaker_client_start_client(alts_handshaker_client* c) {
291   if (c == nullptr) {
292     gpr_log(GPR_ERROR, "client is nullptr in handshaker_client_start_client()");
293     return TSI_INVALID_ARGUMENT;
294   }
295   grpc_byte_buffer* buffer = get_serialized_start_client(c);
296   alts_grpc_handshaker_client* client =
297       reinterpret_cast<alts_grpc_handshaker_client*>(c);
298   if (buffer == nullptr) {
299     gpr_log(GPR_ERROR, "get_serialized_start_client() failed");
300     return TSI_INTERNAL_ERROR;
301   }
302   handshaker_client_send_buffer_destroy(client);
303   client->send_buffer = buffer;
304   tsi_result result = make_grpc_call(&client->base, true /* is_start */);
305   if (result != TSI_OK) {
306     gpr_log(GPR_ERROR, "make_grpc_call() failed");
307   }
308   return result;
309 }
310
311 /* Create and populate a start_server handshaker request, then serialize it. */
312 static grpc_byte_buffer* get_serialized_start_server(
313     alts_handshaker_client* c, grpc_slice* bytes_received) {
314   GPR_ASSERT(c != nullptr);
315   GPR_ASSERT(bytes_received != nullptr);
316   alts_grpc_handshaker_client* client =
317       reinterpret_cast<alts_grpc_handshaker_client*>(c);
318
319   upb::Arena arena;
320   grpc_gcp_HandshakerReq* req = grpc_gcp_HandshakerReq_new(arena.ptr());
321
322   grpc_gcp_StartServerHandshakeReq* start_server =
323       grpc_gcp_HandshakerReq_mutable_server_start(req, arena.ptr());
324   grpc_gcp_StartServerHandshakeReq_add_application_protocols(
325       start_server, upb_strview_makez(ALTS_APPLICATION_PROTOCOL), arena.ptr());
326   grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry* param =
327       grpc_gcp_StartServerHandshakeReq_add_handshake_parameters(start_server,
328                                                                 arena.ptr());
329   grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_set_key(
330       param, grpc_gcp_ALTS);
331   grpc_gcp_ServerHandshakeParameters* value =
332       grpc_gcp_ServerHandshakeParameters_new(arena.ptr());
333   grpc_gcp_ServerHandshakeParameters_add_record_protocols(
334       value, upb_strview_makez(ALTS_RECORD_PROTOCOL), arena.ptr());
335   grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_set_value(param,
336                                                                       value);
337   grpc_gcp_StartServerHandshakeReq_set_in_bytes(
338       start_server, upb_strview_make(reinterpret_cast<const char*>(
339                                          GRPC_SLICE_START_PTR(*bytes_received)),
340                                      GRPC_SLICE_LENGTH(*bytes_received)));
341   grpc_gcp_RpcProtocolVersions* server_version =
342       grpc_gcp_StartServerHandshakeReq_mutable_rpc_versions(start_server,
343                                                             arena.ptr());
344   grpc_gcp_RpcProtocolVersions_assign_from_struct(
345       server_version, arena.ptr(), &client->options->rpc_versions);
346   return get_serialized_handshaker_req(req, arena.ptr());
347 }
348
349 static tsi_result handshaker_client_start_server(alts_handshaker_client* c,
350                                                  grpc_slice* bytes_received) {
351   if (c == nullptr || bytes_received == nullptr) {
352     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_server()");
353     return TSI_INVALID_ARGUMENT;
354   }
355   alts_grpc_handshaker_client* client =
356       reinterpret_cast<alts_grpc_handshaker_client*>(c);
357   grpc_byte_buffer* buffer = get_serialized_start_server(c, bytes_received);
358   if (buffer == nullptr) {
359     gpr_log(GPR_ERROR, "get_serialized_start_server() failed");
360     return TSI_INTERNAL_ERROR;
361   }
362   handshaker_client_send_buffer_destroy(client);
363   client->send_buffer = buffer;
364   tsi_result result = make_grpc_call(&client->base, true /* is_start */);
365   if (result != TSI_OK) {
366     gpr_log(GPR_ERROR, "make_grpc_call() failed");
367   }
368   return result;
369 }
370
371 /* Create and populate a next handshaker request, then serialize it. */
372 static grpc_byte_buffer* get_serialized_next(grpc_slice* bytes_received) {
373   GPR_ASSERT(bytes_received != nullptr);
374   upb::Arena arena;
375   grpc_gcp_HandshakerReq* req = grpc_gcp_HandshakerReq_new(arena.ptr());
376   grpc_gcp_NextHandshakeMessageReq* next =
377       grpc_gcp_HandshakerReq_mutable_next(req, arena.ptr());
378   grpc_gcp_NextHandshakeMessageReq_set_in_bytes(
379       next, upb_strview_make(reinterpret_cast<const char*> GRPC_SLICE_START_PTR(
380                                  *bytes_received),
381                              GRPC_SLICE_LENGTH(*bytes_received)));
382   return get_serialized_handshaker_req(req, arena.ptr());
383 }
384
385 static tsi_result handshaker_client_next(alts_handshaker_client* c,
386                                          grpc_slice* bytes_received) {
387   if (c == nullptr || bytes_received == nullptr) {
388     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_next()");
389     return TSI_INVALID_ARGUMENT;
390   }
391   alts_grpc_handshaker_client* client =
392       reinterpret_cast<alts_grpc_handshaker_client*>(c);
393   grpc_slice_unref_internal(client->recv_bytes);
394   client->recv_bytes = grpc_slice_ref_internal(*bytes_received);
395   grpc_byte_buffer* buffer = get_serialized_next(bytes_received);
396   if (buffer == nullptr) {
397     gpr_log(GPR_ERROR, "get_serialized_next() failed");
398     return TSI_INTERNAL_ERROR;
399   }
400   handshaker_client_send_buffer_destroy(client);
401   client->send_buffer = buffer;
402   tsi_result result = make_grpc_call(&client->base, false /* is_start */);
403   if (result != TSI_OK) {
404     gpr_log(GPR_ERROR, "make_grpc_call() failed");
405   }
406   return result;
407 }
408
409 static void handshaker_client_shutdown(alts_handshaker_client* c) {
410   GPR_ASSERT(c != nullptr);
411   alts_grpc_handshaker_client* client =
412       reinterpret_cast<alts_grpc_handshaker_client*>(c);
413   if (client->call != nullptr) {
414     grpc_call_cancel_internal(client->call);
415   }
416 }
417
418 static void handshaker_client_destruct(alts_handshaker_client* c) {
419   if (c == nullptr) {
420     return;
421   }
422   alts_grpc_handshaker_client* client =
423       reinterpret_cast<alts_grpc_handshaker_client*>(c);
424   if (client->call != nullptr) {
425     grpc_call_unref(client->call);
426   }
427 }
428
429 static const alts_handshaker_client_vtable vtable = {
430     handshaker_client_start_client, handshaker_client_start_server,
431     handshaker_client_next, handshaker_client_shutdown,
432     handshaker_client_destruct};
433
434 alts_handshaker_client* alts_grpc_handshaker_client_create(
435     alts_tsi_handshaker* handshaker, grpc_channel* channel,
436     const char* handshaker_service_url, grpc_pollset_set* interested_parties,
437     grpc_alts_credentials_options* options, const grpc_slice& target_name,
438     grpc_iomgr_cb_func grpc_cb, tsi_handshaker_on_next_done_cb cb,
439     void* user_data, alts_handshaker_client_vtable* vtable_for_testing,
440     bool is_client) {
441   if (channel == nullptr || handshaker_service_url == nullptr) {
442     gpr_log(GPR_ERROR, "Invalid arguments to alts_handshaker_client_create()");
443     return nullptr;
444   }
445   alts_grpc_handshaker_client* client =
446       static_cast<alts_grpc_handshaker_client*>(gpr_zalloc(sizeof(*client)));
447   client->grpc_caller = grpc_call_start_batch_and_execute;
448   client->handshaker = handshaker;
449   client->cb = cb;
450   client->user_data = user_data;
451   client->send_buffer = nullptr;
452   client->recv_buffer = nullptr;
453   client->options = grpc_alts_credentials_options_copy(options);
454   client->target_name = grpc_slice_copy(target_name);
455   client->recv_bytes = grpc_empty_slice();
456   grpc_metadata_array_init(&client->recv_initial_metadata);
457   client->grpc_cb = grpc_cb;
458   client->is_client = is_client;
459   client->buffer_size = TSI_ALTS_INITIAL_BUFFER_SIZE;
460   client->buffer = static_cast<unsigned char*>(gpr_zalloc(client->buffer_size));
461   grpc_slice slice = grpc_slice_from_copied_string(handshaker_service_url);
462   client->call =
463       strcmp(handshaker_service_url, ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING) ==
464               0
465           ? nullptr
466           : grpc_channel_create_pollset_set_call(
467                 channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties,
468                 grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice,
469                 GRPC_MILLIS_INF_FUTURE, nullptr);
470   client->base.vtable =
471       vtable_for_testing == nullptr ? &vtable : vtable_for_testing;
472   GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, client->grpc_cb,
473                     client, grpc_schedule_on_exec_ctx);
474   grpc_slice_unref_internal(slice);
475   return &client->base;
476 }
477
478 namespace grpc_core {
479 namespace internal {
480
481 void alts_handshaker_client_set_grpc_caller_for_testing(
482     alts_handshaker_client* c, alts_grpc_caller caller) {
483   GPR_ASSERT(c != nullptr && caller != nullptr);
484   alts_grpc_handshaker_client* client =
485       reinterpret_cast<alts_grpc_handshaker_client*>(c);
486   client->grpc_caller = caller;
487 }
488
489 grpc_byte_buffer* alts_handshaker_client_get_send_buffer_for_testing(
490     alts_handshaker_client* c) {
491   GPR_ASSERT(c != nullptr);
492   alts_grpc_handshaker_client* client =
493       reinterpret_cast<alts_grpc_handshaker_client*>(c);
494   return client->send_buffer;
495 }
496
497 grpc_byte_buffer** alts_handshaker_client_get_recv_buffer_addr_for_testing(
498     alts_handshaker_client* c) {
499   GPR_ASSERT(c != nullptr);
500   alts_grpc_handshaker_client* client =
501       reinterpret_cast<alts_grpc_handshaker_client*>(c);
502   return &client->recv_buffer;
503 }
504
505 grpc_metadata_array* alts_handshaker_client_get_initial_metadata_for_testing(
506     alts_handshaker_client* c) {
507   GPR_ASSERT(c != nullptr);
508   alts_grpc_handshaker_client* client =
509       reinterpret_cast<alts_grpc_handshaker_client*>(c);
510   return &client->recv_initial_metadata;
511 }
512
513 void alts_handshaker_client_set_recv_bytes_for_testing(
514     alts_handshaker_client* c, grpc_slice* recv_bytes) {
515   GPR_ASSERT(c != nullptr);
516   alts_grpc_handshaker_client* client =
517       reinterpret_cast<alts_grpc_handshaker_client*>(c);
518   client->recv_bytes = grpc_slice_ref_internal(*recv_bytes);
519 }
520
521 void alts_handshaker_client_set_fields_for_testing(
522     alts_handshaker_client* c, alts_tsi_handshaker* handshaker,
523     tsi_handshaker_on_next_done_cb cb, void* user_data,
524     grpc_byte_buffer* recv_buffer, grpc_status_code status) {
525   GPR_ASSERT(c != nullptr);
526   alts_grpc_handshaker_client* client =
527       reinterpret_cast<alts_grpc_handshaker_client*>(c);
528   client->handshaker = handshaker;
529   client->cb = cb;
530   client->user_data = user_data;
531   client->recv_buffer = recv_buffer;
532   client->status = status;
533 }
534
535 void alts_handshaker_client_check_fields_for_testing(
536     alts_handshaker_client* c, tsi_handshaker_on_next_done_cb cb,
537     void* user_data, bool has_sent_start_message, grpc_slice* recv_bytes) {
538   GPR_ASSERT(c != nullptr);
539   alts_grpc_handshaker_client* client =
540       reinterpret_cast<alts_grpc_handshaker_client*>(c);
541   GPR_ASSERT(client->cb == cb);
542   GPR_ASSERT(client->user_data == user_data);
543   if (recv_bytes != nullptr) {
544     GPR_ASSERT(grpc_slice_cmp(client->recv_bytes, *recv_bytes) == 0);
545   }
546   GPR_ASSERT(alts_tsi_handshaker_get_has_sent_start_message_for_testing(
547                  client->handshaker) == has_sent_start_message);
548 }
549
550 void alts_handshaker_client_set_vtable_for_testing(
551     alts_handshaker_client* c, alts_handshaker_client_vtable* vtable) {
552   GPR_ASSERT(c != nullptr);
553   GPR_ASSERT(vtable != nullptr);
554   alts_grpc_handshaker_client* client =
555       reinterpret_cast<alts_grpc_handshaker_client*>(c);
556   client->base.vtable = vtable;
557 }
558
559 alts_tsi_handshaker* alts_handshaker_client_get_handshaker_for_testing(
560     alts_handshaker_client* c) {
561   GPR_ASSERT(c != nullptr);
562   alts_grpc_handshaker_client* client =
563       reinterpret_cast<alts_grpc_handshaker_client*>(c);
564   return client->handshaker;
565 }
566
567 void alts_handshaker_client_set_cb_for_testing(
568     alts_handshaker_client* c, tsi_handshaker_on_next_done_cb cb) {
569   GPR_ASSERT(c != nullptr);
570   alts_grpc_handshaker_client* client =
571       reinterpret_cast<alts_grpc_handshaker_client*>(c);
572   client->cb = cb;
573 }
574
575 grpc_closure* alts_handshaker_client_get_closure_for_testing(
576     alts_handshaker_client* c) {
577   GPR_ASSERT(c != nullptr);
578   alts_grpc_handshaker_client* client =
579       reinterpret_cast<alts_grpc_handshaker_client*>(c);
580   return &client->on_handshaker_service_resp_recv;
581 }
582
583 }  // namespace internal
584 }  // namespace grpc_core
585
586 tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client) {
587   if (client != nullptr && client->vtable != nullptr &&
588       client->vtable->client_start != nullptr) {
589     return client->vtable->client_start(client);
590   }
591   gpr_log(GPR_ERROR,
592           "client or client->vtable has not been initialized properly");
593   return TSI_INVALID_ARGUMENT;
594 }
595
596 tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client,
597                                                grpc_slice* bytes_received) {
598   if (client != nullptr && client->vtable != nullptr &&
599       client->vtable->server_start != nullptr) {
600     return client->vtable->server_start(client, bytes_received);
601   }
602   gpr_log(GPR_ERROR,
603           "client or client->vtable has not been initialized properly");
604   return TSI_INVALID_ARGUMENT;
605 }
606
607 tsi_result alts_handshaker_client_next(alts_handshaker_client* client,
608                                        grpc_slice* bytes_received) {
609   if (client != nullptr && client->vtable != nullptr &&
610       client->vtable->next != nullptr) {
611     return client->vtable->next(client, bytes_received);
612   }
613   gpr_log(GPR_ERROR,
614           "client or client->vtable has not been initialized properly");
615   return TSI_INVALID_ARGUMENT;
616 }
617
618 void alts_handshaker_client_shutdown(alts_handshaker_client* client) {
619   if (client != nullptr && client->vtable != nullptr &&
620       client->vtable->shutdown != nullptr) {
621     client->vtable->shutdown(client);
622   }
623 }
624
625 void alts_handshaker_client_destroy(alts_handshaker_client* c) {
626   if (c != nullptr) {
627     if (c->vtable != nullptr && c->vtable->destruct != nullptr) {
628       c->vtable->destruct(c);
629     }
630     alts_grpc_handshaker_client* client =
631         reinterpret_cast<alts_grpc_handshaker_client*>(c);
632     grpc_byte_buffer_destroy(client->send_buffer);
633     grpc_byte_buffer_destroy(client->recv_buffer);
634     client->send_buffer = nullptr;
635     client->recv_buffer = nullptr;
636     grpc_metadata_array_destroy(&client->recv_initial_metadata);
637     grpc_slice_unref_internal(client->recv_bytes);
638     grpc_slice_unref_internal(client->target_name);
639     grpc_alts_credentials_options_destroy(client->options);
640     gpr_free(client->buffer);
641     gpr_free(client);
642   }
643 }