1 #ifndef AWS_HTTP_H1_ENCODER_H 2 #define AWS_HTTP_H1_ENCODER_H 3 /** 4 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 * SPDX-License-Identifier: Apache-2.0. 6 */ 7 8 #include <aws/http/private/http_impl.h> 9 #include <aws/http/private/request_response_impl.h> 10 11 struct aws_h1_chunk { 12 struct aws_allocator *allocator; 13 struct aws_input_stream *data; 14 uint64_t data_size; 15 aws_http1_stream_write_chunk_complete_fn *on_complete; 16 void *user_data; 17 struct aws_linked_list_node node; 18 /* Buffer containing pre-encoded start line: chunk-size [chunk-ext] CRLF */ 19 struct aws_byte_buf chunk_line; 20 }; 21 22 /** 23 * Message to be submitted to encoder. 24 * Contains data necessary for encoder to write an outgoing request or response. 25 */ 26 struct aws_h1_encoder_message { 27 /* Upon creation, the "head" (everything preceding body) is buffered here. */ 28 struct aws_byte_buf outgoing_head_buf; 29 /* Single stream used for unchunked body */ 30 struct aws_input_stream *body; 31 32 /* Pointer to list of `struct aws_h1_chunk`, used for chunked encoding. 33 * List is owned by aws_h1_stream. 34 * Encoder completes/frees/pops front chunk when it's done sending. 35 * If list goes empty, encoder waits for more chunks to arrive. 36 * A chunk with data_size=0 means "final chunk" */ 37 struct aws_linked_list *pending_chunk_list; 38 39 /* If non-zero, length of unchunked body to send */ 40 uint64_t content_length; 41 bool has_connection_close_header; 42 bool has_chunked_encoding_header; 43 }; 44 45 enum aws_h1_encoder_state { 46 AWS_H1_ENCODER_STATE_INIT, 47 AWS_H1_ENCODER_STATE_HEAD, 48 AWS_H1_ENCODER_STATE_UNCHUNKED_BODY, 49 AWS_H1_ENCODER_STATE_CHUNK_NEXT, 50 AWS_H1_ENCODER_STATE_CHUNK_LINE, 51 AWS_H1_ENCODER_STATE_CHUNK_BODY, 52 AWS_H1_ENCODER_STATE_CHUNK_END, 53 AWS_H1_ENCODER_STATE_CHUNK_TRAILER, 54 AWS_H1_ENCODER_STATE_DONE, 55 }; 56 57 struct aws_h1_encoder { 58 struct aws_allocator *allocator; 59 60 enum aws_h1_encoder_state state; 61 /* Current message being encoded */ 62 struct aws_h1_encoder_message *message; 63 /* Used by some states to track progress. Reset to 0 whenever state changes */ 64 uint64_t progress_bytes; 65 /* Current chunk */ 66 struct aws_h1_chunk *current_chunk; 67 /* Number of chunks sent, just used for logging */ 68 size_t chunk_count; 69 /* Encoder logs with this stream ptr as the ID, and passes this ptr to the chunk_complete callback */ 70 struct aws_http_stream *current_stream; 71 }; 72 73 struct aws_h1_chunk *aws_h1_chunk_new(struct aws_allocator *allocator, const struct aws_http1_chunk_options *options); 74 75 /* Just destroy the chunk (don't fire callback) */ 76 void aws_h1_chunk_destroy(struct aws_h1_chunk *chunk); 77 78 /* Destroy chunk and fire its completion callback */ 79 void aws_h1_chunk_complete_and_destroy(struct aws_h1_chunk *chunk, struct aws_http_stream *http_stream, int error_code); 80 81 int aws_chunk_line_from_options(struct aws_http1_chunk_options *options, struct aws_byte_buf *chunk_line); 82 83 AWS_EXTERN_C_BEGIN 84 85 /* Validate request and cache any info the encoder will need later in the "encoder message". */ 86 AWS_HTTP_API 87 int aws_h1_encoder_message_init_from_request( 88 struct aws_h1_encoder_message *message, 89 struct aws_allocator *allocator, 90 const struct aws_http_message *request, 91 struct aws_linked_list *pending_chunk_list); 92 93 int aws_h1_encoder_message_init_from_response( 94 struct aws_h1_encoder_message *message, 95 struct aws_allocator *allocator, 96 const struct aws_http_message *response, 97 bool body_headers_ignored, 98 struct aws_linked_list *pending_chunk_list); 99 100 AWS_HTTP_API 101 void aws_h1_encoder_message_clean_up(struct aws_h1_encoder_message *message); 102 103 AWS_HTTP_API 104 void aws_h1_encoder_init(struct aws_h1_encoder *encoder, struct aws_allocator *allocator); 105 106 AWS_HTTP_API 107 void aws_h1_encoder_clean_up(struct aws_h1_encoder *encoder); 108 109 AWS_HTTP_API 110 int aws_h1_encoder_start_message( 111 struct aws_h1_encoder *encoder, 112 struct aws_h1_encoder_message *message, 113 struct aws_http_stream *stream); 114 115 AWS_HTTP_API 116 int aws_h1_encoder_process(struct aws_h1_encoder *encoder, struct aws_byte_buf *out_buf); 117 118 AWS_HTTP_API 119 bool aws_h1_encoder_is_message_in_progress(const struct aws_h1_encoder *encoder); 120 121 /* Return true if the encoder is stuck waiting for more chunks to be added to the current message */ 122 AWS_HTTP_API 123 bool aws_h1_encoder_is_waiting_for_chunks(const struct aws_h1_encoder *encoder); 124 125 AWS_EXTERN_C_END 126 127 #endif /* AWS_HTTP_H1_ENCODER_H */ 128