1 /*
2  *
3  * Copyright 2017 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 "test/core/end2end/end2end_tests.h"
20 
21 #include <limits.h>
22 #include <string.h>
23 
24 #include <grpc/support/log.h>
25 #include <grpc/support/sync.h>
26 #include <grpc/support/time.h>
27 
28 #include "src/core/lib/gpr/useful.h"
29 #include "test/core/end2end/cq_verifier.h"
30 
31 #define MAX_CONNECTION_AGE_MS 500
32 #define MAX_CONNECTION_AGE_GRACE_MS 1000
33 #define MAX_CONNECTION_IDLE_MS 9999
34 
35 #define MAX_CONNECTION_AGE_JITTER_MULTIPLIER 1.1
36 #define CALL_DEADLINE_S 10
37 /* The amount of time we wait for the connection to time out, but after it the
38    connection should not use up its grace period. It should be a number between
39    MAX_CONNECTION_AGE_MS and MAX_CONNECTION_AGE_MS +
40    MAX_CONNECTION_AGE_GRACE_MS */
41 #define CQ_MAX_CONNECTION_AGE_WAIT_TIME_S 1
42 /* The amount of time we wait after the connection reaches its max age, it
43    should be shorter than CALL_DEADLINE_S - CQ_MAX_CONNECTION_AGE_WAIT_TIME_S */
44 #define CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S 2
45 /* The grace period for the test to observe the channel shutdown process */
46 #define IMMEDIATE_SHUTDOWN_GRACE_TIME_MS 3000
47 
tag(intptr_t t)48 static void* tag(intptr_t t) { return (void*)t; }
49 
drain_cq(grpc_completion_queue * cq)50 static void drain_cq(grpc_completion_queue* cq) {
51   grpc_event ev;
52   do {
53     ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
54                                     nullptr);
55   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
56 }
57 
shutdown_server(grpc_end2end_test_fixture * f)58 static void shutdown_server(grpc_end2end_test_fixture* f) {
59   if (!f->server) return;
60   grpc_server_destroy(f->server);
61   f->server = nullptr;
62 }
63 
shutdown_client(grpc_end2end_test_fixture * f)64 static void shutdown_client(grpc_end2end_test_fixture* f) {
65   if (!f->client) return;
66   grpc_channel_destroy(f->client);
67   f->client = nullptr;
68 }
69 
end_test(grpc_end2end_test_fixture * f)70 static void end_test(grpc_end2end_test_fixture* f) {
71   shutdown_server(f);
72   shutdown_client(f);
73 
74   grpc_completion_queue_shutdown(f->cq);
75   drain_cq(f->cq);
76   grpc_completion_queue_destroy(f->cq);
77   grpc_completion_queue_destroy(f->shutdown_cq);
78 }
79 
test_max_age_forcibly_close(grpc_end2end_test_config config)80 static void test_max_age_forcibly_close(grpc_end2end_test_config config) {
81   grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr);
82   cq_verifier* cqv = cq_verifier_create(f.cq);
83   grpc_arg server_a[3];
84   server_a[0].type = GRPC_ARG_INTEGER;
85   server_a[0].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_MS);
86   server_a[0].value.integer = MAX_CONNECTION_AGE_MS;
87   server_a[1].type = GRPC_ARG_INTEGER;
88   server_a[1].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS);
89   server_a[1].value.integer = MAX_CONNECTION_AGE_GRACE_MS;
90   server_a[2].type = GRPC_ARG_INTEGER;
91   server_a[2].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_IDLE_MS);
92   server_a[2].value.integer = MAX_CONNECTION_IDLE_MS;
93   grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
94 
95   config.init_client(&f, nullptr);
96   config.init_server(&f, &server_args);
97 
98   grpc_call* c;
99   grpc_call* s;
100   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S);
101   grpc_op ops[6];
102   grpc_op* op;
103   grpc_metadata_array initial_metadata_recv;
104   grpc_metadata_array trailing_metadata_recv;
105   grpc_metadata_array request_metadata_recv;
106   grpc_call_details call_details;
107   grpc_status_code status;
108   grpc_call_error error;
109   grpc_slice details;
110   int was_cancelled = 2;
111 
112   c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
113                                grpc_slice_from_static_string("/foo"), nullptr,
114                                deadline, nullptr);
115   GPR_ASSERT(c);
116 
117   grpc_metadata_array_init(&initial_metadata_recv);
118   grpc_metadata_array_init(&trailing_metadata_recv);
119   grpc_metadata_array_init(&request_metadata_recv);
120   grpc_call_details_init(&call_details);
121 
122   memset(ops, 0, sizeof(ops));
123   op = ops;
124   op->op = GRPC_OP_SEND_INITIAL_METADATA;
125   op->data.send_initial_metadata.count = 0;
126   op->data.send_initial_metadata.metadata = nullptr;
127   op->flags = 0;
128   op->reserved = nullptr;
129   op++;
130   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
131   op->flags = 0;
132   op->reserved = nullptr;
133   op++;
134   op->op = GRPC_OP_RECV_INITIAL_METADATA;
135   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
136   op->flags = 0;
137   op->reserved = nullptr;
138   op++;
139   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
140   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
141   op->data.recv_status_on_client.status = &status;
142   op->data.recv_status_on_client.status_details = &details;
143   op->flags = 0;
144   op->reserved = nullptr;
145   op++;
146   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
147                                 nullptr);
148   GPR_ASSERT(GRPC_CALL_OK == error);
149 
150   error =
151       grpc_server_request_call(f.server, &s, &call_details,
152                                &request_metadata_recv, f.cq, f.cq, tag(101));
153   GPR_ASSERT(GRPC_CALL_OK == error);
154   CQ_EXPECT_COMPLETION(cqv, tag(101), true);
155   cq_verify(cqv);
156 
157   gpr_timespec expect_shutdown_time = grpc_timeout_milliseconds_to_deadline(
158       static_cast<int>(MAX_CONNECTION_AGE_MS *
159                        MAX_CONNECTION_AGE_JITTER_MULTIPLIER) +
160       MAX_CONNECTION_AGE_GRACE_MS + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS);
161 
162   /* Wait for the channel to reach its max age */
163   cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S);
164 
165   /* After the channel reaches its max age, we still do nothing here. And wait
166      for it to use up its max age grace period. */
167   CQ_EXPECT_COMPLETION(cqv, tag(1), true);
168   cq_verify(cqv);
169 
170   gpr_timespec channel_shutdown_time = gpr_now(GPR_CLOCK_MONOTONIC);
171   GPR_ASSERT(gpr_time_cmp(channel_shutdown_time, expect_shutdown_time) < 0);
172 
173   memset(ops, 0, sizeof(ops));
174   op = ops;
175   op->op = GRPC_OP_SEND_INITIAL_METADATA;
176   op->data.send_initial_metadata.count = 0;
177   op->flags = 0;
178   op->reserved = nullptr;
179   op++;
180   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
181   op->data.send_status_from_server.trailing_metadata_count = 0;
182   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
183   grpc_slice status_details = grpc_slice_from_static_string("xyz");
184   op->data.send_status_from_server.status_details = &status_details;
185   op->flags = 0;
186   op->reserved = nullptr;
187   op++;
188   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
189   op->data.recv_close_on_server.cancelled = &was_cancelled;
190   op->flags = 0;
191   op->reserved = nullptr;
192   op++;
193   error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
194                                 nullptr);
195   GPR_ASSERT(GRPC_CALL_OK == error);
196   CQ_EXPECT_COMPLETION(cqv, tag(102), true);
197   cq_verify(cqv);
198 
199   grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
200   CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true);
201   cq_verify(cqv);
202 
203   grpc_call_unref(s);
204 
205   /* The connection should be closed immediately after the max age grace period,
206      the in-progress RPC should fail. */
207   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
208   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
209   GPR_ASSERT(was_cancelled == 1);
210 
211   grpc_slice_unref(details);
212   grpc_metadata_array_destroy(&initial_metadata_recv);
213   grpc_metadata_array_destroy(&trailing_metadata_recv);
214   grpc_metadata_array_destroy(&request_metadata_recv);
215   grpc_call_details_destroy(&call_details);
216   grpc_call_unref(c);
217   cq_verifier_destroy(cqv);
218   end_test(&f);
219   config.tear_down_data(&f);
220 }
221 
test_max_age_gracefully_close(grpc_end2end_test_config config)222 static void test_max_age_gracefully_close(grpc_end2end_test_config config) {
223   grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr);
224   cq_verifier* cqv = cq_verifier_create(f.cq);
225   grpc_arg server_a[3];
226   server_a[0].type = GRPC_ARG_INTEGER;
227   server_a[0].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_MS);
228   server_a[0].value.integer = MAX_CONNECTION_AGE_MS;
229   server_a[1].type = GRPC_ARG_INTEGER;
230   server_a[1].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS);
231   server_a[1].value.integer = INT_MAX;
232   server_a[2].type = GRPC_ARG_INTEGER;
233   server_a[2].key = const_cast<char*>(GRPC_ARG_MAX_CONNECTION_IDLE_MS);
234   server_a[2].value.integer = MAX_CONNECTION_IDLE_MS;
235   grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
236 
237   config.init_client(&f, nullptr);
238   config.init_server(&f, &server_args);
239 
240   grpc_call* c;
241   grpc_call* s;
242   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S);
243   grpc_op ops[6];
244   grpc_op* op;
245   grpc_metadata_array initial_metadata_recv;
246   grpc_metadata_array trailing_metadata_recv;
247   grpc_metadata_array request_metadata_recv;
248   grpc_call_details call_details;
249   grpc_status_code status;
250   grpc_call_error error;
251   grpc_slice details;
252   int was_cancelled = 2;
253 
254   c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
255                                grpc_slice_from_static_string("/foo"), nullptr,
256                                deadline, nullptr);
257   GPR_ASSERT(c);
258 
259   grpc_metadata_array_init(&initial_metadata_recv);
260   grpc_metadata_array_init(&trailing_metadata_recv);
261   grpc_metadata_array_init(&request_metadata_recv);
262   grpc_call_details_init(&call_details);
263 
264   memset(ops, 0, sizeof(ops));
265   op = ops;
266   op->op = GRPC_OP_SEND_INITIAL_METADATA;
267   op->data.send_initial_metadata.count = 0;
268   op->data.send_initial_metadata.metadata = nullptr;
269   op->flags = 0;
270   op->reserved = nullptr;
271   op++;
272   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
273   op->flags = 0;
274   op->reserved = nullptr;
275   op++;
276   op->op = GRPC_OP_RECV_INITIAL_METADATA;
277   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
278   op->flags = 0;
279   op->reserved = nullptr;
280   op++;
281   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
282   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
283   op->data.recv_status_on_client.status = &status;
284   op->data.recv_status_on_client.status_details = &details;
285   op->flags = 0;
286   op->reserved = nullptr;
287   op++;
288   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
289                                 nullptr);
290   GPR_ASSERT(GRPC_CALL_OK == error);
291 
292   error =
293       grpc_server_request_call(f.server, &s, &call_details,
294                                &request_metadata_recv, f.cq, f.cq, tag(101));
295   GPR_ASSERT(GRPC_CALL_OK == error);
296   CQ_EXPECT_COMPLETION(cqv, tag(101), true);
297   cq_verify(cqv);
298 
299   /* Wait for the channel to reach its max age */
300   cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_WAIT_TIME_S);
301 
302   /* The connection is shutting down gracefully. In-progress rpc should not be
303      closed, hence the completion queue should see nothing here. */
304   cq_verify_empty_timeout(cqv, CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S);
305 
306   memset(ops, 0, sizeof(ops));
307   op = ops;
308   op->op = GRPC_OP_SEND_INITIAL_METADATA;
309   op->data.send_initial_metadata.count = 0;
310   op->flags = 0;
311   op->reserved = nullptr;
312   op++;
313   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
314   op->data.send_status_from_server.trailing_metadata_count = 0;
315   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
316   grpc_slice status_details = grpc_slice_from_static_string("xyz");
317   op->data.send_status_from_server.status_details = &status_details;
318   op->flags = 0;
319   op->reserved = nullptr;
320   op++;
321   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
322   op->data.recv_close_on_server.cancelled = &was_cancelled;
323   op->flags = 0;
324   op->reserved = nullptr;
325   op++;
326   error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
327                                 nullptr);
328   GPR_ASSERT(GRPC_CALL_OK == error);
329 
330   CQ_EXPECT_COMPLETION(cqv, tag(102), true);
331   CQ_EXPECT_COMPLETION(cqv, tag(1), true);
332   cq_verify(cqv);
333 
334   grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
335   CQ_EXPECT_COMPLETION(cqv, tag(0xdead), true);
336   cq_verify(cqv);
337 
338   grpc_call_unref(s);
339 
340   /* The connection is closed gracefully with goaway, the rpc should still be
341      completed. */
342   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
343   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
344   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
345   GPR_ASSERT(was_cancelled == 0);
346 
347   grpc_slice_unref(details);
348   grpc_metadata_array_destroy(&initial_metadata_recv);
349   grpc_metadata_array_destroy(&trailing_metadata_recv);
350   grpc_metadata_array_destroy(&request_metadata_recv);
351   grpc_call_details_destroy(&call_details);
352   grpc_call_unref(c);
353   cq_verifier_destroy(cqv);
354   end_test(&f);
355   config.tear_down_data(&f);
356 }
357 
max_connection_age(grpc_end2end_test_config config)358 void max_connection_age(grpc_end2end_test_config config) {
359   test_max_age_forcibly_close(config);
360   test_max_age_gracefully_close(config);
361 }
362 
max_connection_age_pre_init(void)363 void max_connection_age_pre_init(void) {}
364