1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5
6 #include <aws/common/array_list.h>
7 #include <aws/common/mutex.h>
8 #include <aws/common/string.h>
9 #include <aws/http/private/connection_impl.h>
10 #include <aws/http/private/request_response_impl.h>
11 #include <aws/http/private/strutil.h>
12 #include <aws/http/server.h>
13 #include <aws/http/status_code.h>
14 #include <aws/io/logging.h>
15 #include <aws/io/stream.h>
16
17 #if _MSC_VER
18 # pragma warning(disable : 4204) /* non-constant aggregate initializer */
19 #endif
20
21 enum {
22 /* Initial capacity for the aws_http_message.headers array_list. */
23 AWS_HTTP_REQUEST_NUM_RESERVED_HEADERS = 16,
24 };
25
aws_http_header_name_eq(struct aws_byte_cursor name_a,struct aws_byte_cursor name_b)26 bool aws_http_header_name_eq(struct aws_byte_cursor name_a, struct aws_byte_cursor name_b) {
27 return aws_byte_cursor_eq_ignore_case(&name_a, &name_b);
28 }
29
30 /**
31 * -- Datastructure Notes --
32 * Headers are stored in a linear array, rather than a hash-table of arrays.
33 * The linear array was simpler to implement and may be faster due to having fewer allocations.
34 * The API has been designed so we can swap out the implementation later if desired.
35 *
36 * -- String Storage Notes --
37 * We use a single allocation to hold the name and value of each aws_http_header.
38 * We could optimize storage by using something like a string pool. If we do this, be sure to maintain
39 * the address of existing strings when adding new strings (a dynamic aws_byte_buf would not suffice).
40 */
41 struct aws_http_headers {
42 struct aws_allocator *alloc;
43 struct aws_array_list array_list; /* Contains aws_http_header */
44 struct aws_atomic_var refcount;
45 };
46
aws_http_headers_new(struct aws_allocator * allocator)47 struct aws_http_headers *aws_http_headers_new(struct aws_allocator *allocator) {
48 AWS_PRECONDITION(allocator);
49
50 struct aws_http_headers *headers = aws_mem_calloc(allocator, 1, sizeof(struct aws_http_headers));
51 if (!headers) {
52 goto alloc_failed;
53 }
54
55 headers->alloc = allocator;
56 aws_atomic_init_int(&headers->refcount, 1);
57
58 if (aws_array_list_init_dynamic(
59 &headers->array_list, allocator, AWS_HTTP_REQUEST_NUM_RESERVED_HEADERS, sizeof(struct aws_http_header))) {
60 goto array_list_failed;
61 }
62
63 return headers;
64
65 array_list_failed:
66 aws_mem_release(headers->alloc, headers);
67 alloc_failed:
68 return NULL;
69 }
70
aws_http_headers_release(struct aws_http_headers * headers)71 void aws_http_headers_release(struct aws_http_headers *headers) {
72 AWS_PRECONDITION(!headers || headers->alloc);
73 if (!headers) {
74 return;
75 }
76
77 size_t prev_refcount = aws_atomic_fetch_sub(&headers->refcount, 1);
78 if (prev_refcount == 1) {
79 aws_http_headers_clear(headers);
80 aws_array_list_clean_up(&headers->array_list);
81 aws_mem_release(headers->alloc, headers);
82 } else {
83 AWS_ASSERT(prev_refcount != 0);
84 }
85 }
86
aws_http_headers_acquire(struct aws_http_headers * headers)87 void aws_http_headers_acquire(struct aws_http_headers *headers) {
88 AWS_PRECONDITION(headers);
89 aws_atomic_fetch_add(&headers->refcount, 1);
90 }
91
aws_http_headers_add_header(struct aws_http_headers * headers,const struct aws_http_header * header)92 int aws_http_headers_add_header(struct aws_http_headers *headers, const struct aws_http_header *header) {
93 AWS_PRECONDITION(headers);
94 AWS_PRECONDITION(header);
95 AWS_PRECONDITION(aws_byte_cursor_is_valid(&header->name) && aws_byte_cursor_is_valid(&header->value));
96
97 if (header->name.len == 0) {
98 return aws_raise_error(AWS_ERROR_HTTP_INVALID_HEADER_NAME);
99 }
100
101 size_t total_len;
102 if (aws_add_size_checked(header->name.len, header->value.len, &total_len)) {
103 return AWS_OP_ERR;
104 }
105
106 struct aws_http_header header_copy = *header;
107 /* Store our own copy of the strings.
108 * We put the name and value into the same allocation. */
109 uint8_t *strmem = aws_mem_acquire(headers->alloc, total_len);
110 if (!strmem) {
111 return AWS_OP_ERR;
112 }
113
114 struct aws_byte_buf strbuf = aws_byte_buf_from_empty_array(strmem, total_len);
115 aws_byte_buf_append_and_update(&strbuf, &header_copy.name);
116 aws_byte_buf_append_and_update(&strbuf, &header_copy.value);
117
118 if (aws_array_list_push_back(&headers->array_list, &header_copy)) {
119 goto error;
120 }
121
122 return AWS_OP_SUCCESS;
123
124 error:
125 aws_mem_release(headers->alloc, strmem);
126 return AWS_OP_ERR;
127 }
128
aws_http_headers_add(struct aws_http_headers * headers,struct aws_byte_cursor name,struct aws_byte_cursor value)129 int aws_http_headers_add(struct aws_http_headers *headers, struct aws_byte_cursor name, struct aws_byte_cursor value) {
130 struct aws_http_header header = {.name = name, .value = value};
131 return aws_http_headers_add_header(headers, &header);
132 }
133
aws_http_headers_clear(struct aws_http_headers * headers)134 void aws_http_headers_clear(struct aws_http_headers *headers) {
135 AWS_PRECONDITION(headers);
136
137 struct aws_http_header *header = NULL;
138 const size_t count = aws_http_headers_count(headers);
139 for (size_t i = 0; i < count; ++i) {
140 aws_array_list_get_at_ptr(&headers->array_list, (void **)&header, i);
141 AWS_ASSUME(header);
142
143 /* Storage for name & value is in the same allocation */
144 aws_mem_release(headers->alloc, header->name.ptr);
145 }
146
147 aws_array_list_clear(&headers->array_list);
148 }
149
150 /* Does not check index */
s_http_headers_erase_index(struct aws_http_headers * headers,size_t index)151 static void s_http_headers_erase_index(struct aws_http_headers *headers, size_t index) {
152 struct aws_http_header *header = NULL;
153 aws_array_list_get_at_ptr(&headers->array_list, (void **)&header, index);
154 AWS_ASSUME(header);
155
156 /* Storage for name & value is in the same allocation */
157 aws_mem_release(headers->alloc, header->name.ptr);
158
159 aws_array_list_erase(&headers->array_list, index);
160 }
161
aws_http_headers_erase_index(struct aws_http_headers * headers,size_t index)162 int aws_http_headers_erase_index(struct aws_http_headers *headers, size_t index) {
163 AWS_PRECONDITION(headers);
164
165 if (index >= aws_http_headers_count(headers)) {
166 return aws_raise_error(AWS_ERROR_INVALID_INDEX);
167 }
168
169 s_http_headers_erase_index(headers, index);
170 return AWS_OP_SUCCESS;
171 }
172
173 /* Erase entries with name, stop at end_index */
s_http_headers_erase(struct aws_http_headers * headers,struct aws_byte_cursor name,size_t end_index)174 static int s_http_headers_erase(struct aws_http_headers *headers, struct aws_byte_cursor name, size_t end_index) {
175 bool erased_any = false;
176 struct aws_http_header *header = NULL;
177
178 /* Iterating in reverse is simpler */
179 for (size_t n = end_index; n > 0; --n) {
180 const size_t i = n - 1;
181
182 aws_array_list_get_at_ptr(&headers->array_list, (void **)&header, i);
183 AWS_ASSUME(header);
184
185 if (aws_http_header_name_eq(header->name, name)) {
186 s_http_headers_erase_index(headers, i);
187 erased_any = true;
188 }
189 }
190
191 if (!erased_any) {
192 return aws_raise_error(AWS_ERROR_HTTP_HEADER_NOT_FOUND);
193 }
194
195 return AWS_OP_SUCCESS;
196 }
197
aws_http_headers_erase(struct aws_http_headers * headers,struct aws_byte_cursor name)198 int aws_http_headers_erase(struct aws_http_headers *headers, struct aws_byte_cursor name) {
199 AWS_PRECONDITION(headers);
200 AWS_PRECONDITION(aws_byte_cursor_is_valid(&name));
201
202 return s_http_headers_erase(headers, name, aws_http_headers_count(headers));
203 }
204
aws_http_headers_erase_value(struct aws_http_headers * headers,struct aws_byte_cursor name,struct aws_byte_cursor value)205 int aws_http_headers_erase_value(
206 struct aws_http_headers *headers,
207 struct aws_byte_cursor name,
208 struct aws_byte_cursor value) {
209
210 AWS_PRECONDITION(headers);
211 AWS_PRECONDITION(aws_byte_cursor_is_valid(&name) && aws_byte_cursor_is_valid(&value));
212
213 struct aws_http_header *header = NULL;
214 const size_t count = aws_http_headers_count(headers);
215 for (size_t i = 0; i < count; ++i) {
216 aws_array_list_get_at_ptr(&headers->array_list, (void **)&header, i);
217 AWS_ASSUME(header);
218
219 if (aws_http_header_name_eq(header->name, name) && aws_byte_cursor_eq(&header->value, &value)) {
220 s_http_headers_erase_index(headers, i);
221 return AWS_OP_SUCCESS;
222 }
223 }
224
225 return aws_raise_error(AWS_ERROR_HTTP_HEADER_NOT_FOUND);
226 }
227
aws_http_headers_add_array(struct aws_http_headers * headers,const struct aws_http_header * array,size_t count)228 int aws_http_headers_add_array(struct aws_http_headers *headers, const struct aws_http_header *array, size_t count) {
229 AWS_PRECONDITION(headers);
230 AWS_PRECONDITION(AWS_MEM_IS_READABLE(array, count));
231
232 const size_t orig_count = aws_http_headers_count(headers);
233
234 for (size_t i = 0; i < count; ++i) {
235 if (aws_http_headers_add_header(headers, &array[i])) {
236 goto error;
237 }
238 }
239
240 return AWS_OP_SUCCESS;
241
242 error:
243 /* Erase headers from the end until we're back to our previous state */
244 for (size_t new_count = aws_http_headers_count(headers); new_count > orig_count; --new_count) {
245 s_http_headers_erase_index(headers, new_count - 1);
246 }
247
248 return AWS_OP_ERR;
249 }
250
aws_http_headers_set(struct aws_http_headers * headers,struct aws_byte_cursor name,struct aws_byte_cursor value)251 int aws_http_headers_set(struct aws_http_headers *headers, struct aws_byte_cursor name, struct aws_byte_cursor value) {
252 AWS_PRECONDITION(headers);
253 AWS_PRECONDITION(aws_byte_cursor_is_valid(&name) && aws_byte_cursor_is_valid(&value));
254
255 const size_t prev_count = aws_http_headers_count(headers);
256 if (aws_http_headers_add(headers, name, value)) {
257 return AWS_OP_ERR;
258 }
259
260 /* Erase pre-existing headers AFTER add, in case name or value was referencing their memory. */
261 s_http_headers_erase(headers, name, prev_count);
262 return AWS_OP_SUCCESS;
263 }
264
aws_http_headers_count(const struct aws_http_headers * headers)265 size_t aws_http_headers_count(const struct aws_http_headers *headers) {
266 AWS_PRECONDITION(headers);
267
268 return aws_array_list_length(&headers->array_list);
269 }
270
aws_http_headers_get_index(const struct aws_http_headers * headers,size_t index,struct aws_http_header * out_header)271 int aws_http_headers_get_index(
272 const struct aws_http_headers *headers,
273 size_t index,
274 struct aws_http_header *out_header) {
275
276 AWS_PRECONDITION(headers);
277 AWS_PRECONDITION(out_header);
278
279 return aws_array_list_get_at(&headers->array_list, out_header, index);
280 }
281
aws_http_headers_get(const struct aws_http_headers * headers,struct aws_byte_cursor name,struct aws_byte_cursor * out_value)282 int aws_http_headers_get(
283 const struct aws_http_headers *headers,
284 struct aws_byte_cursor name,
285 struct aws_byte_cursor *out_value) {
286
287 AWS_PRECONDITION(headers);
288 AWS_PRECONDITION(out_value);
289 AWS_PRECONDITION(aws_byte_cursor_is_valid(&name));
290
291 struct aws_http_header *header = NULL;
292 const size_t count = aws_http_headers_count(headers);
293 for (size_t i = 0; i < count; ++i) {
294 aws_array_list_get_at_ptr(&headers->array_list, (void **)&header, i);
295 AWS_ASSUME(header);
296
297 if (aws_http_header_name_eq(header->name, name)) {
298 *out_value = header->value;
299 return AWS_OP_SUCCESS;
300 }
301 }
302
303 return aws_raise_error(AWS_ERROR_HTTP_HEADER_NOT_FOUND);
304 }
305
aws_http_headers_has(const struct aws_http_headers * headers,struct aws_byte_cursor name)306 bool aws_http_headers_has(const struct aws_http_headers *headers, struct aws_byte_cursor name) {
307
308 struct aws_byte_cursor out_value;
309 if (aws_http_headers_get(headers, name, &out_value)) {
310 return false;
311 }
312 return true;
313 }
314
315 struct aws_http_message {
316 struct aws_allocator *allocator;
317 struct aws_http_headers *headers;
318 struct aws_input_stream *body_stream;
319 struct aws_atomic_var refcount;
320
321 /* Data specific to the request or response subclasses */
322 union {
323 struct aws_http_message_request_data {
324 struct aws_string *method;
325 struct aws_string *path;
326 } request;
327 struct aws_http_message_response_data {
328 int status;
329 } response;
330 } subclass_data;
331
332 struct aws_http_message_request_data *request_data;
333 struct aws_http_message_response_data *response_data;
334 };
335
s_set_string_from_cursor(struct aws_string ** dst,struct aws_byte_cursor cursor,struct aws_allocator * alloc)336 static int s_set_string_from_cursor(
337 struct aws_string **dst,
338 struct aws_byte_cursor cursor,
339 struct aws_allocator *alloc) {
340
341 AWS_PRECONDITION(dst);
342
343 /* If the cursor is empty, set dst to NULL */
344 struct aws_string *new_str;
345 if (cursor.len) {
346 new_str = aws_string_new_from_cursor(alloc, &cursor);
347 if (!new_str) {
348 return AWS_OP_ERR;
349 }
350 } else {
351 new_str = NULL;
352 }
353
354 /* Replace existing value */
355 aws_string_destroy(*dst);
356
357 *dst = new_str;
358 return AWS_OP_SUCCESS;
359 }
s_message_new_common(struct aws_allocator * allocator,struct aws_http_headers * existing_headers)360 static struct aws_http_message *s_message_new_common(
361 struct aws_allocator *allocator,
362 struct aws_http_headers *existing_headers) {
363
364 struct aws_http_message *message = aws_mem_calloc(allocator, 1, sizeof(struct aws_http_message));
365 if (!message) {
366 goto error;
367 }
368
369 message->allocator = allocator;
370 aws_atomic_init_int(&message->refcount, 1);
371
372 if (existing_headers) {
373 message->headers = existing_headers;
374 aws_http_headers_acquire(message->headers);
375 } else {
376 message->headers = aws_http_headers_new(allocator);
377 if (!message->headers) {
378 goto error;
379 }
380 }
381
382 return message;
383 error:
384 aws_http_message_destroy(message);
385 return NULL;
386 }
387
s_message_new_request_common(struct aws_allocator * allocator,struct aws_http_headers * existing_headers)388 static struct aws_http_message *s_message_new_request_common(
389 struct aws_allocator *allocator,
390 struct aws_http_headers *existing_headers) {
391
392 struct aws_http_message *message = s_message_new_common(allocator, existing_headers);
393 if (message) {
394 message->request_data = &message->subclass_data.request;
395 }
396 return message;
397 }
398
aws_http_message_new_request_with_headers(struct aws_allocator * allocator,struct aws_http_headers * existing_headers)399 struct aws_http_message *aws_http_message_new_request_with_headers(
400 struct aws_allocator *allocator,
401 struct aws_http_headers *existing_headers) {
402
403 AWS_PRECONDITION(allocator);
404 AWS_PRECONDITION(existing_headers);
405
406 return s_message_new_request_common(allocator, existing_headers);
407 }
408
aws_http_message_new_request(struct aws_allocator * allocator)409 struct aws_http_message *aws_http_message_new_request(struct aws_allocator *allocator) {
410 AWS_PRECONDITION(allocator);
411 return s_message_new_request_common(allocator, NULL);
412 }
413
aws_http_message_new_response(struct aws_allocator * allocator)414 struct aws_http_message *aws_http_message_new_response(struct aws_allocator *allocator) {
415 AWS_PRECONDITION(allocator);
416
417 struct aws_http_message *message = s_message_new_common(allocator, NULL);
418 if (message) {
419 message->response_data = &message->subclass_data.response;
420 message->response_data->status = AWS_HTTP_STATUS_CODE_UNKNOWN;
421 }
422 return message;
423 }
424
aws_http_message_destroy(struct aws_http_message * message)425 void aws_http_message_destroy(struct aws_http_message *message) {
426 aws_http_message_release(message);
427 }
428
aws_http_message_release(struct aws_http_message * message)429 void aws_http_message_release(struct aws_http_message *message) {
430 /* Note that release() may also be used by new() functions to clean up if something goes wrong */
431 AWS_PRECONDITION(!message || message->allocator);
432 if (!message) {
433 return;
434 }
435
436 size_t prev_refcount = aws_atomic_fetch_sub(&message->refcount, 1);
437 if (prev_refcount == 1) {
438 if (message->request_data) {
439 aws_string_destroy(message->request_data->method);
440 aws_string_destroy(message->request_data->path);
441 }
442
443 aws_http_headers_release(message->headers);
444
445 aws_mem_release(message->allocator, message);
446 } else {
447 AWS_ASSERT(prev_refcount != 0);
448 }
449 }
450
aws_http_message_acquire(struct aws_http_message * message)451 void aws_http_message_acquire(struct aws_http_message *message) {
452 AWS_PRECONDITION(message);
453 aws_atomic_fetch_add(&message->refcount, 1);
454 }
455
aws_http_message_is_request(const struct aws_http_message * message)456 bool aws_http_message_is_request(const struct aws_http_message *message) {
457 AWS_PRECONDITION(message);
458 return message->request_data;
459 }
460
aws_http_message_is_response(const struct aws_http_message * message)461 bool aws_http_message_is_response(const struct aws_http_message *message) {
462 AWS_PRECONDITION(message);
463 return message->response_data;
464 }
465
aws_http_message_set_request_method(struct aws_http_message * request_message,struct aws_byte_cursor method)466 int aws_http_message_set_request_method(struct aws_http_message *request_message, struct aws_byte_cursor method) {
467 AWS_PRECONDITION(request_message);
468 AWS_PRECONDITION(aws_byte_cursor_is_valid(&method));
469 AWS_PRECONDITION(request_message->request_data);
470
471 if (request_message->request_data) {
472 return s_set_string_from_cursor(&request_message->request_data->method, method, request_message->allocator);
473 }
474
475 return aws_raise_error(AWS_ERROR_INVALID_STATE);
476 }
477
aws_http_message_get_request_method(const struct aws_http_message * request_message,struct aws_byte_cursor * out_method)478 int aws_http_message_get_request_method(
479 const struct aws_http_message *request_message,
480 struct aws_byte_cursor *out_method) {
481
482 AWS_PRECONDITION(request_message);
483 AWS_PRECONDITION(out_method);
484 AWS_PRECONDITION(request_message->request_data);
485
486 if (request_message->request_data && request_message->request_data->method) {
487 *out_method = aws_byte_cursor_from_string(request_message->request_data->method);
488 return AWS_OP_SUCCESS;
489 }
490
491 AWS_ZERO_STRUCT(*out_method);
492 return aws_raise_error(AWS_ERROR_HTTP_DATA_NOT_AVAILABLE);
493 }
494
aws_http_message_set_request_path(struct aws_http_message * request_message,struct aws_byte_cursor path)495 int aws_http_message_set_request_path(struct aws_http_message *request_message, struct aws_byte_cursor path) {
496 AWS_PRECONDITION(request_message);
497 AWS_PRECONDITION(aws_byte_cursor_is_valid(&path));
498 AWS_PRECONDITION(request_message->request_data);
499
500 if (request_message->request_data) {
501 return s_set_string_from_cursor(&request_message->request_data->path, path, request_message->allocator);
502 }
503
504 return aws_raise_error(AWS_ERROR_INVALID_STATE);
505 }
506
aws_http_message_get_request_path(const struct aws_http_message * request_message,struct aws_byte_cursor * out_path)507 int aws_http_message_get_request_path(
508 const struct aws_http_message *request_message,
509 struct aws_byte_cursor *out_path) {
510
511 AWS_PRECONDITION(request_message);
512 AWS_PRECONDITION(out_path);
513 AWS_PRECONDITION(request_message->request_data);
514
515 if (request_message->request_data && request_message->request_data->path) {
516 *out_path = aws_byte_cursor_from_string(request_message->request_data->path);
517 return AWS_OP_SUCCESS;
518 }
519
520 AWS_ZERO_STRUCT(*out_path);
521 return aws_raise_error(AWS_ERROR_HTTP_DATA_NOT_AVAILABLE);
522 }
523
aws_http_message_get_response_status(const struct aws_http_message * response_message,int * out_status_code)524 int aws_http_message_get_response_status(const struct aws_http_message *response_message, int *out_status_code) {
525 AWS_PRECONDITION(response_message);
526 AWS_PRECONDITION(out_status_code);
527 AWS_PRECONDITION(response_message->response_data);
528
529 *out_status_code = AWS_HTTP_STATUS_CODE_UNKNOWN;
530
531 if (response_message->response_data && (response_message->response_data->status != AWS_HTTP_STATUS_CODE_UNKNOWN)) {
532 *out_status_code = response_message->response_data->status;
533 return AWS_OP_SUCCESS;
534 }
535
536 return aws_raise_error(AWS_ERROR_HTTP_DATA_NOT_AVAILABLE);
537 }
538
aws_http_message_set_response_status(struct aws_http_message * response_message,int status_code)539 int aws_http_message_set_response_status(struct aws_http_message *response_message, int status_code) {
540 AWS_PRECONDITION(response_message);
541 AWS_PRECONDITION(response_message->response_data);
542
543 if (response_message->response_data) {
544 /* Status code must be printable with exactly 3 digits */
545 if (status_code >= 0 && status_code <= 999) {
546 response_message->response_data->status = status_code;
547 return AWS_OP_SUCCESS;
548 }
549
550 return aws_raise_error(AWS_ERROR_HTTP_INVALID_STATUS_CODE);
551 }
552
553 return aws_raise_error(AWS_ERROR_INVALID_STATE);
554 }
555
aws_http_message_set_body_stream(struct aws_http_message * message,struct aws_input_stream * body_stream)556 void aws_http_message_set_body_stream(struct aws_http_message *message, struct aws_input_stream *body_stream) {
557 AWS_PRECONDITION(message);
558 message->body_stream = body_stream;
559 }
560
aws_http1_stream_write_chunk(struct aws_http_stream * http1_stream,const struct aws_http1_chunk_options * options)561 int aws_http1_stream_write_chunk(struct aws_http_stream *http1_stream, const struct aws_http1_chunk_options *options) {
562 AWS_PRECONDITION(http1_stream);
563 AWS_PRECONDITION(http1_stream->vtable);
564 AWS_PRECONDITION(options);
565 if (!http1_stream->vtable->http1_write_chunk) {
566 AWS_LOGF_TRACE(
567 AWS_LS_HTTP_STREAM,
568 "id=%p: HTTP/1 stream only function invoked on other stream, ignoring call.",
569 (void *)http1_stream);
570 return aws_raise_error(AWS_ERROR_INVALID_STATE);
571 }
572
573 return http1_stream->vtable->http1_write_chunk(http1_stream, options);
574 }
575
aws_http_message_get_body_stream(const struct aws_http_message * message)576 struct aws_input_stream *aws_http_message_get_body_stream(const struct aws_http_message *message) {
577 AWS_PRECONDITION(message);
578 return message->body_stream;
579 }
580
aws_http_message_get_headers(struct aws_http_message * message)581 struct aws_http_headers *aws_http_message_get_headers(struct aws_http_message *message) {
582 AWS_PRECONDITION(message);
583 return message->headers;
584 }
585
aws_http_message_get_const_headers(const struct aws_http_message * message)586 const struct aws_http_headers *aws_http_message_get_const_headers(const struct aws_http_message *message) {
587 AWS_PRECONDITION(message);
588 return message->headers;
589 }
590
aws_http_message_add_header(struct aws_http_message * message,struct aws_http_header header)591 int aws_http_message_add_header(struct aws_http_message *message, struct aws_http_header header) {
592 return aws_http_headers_add(message->headers, header.name, header.value);
593 }
594
aws_http_message_add_header_array(struct aws_http_message * message,const struct aws_http_header * headers,size_t num_headers)595 int aws_http_message_add_header_array(
596 struct aws_http_message *message,
597 const struct aws_http_header *headers,
598 size_t num_headers) {
599
600 return aws_http_headers_add_array(message->headers, headers, num_headers);
601 }
602
aws_http_message_erase_header(struct aws_http_message * message,size_t index)603 int aws_http_message_erase_header(struct aws_http_message *message, size_t index) {
604 return aws_http_headers_erase_index(message->headers, index);
605 }
606
aws_http_message_get_header_count(const struct aws_http_message * message)607 size_t aws_http_message_get_header_count(const struct aws_http_message *message) {
608 return aws_http_headers_count(message->headers);
609 }
610
aws_http_message_get_header(const struct aws_http_message * message,struct aws_http_header * out_header,size_t index)611 int aws_http_message_get_header(
612 const struct aws_http_message *message,
613 struct aws_http_header *out_header,
614 size_t index) {
615
616 return aws_http_headers_get_index(message->headers, index, out_header);
617 }
618
aws_http_connection_make_request(struct aws_http_connection * client_connection,const struct aws_http_make_request_options * options)619 struct aws_http_stream *aws_http_connection_make_request(
620 struct aws_http_connection *client_connection,
621 const struct aws_http_make_request_options *options) {
622
623 AWS_PRECONDITION(client_connection);
624 AWS_PRECONDITION(aws_http_connection_is_client(client_connection));
625 AWS_PRECONDITION(options);
626 if (options->self_size == 0 || !options->request || !aws_http_message_is_request(options->request)) {
627
628 AWS_LOGF_ERROR(
629 AWS_LS_HTTP_CONNECTION,
630 "id=%p: Cannot create client request, options are invalid.",
631 (void *)client_connection);
632 aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
633 return NULL;
634 }
635
636 /* Connection owns stream, and must outlive stream */
637 aws_http_connection_acquire(client_connection);
638
639 struct aws_http_stream *stream = client_connection->vtable->make_request(client_connection, options);
640 if (!stream) {
641 aws_http_connection_release(client_connection);
642 return NULL;
643 }
644
645 return stream;
646 }
647
aws_http_stream_activate(struct aws_http_stream * stream)648 int aws_http_stream_activate(struct aws_http_stream *stream) {
649 AWS_PRECONDITION(stream);
650 AWS_PRECONDITION(stream->vtable);
651 AWS_PRECONDITION(stream->vtable->activate);
652 /* make sure it's actually a client calling us. This is always a programmer bug, so just assert and die. */
653 AWS_PRECONDITION(aws_http_connection_is_client(stream->owning_connection));
654
655 return stream->vtable->activate(stream);
656 }
657
aws_http_stream_new_server_request_handler(const struct aws_http_request_handler_options * options)658 struct aws_http_stream *aws_http_stream_new_server_request_handler(
659 const struct aws_http_request_handler_options *options) {
660 AWS_PRECONDITION(options);
661 if (options->self_size == 0 || !options->server_connection ||
662 !aws_http_connection_is_server(options->server_connection)) {
663
664 AWS_LOGF_ERROR(
665 AWS_LS_HTTP_CONNECTION,
666 "id=%p: Cannot create server request handler stream, options are invalid.",
667 (void *)options->server_connection);
668 aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
669 return NULL;
670 }
671
672 return options->server_connection->vtable->new_server_request_handler_stream(options);
673 }
674
aws_http_stream_send_response(struct aws_http_stream * stream,struct aws_http_message * response)675 int aws_http_stream_send_response(struct aws_http_stream *stream, struct aws_http_message *response) {
676 AWS_PRECONDITION(stream);
677 AWS_PRECONDITION(response);
678 AWS_PRECONDITION(aws_http_message_is_response(response));
679 return stream->owning_connection->vtable->stream_send_response(stream, response);
680 }
681
aws_http_stream_release(struct aws_http_stream * stream)682 void aws_http_stream_release(struct aws_http_stream *stream) {
683 if (!stream) {
684 return;
685 }
686
687 size_t prev_refcount = aws_atomic_fetch_sub(&stream->refcount, 1);
688 if (prev_refcount == 1) {
689 AWS_LOGF_TRACE(AWS_LS_HTTP_STREAM, "id=%p: Final stream refcount released.", (void *)stream);
690
691 struct aws_http_connection *owning_connection = stream->owning_connection;
692 stream->vtable->destroy(stream);
693
694 /* Connection needed to outlive stream, but it's free to go now */
695 aws_http_connection_release(owning_connection);
696 } else {
697 AWS_ASSERT(prev_refcount != 0);
698 AWS_LOGF_TRACE(
699 AWS_LS_HTTP_STREAM, "id=%p: Stream refcount released, %zu remaining.", (void *)stream, prev_refcount - 1);
700 }
701 }
702
aws_http_stream_get_connection(const struct aws_http_stream * stream)703 struct aws_http_connection *aws_http_stream_get_connection(const struct aws_http_stream *stream) {
704 AWS_ASSERT(stream);
705 return stream->owning_connection;
706 }
707
aws_http_stream_get_incoming_response_status(const struct aws_http_stream * stream,int * out_status)708 int aws_http_stream_get_incoming_response_status(const struct aws_http_stream *stream, int *out_status) {
709 AWS_ASSERT(stream && stream->client_data);
710
711 if (stream->client_data->response_status == (int)AWS_HTTP_STATUS_CODE_UNKNOWN) {
712 AWS_LOGF_ERROR(AWS_LS_HTTP_STREAM, "id=%p: Status code not yet received.", (void *)stream);
713 return aws_raise_error(AWS_ERROR_HTTP_DATA_NOT_AVAILABLE);
714 }
715
716 *out_status = stream->client_data->response_status;
717 return AWS_OP_SUCCESS;
718 }
719
aws_http_stream_get_incoming_request_method(const struct aws_http_stream * stream,struct aws_byte_cursor * out_method)720 int aws_http_stream_get_incoming_request_method(
721 const struct aws_http_stream *stream,
722 struct aws_byte_cursor *out_method) {
723 AWS_ASSERT(stream && stream->server_data);
724
725 if (!stream->server_data->request_method_str.ptr) {
726 AWS_LOGF_ERROR(AWS_LS_HTTP_STREAM, "id=%p: Request method not yet received.", (void *)stream);
727 return aws_raise_error(AWS_ERROR_HTTP_DATA_NOT_AVAILABLE);
728 }
729
730 *out_method = stream->server_data->request_method_str;
731 return AWS_OP_SUCCESS;
732 }
733
aws_http_stream_get_incoming_request_uri(const struct aws_http_stream * stream,struct aws_byte_cursor * out_uri)734 int aws_http_stream_get_incoming_request_uri(const struct aws_http_stream *stream, struct aws_byte_cursor *out_uri) {
735 AWS_ASSERT(stream && stream->server_data);
736
737 if (!stream->server_data->request_path.ptr) {
738 AWS_LOGF_ERROR(AWS_LS_HTTP_STREAM, "id=%p: Request URI not yet received.", (void *)stream);
739 return aws_raise_error(AWS_ERROR_HTTP_DATA_NOT_AVAILABLE);
740 }
741
742 *out_uri = stream->server_data->request_path;
743 return AWS_OP_SUCCESS;
744 }
745
aws_http_stream_update_window(struct aws_http_stream * stream,size_t increment_size)746 void aws_http_stream_update_window(struct aws_http_stream *stream, size_t increment_size) {
747 stream->vtable->update_window(stream, increment_size);
748 }
749
aws_http_stream_get_id(const struct aws_http_stream * stream)750 uint32_t aws_http_stream_get_id(const struct aws_http_stream *stream) {
751 return stream->id;
752 }
753
aws_http2_stream_reset(struct aws_http_stream * http2_stream,uint32_t http2_error)754 int aws_http2_stream_reset(struct aws_http_stream *http2_stream, uint32_t http2_error) {
755 AWS_PRECONDITION(http2_stream);
756 AWS_PRECONDITION(http2_stream->vtable);
757 if (!http2_stream->vtable->http2_reset_stream) {
758 AWS_LOGF_TRACE(
759 AWS_LS_HTTP_STREAM,
760 "id=%p: HTTP/2 stream only function invoked on other stream, ignoring call.",
761 (void *)http2_stream);
762 return aws_raise_error(AWS_ERROR_INVALID_STATE);
763 }
764 return http2_stream->vtable->http2_reset_stream(http2_stream, http2_error);
765 }
766
aws_http2_stream_get_received_reset_error_code(struct aws_http_stream * http2_stream,uint32_t * out_http2_error)767 int aws_http2_stream_get_received_reset_error_code(struct aws_http_stream *http2_stream, uint32_t *out_http2_error) {
768 AWS_PRECONDITION(http2_stream);
769 AWS_PRECONDITION(http2_stream->vtable);
770 AWS_PRECONDITION(out_http2_error);
771 if (!http2_stream->vtable->http2_get_received_error_code) {
772 AWS_LOGF_TRACE(
773 AWS_LS_HTTP_STREAM,
774 "id=%p: HTTP/2 stream only function invoked on other stream, ignoring call.",
775 (void *)http2_stream);
776 return aws_raise_error(AWS_ERROR_INVALID_STATE);
777 }
778 return http2_stream->vtable->http2_get_received_error_code(http2_stream, out_http2_error);
779 }
780
aws_http2_stream_get_sent_reset_error_code(struct aws_http_stream * http2_stream,uint32_t * out_http2_error)781 int aws_http2_stream_get_sent_reset_error_code(struct aws_http_stream *http2_stream, uint32_t *out_http2_error) {
782 AWS_PRECONDITION(http2_stream);
783 AWS_PRECONDITION(http2_stream->vtable);
784 AWS_PRECONDITION(out_http2_error);
785 if (!http2_stream->vtable->http2_get_sent_error_code) {
786 AWS_LOGF_TRACE(
787 AWS_LS_HTTP_STREAM,
788 "id=%p: HTTP/2 stream only function invoked on other stream, ignoring call.",
789 (void *)http2_stream);
790 return aws_raise_error(AWS_ERROR_INVALID_STATE);
791 }
792 return http2_stream->vtable->http2_get_sent_error_code(http2_stream, out_http2_error);
793 }
794