1 #ifndef AWS_EVENT_STREAM_H_
2 #define AWS_EVENT_STREAM_H_
3 
4 /**
5  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6  * SPDX-License-Identifier: Apache-2.0.
7  */
8 
9 #include <aws/common/array_list.h>
10 #include <aws/common/byte_buf.h>
11 #include <aws/common/logging.h>
12 #include <aws/event-stream/event_stream_exports.h>
13 
14 #include <stdio.h>
15 
16 #define AWS_C_EVENT_STREAM_PACKAGE_ID 4
17 /* max message size is 16MB */
18 #define AWS_EVENT_STREAM_MAX_MESSAGE_SIZE (16 * 1024 * 1024)
19 
20 /* max header size is 128kb */
21 #define AWS_EVENT_STREAM_MAX_HEADERS_SIZE (128 * 1024)
22 
23 enum aws_event_stream_errors {
24     AWS_ERROR_EVENT_STREAM_BUFFER_LENGTH_MISMATCH = AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_EVENT_STREAM_PACKAGE_ID),
25     AWS_ERROR_EVENT_STREAM_INSUFFICIENT_BUFFER_LEN,
26     AWS_ERROR_EVENT_STREAM_MESSAGE_FIELD_SIZE_EXCEEDED,
27     AWS_ERROR_EVENT_STREAM_PRELUDE_CHECKSUM_FAILURE,
28     AWS_ERROR_EVENT_STREAM_MESSAGE_CHECKSUM_FAILURE,
29     AWS_ERROR_EVENT_STREAM_MESSAGE_INVALID_HEADERS_LEN,
30     AWS_ERROR_EVENT_STREAM_MESSAGE_UNKNOWN_HEADER_TYPE,
31     AWS_ERROR_EVENT_STREAM_MESSAGE_PARSER_ILLEGAL_STATE,
32     AWS_ERROR_EVENT_STREAM_RPC_CONNECTION_CLOSED,
33     AWS_ERROR_EVENT_STREAM_RPC_PROTOCOL_ERROR,
34     AWS_ERROR_EVENT_STREAM_RPC_STREAM_CLOSED,
35     AWS_ERROR_EVENT_STREAM_RPC_STREAM_NOT_ACTIVATED,
36 
37     AWS_ERROR_EVENT_STREAM_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_EVENT_STREAM_PACKAGE_ID),
38 };
39 
40 enum aws_event_stream_log_subject {
41     AWS_LS_EVENT_STREAM_GENERAL = AWS_LOG_SUBJECT_BEGIN_RANGE(AWS_C_EVENT_STREAM_PACKAGE_ID),
42     AWS_LS_EVENT_STREAM_CHANNEL_HANDLER,
43     AWS_LS_EVENT_STREAM_RPC_SERVER,
44     AWS_LS_EVENT_STREAM_RPC_CLIENT,
45 
46     AWS_LS_EVENT_STREAM_LAST = AWS_LOG_SUBJECT_END_RANGE(AWS_C_EVENT_STREAM_PACKAGE_ID),
47 };
48 
49 struct aws_event_stream_message_prelude {
50     uint32_t total_len;
51     uint32_t headers_len;
52     uint32_t prelude_crc;
53 };
54 
55 struct aws_event_stream_message {
56     struct aws_allocator *alloc;
57     uint8_t *message_buffer;
58     uint8_t owns_buffer;
59 };
60 
61 #define AWS_EVENT_STREAM_PRELUDE_LENGTH (uint32_t)(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t))
62 
63 #define AWS_EVENT_STREAM_TRAILER_LENGTH (uint32_t)(sizeof(uint32_t))
64 
65 enum aws_event_stream_header_value_type {
66     AWS_EVENT_STREAM_HEADER_BOOL_TRUE = 0,
67     AWS_EVENT_STREAM_HEADER_BOOL_FALSE,
68     AWS_EVENT_STREAM_HEADER_BYTE,
69     AWS_EVENT_STREAM_HEADER_INT16,
70     AWS_EVENT_STREAM_HEADER_INT32,
71     AWS_EVENT_STREAM_HEADER_INT64,
72     AWS_EVENT_STREAM_HEADER_BYTE_BUF,
73     AWS_EVENT_STREAM_HEADER_STRING,
74     /* 64 bit integer (millis since epoch) */
75     AWS_EVENT_STREAM_HEADER_TIMESTAMP,
76     AWS_EVENT_STREAM_HEADER_UUID
77 };
78 
79 struct aws_event_stream_header_value_pair {
80     uint8_t header_name_len;
81     char header_name[INT8_MAX];
82     enum aws_event_stream_header_value_type header_value_type;
83     union {
84         uint8_t *variable_len_val;
85         uint8_t static_val[16];
86     } header_value;
87 
88     uint16_t header_value_len;
89     int8_t value_owned;
90 };
91 
92 struct aws_event_stream_streaming_decoder;
93 typedef int(aws_event_stream_process_state_fn)(
94     struct aws_event_stream_streaming_decoder *decoder,
95     const uint8_t *data,
96     size_t len,
97     size_t *processed);
98 
99 /**
100  * Called by aws_aws_event_stream_streaming_decoder when payload data has been received.
101  * 'data' doesn't belong to you, so copy the data if it is needed beyond the scope of your callback.
102  * final_segment == 1 indicates the current data is the last payload buffer for that message.
103  */
104 typedef void(aws_event_stream_process_on_payload_segment_fn)(
105     struct aws_event_stream_streaming_decoder *decoder,
106     struct aws_byte_buf *payload,
107     int8_t final_segment,
108     void *user_data);
109 
110 /**
111  * Called by aws_aws_event_stream_streaming_decoder when a new message has arrived. The prelude will contain metadata
112  * about the message. At this point no headers or payload have been received. prelude is copyable.
113  */
114 typedef void(aws_event_stream_prelude_received_fn)(
115     struct aws_event_stream_streaming_decoder *decoder,
116     struct aws_event_stream_message_prelude *prelude,
117     void *user_data);
118 
119 /**
120  * Called by aws_aws_event_stream_streaming_decoder when a header is encountered. 'header' is not yours. Copy the data
121  * you want from it if your scope extends beyond your callback.
122  */
123 typedef void(aws_event_stream_header_received_fn)(
124     struct aws_event_stream_streaming_decoder *decoder,
125     struct aws_event_stream_message_prelude *prelude,
126     struct aws_event_stream_header_value_pair *header,
127     void *user_data);
128 
129 /**
130  * Called by aws_aws_event_stream_streaming_decoder when an error is encountered. The decoder is not in a good state for
131  * usage after this callback.
132  */
133 typedef void(aws_event_stream_on_error_fn)(
134     struct aws_event_stream_streaming_decoder *decoder,
135     struct aws_event_stream_message_prelude *prelude,
136     int error_code,
137     const char *message,
138     void *user_data);
139 
140 struct aws_event_stream_streaming_decoder {
141     struct aws_allocator *alloc;
142     uint8_t working_buffer[AWS_EVENT_STREAM_PRELUDE_LENGTH];
143     size_t message_pos;
144     uint32_t running_crc;
145     size_t current_header_name_offset;
146     size_t current_header_value_offset;
147     struct aws_event_stream_header_value_pair current_header;
148     struct aws_event_stream_message_prelude prelude;
149     aws_event_stream_process_state_fn *state;
150     aws_event_stream_process_on_payload_segment_fn *on_payload;
151     aws_event_stream_prelude_received_fn *on_prelude;
152     aws_event_stream_header_received_fn *on_header;
153     aws_event_stream_on_error_fn *on_error;
154     void *user_context;
155 };
156 
157 AWS_EXTERN_C_BEGIN
158 
159 /**
160  * Initializes with a list of headers, the payload, and a payload length. CRCs will be computed for you.
161  * If headers or payload is NULL, then the fields will be appropriately set to indicate no headers and/or no payload.
162  * Both payload and headers will result in an allocation.
163  */
164 AWS_EVENT_STREAM_API int aws_event_stream_message_init(
165     struct aws_event_stream_message *message,
166     struct aws_allocator *alloc,
167     struct aws_array_list *headers,
168     struct aws_byte_buf *payload);
169 
170 /**
171  * Zero allocation, Zero copy. The message will simply wrap the buffer. The message functions are only useful as long as
172  * buffer is referencable memory.
173  */
174 AWS_EVENT_STREAM_API int aws_event_stream_message_from_buffer(
175     struct aws_event_stream_message *message,
176     struct aws_allocator *alloc,
177     struct aws_byte_buf *buffer);
178 
179 /**
180  * Allocates memory and copies buffer. Otherwise the same as aws_aws_event_stream_message_from_buffer. This is slower,
181  * but possibly safer.
182  */
183 AWS_EVENT_STREAM_API int aws_event_stream_message_from_buffer_copy(
184     struct aws_event_stream_message *message,
185     struct aws_allocator *alloc,
186     const struct aws_byte_buf *buffer);
187 
188 /**
189  * Cleans up any internally allocated memory. Always call this for API compatibility reasons, even if you only used the
190  * aws_aws_event_stream_message_from_buffer function.
191  */
192 AWS_EVENT_STREAM_API void aws_event_stream_message_clean_up(struct aws_event_stream_message *message);
193 
194 /**
195  * Returns the total length of the message (including the length field).
196  */
197 AWS_EVENT_STREAM_API uint32_t aws_event_stream_message_total_length(const struct aws_event_stream_message *message);
198 
199 /**
200  * Returns the length of the headers portion of the message.
201  */
202 AWS_EVENT_STREAM_API uint32_t aws_event_stream_message_headers_len(const struct aws_event_stream_message *message);
203 
204 /**
205  * Returns the prelude crc (crc32)
206  */
207 AWS_EVENT_STREAM_API uint32_t aws_event_stream_message_prelude_crc(const struct aws_event_stream_message *message);
208 
209 /**
210  * Writes the message to fd in json format. All strings and binary fields are base64 encoded.
211  */
212 AWS_EVENT_STREAM_API int aws_event_stream_message_to_debug_str(
213     FILE *fd,
214     const struct aws_event_stream_message *message);
215 
216 /**
217  * Adds the headers for the message to list. The memory in each header is owned as part of the message, do not free it
218  * or pass its address around.
219  */
220 AWS_EVENT_STREAM_API int aws_event_stream_message_headers(
221     const struct aws_event_stream_message *message,
222     struct aws_array_list *headers);
223 
224 /**
225  * Returns a pointer to the beginning of the message payload.
226  */
227 AWS_EVENT_STREAM_API const uint8_t *aws_event_stream_message_payload(const struct aws_event_stream_message *message);
228 
229 /**
230  * Returns the length of the message payload.
231  */
232 AWS_EVENT_STREAM_API uint32_t aws_event_stream_message_payload_len(const struct aws_event_stream_message *message);
233 
234 /**
235  * Returns the checksum of the entire message (crc32)
236  */
237 AWS_EVENT_STREAM_API uint32_t aws_event_stream_message_message_crc(const struct aws_event_stream_message *message);
238 
239 /**
240  * Returns the message as a buffer ready for transport.
241  */
242 AWS_EVENT_STREAM_API const uint8_t *aws_event_stream_message_buffer(const struct aws_event_stream_message *message);
243 
244 AWS_EVENT_STREAM_API uint32_t
245     aws_event_stream_compute_headers_required_buffer_len(const struct aws_array_list *headers);
246 
247 AWS_EVENT_STREAM_API size_t
248     aws_event_stream_write_headers_to_buffer(const struct aws_array_list *headers, uint8_t *buffer);
249 
250 /** Get the headers from the buffer, store them in the headers list.
251  * the user's responsibility to cleanup the list when they are finished with it.
252  * no buffer copies happen here, the lifetime of the buffer, must outlive the usage of the headers.
253  * returns error codes defined in the public interface.
254  */
255 AWS_EVENT_STREAM_API int aws_event_stream_read_headers_from_buffer(
256     struct aws_array_list *headers,
257     const uint8_t *buffer,
258     size_t headers_len);
259 /**
260  * Initialize a streaming decoder for messages with callbacks for usage and an optional user context pointer.
261  */
262 AWS_EVENT_STREAM_API void aws_event_stream_streaming_decoder_init(
263     struct aws_event_stream_streaming_decoder *decoder,
264     struct aws_allocator *alloc,
265     aws_event_stream_process_on_payload_segment_fn *on_payload_segment,
266     aws_event_stream_prelude_received_fn *on_prelude,
267     aws_event_stream_header_received_fn *on_header,
268     aws_event_stream_on_error_fn *on_error,
269     void *user_data);
270 
271 /**
272  * Currently, no memory is allocated inside aws_aws_event_stream_streaming_decoder, but for future API compatibility,
273  * you should call this when finished with it.
274  */
275 AWS_EVENT_STREAM_API void aws_event_stream_streaming_decoder_clean_up(
276     struct aws_event_stream_streaming_decoder *decoder);
277 
278 /**
279  * initializes a headers list for you. It will default to a capacity of 4 in dynamic mode.
280  */
281 AWS_EVENT_STREAM_API int aws_event_stream_headers_list_init(
282     struct aws_array_list *headers,
283     struct aws_allocator *allocator);
284 
285 /**
286  * Cleans up the headers list. Also deallocates any headers that were the result of a copy flag for strings or buffer.
287  */
288 AWS_EVENT_STREAM_API void aws_event_stream_headers_list_cleanup(struct aws_array_list *headers);
289 
290 /**
291  * Adds a string header to the list of headers. If copy is set to true, this will result in an allocation for the header
292  * value. Otherwise, the value will be set to the memory address of 'value'.
293  */
294 AWS_EVENT_STREAM_API int aws_event_stream_add_string_header(
295     struct aws_array_list *headers,
296     const char *name,
297     uint8_t name_len,
298     const char *value,
299     uint16_t value_len,
300     int8_t copy);
301 
302 AWS_EVENT_STREAM_API struct aws_event_stream_header_value_pair aws_event_stream_create_string_header(
303     struct aws_byte_cursor name,
304     struct aws_byte_cursor value);
305 
306 AWS_EVENT_STREAM_API struct aws_event_stream_header_value_pair aws_event_stream_create_int32_header(
307     struct aws_byte_cursor name,
308     int32_t value);
309 
310 /**
311  * Adds a byte header to the list of headers.
312  */
313 AWS_EVENT_STREAM_API int aws_event_stream_add_byte_header(
314     struct aws_array_list *headers,
315     const char *name,
316     uint8_t name_len,
317     int8_t value);
318 
319 /**
320  * Adds a bool header to the list of headers.
321  */
322 AWS_EVENT_STREAM_API int aws_event_stream_add_bool_header(
323     struct aws_array_list *headers,
324     const char *name,
325     uint8_t name_len,
326     int8_t value);
327 
328 /**
329  * adds a 16 bit integer to the list of headers.
330  */
331 AWS_EVENT_STREAM_API int aws_event_stream_add_int16_header(
332     struct aws_array_list *headers,
333     const char *name,
334     uint8_t name_len,
335     int16_t value);
336 
337 /**
338  * adds a 32 bit integer to the list of headers.
339  */
340 AWS_EVENT_STREAM_API int aws_event_stream_add_int32_header(
341     struct aws_array_list *headers,
342     const char *name,
343     uint8_t name_len,
344     int32_t value);
345 
346 /**
347  * adds a 64 bit integer to the list of headers.
348  */
349 AWS_EVENT_STREAM_API int aws_event_stream_add_int64_header(
350     struct aws_array_list *headers,
351     const char *name,
352     uint8_t name_len,
353     int64_t value);
354 
355 /**
356  * Adds a byte-buffer header to the list of headers. If copy is set to true, this will result in an allocation for the
357  * header value. Otherwise, the value will be set to the memory address of 'value'.
358  */
359 AWS_EVENT_STREAM_API int aws_event_stream_add_bytebuf_header(
360     struct aws_array_list *headers,
361     const char *name,
362     uint8_t name_len,
363     uint8_t *value,
364     uint16_t value_len,
365     int8_t copy);
366 
367 /**
368  * adds a 64 bit integer representing milliseconds since unix epoch to the list of headers.
369  */
370 AWS_EVENT_STREAM_API int aws_event_stream_add_timestamp_header(
371     struct aws_array_list *headers,
372     const char *name,
373     uint8_t name_len,
374     int64_t value);
375 
376 /**
377  * adds a uuid buffer to the list of headers. Value must always be 16 bytes long.
378  */
379 AWS_EVENT_STREAM_API int aws_event_stream_add_uuid_header(
380     struct aws_array_list *headers,
381     const char *name,
382     uint8_t name_len,
383     const uint8_t *value);
384 
385 /**
386  * Returns the header name. Note: this value is not null terminated
387  */
388 AWS_EVENT_STREAM_API struct aws_byte_buf aws_event_stream_header_name(
389     struct aws_event_stream_header_value_pair *header);
390 
391 /**
392  * Returns the header value as a string. Note: this value is not null terminated.
393  */
394 AWS_EVENT_STREAM_API struct aws_byte_buf aws_event_stream_header_value_as_string(
395     struct aws_event_stream_header_value_pair *header);
396 
397 /**
398  * Returns the header value as a byte
399  */
400 AWS_EVENT_STREAM_API int8_t aws_event_stream_header_value_as_byte(struct aws_event_stream_header_value_pair *header);
401 
402 /**
403  * Returns the header value as a boolean value.
404  */
405 AWS_EVENT_STREAM_API int8_t aws_event_stream_header_value_as_bool(struct aws_event_stream_header_value_pair *header);
406 
407 /**
408  * Returns the header value as a 16 bit integer.
409  */
410 AWS_EVENT_STREAM_API int16_t aws_event_stream_header_value_as_int16(struct aws_event_stream_header_value_pair *header);
411 
412 /**
413  * Returns the header value as a 32 bit integer.
414  */
415 AWS_EVENT_STREAM_API int32_t aws_event_stream_header_value_as_int32(struct aws_event_stream_header_value_pair *header);
416 
417 /**
418  * Returns the header value as a 64 bit integer.
419  */
420 AWS_EVENT_STREAM_API int64_t aws_event_stream_header_value_as_int64(struct aws_event_stream_header_value_pair *header);
421 
422 /**
423  * Returns the header value as a pointer to a byte buffer, call aws_event_stream_header_value_length to determine
424  * the length of the buffer.
425  */
426 AWS_EVENT_STREAM_API struct aws_byte_buf aws_event_stream_header_value_as_bytebuf(
427     struct aws_event_stream_header_value_pair *header);
428 
429 /**
430  * Returns the header value as a 64 bit integer representing milliseconds since unix epoch.
431  */
432 AWS_EVENT_STREAM_API int64_t
433     aws_event_stream_header_value_as_timestamp(struct aws_event_stream_header_value_pair *header);
434 
435 /**
436  * Returns the header value a byte buffer which is 16 bytes long. Represents a UUID.
437  */
438 AWS_EVENT_STREAM_API struct aws_byte_buf aws_event_stream_header_value_as_uuid(
439     struct aws_event_stream_header_value_pair *header);
440 
441 /**
442  * Returns the length of the header value buffer. This is mostly intended for string and byte buffer types.
443  */
444 AWS_EVENT_STREAM_API uint16_t aws_event_stream_header_value_length(struct aws_event_stream_header_value_pair *header);
445 
446 /**
447  * The main driver of the decoder. Pass data that should be decoded with its length. A likely use-case here is in
448  * response to a read event from an io-device
449  */
450 AWS_EVENT_STREAM_API int aws_event_stream_streaming_decoder_pump(
451     struct aws_event_stream_streaming_decoder *decoder,
452     const struct aws_byte_buf *data);
453 
454 /**
455  * Initializes internal datastructures used by aws-c-event-stream.
456  * Must be called before using any functionality in aws-c-event-stream.
457  */
458 AWS_EVENT_STREAM_API void aws_event_stream_library_init(struct aws_allocator *allocator);
459 
460 /**
461  * Clean up internal datastructures used by aws-c-event-stream.
462  * Must not be called until application is done using functionality in aws-c-event-stream.
463  */
464 AWS_EVENT_STREAM_API void aws_event_stream_library_clean_up(void);
465 
466 AWS_EXTERN_C_END
467 
468 #endif /* AWS_EVENT_STREAM_H_ */
469