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/transport_security_common_api.h" 22 23 bool grpc_gcp_rpc_protocol_versions_set_max( 24 grpc_gcp_rpc_protocol_versions* versions, uint32_t max_major, 25 uint32_t max_minor) { 26 if (versions == nullptr) { 27 gpr_log(GPR_ERROR, 28 "versions is nullptr in " 29 "grpc_gcp_rpc_protocol_versions_set_max()."); 30 return false; 31 } 32 versions->has_max_rpc_version = true; 33 versions->max_rpc_version.has_major = true; 34 versions->max_rpc_version.has_minor = true; 35 versions->max_rpc_version.major = max_major; 36 versions->max_rpc_version.minor = max_minor; 37 return true; 38 } 39 40 bool grpc_gcp_rpc_protocol_versions_set_min( 41 grpc_gcp_rpc_protocol_versions* versions, uint32_t min_major, 42 uint32_t min_minor) { 43 if (versions == nullptr) { 44 gpr_log(GPR_ERROR, 45 "versions is nullptr in " 46 "grpc_gcp_rpc_protocol_versions_set_min()."); 47 return false; 48 } 49 versions->has_min_rpc_version = true; 50 versions->min_rpc_version.has_major = true; 51 versions->min_rpc_version.has_minor = true; 52 versions->min_rpc_version.major = min_major; 53 versions->min_rpc_version.minor = min_minor; 54 return true; 55 } 56 57 size_t grpc_gcp_rpc_protocol_versions_encode_length( 58 const grpc_gcp_rpc_protocol_versions* versions) { 59 if (versions == nullptr) { 60 gpr_log(GPR_ERROR, 61 "Invalid nullptr arguments to " 62 "grpc_gcp_rpc_protocol_versions_encode_length()."); 63 return 0; 64 } 65 pb_ostream_t size_stream; 66 memset(&size_stream, 0, sizeof(pb_ostream_t)); 67 if (!pb_encode(&size_stream, grpc_gcp_RpcProtocolVersions_fields, versions)) { 68 gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream)); 69 return 0; 70 } 71 return size_stream.bytes_written; 72 } 73 74 bool grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes( 75 const grpc_gcp_rpc_protocol_versions* versions, uint8_t* bytes, 76 size_t bytes_length) { 77 if (versions == nullptr || bytes == nullptr || bytes_length == 0) { 78 gpr_log(GPR_ERROR, 79 "Invalid nullptr arguments to " 80 "grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes()."); 81 return false; 82 } 83 pb_ostream_t output_stream = pb_ostream_from_buffer(bytes, bytes_length); 84 if (!pb_encode(&output_stream, grpc_gcp_RpcProtocolVersions_fields, 85 versions)) { 86 gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&output_stream)); 87 return false; 88 } 89 return true; 90 } 91 92 bool grpc_gcp_rpc_protocol_versions_encode( 93 const grpc_gcp_rpc_protocol_versions* versions, grpc_slice* slice) { 94 if (versions == nullptr || slice == nullptr) { 95 gpr_log(GPR_ERROR, 96 "Invalid nullptr arguments to " 97 "grpc_gcp_rpc_protocol_versions_encode()."); 98 return false; 99 } 100 size_t encoded_length = 101 grpc_gcp_rpc_protocol_versions_encode_length(versions); 102 if (encoded_length == 0) return false; 103 *slice = grpc_slice_malloc(encoded_length); 104 return grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes( 105 versions, GRPC_SLICE_START_PTR(*slice), encoded_length); 106 } 107 108 bool grpc_gcp_rpc_protocol_versions_decode( 109 grpc_slice slice, grpc_gcp_rpc_protocol_versions* versions) { 110 if (versions == nullptr) { 111 gpr_log(GPR_ERROR, 112 "version is nullptr in " 113 "grpc_gcp_rpc_protocol_versions_decode()."); 114 return false; 115 } 116 pb_istream_t stream = pb_istream_from_buffer(GRPC_SLICE_START_PTR(slice), 117 GRPC_SLICE_LENGTH(slice)); 118 if (!pb_decode(&stream, grpc_gcp_RpcProtocolVersions_fields, versions)) { 119 gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); 120 return false; 121 } 122 return true; 123 } 124 125 bool grpc_gcp_rpc_protocol_versions_copy( 126 const grpc_gcp_rpc_protocol_versions* src, 127 grpc_gcp_rpc_protocol_versions* dst) { 128 if ((src == nullptr && dst != nullptr) || 129 (src != nullptr && dst == nullptr)) { 130 gpr_log(GPR_ERROR, 131 "Invalid arguments to " 132 "grpc_gcp_rpc_protocol_versions_copy()."); 133 return false; 134 } 135 if (src == nullptr) { 136 return true; 137 } 138 grpc_gcp_rpc_protocol_versions_set_max(dst, src->max_rpc_version.major, 139 src->max_rpc_version.minor); 140 grpc_gcp_rpc_protocol_versions_set_min(dst, src->min_rpc_version.major, 141 src->min_rpc_version.minor); 142 return true; 143 } 144 145 namespace grpc_core { 146 namespace internal { 147 148 int grpc_gcp_rpc_protocol_version_compare( 149 const grpc_gcp_rpc_protocol_versions_version* v1, 150 const grpc_gcp_rpc_protocol_versions_version* v2) { 151 if ((v1->major > v2->major) || 152 (v1->major == v2->major && v1->minor > v2->minor)) { 153 return 1; 154 } 155 if ((v1->major < v2->major) || 156 (v1->major == v2->major && v1->minor < v2->minor)) { 157 return -1; 158 } 159 return 0; 160 } 161 162 } // namespace internal 163 } // namespace grpc_core 164 165 bool grpc_gcp_rpc_protocol_versions_check( 166 const grpc_gcp_rpc_protocol_versions* local_versions, 167 const grpc_gcp_rpc_protocol_versions* peer_versions, 168 grpc_gcp_rpc_protocol_versions_version* highest_common_version) { 169 if (local_versions == nullptr || peer_versions == nullptr) { 170 gpr_log(GPR_ERROR, 171 "Invalid arguments to " 172 "grpc_gcp_rpc_protocol_versions_check()."); 173 return false; 174 } 175 /* max_common_version is MIN(local.max, peer.max) */ 176 const grpc_gcp_rpc_protocol_versions_version* max_common_version = 177 grpc_core::internal::grpc_gcp_rpc_protocol_version_compare( 178 &local_versions->max_rpc_version, &peer_versions->max_rpc_version) > 0 179 ? &peer_versions->max_rpc_version 180 : &local_versions->max_rpc_version; 181 /* min_common_version is MAX(local.min, peer.min) */ 182 const grpc_gcp_rpc_protocol_versions_version* min_common_version = 183 grpc_core::internal::grpc_gcp_rpc_protocol_version_compare( 184 &local_versions->min_rpc_version, &peer_versions->min_rpc_version) > 0 185 ? &local_versions->min_rpc_version 186 : &peer_versions->min_rpc_version; 187 bool result = grpc_core::internal::grpc_gcp_rpc_protocol_version_compare( 188 max_common_version, min_common_version) >= 0 189 ? true 190 : false; 191 if (result && highest_common_version != nullptr) { 192 memcpy(highest_common_version, max_common_version, 193 sizeof(grpc_gcp_rpc_protocol_versions_version)); 194 } 195 return result; 196 } 197