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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. */ 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. */ 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 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. */ 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 */ 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 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. */ 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 */ 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 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. */ 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. */ 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. */ 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. */ 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. */ 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