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/hash_table.h>
7 #include <aws/compression/compression.h>
8 #include <aws/http/private/hpack.h>
9 #include <aws/http/private/http_impl.h>
10 #include <aws/http/status_code.h>
11 #include <aws/io/logging.h>
12 
13 #include <ctype.h>
14 
15 #define AWS_DEFINE_ERROR_INFO_HTTP(CODE, STR) [(CODE)-0x0800] = AWS_DEFINE_ERROR_INFO(CODE, STR, "aws-c-http")
16 
17 /* clang-format off */
18 static struct aws_error_info s_errors[] = {
19     AWS_DEFINE_ERROR_INFO_HTTP(
20         AWS_ERROR_HTTP_UNKNOWN,
21         "Encountered an unknown error."),
22     AWS_DEFINE_ERROR_INFO_HTTP(
23         AWS_ERROR_HTTP_HEADER_NOT_FOUND,
24         "The specified header was not found"),
25     AWS_DEFINE_ERROR_INFO_HTTP(
26         AWS_ERROR_HTTP_INVALID_HEADER_FIELD,
27         "Invalid header field, including a forbidden header field."),
28     AWS_DEFINE_ERROR_INFO_HTTP(
29         AWS_ERROR_HTTP_INVALID_HEADER_NAME,
30         "Invalid header name."),
31     AWS_DEFINE_ERROR_INFO_HTTP(
32         AWS_ERROR_HTTP_INVALID_HEADER_VALUE,
33         "Invalid header value."),
34     AWS_DEFINE_ERROR_INFO_HTTP(
35         AWS_ERROR_HTTP_INVALID_METHOD,
36         "Method is invalid."),
37     AWS_DEFINE_ERROR_INFO_HTTP(
38         AWS_ERROR_HTTP_INVALID_PATH,
39         "Path is invalid."),
40     AWS_DEFINE_ERROR_INFO_HTTP(
41         AWS_ERROR_HTTP_INVALID_STATUS_CODE,
42         "Status code is invalid."),
43     AWS_DEFINE_ERROR_INFO_HTTP(
44         AWS_ERROR_HTTP_MISSING_BODY_STREAM,
45         "Given the provided headers (ex: Content-Length), a body is expected."),
46     AWS_DEFINE_ERROR_INFO_HTTP(
47         AWS_ERROR_HTTP_INVALID_BODY_STREAM,
48         "A body stream provided, but the message does not allow body (ex: response for HEAD Request and 304 response)"),
49     AWS_DEFINE_ERROR_INFO_HTTP(
50         AWS_ERROR_HTTP_CONNECTION_CLOSED,
51         "The connection has closed or is closing."),
52     AWS_DEFINE_ERROR_INFO_HTTP(
53         AWS_ERROR_HTTP_SWITCHED_PROTOCOLS,
54         "The connection has switched protocols."),
55     AWS_DEFINE_ERROR_INFO_HTTP(
56         AWS_ERROR_HTTP_UNSUPPORTED_PROTOCOL,
57         "An unsupported protocol was encountered."),
58     AWS_DEFINE_ERROR_INFO_HTTP(
59         AWS_ERROR_HTTP_REACTION_REQUIRED,
60         "A necessary function was not invoked from a user callback."),
61     AWS_DEFINE_ERROR_INFO_HTTP(
62         AWS_ERROR_HTTP_DATA_NOT_AVAILABLE,
63         "This data is not yet available."),
64     AWS_DEFINE_ERROR_INFO_HTTP(
65         AWS_ERROR_HTTP_OUTGOING_STREAM_LENGTH_INCORRECT,
66         "Amount of data streamed out does not match the previously declared length."),
67     AWS_DEFINE_ERROR_INFO_HTTP(
68         AWS_ERROR_HTTP_CALLBACK_FAILURE,
69         "A callback has reported failure."),
70     AWS_DEFINE_ERROR_INFO_HTTP(
71         AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE,
72         "Failed to upgrade HTTP connection to Websocket."),
73     AWS_DEFINE_ERROR_INFO_HTTP(
74         AWS_ERROR_HTTP_WEBSOCKET_CLOSE_FRAME_SENT,
75         "Websocket has sent CLOSE frame, no more data will be sent."),
76     AWS_DEFINE_ERROR_INFO_HTTP(
77         AWS_ERROR_HTTP_WEBSOCKET_IS_MIDCHANNEL_HANDLER,
78         "Operation cannot be performed because websocket has been converted to a midchannel handler."),
79     AWS_DEFINE_ERROR_INFO_HTTP(
80         AWS_ERROR_HTTP_CONNECTION_MANAGER_INVALID_STATE_FOR_ACQUIRE,
81         "Acquire called after the connection manager's ref count has reached zero"),
82     AWS_DEFINE_ERROR_INFO_HTTP(
83         AWS_ERROR_HTTP_CONNECTION_MANAGER_VENDED_CONNECTION_UNDERFLOW,
84         "Release called when the connection manager's vended connection count was zero"),
85     AWS_DEFINE_ERROR_INFO_HTTP(
86         AWS_ERROR_HTTP_SERVER_CLOSED,
87         "The http server is closed, no more connections will be accepted"),
88     AWS_DEFINE_ERROR_INFO_HTTP(
89         AWS_ERROR_HTTP_PROXY_CONNECT_FAILED,
90         "Proxy-based connection establishment failed because the CONNECT call failed"),
91     AWS_DEFINE_ERROR_INFO_HTTP(
92         AWS_ERROR_HTTP_CONNECTION_MANAGER_SHUTTING_DOWN,
93         "Connection acquisition failed because connection manager is shutting down"),
94     AWS_DEFINE_ERROR_INFO_HTTP(
95         AWS_ERROR_HTTP_CHANNEL_THROUGHPUT_FAILURE,
96         "Http connection channel shut down due to failure to meet throughput minimum"),
97     AWS_DEFINE_ERROR_INFO_HTTP(
98         AWS_ERROR_HTTP_PROTOCOL_ERROR,
99         "Protocol rules violated by peer"),
100     AWS_DEFINE_ERROR_INFO_HTTP(
101         AWS_ERROR_HTTP_STREAM_IDS_EXHAUSTED,
102         "Connection exhausted all possible HTTP-stream IDs. Establish a new connection for new streams."),
103     AWS_DEFINE_ERROR_INFO_HTTP(
104         AWS_ERROR_HTTP_GOAWAY_RECEIVED,
105         "Peer sent GOAWAY to initiate connection shutdown. Establish a new connection to retry the HTTP-streams."),
106     AWS_DEFINE_ERROR_INFO_HTTP(
107         AWS_ERROR_HTTP_RST_STREAM_RECEIVED,
108         "Peer sent RST_STREAM to terminate HTTP-stream."),
109     AWS_DEFINE_ERROR_INFO_HTTP(
110         AWS_ERROR_HTTP_RST_STREAM_SENT,
111         "RST_STREAM has sent from local implementation and HTTP-stream has been terminated."),
112     AWS_DEFINE_ERROR_INFO_HTTP(
113         AWS_ERROR_HTTP_STREAM_NOT_ACTIVATED,
114         "HTTP-stream must be activated before use."),
115     AWS_DEFINE_ERROR_INFO_HTTP(
116         AWS_ERROR_HTTP_STREAM_HAS_COMPLETED,
117         "HTTP-stream has completed, action cannot be performed."),
118     AWS_DEFINE_ERROR_INFO_HTTP(
119         AWS_ERROR_HTTP_PROXY_STRATEGY_NTLM_CHALLENGE_TOKEN_MISSING,
120         "NTLM Proxy strategy was initiated without a challenge token"),
121     AWS_DEFINE_ERROR_INFO_HTTP(
122         AWS_ERROR_HTTP_PROXY_STRATEGY_TOKEN_RETRIEVAL_FAILURE,
123         "Failure in user code while retrieving proxy auth token"),
124     AWS_DEFINE_ERROR_INFO_HTTP(
125         AWS_ERROR_HTTP_PROXY_CONNECT_FAILED_RETRYABLE,
126         "Proxy connection attempt failed but the negotiation could be continued on a new connection"),
127     AWS_DEFINE_ERROR_INFO_HTTP(
128         AWS_ERROR_HTTP_PROTOCOL_SWITCH_FAILURE,
129         "Internal state failure prevent connection from switching protocols"),
130 };
131 /* clang-format on */
132 
133 static struct aws_error_info_list s_error_list = {
134     .error_list = s_errors,
135     .count = AWS_ARRAY_SIZE(s_errors),
136 };
137 
138 static struct aws_log_subject_info s_log_subject_infos[] = {
139     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_GENERAL, "http", "Misc HTTP logging"),
140     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_CONNECTION, "http-connection", "HTTP client or server connection"),
141     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_ENCODER, "http-encoder", "HTTP data encoder"),
142     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_DECODER, "http-decoder", "HTTP data decoder"),
143     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_SERVER, "http-server", "HTTP server socket listening for incoming connections"),
144     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_STREAM, "http-stream", "HTTP request-response exchange"),
145     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_CONNECTION_MANAGER, "connection-manager", "HTTP connection manager"),
146     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_WEBSOCKET, "websocket", "Websocket"),
147     DEFINE_LOG_SUBJECT_INFO(AWS_LS_HTTP_WEBSOCKET_SETUP, "websocket-setup", "Websocket setup"),
148     DEFINE_LOG_SUBJECT_INFO(
149         AWS_LS_HTTP_PROXY_NEGOTIATION,
150         "proxy-negotiation",
151         "Negotiating an http connection with a proxy server"),
152 };
153 
154 static struct aws_log_subject_info_list s_log_subject_list = {
155     .subject_list = s_log_subject_infos,
156     .count = AWS_ARRAY_SIZE(s_log_subject_infos),
157 };
158 
159 struct aws_enum_value {
160     struct aws_allocator *allocator;
161     int value;
162 };
163 
s_destroy_enum_value(void * value)164 static void s_destroy_enum_value(void *value) {
165     struct aws_enum_value *enum_value = value;
166     aws_mem_release(enum_value->allocator, enum_value);
167 }
168 
169 /**
170  * Given array of aws_byte_cursors, init hashtable where...
171  * Key is aws_byte_cursor* (pointing into cursor from array) and comparisons are case-insensitive.
172  * Value is the array index cast to a void*.
173  */
s_init_str_to_enum_hash_table(struct aws_hash_table * table,struct aws_allocator * alloc,struct aws_byte_cursor * str_array,int start_index,int end_index,bool ignore_case)174 static void s_init_str_to_enum_hash_table(
175     struct aws_hash_table *table,
176     struct aws_allocator *alloc,
177     struct aws_byte_cursor *str_array,
178     int start_index,
179     int end_index,
180     bool ignore_case) {
181 
182     int err = aws_hash_table_init(
183         table,
184         alloc,
185         end_index - start_index,
186         ignore_case ? aws_hash_byte_cursor_ptr_ignore_case : aws_hash_byte_cursor_ptr,
187         (aws_hash_callback_eq_fn *)(ignore_case ? aws_byte_cursor_eq_ignore_case : aws_byte_cursor_eq),
188         NULL,
189         s_destroy_enum_value);
190     AWS_FATAL_ASSERT(!err);
191 
192     for (int i = start_index; i < end_index; ++i) {
193         int was_created = 0;
194         struct aws_enum_value *enum_value = aws_mem_calloc(alloc, 1, sizeof(struct aws_enum_value));
195         AWS_FATAL_ASSERT(enum_value);
196         enum_value->allocator = alloc;
197         enum_value->value = i;
198 
199         AWS_FATAL_ASSERT(str_array[i].ptr && "Missing enum string");
200         err = aws_hash_table_put(table, &str_array[i], (void *)enum_value, &was_created);
201         AWS_FATAL_ASSERT(!err && was_created);
202     }
203 }
204 
205 /**
206  * Given key, get value from table initialized by s_init_str_to_enum_hash_table().
207  * Returns -1 if key not found.
208  */
s_find_in_str_to_enum_hash_table(const struct aws_hash_table * table,struct aws_byte_cursor * key)209 static int s_find_in_str_to_enum_hash_table(const struct aws_hash_table *table, struct aws_byte_cursor *key) {
210     struct aws_hash_element *elem;
211     aws_hash_table_find(table, key, &elem);
212     if (elem) {
213         struct aws_enum_value *enum_value = elem->value;
214         return enum_value->value;
215     }
216     return -1;
217 }
218 
219 /* METHODS */
220 static struct aws_hash_table s_method_str_to_enum;                         /* for string -> enum lookup */
221 static struct aws_byte_cursor s_method_enum_to_str[AWS_HTTP_METHOD_COUNT]; /* for enum -> string lookup */
222 
s_methods_init(struct aws_allocator * alloc)223 static void s_methods_init(struct aws_allocator *alloc) {
224     s_method_enum_to_str[AWS_HTTP_METHOD_GET] = aws_http_method_get;
225     s_method_enum_to_str[AWS_HTTP_METHOD_HEAD] = aws_http_method_head;
226     s_method_enum_to_str[AWS_HTTP_METHOD_CONNECT] = aws_http_method_connect;
227 
228     s_init_str_to_enum_hash_table(
229         &s_method_str_to_enum,
230         alloc,
231         s_method_enum_to_str,
232         AWS_HTTP_METHOD_UNKNOWN + 1,
233         AWS_HTTP_METHOD_COUNT,
234         false /* DO NOT ignore case of method */);
235 }
236 
s_methods_clean_up(void)237 static void s_methods_clean_up(void) {
238     aws_hash_table_clean_up(&s_method_str_to_enum);
239 }
240 
aws_http_str_to_method(struct aws_byte_cursor cursor)241 enum aws_http_method aws_http_str_to_method(struct aws_byte_cursor cursor) {
242     int method = s_find_in_str_to_enum_hash_table(&s_method_str_to_enum, &cursor);
243     if (method >= 0) {
244         return (enum aws_http_method)method;
245     }
246     return AWS_HTTP_METHOD_UNKNOWN;
247 }
248 
249 /* VERSIONS */
250 static struct aws_byte_cursor s_version_enum_to_str[AWS_HTTP_HEADER_COUNT]; /* for enum -> string lookup */
251 
s_versions_init(struct aws_allocator * alloc)252 static void s_versions_init(struct aws_allocator *alloc) {
253     (void)alloc;
254     s_version_enum_to_str[AWS_HTTP_VERSION_UNKNOWN] = aws_byte_cursor_from_c_str("Unknown");
255     s_version_enum_to_str[AWS_HTTP_VERSION_1_0] = aws_byte_cursor_from_c_str("HTTP/1.0");
256     s_version_enum_to_str[AWS_HTTP_VERSION_1_1] = aws_byte_cursor_from_c_str("HTTP/1.1");
257     s_version_enum_to_str[AWS_HTTP_VERSION_2] = aws_byte_cursor_from_c_str("HTTP/2");
258 }
259 
s_versions_clean_up(void)260 static void s_versions_clean_up(void) {}
261 
aws_http_version_to_str(enum aws_http_version version)262 struct aws_byte_cursor aws_http_version_to_str(enum aws_http_version version) {
263     if ((int)version < AWS_HTTP_VERSION_UNKNOWN || (int)version >= AWS_HTTP_VERSION_COUNT) {
264         version = AWS_HTTP_VERSION_UNKNOWN;
265     }
266 
267     return s_version_enum_to_str[version];
268 }
269 
270 /* HEADERS */
271 static struct aws_hash_table s_header_str_to_enum;           /* for case-insensitive string -> enum lookup */
272 static struct aws_hash_table s_lowercase_header_str_to_enum; /* for case-sensitive string -> enum lookup */
273 static struct aws_byte_cursor s_header_enum_to_str[AWS_HTTP_HEADER_COUNT]; /* for enum -> string lookup */
274 
s_headers_init(struct aws_allocator * alloc)275 static void s_headers_init(struct aws_allocator *alloc) {
276     s_header_enum_to_str[AWS_HTTP_HEADER_METHOD] = aws_byte_cursor_from_c_str(":method");
277     s_header_enum_to_str[AWS_HTTP_HEADER_SCHEME] = aws_byte_cursor_from_c_str(":scheme");
278     s_header_enum_to_str[AWS_HTTP_HEADER_AUTHORITY] = aws_byte_cursor_from_c_str(":authority");
279     s_header_enum_to_str[AWS_HTTP_HEADER_PATH] = aws_byte_cursor_from_c_str(":path");
280     s_header_enum_to_str[AWS_HTTP_HEADER_STATUS] = aws_byte_cursor_from_c_str(":status");
281     s_header_enum_to_str[AWS_HTTP_HEADER_COOKIE] = aws_byte_cursor_from_c_str("cookie");
282     s_header_enum_to_str[AWS_HTTP_HEADER_HOST] = aws_byte_cursor_from_c_str("host");
283     s_header_enum_to_str[AWS_HTTP_HEADER_CONNECTION] = aws_byte_cursor_from_c_str("connection");
284     s_header_enum_to_str[AWS_HTTP_HEADER_CONTENT_LENGTH] = aws_byte_cursor_from_c_str("content-length");
285     s_header_enum_to_str[AWS_HTTP_HEADER_EXPECT] = aws_byte_cursor_from_c_str("expect");
286     s_header_enum_to_str[AWS_HTTP_HEADER_TRANSFER_ENCODING] = aws_byte_cursor_from_c_str("transfer-encoding");
287 
288     s_init_str_to_enum_hash_table(
289         &s_header_str_to_enum,
290         alloc,
291         s_header_enum_to_str,
292         AWS_HTTP_HEADER_UNKNOWN + 1,
293         AWS_HTTP_HEADER_COUNT,
294         true /* ignore case */);
295 
296     s_init_str_to_enum_hash_table(
297         &s_lowercase_header_str_to_enum,
298         alloc,
299         s_header_enum_to_str,
300         AWS_HTTP_HEADER_UNKNOWN + 1,
301         AWS_HTTP_HEADER_COUNT,
302         false /* ignore case */);
303 }
304 
s_headers_clean_up(void)305 static void s_headers_clean_up(void) {
306     aws_hash_table_clean_up(&s_header_str_to_enum);
307     aws_hash_table_clean_up(&s_lowercase_header_str_to_enum);
308 }
309 
aws_http_str_to_header_name(struct aws_byte_cursor cursor)310 enum aws_http_header_name aws_http_str_to_header_name(struct aws_byte_cursor cursor) {
311     int header = s_find_in_str_to_enum_hash_table(&s_header_str_to_enum, &cursor);
312     if (header >= 0) {
313         return (enum aws_http_header_name)header;
314     }
315     return AWS_HTTP_HEADER_UNKNOWN;
316 }
317 
aws_http_lowercase_str_to_header_name(struct aws_byte_cursor cursor)318 enum aws_http_header_name aws_http_lowercase_str_to_header_name(struct aws_byte_cursor cursor) {
319     int header = s_find_in_str_to_enum_hash_table(&s_lowercase_header_str_to_enum, &cursor);
320     if (header >= 0) {
321         return (enum aws_http_header_name)header;
322     }
323     return AWS_HTTP_HEADER_UNKNOWN;
324 }
325 
326 /* STATUS */
aws_http_status_text(int status_code)327 const char *aws_http_status_text(int status_code) {
328     /**
329      * Data from Internet Assigned Numbers Authority (IANA):
330      * https://www.iana.org/assignments/http-status-codes/http-status-codes.txt
331      */
332     switch (status_code) {
333         case AWS_HTTP_STATUS_CODE_100_CONTINUE:
334             return "Continue";
335         case AWS_HTTP_STATUS_CODE_101_SWITCHING_PROTOCOLS:
336             return "Switching Protocols";
337         case AWS_HTTP_STATUS_CODE_102_PROCESSING:
338             return "Processing";
339         case AWS_HTTP_STATUS_CODE_103_EARLY_HINTS:
340             return "Early Hints";
341         case AWS_HTTP_STATUS_CODE_200_OK:
342             return "OK";
343         case AWS_HTTP_STATUS_CODE_201_CREATED:
344             return "Created";
345         case AWS_HTTP_STATUS_CODE_202_ACCEPTED:
346             return "Accepted";
347         case AWS_HTTP_STATUS_CODE_203_NON_AUTHORITATIVE_INFORMATION:
348             return "Non-Authoritative Information";
349         case AWS_HTTP_STATUS_CODE_204_NO_CONTENT:
350             return "No Content";
351         case AWS_HTTP_STATUS_CODE_205_RESET_CONTENT:
352             return "Reset Content";
353         case AWS_HTTP_STATUS_CODE_206_PARTIAL_CONTENT:
354             return "Partial Content";
355         case AWS_HTTP_STATUS_CODE_207_MULTI_STATUS:
356             return "Multi-Status";
357         case AWS_HTTP_STATUS_CODE_208_ALREADY_REPORTED:
358             return "Already Reported";
359         case AWS_HTTP_STATUS_CODE_226_IM_USED:
360             return "IM Used";
361         case AWS_HTTP_STATUS_CODE_300_MULTIPLE_CHOICES:
362             return "Multiple Choices";
363         case AWS_HTTP_STATUS_CODE_301_MOVED_PERMANENTLY:
364             return "Moved Permanently";
365         case AWS_HTTP_STATUS_CODE_302_FOUND:
366             return "Found";
367         case AWS_HTTP_STATUS_CODE_303_SEE_OTHER:
368             return "See Other";
369         case AWS_HTTP_STATUS_CODE_304_NOT_MODIFIED:
370             return "Not Modified";
371         case AWS_HTTP_STATUS_CODE_305_USE_PROXY:
372             return "Use Proxy";
373         case AWS_HTTP_STATUS_CODE_307_TEMPORARY_REDIRECT:
374             return "Temporary Redirect";
375         case AWS_HTTP_STATUS_CODE_308_PERMANENT_REDIRECT:
376             return "Permanent Redirect";
377         case AWS_HTTP_STATUS_CODE_400_BAD_REQUEST:
378             return "Bad Request";
379         case AWS_HTTP_STATUS_CODE_401_UNAUTHORIZED:
380             return "Unauthorized";
381         case AWS_HTTP_STATUS_CODE_402_PAYMENT_REQUIRED:
382             return "Payment Required";
383         case AWS_HTTP_STATUS_CODE_403_FORBIDDEN:
384             return "Forbidden";
385         case AWS_HTTP_STATUS_CODE_404_NOT_FOUND:
386             return "Not Found";
387         case AWS_HTTP_STATUS_CODE_405_METHOD_NOT_ALLOWED:
388             return "Method Not Allowed";
389         case AWS_HTTP_STATUS_CODE_406_NOT_ACCEPTABLE:
390             return "Not Acceptable";
391         case AWS_HTTP_STATUS_CODE_407_PROXY_AUTHENTICATION_REQUIRED:
392             return "Proxy Authentication Required";
393         case AWS_HTTP_STATUS_CODE_408_REQUEST_TIMEOUT:
394             return "Request Timeout";
395         case AWS_HTTP_STATUS_CODE_409_CONFLICT:
396             return "Conflict";
397         case AWS_HTTP_STATUS_CODE_410_GONE:
398             return "Gone";
399         case AWS_HTTP_STATUS_CODE_411_LENGTH_REQUIRED:
400             return "Length Required";
401         case AWS_HTTP_STATUS_CODE_412_PRECONDITION_FAILED:
402             return "Precondition Failed";
403         case AWS_HTTP_STATUS_CODE_413_REQUEST_ENTITY_TOO_LARGE:
404             return "Payload Too Large";
405         case AWS_HTTP_STATUS_CODE_414_REQUEST_URI_TOO_LONG:
406             return "URI Too Long";
407         case AWS_HTTP_STATUS_CODE_415_UNSUPPORTED_MEDIA_TYPE:
408             return "Unsupported Media Type";
409         case AWS_HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE:
410             return "Range Not Satisfiable";
411         case AWS_HTTP_STATUS_CODE_417_EXPECTATION_FAILED:
412             return "Expectation Failed";
413         case AWS_HTTP_STATUS_CODE_421_MISDIRECTED_REQUEST:
414             return "Misdirected Request";
415         case AWS_HTTP_STATUS_CODE_422_UNPROCESSABLE_ENTITY:
416             return "Unprocessable Entity";
417         case AWS_HTTP_STATUS_CODE_423_LOCKED:
418             return "Locked";
419         case AWS_HTTP_STATUS_CODE_424_FAILED_DEPENDENCY:
420             return "Failed Dependency";
421         case AWS_HTTP_STATUS_CODE_425_TOO_EARLY:
422             return "Too Early";
423         case AWS_HTTP_STATUS_CODE_426_UPGRADE_REQUIRED:
424             return "Upgrade Required";
425         case AWS_HTTP_STATUS_CODE_428_PRECONDITION_REQUIRED:
426             return "Precondition Required";
427         case AWS_HTTP_STATUS_CODE_429_TOO_MANY_REQUESTS:
428             return "Too Many Requests";
429         case AWS_HTTP_STATUS_CODE_431_REQUEST_HEADER_FIELDS_TOO_LARGE:
430             return "Request Header Fields Too Large";
431         case AWS_HTTP_STATUS_CODE_451_UNAVAILABLE_FOR_LEGAL_REASON:
432             return "Unavailable For Legal Reasons";
433         case AWS_HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR:
434             return "Internal Server Error";
435         case AWS_HTTP_STATUS_CODE_501_NOT_IMPLEMENTED:
436             return "Not Implemented";
437         case AWS_HTTP_STATUS_CODE_502_BAD_GATEWAY:
438             return "Bad Gateway";
439         case AWS_HTTP_STATUS_CODE_503_SERVICE_UNAVAILABLE:
440             return "Service Unavailable";
441         case AWS_HTTP_STATUS_CODE_504_GATEWAY_TIMEOUT:
442             return "Gateway Timeout";
443         case AWS_HTTP_STATUS_CODE_505_HTTP_VERSION_NOT_SUPPORTED:
444             return "HTTP Version Not Supported";
445         case AWS_HTTP_STATUS_CODE_506_VARIANT_ALSO_NEGOTIATES:
446             return "Variant Also Negotiates";
447         case AWS_HTTP_STATUS_CODE_507_INSUFFICIENT_STORAGE:
448             return "Insufficient Storage";
449         case AWS_HTTP_STATUS_CODE_508_LOOP_DETECTED:
450             return "Loop Detected";
451         case AWS_HTTP_STATUS_CODE_510_NOT_EXTENDED:
452             return "Not Extended";
453         case AWS_HTTP_STATUS_CODE_511_NETWORK_AUTHENTICATION_REQUIRED:
454             return "Network Authentication Required";
455         default:
456             return "";
457     }
458 }
459 
460 static bool s_library_initialized = false;
aws_http_library_init(struct aws_allocator * alloc)461 void aws_http_library_init(struct aws_allocator *alloc) {
462     if (s_library_initialized) {
463         return;
464     }
465     s_library_initialized = true;
466 
467     aws_io_library_init(alloc);
468     aws_compression_library_init(alloc);
469     aws_register_error_info(&s_error_list);
470     aws_register_log_subject_info_list(&s_log_subject_list);
471     s_methods_init(alloc);
472     s_headers_init(alloc);
473     s_versions_init(alloc);
474     aws_hpack_static_table_init(alloc);
475 }
476 
aws_http_library_clean_up(void)477 void aws_http_library_clean_up(void) {
478     if (!s_library_initialized) {
479         return;
480     }
481     s_library_initialized = false;
482 
483     aws_thread_join_all_managed();
484     aws_unregister_error_info(&s_error_list);
485     aws_unregister_log_subject_info_list(&s_log_subject_list);
486     s_methods_clean_up();
487     s_headers_clean_up();
488     s_versions_clean_up();
489     aws_hpack_static_table_clean_up();
490     aws_compression_library_clean_up();
491     aws_io_library_clean_up();
492 }
493 
aws_http_fatal_assert_library_initialized()494 void aws_http_fatal_assert_library_initialized() {
495     if (!s_library_initialized) {
496         AWS_LOGF_FATAL(
497             AWS_LS_HTTP_GENERAL,
498             "aws_http_library_init() must be called before using any functionality in aws-c-http.");
499 
500         AWS_FATAL_ASSERT(s_library_initialized);
501     }
502 }
503 
504 const struct aws_byte_cursor aws_http_method_get = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GET");
505 const struct aws_byte_cursor aws_http_method_head = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("HEAD");
506 const struct aws_byte_cursor aws_http_method_post = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("POST");
507 const struct aws_byte_cursor aws_http_method_put = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("PUT");
508 const struct aws_byte_cursor aws_http_method_delete = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("DELETE");
509 const struct aws_byte_cursor aws_http_method_connect = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CONNECT");
510 const struct aws_byte_cursor aws_http_method_options = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("OPTIONS");
511 
512 const struct aws_byte_cursor aws_http_header_method = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":method");
513 const struct aws_byte_cursor aws_http_header_scheme = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":scheme");
514 const struct aws_byte_cursor aws_http_header_authority = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":authority");
515 const struct aws_byte_cursor aws_http_header_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":path");
516 const struct aws_byte_cursor aws_http_header_status = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(":status");
517 
518 const struct aws_byte_cursor aws_http_scheme_http = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("http");
519 const struct aws_byte_cursor aws_http_scheme_https = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("https");
520