Home | History | Annotate | Download | only in handshaker
      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