1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5
6 #include <aws/io/channel.h>
7 #include <aws/io/event_loop.h>
8 #include <aws/io/tls_channel_handler.h>
9 #include <aws/testing/aws_test_harness.h>
10
11 #include <aws/common/clock.h>
12 #include <aws/common/condition_variable.h>
13
14 struct alpn_channel_setup_test_args {
15 struct aws_condition_variable condition_variable;
16 struct aws_mutex mutex;
17 int error_code;
18 bool shutdown_finished;
19 bool setup_completed;
20 };
21
s_alpn_channel_setup_test_on_setup_completed(struct aws_channel * channel,int error_code,void * ctx)22 static void s_alpn_channel_setup_test_on_setup_completed(struct aws_channel *channel, int error_code, void *ctx) {
23 (void)channel;
24
25 struct alpn_channel_setup_test_args *setup_test_args = (struct alpn_channel_setup_test_args *)ctx;
26 aws_mutex_lock(&setup_test_args->mutex);
27 setup_test_args->setup_completed = true;
28 setup_test_args->error_code |= error_code;
29 aws_mutex_unlock(&setup_test_args->mutex);
30 aws_condition_variable_notify_one(&setup_test_args->condition_variable);
31 }
32
s_alpn_test_setup_completed_predicate(void * arg)33 static bool s_alpn_test_setup_completed_predicate(void *arg) {
34 struct alpn_channel_setup_test_args *setup_test_args = (struct alpn_channel_setup_test_args *)arg;
35 return setup_test_args->setup_completed;
36 }
37
38 struct alpn_test_on_negotiation_args {
39 struct aws_allocator *allocator;
40 struct aws_channel_slot *new_slot;
41 struct aws_channel_handler *new_handler;
42 struct aws_byte_buf protocol;
43 };
44
s_alpn_test_shutdown(struct aws_channel_handler * handler,struct aws_channel_slot * slot,enum aws_channel_direction dir,int error_code,bool abort_immediately)45 static int s_alpn_test_shutdown(
46 struct aws_channel_handler *handler,
47 struct aws_channel_slot *slot,
48 enum aws_channel_direction dir,
49 int error_code,
50 bool abort_immediately) {
51 (void)handler;
52
53 return aws_channel_slot_on_handler_shutdown_complete(slot, dir, error_code, abort_immediately);
54 }
55
s_alpn_test_message_overhead(struct aws_channel_handler * handler)56 static size_t s_alpn_test_message_overhead(struct aws_channel_handler *handler) {
57 (void)handler;
58
59 return 0;
60 }
61
s_alpn_test_initial_window_size(struct aws_channel_handler * handler)62 static size_t s_alpn_test_initial_window_size(struct aws_channel_handler *handler) {
63 (void)handler;
64
65 return SIZE_MAX;
66 }
67
s_alpn_test_destroy(struct aws_channel_handler * handler)68 static void s_alpn_test_destroy(struct aws_channel_handler *handler) {
69 aws_mem_release(handler->alloc, (void *)handler);
70 }
71
72 struct aws_channel_handler_vtable s_alpn_test_vtable = {
73 .destroy = s_alpn_test_destroy,
74 .shutdown = s_alpn_test_shutdown,
75 .initial_window_size = s_alpn_test_initial_window_size,
76 .message_overhead = s_alpn_test_message_overhead,
77 };
78
s_alpn_tls_successful_negotiation(struct aws_channel_slot * new_slot,struct aws_byte_buf * protocol,void * ctx)79 static struct aws_channel_handler *s_alpn_tls_successful_negotiation(
80 struct aws_channel_slot *new_slot,
81 struct aws_byte_buf *protocol,
82 void *ctx) {
83 struct alpn_test_on_negotiation_args *negotiation_args = (struct alpn_test_on_negotiation_args *)ctx;
84
85 struct aws_channel_handler *handler =
86 aws_mem_calloc(negotiation_args->allocator, 1, sizeof(struct aws_channel_handler));
87
88 negotiation_args->new_handler = handler;
89 negotiation_args->protocol = *protocol;
90 negotiation_args->new_slot = new_slot;
91
92 handler->vtable = &s_alpn_test_vtable;
93 handler->alloc = negotiation_args->allocator;
94
95 return handler;
96 }
97
s_alpn_test_shutdown_predicate(void * arg)98 static bool s_alpn_test_shutdown_predicate(void *arg) {
99 struct alpn_channel_setup_test_args *test_args = (struct alpn_channel_setup_test_args *)arg;
100 return test_args->shutdown_finished;
101 }
102
s_on_server_channel_on_shutdown(struct aws_channel * channel,int error_code,void * user_data)103 static void s_on_server_channel_on_shutdown(struct aws_channel *channel, int error_code, void *user_data) {
104
105 (void)channel;
106 (void)error_code;
107
108 struct alpn_channel_setup_test_args *test_args = (struct alpn_channel_setup_test_args *)user_data;
109
110 aws_mutex_lock(&test_args->mutex);
111 test_args->shutdown_finished = true;
112 aws_mutex_unlock(&test_args->mutex);
113
114 aws_condition_variable_notify_one(&test_args->condition_variable);
115 }
116
s_test_alpn_successfully_negotiates(struct aws_allocator * allocator,void * ctx)117 static int s_test_alpn_successfully_negotiates(struct aws_allocator *allocator, void *ctx) {
118
119 (void)ctx;
120
121 struct aws_event_loop *event_loop = aws_event_loop_new_default(allocator, aws_high_res_clock_get_ticks);
122
123 ASSERT_NOT_NULL(event_loop, "Event loop creation failed with error: %s", aws_error_debug_str(aws_last_error()));
124 ASSERT_SUCCESS(aws_event_loop_run(event_loop));
125 struct aws_channel *channel;
126
127 struct alpn_channel_setup_test_args test_args = {.error_code = 0,
128 .condition_variable = AWS_CONDITION_VARIABLE_INIT,
129 .mutex = AWS_MUTEX_INIT,
130 .setup_completed = false,
131 .shutdown_finished = false};
132
133 struct aws_channel_options args = {
134 .on_setup_completed = s_alpn_channel_setup_test_on_setup_completed,
135 .setup_user_data = &test_args,
136 .on_shutdown_completed = s_on_server_channel_on_shutdown,
137 .shutdown_user_data = &test_args,
138 .event_loop = event_loop,
139 };
140
141 channel = aws_channel_new(allocator, &args);
142 ASSERT_NOT_NULL(channel);
143 ASSERT_SUCCESS(aws_mutex_lock(&test_args.mutex));
144 ASSERT_SUCCESS(aws_condition_variable_wait_pred(
145 &test_args.condition_variable, &test_args.mutex, s_alpn_test_setup_completed_predicate, &test_args));
146 ASSERT_SUCCESS(aws_mutex_unlock(&test_args.mutex));
147
148 struct aws_channel_slot *slot = aws_channel_slot_new(channel);
149 ASSERT_NOT_NULL(slot);
150
151 struct alpn_test_on_negotiation_args on_negotiation_args = {
152 .new_slot = NULL, .protocol = {0}, .new_handler = NULL, .allocator = allocator};
153
154 struct aws_channel_handler *handler =
155 aws_tls_alpn_handler_new(allocator, s_alpn_tls_successful_negotiation, &on_negotiation_args);
156 ASSERT_NOT_NULL(handler);
157 ASSERT_SUCCESS(aws_channel_slot_set_handler(slot, handler));
158
159 struct aws_tls_negotiated_protocol_message protocol_message = {.protocol = aws_byte_buf_from_c_str("h2")};
160
161 struct aws_io_message message = {
162 .allocator = NULL,
163 .user_data = NULL,
164 .message_tag = AWS_TLS_NEGOTIATED_PROTOCOL_MESSAGE,
165 .message_data = aws_byte_buf_from_array(
166 (const uint8_t *)&protocol_message, sizeof(struct aws_tls_negotiated_protocol_message)),
167 .copy_mark = 0,
168 .on_completion = NULL,
169 .message_type = AWS_IO_MESSAGE_APPLICATION_DATA};
170
171 ASSERT_SUCCESS(aws_channel_handler_process_read_message(handler, slot, &message));
172 ASSERT_BIN_ARRAYS_EQUALS(
173 protocol_message.protocol.buffer,
174 protocol_message.protocol.len,
175 on_negotiation_args.protocol.buffer,
176 on_negotiation_args.protocol.len);
177
178 aws_channel_shutdown(channel, AWS_OP_SUCCESS);
179 ASSERT_SUCCESS(aws_mutex_lock(&test_args.mutex));
180 ASSERT_SUCCESS(aws_condition_variable_wait_pred(
181 &test_args.condition_variable, &test_args.mutex, s_alpn_test_shutdown_predicate, &test_args));
182 ASSERT_SUCCESS(aws_mutex_unlock(&test_args.mutex));
183
184 aws_channel_destroy(channel);
185 aws_event_loop_destroy(event_loop);
186
187 return AWS_OP_SUCCESS;
188 }
189
AWS_TEST_CASE(alpn_successfully_negotiates,s_test_alpn_successfully_negotiates)190 AWS_TEST_CASE(alpn_successfully_negotiates, s_test_alpn_successfully_negotiates)
191
192 static int s_test_alpn_no_protocol_message(struct aws_allocator *allocator, void *ctx) {
193
194 (void)ctx;
195
196 struct aws_event_loop *event_loop = aws_event_loop_new_default(allocator, aws_high_res_clock_get_ticks);
197
198 ASSERT_NOT_NULL(event_loop, "Event loop creation failed with error: %s", aws_error_debug_str(aws_last_error()));
199 ASSERT_SUCCESS(aws_event_loop_run(event_loop));
200 struct aws_channel *channel;
201
202 struct alpn_channel_setup_test_args test_args = {.error_code = 0,
203 .condition_variable = AWS_CONDITION_VARIABLE_INIT,
204 .mutex = AWS_MUTEX_INIT,
205 .shutdown_finished = false};
206
207 struct aws_channel_options args = {
208 .on_setup_completed = s_alpn_channel_setup_test_on_setup_completed,
209 .setup_user_data = &test_args,
210 .on_shutdown_completed = s_on_server_channel_on_shutdown,
211 .shutdown_user_data = &test_args,
212 .event_loop = event_loop,
213 };
214
215 channel = aws_channel_new(allocator, &args);
216 ASSERT_NOT_NULL(channel);
217 ASSERT_SUCCESS(aws_mutex_lock(&test_args.mutex));
218 ASSERT_SUCCESS(aws_condition_variable_wait_pred(
219 &test_args.condition_variable, &test_args.mutex, s_alpn_test_setup_completed_predicate, &test_args));
220 ASSERT_SUCCESS(aws_mutex_unlock(&test_args.mutex));
221
222 struct aws_channel_slot *slot = aws_channel_slot_new(channel);
223 ASSERT_NOT_NULL(slot);
224
225 struct alpn_test_on_negotiation_args on_negotiation_args = {
226 .new_slot = NULL, .protocol = {0}, .new_handler = NULL, .allocator = allocator};
227
228 struct aws_channel_handler *handler =
229 aws_tls_alpn_handler_new(allocator, s_alpn_tls_successful_negotiation, &on_negotiation_args);
230 ASSERT_NOT_NULL(handler);
231 ASSERT_SUCCESS(aws_channel_slot_set_handler(slot, handler));
232
233 /*this is just for the test since it's the only slot in the channel */
234 handler->vtable->shutdown = s_alpn_test_shutdown;
235
236 struct aws_io_message message = {
237 .allocator = NULL,
238 .user_data = NULL,
239 .message_tag = 0,
240 .copy_mark = 0,
241 .on_completion = NULL,
242 .message_type = AWS_IO_MESSAGE_APPLICATION_DATA,
243 };
244
245 ASSERT_ERROR(AWS_IO_MISSING_ALPN_MESSAGE, aws_channel_handler_process_read_message(handler, slot, &message));
246
247 aws_channel_shutdown(channel, AWS_OP_SUCCESS);
248 ASSERT_SUCCESS(aws_mutex_lock(&test_args.mutex));
249 ASSERT_SUCCESS(aws_condition_variable_wait_pred(
250 &test_args.condition_variable, &test_args.mutex, s_alpn_test_shutdown_predicate, &test_args));
251 ASSERT_SUCCESS(aws_mutex_unlock(&test_args.mutex));
252 aws_channel_destroy(channel);
253 aws_event_loop_destroy(event_loop);
254
255 return AWS_OP_SUCCESS;
256 }
257
AWS_TEST_CASE(alpn_no_protocol_message,s_test_alpn_no_protocol_message)258 AWS_TEST_CASE(alpn_no_protocol_message, s_test_alpn_no_protocol_message)
259
260 static struct aws_channel_handler *s_alpn_tls_failed_negotiation(
261 struct aws_channel_slot *new_slot,
262 struct aws_byte_buf *protocol,
263 void *ctx) {
264
265 (void)new_slot;
266 (void)protocol;
267 (void)ctx;
268
269 return NULL;
270 }
271
s_test_alpn_error_creating_handler(struct aws_allocator * allocator,void * ctx)272 static int s_test_alpn_error_creating_handler(struct aws_allocator *allocator, void *ctx) {
273
274 (void)ctx;
275
276 struct aws_event_loop *event_loop = aws_event_loop_new_default(allocator, aws_high_res_clock_get_ticks);
277
278 ASSERT_NOT_NULL(event_loop, "Event loop creation failed with error: %s", aws_error_debug_str(aws_last_error()));
279 ASSERT_SUCCESS(aws_event_loop_run(event_loop));
280 struct aws_channel *channel;
281
282 struct alpn_channel_setup_test_args test_args = {.error_code = 0,
283 .condition_variable = AWS_CONDITION_VARIABLE_INIT,
284 .mutex = AWS_MUTEX_INIT,
285 .shutdown_finished = false};
286
287 struct aws_channel_options args = {
288 .on_setup_completed = s_alpn_channel_setup_test_on_setup_completed,
289 .setup_user_data = &test_args,
290 .on_shutdown_completed = s_on_server_channel_on_shutdown,
291 .shutdown_user_data = &test_args,
292 .event_loop = event_loop,
293 };
294
295 channel = aws_channel_new(allocator, &args);
296 ASSERT_NOT_NULL(channel);
297 ASSERT_SUCCESS(aws_mutex_lock(&test_args.mutex));
298 ASSERT_SUCCESS(aws_condition_variable_wait_pred(
299 &test_args.condition_variable, &test_args.mutex, s_alpn_test_setup_completed_predicate, &test_args));
300 ASSERT_SUCCESS(aws_mutex_unlock(&test_args.mutex));
301
302 struct aws_channel_slot *slot = aws_channel_slot_new(channel);
303 ASSERT_NOT_NULL(slot);
304
305 struct aws_tls_negotiated_protocol_message protocol_message = {.protocol = aws_byte_buf_from_c_str("h2")};
306
307 struct aws_io_message message = {
308 .allocator = NULL,
309 .user_data = NULL,
310 .message_tag = AWS_TLS_NEGOTIATED_PROTOCOL_MESSAGE,
311 .message_data = aws_byte_buf_from_array(
312 (const uint8_t *)&protocol_message, sizeof(struct aws_tls_negotiated_protocol_message)),
313 .copy_mark = 0,
314 .on_completion = NULL,
315 .message_type = AWS_IO_MESSAGE_APPLICATION_DATA};
316
317 struct alpn_test_on_negotiation_args on_negotiation_args = {
318 .new_slot = NULL, .protocol = {0}, .new_handler = NULL, .allocator = allocator};
319
320 struct aws_channel_handler *handler =
321 aws_tls_alpn_handler_new(allocator, s_alpn_tls_failed_negotiation, &on_negotiation_args);
322 ASSERT_NOT_NULL(handler);
323 ASSERT_SUCCESS(aws_channel_slot_set_handler(slot, handler));
324
325 /*this is just for the test since it's the only slot in the channel */
326 handler->vtable->shutdown = s_alpn_test_shutdown;
327
328 ASSERT_ERROR(
329 AWS_IO_UNHANDLED_ALPN_PROTOCOL_MESSAGE, aws_channel_handler_process_read_message(handler, slot, &message));
330
331 aws_channel_shutdown(channel, AWS_OP_SUCCESS);
332 ASSERT_SUCCESS(aws_mutex_lock(&test_args.mutex));
333 ASSERT_SUCCESS(aws_condition_variable_wait_pred(
334 &test_args.condition_variable, &test_args.mutex, s_alpn_test_shutdown_predicate, &test_args));
335 ASSERT_SUCCESS(aws_mutex_unlock(&test_args.mutex));
336 aws_channel_destroy(channel);
337 aws_event_loop_destroy(event_loop);
338
339 return AWS_OP_SUCCESS;
340 }
341
342 AWS_TEST_CASE(alpn_error_creating_handler, s_test_alpn_error_creating_handler)
343