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