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 <string.h>
20
21 #include <string>
22
23 #include <gtest/gtest.h>
24
25 #include "absl/types/optional.h"
26
27 #include <grpc/grpc.h>
28 #include <grpc/grpc_security.h>
29 #include <grpc/grpc_security_constants.h>
30 #include <grpc/impl/channel_arg_names.h>
31 #include <grpc/impl/propagation_bits.h>
32 #include <grpc/slice.h>
33 #include <grpc/status.h>
34 #include <grpc/support/log.h>
35 #include <grpc/support/time.h>
36
37 #include "src/core/lib/channel/channel_args.h"
38 #include "src/core/lib/config/config_vars.h"
39 #include "src/core/lib/gpr/useful.h"
40 #include "src/core/lib/gprpp/host_port.h"
41 #include "src/core/lib/iomgr/error.h"
42 #include "src/core/lib/iomgr/exec_ctx.h"
43 #include "test/core/end2end/cq_verifier.h"
44 #include "test/core/util/port.h"
45 #include "test/core/util/test_config.h"
46 #include "test/core/util/tls_utils.h"
47
48 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
49 #define CLIENT_CERT_PATH "src/core/tsi/test_creds/client.pem"
50 #define CLIENT_KEY_PATH "src/core/tsi/test_creds/client.key"
51 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
52 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
53
54 namespace grpc {
55 namespace testing {
56 namespace {
57
five_seconds_time()58 gpr_timespec five_seconds_time() { return grpc_timeout_seconds_to_deadline(5); }
59
server_create(grpc_completion_queue * cq,const char * server_addr)60 grpc_server* server_create(grpc_completion_queue* cq, const char* server_addr) {
61 std::string ca_cert = grpc_core::testing::GetFileContents(CA_CERT_PATH);
62 std::string server_cert =
63 grpc_core::testing::GetFileContents(SERVER_CERT_PATH);
64 std::string server_key = grpc_core::testing::GetFileContents(SERVER_KEY_PATH);
65 grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {server_key.c_str(),
66 server_cert.c_str()};
67 grpc_server_credentials* server_creds = grpc_ssl_server_credentials_create_ex(
68 ca_cert.c_str(), &pem_cert_key_pair, 1,
69 GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, nullptr);
70
71 grpc_server* server = grpc_server_create(nullptr, nullptr);
72 grpc_server_register_completion_queue(server, cq, nullptr);
73 GPR_ASSERT(grpc_server_add_http2_port(server, server_addr, server_creds));
74 grpc_server_credentials_release(server_creds);
75 grpc_server_start(server);
76 return server;
77 }
78
client_create(const char * server_addr,grpc_ssl_session_cache * cache)79 grpc_channel* client_create(const char* server_addr,
80 grpc_ssl_session_cache* cache) {
81 std::string ca_cert = grpc_core::testing::GetFileContents(CA_CERT_PATH);
82 std::string client_cert =
83 grpc_core::testing::GetFileContents(CLIENT_CERT_PATH);
84 std::string client_key = grpc_core::testing::GetFileContents(CLIENT_KEY_PATH);
85 grpc_ssl_pem_key_cert_pair signed_client_key_cert_pair = {
86 client_key.c_str(), client_cert.c_str()};
87 grpc_channel_credentials* client_creds = grpc_ssl_credentials_create(
88 ca_cert.c_str(), &signed_client_key_cert_pair, nullptr, nullptr);
89
90 grpc_arg args[] = {
91 grpc_channel_arg_string_create(
92 const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
93 const_cast<char*>("waterzooi.test.google.be")),
94 grpc_ssl_session_cache_create_channel_arg(cache),
95 };
96
97 grpc_channel_args* client_args =
98 grpc_channel_args_copy_and_add(nullptr, args, GPR_ARRAY_SIZE(args));
99
100 grpc_channel* client =
101 grpc_channel_create(server_addr, client_creds, client_args);
102 GPR_ASSERT(client != nullptr);
103 grpc_channel_credentials_release(client_creds);
104
105 {
106 grpc_core::ExecCtx exec_ctx;
107 grpc_channel_args_destroy(client_args);
108 }
109
110 return client;
111 }
112
do_round_trip(grpc_completion_queue * cq,grpc_server * server,const char * server_addr,grpc_ssl_session_cache * cache,bool expect_session_reuse)113 void do_round_trip(grpc_completion_queue* cq, grpc_server* server,
114 const char* server_addr, grpc_ssl_session_cache* cache,
115 bool expect_session_reuse) {
116 grpc_channel* client = client_create(server_addr, cache);
117
118 grpc_core::CqVerifier cqv(cq);
119 grpc_op ops[6];
120 grpc_op* op;
121 grpc_metadata_array initial_metadata_recv;
122 grpc_metadata_array trailing_metadata_recv;
123 grpc_metadata_array request_metadata_recv;
124 grpc_call_details call_details;
125 grpc_status_code status;
126 grpc_call_error error;
127 grpc_slice details;
128 int was_cancelled = 2;
129
130 gpr_timespec deadline = grpc_timeout_seconds_to_deadline(60);
131 grpc_call* c = grpc_channel_create_call(
132 client, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
133 grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr);
134 GPR_ASSERT(c);
135
136 grpc_metadata_array_init(&initial_metadata_recv);
137 grpc_metadata_array_init(&trailing_metadata_recv);
138 grpc_metadata_array_init(&request_metadata_recv);
139 grpc_call_details_init(&call_details);
140
141 memset(ops, 0, sizeof(ops));
142 op = ops;
143 op->op = GRPC_OP_SEND_INITIAL_METADATA;
144 op->data.send_initial_metadata.count = 0;
145 op->flags = 0;
146 op->reserved = nullptr;
147 op++;
148 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
149 op->flags = 0;
150 op->reserved = nullptr;
151 op++;
152 op->op = GRPC_OP_RECV_INITIAL_METADATA;
153 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
154 op->flags = 0;
155 op->reserved = nullptr;
156 op++;
157 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
158 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
159 op->data.recv_status_on_client.status = &status;
160 op->data.recv_status_on_client.status_details = &details;
161 op->flags = 0;
162 op->reserved = nullptr;
163 op++;
164 error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops),
165 grpc_core::CqVerifier::tag(1), nullptr);
166 GPR_ASSERT(GRPC_CALL_OK == error);
167
168 grpc_call* s;
169 error = grpc_server_request_call(server, &s, &call_details,
170 &request_metadata_recv, cq, cq,
171 grpc_core::CqVerifier::tag(101));
172 GPR_ASSERT(GRPC_CALL_OK == error);
173 cqv.Expect(grpc_core::CqVerifier::tag(101), true);
174 cqv.Verify();
175
176 grpc_auth_context* auth = grpc_call_auth_context(s);
177 grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
178 auth, GRPC_SSL_SESSION_REUSED_PROPERTY);
179 const grpc_auth_property* property = grpc_auth_property_iterator_next(&it);
180 GPR_ASSERT(property != nullptr);
181 if (expect_session_reuse) {
182 GPR_ASSERT(strcmp(property->value, "true") == 0);
183 } else {
184 GPR_ASSERT(strcmp(property->value, "false") == 0);
185 }
186 grpc_auth_context_release(auth);
187
188 memset(ops, 0, sizeof(ops));
189 op = ops;
190 op->op = GRPC_OP_SEND_INITIAL_METADATA;
191 op->data.send_initial_metadata.count = 0;
192 op->flags = 0;
193 op->reserved = nullptr;
194 op++;
195 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
196 op->data.recv_close_on_server.cancelled = &was_cancelled;
197 op->flags = 0;
198 op->reserved = nullptr;
199 op++;
200 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
201 op->data.send_status_from_server.trailing_metadata_count = 0;
202 op->data.send_status_from_server.status = GRPC_STATUS_OK;
203 op->flags = 0;
204 op->reserved = nullptr;
205 op++;
206 error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops),
207 grpc_core::CqVerifier::tag(103), nullptr);
208 GPR_ASSERT(GRPC_CALL_OK == error);
209
210 cqv.Expect(grpc_core::CqVerifier::tag(103), true);
211 cqv.Expect(grpc_core::CqVerifier::tag(1), true);
212 cqv.Verify();
213
214 grpc_metadata_array_destroy(&initial_metadata_recv);
215 grpc_metadata_array_destroy(&trailing_metadata_recv);
216 grpc_metadata_array_destroy(&request_metadata_recv);
217 grpc_call_details_destroy(&call_details);
218
219 grpc_call_unref(c);
220 grpc_call_unref(s);
221
222 grpc_channel_destroy(client);
223 }
224
drain_cq(grpc_completion_queue * cq)225 void drain_cq(grpc_completion_queue* cq) {
226 grpc_event ev;
227 do {
228 ev = grpc_completion_queue_next(cq, five_seconds_time(), nullptr);
229 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
230 }
231
TEST(H2SessionReuseTest,SingleReuse)232 TEST(H2SessionReuseTest, SingleReuse) {
233 int port = grpc_pick_unused_port_or_die();
234
235 std::string server_addr = grpc_core::JoinHostPort("localhost", port);
236
237 grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
238 grpc_ssl_session_cache* cache = grpc_ssl_session_cache_create_lru(16);
239
240 grpc_server* server = server_create(cq, server_addr.c_str());
241
242 do_round_trip(cq, server, server_addr.c_str(), cache, false);
243 do_round_trip(cq, server, server_addr.c_str(), cache, true);
244 do_round_trip(cq, server, server_addr.c_str(), cache, true);
245
246 grpc_ssl_session_cache_destroy(cache);
247
248 GPR_ASSERT(grpc_completion_queue_next(
249 cq, grpc_timeout_milliseconds_to_deadline(100), nullptr)
250 .type == GRPC_QUEUE_TIMEOUT);
251
252 grpc_server_shutdown_and_notify(server, cq, grpc_core::CqVerifier::tag(1000));
253 grpc_event ev;
254 do {
255 ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
256 nullptr);
257 } while (ev.type != GRPC_OP_COMPLETE ||
258 ev.tag != grpc_core::CqVerifier::tag(1000));
259 grpc_server_destroy(server);
260
261 grpc_completion_queue_shutdown(cq);
262 drain_cq(cq);
263 grpc_completion_queue_destroy(cq);
264 }
265
266 } // namespace
267 } // namespace testing
268 } // namespace grpc
269
main(int argc,char ** argv)270 int main(int argc, char** argv) {
271 grpc::testing::TestEnvironment env(&argc, argv);
272 grpc_core::ConfigVars::Overrides overrides;
273 overrides.default_ssl_roots_file_path = CA_CERT_PATH;
274 grpc_core::ConfigVars::SetOverrides(overrides);
275
276 grpc_init();
277 ::testing::InitGoogleTest(&argc, argv);
278 int ret = RUN_ALL_TESTS();
279 grpc_shutdown();
280
281 return ret;
282 }
283