• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h"
20 
21 const size_t kHandshakeProtocolNum = 3;
22 
grpc_gcp_handshaker_decoded_req_create(grpc_gcp_handshaker_req_type type)23 grpc_gcp_handshaker_req* grpc_gcp_handshaker_decoded_req_create(
24     grpc_gcp_handshaker_req_type type) {
25   grpc_gcp_handshaker_req* req =
26       static_cast<grpc_gcp_handshaker_req*>(gpr_zalloc(sizeof(*req)));
27   switch (type) {
28     case CLIENT_START_REQ:
29       req->has_client_start = true;
30       req->client_start.target_identities.funcs.decode =
31           decode_repeated_identity_cb;
32       req->client_start.application_protocols.funcs.decode =
33           decode_repeated_string_cb;
34       req->client_start.record_protocols.funcs.decode =
35           decode_repeated_string_cb;
36       req->client_start.local_identity.hostname.funcs.decode =
37           decode_string_or_bytes_cb;
38       req->client_start.local_identity.service_account.funcs.decode =
39           decode_string_or_bytes_cb;
40       req->client_start.local_endpoint.ip_address.funcs.decode =
41           decode_string_or_bytes_cb;
42       req->client_start.remote_endpoint.ip_address.funcs.decode =
43           decode_string_or_bytes_cb;
44       req->client_start.target_name.funcs.decode = decode_string_or_bytes_cb;
45       break;
46     case SERVER_START_REQ:
47       req->has_server_start = true;
48       req->server_start.application_protocols.funcs.decode =
49           &decode_repeated_string_cb;
50       for (size_t i = 0; i < kHandshakeProtocolNum; i++) {
51         req->server_start.handshake_parameters[i]
52             .value.local_identities.funcs.decode = &decode_repeated_identity_cb;
53         req->server_start.handshake_parameters[i]
54             .value.record_protocols.funcs.decode = &decode_repeated_string_cb;
55       }
56       req->server_start.in_bytes.funcs.decode = decode_string_or_bytes_cb;
57       req->server_start.local_endpoint.ip_address.funcs.decode =
58           decode_string_or_bytes_cb;
59       req->server_start.remote_endpoint.ip_address.funcs.decode =
60           decode_string_or_bytes_cb;
61       break;
62     case NEXT_REQ:
63       req->has_next = true;
64       break;
65   }
66   return req;
67 }
68 
grpc_gcp_handshaker_resp_set_application_protocol(grpc_gcp_handshaker_resp * resp,const char * application_protocol)69 bool grpc_gcp_handshaker_resp_set_application_protocol(
70     grpc_gcp_handshaker_resp* resp, const char* application_protocol) {
71   if (resp == nullptr || application_protocol == nullptr) {
72     gpr_log(GPR_ERROR,
73             "Invalid nullptr arguments to "
74             "handshaker_resp_set_application_protocol().");
75     return false;
76   }
77   resp->has_result = true;
78   grpc_slice* slice =
79       create_slice(application_protocol, strlen(application_protocol));
80   resp->result.application_protocol.arg = slice;
81   resp->result.application_protocol.funcs.encode = encode_string_or_bytes_cb;
82   return true;
83 }
84 
grpc_gcp_handshaker_resp_set_record_protocol(grpc_gcp_handshaker_resp * resp,const char * record_protocol)85 bool grpc_gcp_handshaker_resp_set_record_protocol(
86     grpc_gcp_handshaker_resp* resp, const char* record_protocol) {
87   if (resp == nullptr || record_protocol == nullptr) {
88     gpr_log(GPR_ERROR,
89             "Invalid nullptr arguments to "
90             "handshaker_resp_set_record_protocol().");
91     return false;
92   }
93   resp->has_result = true;
94   grpc_slice* slice = create_slice(record_protocol, strlen(record_protocol));
95   resp->result.record_protocol.arg = slice;
96   resp->result.record_protocol.funcs.encode = encode_string_or_bytes_cb;
97   return true;
98 }
99 
grpc_gcp_handshaker_resp_set_key_data(grpc_gcp_handshaker_resp * resp,const char * key_data,size_t size)100 bool grpc_gcp_handshaker_resp_set_key_data(grpc_gcp_handshaker_resp* resp,
101                                            const char* key_data, size_t size) {
102   if (resp == nullptr || key_data == nullptr) {
103     gpr_log(GPR_ERROR,
104             "Invalid nullptr arguments to handshaker_resp_set_key_data().");
105     return false;
106   }
107   resp->has_result = true;
108   grpc_slice* slice = create_slice(key_data, size);
109   resp->result.key_data.arg = slice;
110   resp->result.key_data.funcs.encode = encode_string_or_bytes_cb;
111   return true;
112 }
113 
set_identity_hostname(grpc_gcp_identity * identity,const char * hostname)114 static void set_identity_hostname(grpc_gcp_identity* identity,
115                                   const char* hostname) {
116   grpc_slice* slice = create_slice(hostname, strlen(hostname));
117   identity->hostname.arg = slice;
118   identity->hostname.funcs.encode = encode_string_or_bytes_cb;
119 }
120 
set_identity_service_account(grpc_gcp_identity * identity,const char * service_account)121 static void set_identity_service_account(grpc_gcp_identity* identity,
122                                          const char* service_account) {
123   grpc_slice* slice = create_slice(service_account, strlen(service_account));
124   identity->service_account.arg = slice;
125   identity->service_account.funcs.encode = encode_string_or_bytes_cb;
126 }
127 
grpc_gcp_handshaker_resp_set_local_identity_hostname(grpc_gcp_handshaker_resp * resp,const char * hostname)128 bool grpc_gcp_handshaker_resp_set_local_identity_hostname(
129     grpc_gcp_handshaker_resp* resp, const char* hostname) {
130   if (resp == nullptr || hostname == nullptr) {
131     gpr_log(GPR_ERROR,
132             "Invalid nullptr arguments to "
133             "grpc_gcp_handshaker_resp_set_local_identity_hostname().");
134     return false;
135   }
136   resp->has_result = true;
137   resp->result.has_local_identity = true;
138   set_identity_hostname(&resp->result.local_identity, hostname);
139   return true;
140 }
141 
grpc_gcp_handshaker_resp_set_local_identity_service_account(grpc_gcp_handshaker_resp * resp,const char * service_account)142 bool grpc_gcp_handshaker_resp_set_local_identity_service_account(
143     grpc_gcp_handshaker_resp* resp, const char* service_account) {
144   if (resp == nullptr || service_account == nullptr) {
145     gpr_log(GPR_ERROR,
146             "Invalid nullptr arguments to "
147             "grpc_gcp_handshaker_resp_set_local_identity_service_account().");
148     return false;
149   }
150   resp->has_result = true;
151   resp->result.has_local_identity = true;
152   set_identity_service_account(&resp->result.local_identity, service_account);
153   return true;
154 }
155 
grpc_gcp_handshaker_resp_set_peer_identity_hostname(grpc_gcp_handshaker_resp * resp,const char * hostname)156 bool grpc_gcp_handshaker_resp_set_peer_identity_hostname(
157     grpc_gcp_handshaker_resp* resp, const char* hostname) {
158   if (resp == nullptr || hostname == nullptr) {
159     gpr_log(GPR_ERROR,
160             "Invalid nullptr arguments to "
161             "grpc_gcp_handshaker_resp_set_peer_identity_hostname().");
162     return false;
163   }
164   resp->has_result = true;
165   resp->result.has_peer_identity = true;
166   set_identity_hostname(&resp->result.peer_identity, hostname);
167   return true;
168 }
169 
grpc_gcp_handshaker_resp_set_peer_identity_service_account(grpc_gcp_handshaker_resp * resp,const char * service_account)170 bool grpc_gcp_handshaker_resp_set_peer_identity_service_account(
171     grpc_gcp_handshaker_resp* resp, const char* service_account) {
172   if (resp == nullptr || service_account == nullptr) {
173     gpr_log(GPR_ERROR,
174             "Invalid nullptr arguments to "
175             "grpc_gcp_handshaker_resp_set_peer_identity_service_account().");
176     return false;
177   }
178   resp->has_result = true;
179   resp->result.has_peer_identity = true;
180   set_identity_service_account(&resp->result.peer_identity, service_account);
181   return true;
182 }
183 
grpc_gcp_handshaker_resp_set_channel_open(grpc_gcp_handshaker_resp * resp,bool keep_channel_open)184 bool grpc_gcp_handshaker_resp_set_channel_open(grpc_gcp_handshaker_resp* resp,
185                                                bool keep_channel_open) {
186   if (resp == nullptr) {
187     gpr_log(GPR_ERROR,
188             "Invalid nullptr argument to "
189             "grpc_gcp_handshaker_resp_set_channel_open().");
190     return false;
191   }
192   resp->has_result = true;
193   resp->result.has_keep_channel_open = true;
194   resp->result.keep_channel_open = keep_channel_open;
195   return true;
196 }
197 
grpc_gcp_handshaker_resp_set_code(grpc_gcp_handshaker_resp * resp,uint32_t code)198 bool grpc_gcp_handshaker_resp_set_code(grpc_gcp_handshaker_resp* resp,
199                                        uint32_t code) {
200   if (resp == nullptr) {
201     gpr_log(GPR_ERROR,
202             "Invalid nullptr argument to grpc_gcp_handshaker_resp_set_code().");
203     return false;
204   }
205   resp->has_status = true;
206   resp->status.has_code = true;
207   resp->status.code = code;
208   return true;
209 }
210 
grpc_gcp_handshaker_resp_set_details(grpc_gcp_handshaker_resp * resp,const char * details)211 bool grpc_gcp_handshaker_resp_set_details(grpc_gcp_handshaker_resp* resp,
212                                           const char* details) {
213   if (resp == nullptr || details == nullptr) {
214     gpr_log(
215         GPR_ERROR,
216         "Invalid nullptr arguments to grpc_gcp_handshaker_resp_set_details().");
217     return false;
218   }
219   resp->has_status = true;
220   grpc_slice* slice = create_slice(details, strlen(details));
221   resp->status.details.arg = slice;
222   resp->status.details.funcs.encode = encode_string_or_bytes_cb;
223   return true;
224 }
225 
grpc_gcp_handshaker_resp_set_out_frames(grpc_gcp_handshaker_resp * resp,const char * out_frames,size_t size)226 bool grpc_gcp_handshaker_resp_set_out_frames(grpc_gcp_handshaker_resp* resp,
227                                              const char* out_frames,
228                                              size_t size) {
229   if (resp == nullptr || out_frames == nullptr) {
230     gpr_log(GPR_ERROR,
231             "Invalid nullptr arguments to "
232             "grpc_gcp_handshaker_resp_set_out_frames().");
233     return false;
234   }
235   grpc_slice* slice = create_slice(out_frames, size);
236   resp->out_frames.arg = slice;
237   resp->out_frames.funcs.encode = encode_string_or_bytes_cb;
238   return true;
239 }
240 
grpc_gcp_handshaker_resp_set_bytes_consumed(grpc_gcp_handshaker_resp * resp,int32_t bytes_consumed)241 bool grpc_gcp_handshaker_resp_set_bytes_consumed(grpc_gcp_handshaker_resp* resp,
242                                                  int32_t bytes_consumed) {
243   if (resp == nullptr) {
244     gpr_log(GPR_ERROR,
245             "Invalid nullptr argument to "
246             "grpc_gcp_handshaker_resp_set_bytes_consumed().");
247     return false;
248   }
249   resp->has_bytes_consumed = true;
250   resp->bytes_consumed = bytes_consumed;
251   return true;
252 }
253 
grpc_gcp_handshaker_resp_set_peer_rpc_versions(grpc_gcp_handshaker_resp * resp,uint32_t max_major,uint32_t max_minor,uint32_t min_major,uint32_t min_minor)254 bool grpc_gcp_handshaker_resp_set_peer_rpc_versions(
255     grpc_gcp_handshaker_resp* resp, uint32_t max_major, uint32_t max_minor,
256     uint32_t min_major, uint32_t min_minor) {
257   if (resp == nullptr) {
258     gpr_log(GPR_ERROR,
259             "Invalid nullptr argument to "
260             "grpc_gcp_handshaker_resp_set_peer_rpc_versions().");
261     return false;
262   }
263   resp->has_result = true;
264   resp->result.has_peer_rpc_versions = true;
265   grpc_gcp_rpc_protocol_versions* versions = &resp->result.peer_rpc_versions;
266   versions->has_max_rpc_version = true;
267   versions->has_min_rpc_version = true;
268   versions->max_rpc_version.has_major = true;
269   versions->max_rpc_version.has_minor = true;
270   versions->min_rpc_version.has_major = true;
271   versions->min_rpc_version.has_minor = true;
272   versions->max_rpc_version.major = max_major;
273   versions->max_rpc_version.minor = max_minor;
274   versions->min_rpc_version.major = min_major;
275   versions->min_rpc_version.minor = min_minor;
276   return true;
277 }
278 
grpc_gcp_handshaker_resp_encode(grpc_gcp_handshaker_resp * resp,grpc_slice * slice)279 bool grpc_gcp_handshaker_resp_encode(grpc_gcp_handshaker_resp* resp,
280                                      grpc_slice* slice) {
281   if (resp == nullptr || slice == nullptr) {
282     gpr_log(GPR_ERROR,
283             "Invalid nullptr arguments to grpc_gcp_handshaker_resp_encode().");
284     return false;
285   }
286   pb_ostream_t size_stream;
287   memset(&size_stream, 0, sizeof(pb_ostream_t));
288   if (!pb_encode(&size_stream, grpc_gcp_HandshakerResp_fields, resp)) {
289     gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream));
290     return false;
291   }
292   size_t encoded_length = size_stream.bytes_written;
293   *slice = grpc_slice_malloc(encoded_length);
294   pb_ostream_t output_stream =
295       pb_ostream_from_buffer(GRPC_SLICE_START_PTR(*slice), encoded_length);
296   if (!pb_encode(&output_stream, grpc_gcp_HandshakerResp_fields, resp)) {
297     gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream));
298     return false;
299   }
300   return true;
301 }
302 
grpc_gcp_handshaker_req_decode(grpc_slice slice,grpc_gcp_handshaker_req * req)303 bool grpc_gcp_handshaker_req_decode(grpc_slice slice,
304                                     grpc_gcp_handshaker_req* req) {
305   if (req == nullptr) {
306     gpr_log(GPR_ERROR,
307             "Invalid nullptr argument to grpc_gcp_handshaker_req_decode().");
308     return false;
309   }
310   pb_istream_t stream = pb_istream_from_buffer(GRPC_SLICE_START_PTR(slice),
311                                                GRPC_SLICE_LENGTH(slice));
312   req->next.in_bytes.funcs.decode = decode_string_or_bytes_cb;
313   if (!pb_decode(&stream, grpc_gcp_HandshakerReq_fields, req)) {
314     gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
315     return false;
316   }
317   return true;
318 }
319 
320 /* Check equality of a pair of grpc_slice fields. */
slice_equals(grpc_slice * l_slice,grpc_slice * r_slice)321 static bool slice_equals(grpc_slice* l_slice, grpc_slice* r_slice) {
322   if (l_slice == nullptr && r_slice == nullptr) {
323     return true;
324   }
325   if (l_slice != nullptr && r_slice != nullptr) {
326     return grpc_slice_eq(*l_slice, *r_slice);
327   }
328   return false;
329 }
330 
331 /* Check equality of a pair of grpc_gcp_identity fields. */
handshaker_identity_equals(const grpc_gcp_identity * l_id,const grpc_gcp_identity * r_id)332 static bool handshaker_identity_equals(const grpc_gcp_identity* l_id,
333                                        const grpc_gcp_identity* r_id) {
334   if (!((l_id->hostname.arg != nullptr) != (r_id->hostname.arg != nullptr))) {
335     if (l_id->hostname.arg != nullptr) {
336       return slice_equals(static_cast<grpc_slice*>(l_id->hostname.arg),
337                           static_cast<grpc_slice*>(r_id->hostname.arg));
338     }
339   } else {
340     return false;
341   }
342   if (!((l_id->service_account.arg != nullptr) !=
343         (r_id->service_account.arg != nullptr))) {
344     if (l_id->service_account.arg != nullptr) {
345       return slice_equals(static_cast<grpc_slice*>(l_id->service_account.arg),
346                           static_cast<grpc_slice*>(r_id->service_account.arg));
347     }
348   } else {
349     return false;
350   }
351   return true;
352 }
353 
handshaker_rpc_versions_equals(const grpc_gcp_rpc_protocol_versions * l_version,const grpc_gcp_rpc_protocol_versions * r_version)354 static bool handshaker_rpc_versions_equals(
355     const grpc_gcp_rpc_protocol_versions* l_version,
356     const grpc_gcp_rpc_protocol_versions* r_version) {
357   bool result = true;
358   result &=
359       (l_version->max_rpc_version.major == r_version->max_rpc_version.major);
360   result &=
361       (l_version->max_rpc_version.minor == r_version->max_rpc_version.minor);
362   result &=
363       (l_version->min_rpc_version.major == r_version->min_rpc_version.major);
364   result &=
365       (l_version->min_rpc_version.minor == r_version->min_rpc_version.minor);
366   return result;
367 }
368 
369 /* Check equality of a pair of grpc_gcp_endpoint fields. */
handshaker_endpoint_equals(const grpc_gcp_endpoint * l_end,const grpc_gcp_endpoint * r_end)370 static bool handshaker_endpoint_equals(const grpc_gcp_endpoint* l_end,
371                                        const grpc_gcp_endpoint* r_end) {
372   bool result = true;
373   result &= (l_end->port == r_end->port);
374   result &= (l_end->protocol == r_end->protocol);
375   if (!((l_end->ip_address.arg != nullptr) !=
376         (r_end->ip_address.arg != nullptr))) {
377     if (l_end->ip_address.arg != nullptr) {
378       result &= slice_equals(static_cast<grpc_slice*>(l_end->ip_address.arg),
379                              static_cast<grpc_slice*>(r_end->ip_address.arg));
380     }
381   } else {
382     return false;
383   }
384   return result;
385 }
386 /**
387  * Check if a specific repeated field (i.e., target) is contained in a repeated
388  * field list (i.e., head).
389  */
repeated_field_list_contains_identity(const repeated_field * head,const repeated_field * target)390 static bool repeated_field_list_contains_identity(
391     const repeated_field* head, const repeated_field* target) {
392   repeated_field* field = const_cast<repeated_field*>(head);
393   while (field != nullptr) {
394     if (handshaker_identity_equals(
395             static_cast<const grpc_gcp_identity*>(field->data),
396             static_cast<const grpc_gcp_identity*>(target->data))) {
397       return true;
398     }
399     field = field->next;
400   }
401   return false;
402 }
403 
repeated_field_list_contains_string(const repeated_field * head,const repeated_field * target)404 static bool repeated_field_list_contains_string(const repeated_field* head,
405                                                 const repeated_field* target) {
406   repeated_field* field = const_cast<repeated_field*>(head);
407   while (field != nullptr) {
408     if (slice_equals((grpc_slice*)field->data, (grpc_slice*)target->data)) {
409       return true;
410     }
411     field = field->next;
412   }
413   return false;
414 }
415 
416 /* Return a length of repeated field list. */
repeated_field_list_get_length(const repeated_field * head)417 static size_t repeated_field_list_get_length(const repeated_field* head) {
418   repeated_field* field = const_cast<repeated_field*>(head);
419   size_t len = 0;
420   while (field != nullptr) {
421     len++;
422     field = field->next;
423   }
424   return len;
425 }
426 
427 /**
428  * Check if a pair of repeated field lists contain the same set of repeated
429  * fields.
430  */
repeated_field_list_equals_identity(const repeated_field * l_head,const repeated_field * r_head)431 static bool repeated_field_list_equals_identity(const repeated_field* l_head,
432                                                 const repeated_field* r_head) {
433   if (repeated_field_list_get_length(l_head) !=
434       repeated_field_list_get_length(r_head)) {
435     return false;
436   }
437   repeated_field* field = const_cast<repeated_field*>(l_head);
438   repeated_field* head = const_cast<repeated_field*>(r_head);
439   while (field != nullptr) {
440     if (!repeated_field_list_contains_identity(head, field)) {
441       return false;
442     }
443     field = field->next;
444   }
445   return true;
446 }
447 
repeated_field_list_equals_string(const repeated_field * l_head,const repeated_field * r_head)448 static bool repeated_field_list_equals_string(const repeated_field* l_head,
449                                               const repeated_field* r_head) {
450   if (repeated_field_list_get_length(l_head) !=
451       repeated_field_list_get_length(r_head)) {
452     return false;
453   }
454   repeated_field* field = const_cast<repeated_field*>(l_head);
455   repeated_field* head = const_cast<repeated_field*>(r_head);
456   while (field != nullptr) {
457     if (!repeated_field_list_contains_string(head, field)) {
458       return false;
459     }
460     field = field->next;
461   }
462   return true;
463 }
464 
465 /* Check equality of a pair of ALTS client_start handshake requests. */
grpc_gcp_handshaker_client_start_req_equals(grpc_gcp_start_client_handshake_req * l_req,grpc_gcp_start_client_handshake_req * r_req)466 bool grpc_gcp_handshaker_client_start_req_equals(
467     grpc_gcp_start_client_handshake_req* l_req,
468     grpc_gcp_start_client_handshake_req* r_req) {
469   bool result = true;
470   /* Compare handshake_security_protocol. */
471   result &=
472       l_req->handshake_security_protocol == r_req->handshake_security_protocol;
473   /* Compare application_protocols, record_protocols, and target_identities. */
474   result &= repeated_field_list_equals_string(
475       static_cast<const repeated_field*>(l_req->application_protocols.arg),
476       static_cast<const repeated_field*>(r_req->application_protocols.arg));
477   result &= repeated_field_list_equals_string(
478       static_cast<const repeated_field*>(l_req->record_protocols.arg),
479       static_cast<const repeated_field*>(r_req->record_protocols.arg));
480   result &= repeated_field_list_equals_identity(
481       static_cast<const repeated_field*>(l_req->target_identities.arg),
482       static_cast<const repeated_field*>(r_req->target_identities.arg));
483   if ((l_req->has_local_identity ^ r_req->has_local_identity) |
484       (l_req->has_local_endpoint ^ r_req->has_local_endpoint) |
485       ((l_req->has_remote_endpoint ^ r_req->has_remote_endpoint)) |
486       (l_req->has_rpc_versions ^ r_req->has_rpc_versions)) {
487     return false;
488   }
489   /* Compare local_identity, local_endpoint, and remote_endpoint. */
490   if (l_req->has_local_identity) {
491     result &= handshaker_identity_equals(&l_req->local_identity,
492                                          &r_req->local_identity);
493   }
494   if (l_req->has_local_endpoint) {
495     result &= handshaker_endpoint_equals(&l_req->local_endpoint,
496                                          &r_req->local_endpoint);
497   }
498   if (l_req->has_remote_endpoint) {
499     result &= handshaker_endpoint_equals(&l_req->remote_endpoint,
500                                          &r_req->remote_endpoint);
501   }
502   if (l_req->has_rpc_versions) {
503     result &= handshaker_rpc_versions_equals(&l_req->rpc_versions,
504                                              &r_req->rpc_versions);
505   }
506   return result;
507 }
508 
509 /* Check equality of a pair of ALTS server_start handshake requests. */
grpc_gcp_handshaker_server_start_req_equals(grpc_gcp_start_server_handshake_req * l_req,grpc_gcp_start_server_handshake_req * r_req)510 bool grpc_gcp_handshaker_server_start_req_equals(
511     grpc_gcp_start_server_handshake_req* l_req,
512     grpc_gcp_start_server_handshake_req* r_req) {
513   bool result = true;
514   /* Compare application_protocols. */
515   result &= repeated_field_list_equals_string(
516       static_cast<const repeated_field*>(l_req->application_protocols.arg),
517       static_cast<const repeated_field*>(r_req->application_protocols.arg));
518   /* Compare handshake_parameters. */
519   size_t i = 0, j = 0;
520   result &=
521       (l_req->handshake_parameters_count == r_req->handshake_parameters_count);
522   for (i = 0; i < l_req->handshake_parameters_count; i++) {
523     bool found = false;
524     for (j = 0; j < r_req->handshake_parameters_count; j++) {
525       if (l_req->handshake_parameters[i].key ==
526           r_req->handshake_parameters[j].key) {
527         found = true;
528         result &= repeated_field_list_equals_string(
529             static_cast<const repeated_field*>(
530                 l_req->handshake_parameters[i].value.record_protocols.arg),
531             static_cast<const repeated_field*>(
532                 r_req->handshake_parameters[j].value.record_protocols.arg));
533         result &= repeated_field_list_equals_identity(
534             static_cast<const repeated_field*>(
535                 l_req->handshake_parameters[i].value.local_identities.arg),
536             static_cast<const repeated_field*>(
537                 r_req->handshake_parameters[j].value.local_identities.arg));
538       }
539     }
540     if (!found) {
541       return false;
542     }
543   }
544   /* Compare in_bytes, local_endpoint, remote_endpoint. */
545   result &= slice_equals(static_cast<grpc_slice*>(l_req->in_bytes.arg),
546                          static_cast<grpc_slice*>(r_req->in_bytes.arg));
547   if ((l_req->has_local_endpoint ^ r_req->has_local_endpoint) |
548       (l_req->has_remote_endpoint ^ r_req->has_remote_endpoint) |
549       (l_req->has_rpc_versions ^ r_req->has_rpc_versions))
550     return false;
551   if (l_req->has_local_endpoint) {
552     result &= handshaker_endpoint_equals(&l_req->local_endpoint,
553                                          &r_req->local_endpoint);
554   }
555   if (l_req->has_remote_endpoint) {
556     result &= handshaker_endpoint_equals(&l_req->remote_endpoint,
557                                          &r_req->remote_endpoint);
558   }
559   if (l_req->has_rpc_versions) {
560     result &= handshaker_rpc_versions_equals(&l_req->rpc_versions,
561                                              &r_req->rpc_versions);
562   }
563   return result;
564 }
565 
566 /* Check equality of a pair of ALTS handshake requests. */
grpc_gcp_handshaker_req_equals(grpc_gcp_handshaker_req * l_req,grpc_gcp_handshaker_req * r_req)567 bool grpc_gcp_handshaker_req_equals(grpc_gcp_handshaker_req* l_req,
568                                     grpc_gcp_handshaker_req* r_req) {
569   if (l_req->has_next && r_req->has_next) {
570     return slice_equals(static_cast<grpc_slice*>(l_req->next.in_bytes.arg),
571                         static_cast<grpc_slice*>(r_req->next.in_bytes.arg));
572   } else if (l_req->has_client_start && r_req->has_client_start) {
573     return grpc_gcp_handshaker_client_start_req_equals(&l_req->client_start,
574                                                        &r_req->client_start);
575   } else if (l_req->has_server_start && r_req->has_server_start) {
576     return grpc_gcp_handshaker_server_start_req_equals(&l_req->server_start,
577                                                        &r_req->server_start);
578   }
579   return false;
580 }
581 
582 /* Check equality of a pair of ALTS handshake results. */
grpc_gcp_handshaker_resp_result_equals(grpc_gcp_handshaker_result * l_result,grpc_gcp_handshaker_result * r_result)583 bool grpc_gcp_handshaker_resp_result_equals(
584     grpc_gcp_handshaker_result* l_result,
585     grpc_gcp_handshaker_result* r_result) {
586   bool result = true;
587   /* Compare application_protocol, record_protocol, and key_data. */
588   result &= slice_equals(
589       static_cast<grpc_slice*>(l_result->application_protocol.arg),
590       static_cast<grpc_slice*>(r_result->application_protocol.arg));
591   result &=
592       slice_equals(static_cast<grpc_slice*>(l_result->record_protocol.arg),
593                    static_cast<grpc_slice*>(r_result->record_protocol.arg));
594   result &= slice_equals(static_cast<grpc_slice*>(l_result->key_data.arg),
595                          static_cast<grpc_slice*>(r_result->key_data.arg));
596   /* Compare local_identity, peer_identity, and keep_channel_open. */
597   if ((l_result->has_local_identity ^ r_result->has_local_identity) |
598       (l_result->has_peer_identity ^ r_result->has_peer_identity) |
599       (l_result->has_peer_rpc_versions ^ r_result->has_peer_rpc_versions)) {
600     return false;
601   }
602   if (l_result->has_local_identity) {
603     result &= handshaker_identity_equals(&l_result->local_identity,
604                                          &r_result->local_identity);
605   }
606   if (l_result->has_peer_identity) {
607     result &= handshaker_identity_equals(&l_result->peer_identity,
608                                          &r_result->peer_identity);
609   }
610   if (l_result->has_peer_rpc_versions) {
611     result &= handshaker_rpc_versions_equals(&l_result->peer_rpc_versions,
612                                              &r_result->peer_rpc_versions);
613   }
614   result &= (l_result->keep_channel_open == r_result->keep_channel_open);
615   return result;
616 }
617 
618 /* Check equality of a pair of ALTS handshake responses. */
grpc_gcp_handshaker_resp_equals(grpc_gcp_handshaker_resp * l_resp,grpc_gcp_handshaker_resp * r_resp)619 bool grpc_gcp_handshaker_resp_equals(grpc_gcp_handshaker_resp* l_resp,
620                                      grpc_gcp_handshaker_resp* r_resp) {
621   bool result = true;
622   /* Compare out_frames and bytes_consumed. */
623   result &= slice_equals(static_cast<grpc_slice*>(l_resp->out_frames.arg),
624                          static_cast<grpc_slice*>(r_resp->out_frames.arg));
625   result &= (l_resp->bytes_consumed == r_resp->bytes_consumed);
626   /* Compare result and status. */
627   if ((l_resp->has_result ^ r_resp->has_result) |
628       (l_resp->has_status ^ r_resp->has_status)) {
629     return false;
630   }
631   if (l_resp->has_result) {
632     result &= grpc_gcp_handshaker_resp_result_equals(&l_resp->result,
633                                                      &r_resp->result);
634   }
635   if (l_resp->has_status) {
636     result &= (l_resp->status.code == r_resp->status.code);
637     result &=
638         slice_equals(static_cast<grpc_slice*>(l_resp->status.details.arg),
639                      static_cast<grpc_slice*>(r_resp->status.details.arg));
640   }
641   return result;
642 }
643