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 #include "upb/upb.hpp"
24 
grpc_gcp_rpc_protocol_versions_set_max(grpc_gcp_rpc_protocol_versions * versions,uint32_t max_major,uint32_t max_minor)25 bool grpc_gcp_rpc_protocol_versions_set_max(
26     grpc_gcp_rpc_protocol_versions* versions, uint32_t max_major,
27     uint32_t max_minor) {
28   if (versions == nullptr) {
29     gpr_log(GPR_ERROR,
30             "versions is nullptr in "
31             "grpc_gcp_rpc_protocol_versions_set_max().");
32     return false;
33   }
34   versions->max_rpc_version.major = max_major;
35   versions->max_rpc_version.minor = max_minor;
36   return true;
37 }
38 
grpc_gcp_rpc_protocol_versions_set_min(grpc_gcp_rpc_protocol_versions * versions,uint32_t min_major,uint32_t min_minor)39 bool grpc_gcp_rpc_protocol_versions_set_min(
40     grpc_gcp_rpc_protocol_versions* versions, uint32_t min_major,
41     uint32_t min_minor) {
42   if (versions == nullptr) {
43     gpr_log(GPR_ERROR,
44             "versions is nullptr in "
45             "grpc_gcp_rpc_protocol_versions_set_min().");
46     return false;
47   }
48   versions->min_rpc_version.major = min_major;
49   versions->min_rpc_version.minor = min_minor;
50   return true;
51 }
52 
grpc_gcp_rpc_protocol_versions_encode(const grpc_gcp_rpc_protocol_versions * versions,grpc_slice * slice)53 bool grpc_gcp_rpc_protocol_versions_encode(
54     const grpc_gcp_rpc_protocol_versions* versions, grpc_slice* slice) {
55   if (versions == nullptr || slice == nullptr) {
56     gpr_log(GPR_ERROR,
57             "Invalid nullptr arguments to "
58             "grpc_gcp_rpc_protocol_versions_encode().");
59     return false;
60   }
61   upb::Arena arena;
62   grpc_gcp_RpcProtocolVersions* versions_msg =
63       grpc_gcp_RpcProtocolVersions_new(arena.ptr());
64   grpc_gcp_RpcProtocolVersions_assign_from_struct(versions_msg, arena.ptr(),
65                                                   versions);
66   return grpc_gcp_rpc_protocol_versions_encode(versions_msg, arena.ptr(),
67                                                slice);
68 }
69 
grpc_gcp_rpc_protocol_versions_encode(const grpc_gcp_RpcProtocolVersions * versions,upb_arena * arena,grpc_slice * slice)70 bool grpc_gcp_rpc_protocol_versions_encode(
71     const grpc_gcp_RpcProtocolVersions* versions, upb_arena* arena,
72     grpc_slice* slice) {
73   if (versions == nullptr || arena == nullptr || slice == nullptr) {
74     gpr_log(GPR_ERROR,
75             "Invalid nullptr arguments to "
76             "grpc_gcp_rpc_protocol_versions_encode().");
77     return false;
78   }
79   size_t buf_length;
80   char* buf =
81       grpc_gcp_RpcProtocolVersions_serialize(versions, arena, &buf_length);
82   if (buf == nullptr) {
83     return false;
84   }
85   *slice = grpc_slice_from_copied_buffer(buf, buf_length);
86   return true;
87 }
88 
grpc_gcp_rpc_protocol_versions_decode(const grpc_slice & slice,grpc_gcp_rpc_protocol_versions * versions)89 bool grpc_gcp_rpc_protocol_versions_decode(
90     const grpc_slice& slice, grpc_gcp_rpc_protocol_versions* versions) {
91   if (versions == nullptr) {
92     gpr_log(GPR_ERROR,
93             "version is nullptr in "
94             "grpc_gcp_rpc_protocol_versions_decode().");
95     return false;
96   }
97   upb::Arena arena;
98   grpc_gcp_RpcProtocolVersions* versions_msg =
99       grpc_gcp_RpcProtocolVersions_parse(
100           reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(slice)),
101           GRPC_SLICE_LENGTH(slice), arena.ptr());
102   if (versions_msg == nullptr) {
103     gpr_log(GPR_ERROR, "cannot deserialize RpcProtocolVersions message");
104     return false;
105   }
106   grpc_gcp_rpc_protocol_versions_assign_from_upb(versions, versions_msg);
107   return true;
108 }
109 
grpc_gcp_rpc_protocol_versions_assign_from_upb(grpc_gcp_rpc_protocol_versions * versions,const grpc_gcp_RpcProtocolVersions * value)110 void grpc_gcp_rpc_protocol_versions_assign_from_upb(
111     grpc_gcp_rpc_protocol_versions* versions,
112     const grpc_gcp_RpcProtocolVersions* value) {
113   const grpc_gcp_RpcProtocolVersions_Version* max_version_msg =
114       grpc_gcp_RpcProtocolVersions_max_rpc_version(value);
115   if (max_version_msg != nullptr) {
116     versions->max_rpc_version.major =
117         grpc_gcp_RpcProtocolVersions_Version_major(max_version_msg);
118     versions->max_rpc_version.minor =
119         grpc_gcp_RpcProtocolVersions_Version_minor(max_version_msg);
120   } else {
121     versions->max_rpc_version.major = 0;
122     versions->max_rpc_version.minor = 0;
123   }
124   const grpc_gcp_RpcProtocolVersions_Version* min_version_msg =
125       grpc_gcp_RpcProtocolVersions_min_rpc_version(value);
126   if (min_version_msg != nullptr) {
127     versions->min_rpc_version.major =
128         grpc_gcp_RpcProtocolVersions_Version_major(min_version_msg);
129     versions->min_rpc_version.minor =
130         grpc_gcp_RpcProtocolVersions_Version_minor(min_version_msg);
131   } else {
132     versions->min_rpc_version.major = 0;
133     versions->min_rpc_version.minor = 0;
134   }
135 }
136 
grpc_gcp_RpcProtocolVersions_assign_from_struct(grpc_gcp_RpcProtocolVersions * versions,upb_arena * arena,const grpc_gcp_rpc_protocol_versions * value)137 void grpc_gcp_RpcProtocolVersions_assign_from_struct(
138     grpc_gcp_RpcProtocolVersions* versions, upb_arena* arena,
139     const grpc_gcp_rpc_protocol_versions* value) {
140   grpc_gcp_RpcProtocolVersions_Version* max_version_msg =
141       grpc_gcp_RpcProtocolVersions_mutable_max_rpc_version(versions, arena);
142   grpc_gcp_RpcProtocolVersions_Version_set_major(max_version_msg,
143                                                  value->max_rpc_version.major);
144   grpc_gcp_RpcProtocolVersions_Version_set_minor(max_version_msg,
145                                                  value->max_rpc_version.minor);
146   grpc_gcp_RpcProtocolVersions_Version* min_version_msg =
147       grpc_gcp_RpcProtocolVersions_mutable_min_rpc_version(versions, arena);
148   grpc_gcp_RpcProtocolVersions_Version_set_major(min_version_msg,
149                                                  value->min_rpc_version.major);
150   grpc_gcp_RpcProtocolVersions_Version_set_minor(min_version_msg,
151                                                  value->min_rpc_version.minor);
152 }
153 
grpc_gcp_rpc_protocol_versions_copy(const grpc_gcp_rpc_protocol_versions * src,grpc_gcp_rpc_protocol_versions * dst)154 bool grpc_gcp_rpc_protocol_versions_copy(
155     const grpc_gcp_rpc_protocol_versions* src,
156     grpc_gcp_rpc_protocol_versions* dst) {
157   if ((src == nullptr && dst != nullptr) ||
158       (src != nullptr && dst == nullptr)) {
159     gpr_log(GPR_ERROR,
160             "Invalid arguments to "
161             "grpc_gcp_rpc_protocol_versions_copy().");
162     return false;
163   }
164   if (src == nullptr) {
165     return true;
166   }
167   grpc_gcp_rpc_protocol_versions_set_max(dst, src->max_rpc_version.major,
168                                          src->max_rpc_version.minor);
169   grpc_gcp_rpc_protocol_versions_set_min(dst, src->min_rpc_version.major,
170                                          src->min_rpc_version.minor);
171   return true;
172 }
173 
174 namespace grpc_core {
175 namespace internal {
176 
grpc_gcp_rpc_protocol_version_compare(const grpc_gcp_rpc_protocol_versions_version * v1,const grpc_gcp_rpc_protocol_versions_version * v2)177 int grpc_gcp_rpc_protocol_version_compare(
178     const grpc_gcp_rpc_protocol_versions_version* v1,
179     const grpc_gcp_rpc_protocol_versions_version* v2) {
180   if ((v1->major > v2->major) ||
181       (v1->major == v2->major && v1->minor > v2->minor)) {
182     return 1;
183   }
184   if ((v1->major < v2->major) ||
185       (v1->major == v2->major && v1->minor < v2->minor)) {
186     return -1;
187   }
188   return 0;
189 }
190 
191 }  // namespace internal
192 }  // namespace grpc_core
193 
grpc_gcp_rpc_protocol_versions_check(const grpc_gcp_rpc_protocol_versions * local_versions,const grpc_gcp_rpc_protocol_versions * peer_versions,grpc_gcp_rpc_protocol_versions_version * highest_common_version)194 bool grpc_gcp_rpc_protocol_versions_check(
195     const grpc_gcp_rpc_protocol_versions* local_versions,
196     const grpc_gcp_rpc_protocol_versions* peer_versions,
197     grpc_gcp_rpc_protocol_versions_version* highest_common_version) {
198   if (local_versions == nullptr || peer_versions == nullptr) {
199     gpr_log(GPR_ERROR,
200             "Invalid arguments to "
201             "grpc_gcp_rpc_protocol_versions_check().");
202     return false;
203   }
204   /* max_common_version is MIN(local.max, peer.max) */
205   const grpc_gcp_rpc_protocol_versions_version* max_common_version =
206       grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
207           &local_versions->max_rpc_version, &peer_versions->max_rpc_version) > 0
208           ? &peer_versions->max_rpc_version
209           : &local_versions->max_rpc_version;
210   /* min_common_version is MAX(local.min, peer.min) */
211   const grpc_gcp_rpc_protocol_versions_version* min_common_version =
212       grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
213           &local_versions->min_rpc_version, &peer_versions->min_rpc_version) > 0
214           ? &local_versions->min_rpc_version
215           : &peer_versions->min_rpc_version;
216   bool result = grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
217                     max_common_version, min_common_version) >= 0;
218   if (result && highest_common_version != nullptr) {
219     memcpy(highest_common_version, max_common_version,
220            sizeof(grpc_gcp_rpc_protocol_versions_version));
221   }
222   return result;
223 }
224