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
grpc_gcp_rpc_protocol_versions_set_max(grpc_gcp_rpc_protocol_versions * versions,uint32_t max_major,uint32_t max_minor)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
grpc_gcp_rpc_protocol_versions_set_min(grpc_gcp_rpc_protocol_versions * versions,uint32_t min_major,uint32_t min_minor)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
grpc_gcp_rpc_protocol_versions_encode_length(const grpc_gcp_rpc_protocol_versions * versions)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
grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes(const grpc_gcp_rpc_protocol_versions * versions,uint8_t * bytes,size_t bytes_length)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
grpc_gcp_rpc_protocol_versions_encode(const grpc_gcp_rpc_protocol_versions * versions,grpc_slice * slice)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
grpc_gcp_rpc_protocol_versions_decode(grpc_slice slice,grpc_gcp_rpc_protocol_versions * versions)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
grpc_gcp_rpc_protocol_versions_copy(const grpc_gcp_rpc_protocol_versions * src,grpc_gcp_rpc_protocol_versions * dst)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
grpc_gcp_rpc_protocol_version_compare(const grpc_gcp_rpc_protocol_versions_version * v1,const grpc_gcp_rpc_protocol_versions_version * v2)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
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)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