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