Lesson 35 - Get Compute Auth Token Working

This commit is contained in:
Norman Lansing
2026-02-28 12:32:28 -05:00
parent 1d477ee42a
commit 4fde462bce
7743 changed files with 1397833 additions and 18 deletions

View File

@@ -0,0 +1,699 @@
#ifndef AWS_MQTT_CLIENT_H
#define AWS_MQTT_CLIENT_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/common/hash_table.h>
#include <aws/common/byte_buf.h>
#include <aws/common/ref_count.h>
#include <aws/common/string.h>
#include <aws/io/event_loop.h>
#include <aws/io/host_resolver.h>
#include <aws/mqtt/mqtt.h>
AWS_PUSH_SANE_WARNING_LEVEL
/* forward declares */
struct aws_client_bootstrap;
struct aws_http_header;
struct aws_http_message;
struct aws_http_proxy_options;
struct aws_mqtt5_client;
struct aws_socket_options;
struct aws_tls_connection_options;
/**
* Empty struct that is passed when on_connection_closed is called.
* Currently holds nothing but will allow expanding in the future should it be needed.
*/
struct on_connection_closed_data;
struct aws_mqtt_client {
struct aws_allocator *allocator;
struct aws_client_bootstrap *bootstrap;
struct aws_ref_count ref_count;
};
struct aws_mqtt_client_connection;
/**
* Callback called when a request roundtrip is complete (QoS0 immediately, QoS1 on PUBACK, QoS2 on PUBCOMP). Either
* succeed or not
*/
typedef void(aws_mqtt_op_complete_fn)(
struct aws_mqtt_client_connection *connection,
uint16_t packet_id,
int error_code,
void *userdata);
/**
* Called when a connection attempt is completed, either in success or error.
*
* If error code is AWS_ERROR_SUCCESS, then a CONNACK has been received from the server and return_code and
* session_present contain the values received. If error_code is not AWS_ERROR_SUCCESS, it refers to the internal error
* that occurred during connection, and return_code and session_present are invalid.
*/
typedef void(aws_mqtt_client_on_connection_complete_fn)(
struct aws_mqtt_client_connection *connection,
int error_code,
enum aws_mqtt_connect_return_code return_code,
bool session_present,
void *userdata);
/* Called when a connection attempt succeed (with a successful CONNACK)
*
* The callback is derived from aws_mqtt_client_on_connection_complete_fn.
* It gets triggered when connection succeed (with a successful CONNACK)
*/
typedef void(aws_mqtt_client_on_connection_success_fn)(
struct aws_mqtt_client_connection *connection,
enum aws_mqtt_connect_return_code return_code,
bool session_present,
void *userdata);
/* Called if the connection attempt failed.
*
* The callback is derived from aws_mqtt_client_on_connection_complete_fn.
* It gets triggered when connection failed.
*/
typedef void(aws_mqtt_client_on_connection_failure_fn)(
struct aws_mqtt_client_connection *connection,
int error_code,
void *userdata);
/* Called if the connection to the server is lost. */
typedef void(aws_mqtt_client_on_connection_interrupted_fn)(
struct aws_mqtt_client_connection *connection,
int error_code,
void *userdata);
/**
* Called if the connection to the server is closed by user request
* Note: Currently the "data" argument is always NULL, but this may change in the future if additional data is needed to
* be sent.
*/
typedef void(aws_mqtt_client_on_connection_closed_fn)(
struct aws_mqtt_client_connection *connection,
struct on_connection_closed_data *data,
void *userdata);
/**
* Called when a connection to the server is resumed
* (if clean_session is true, calling aws_mqtt_resubscribe_existing_topics is suggested)
*/
typedef void(aws_mqtt_client_on_connection_resumed_fn)(
struct aws_mqtt_client_connection *connection,
enum aws_mqtt_connect_return_code return_code,
bool session_present,
void *userdata);
/**
* Called when a multi-topic subscription request is complete.
* Note: If any topic_suback's qos value is AWS_MQTT_QOS_FAILURE,
* then that topic subscription was rejected by the broker.
*/
typedef void(aws_mqtt_suback_multi_fn)(
struct aws_mqtt_client_connection *connection,
uint16_t packet_id,
const struct aws_array_list *topic_subacks, /* contains aws_mqtt_topic_subscription pointers */
int error_code,
void *userdata);
/**
* Called when a single-topic subscription request is complete.
* Note: If the qos value is AWS_MQTT_QOS_FAILURE,
* then the subscription was rejected by the broker.
*/
typedef void(aws_mqtt_suback_fn)(
struct aws_mqtt_client_connection *connection,
uint16_t packet_id,
const struct aws_byte_cursor *topic,
enum aws_mqtt_qos qos,
int error_code,
void *userdata);
/**
* Called when a publish message is received.
*
* \param[in] connection The connection object
* \param[in] topic The information channel to which the payload data was published.
* \param[in] payload The payload data.
* \param[in] dup DUP flag. If true, this might be re-delivery of an earlier attempt to send the message.
* \param[in] qos Quality of Service used to deliver the message.
* \param[in] retain Retain flag. If true, the message was sent as a result of a new subscription being
* made by the client.
*/
typedef void(aws_mqtt_client_publish_received_fn)(
struct aws_mqtt_client_connection *connection,
const struct aws_byte_cursor *topic,
const struct aws_byte_cursor *payload,
bool dup,
enum aws_mqtt_qos qos,
bool retain,
void *userdata);
/** Called when a connection is closed, right before any resources are deleted */
typedef void(aws_mqtt_client_on_disconnect_fn)(struct aws_mqtt_client_connection *connection, void *userdata);
/**
* Signature of callback invoked on a connection destruction.
*/
typedef void(aws_mqtt_client_on_connection_termination_fn)(void *userdata);
/**
* Function to invoke when the websocket handshake request transformation completes.
* This function MUST be invoked or the application will soft-lock.
*
* `request` and `complete_ctx` must be the same pointers provided to the `aws_mqtt_transform_websocket_handshake_fn`.
* `error_code` should should be AWS_ERROR_SUCCESS if transformation was successful,
* otherwise pass a different AWS_ERROR_X value.
*/
typedef void(aws_mqtt_transform_websocket_handshake_complete_fn)(
struct aws_http_message *request,
int error_code,
void *complete_ctx);
/**
* Function that may transform the websocket handshake request.
* Called each time a websocket connection is attempted.
*
* The default request uses path "/mqtt". All required headers are present,
* plus the optional header "Sec-WebSocket-Protocol: mqtt".
*
* The user MUST invoke the `complete_fn` when transformation is complete or the application will soft-lock.
* When invoking the `complete_fn`, pass along the `request` and `complete_ctx` provided here and an error code.
* The error code should be AWS_ERROR_SUCCESS if transformation was successful,
* otherwise pass a different AWS_ERROR_X value.
*/
typedef void(aws_mqtt_transform_websocket_handshake_fn)(
struct aws_http_message *request,
void *user_data,
aws_mqtt_transform_websocket_handshake_complete_fn *complete_fn,
void *complete_ctx);
/**
* Function that may accept or reject a websocket handshake response.
* Called each time a valid websocket connection is established.
*
* All required headers have been checked already (ex: "Sec-Websocket-Accept"),
*
* Return AWS_OP_SUCCESS to accept the connection or AWS_OP_ERR to stop the connection attempt.
*/
typedef int aws_mqtt_validate_websocket_handshake_fn(
struct aws_mqtt_client_connection *connection,
const struct aws_http_header *header_array,
size_t num_headers,
void *userdata);
/** Passed to subscribe() and suback callbacks */
struct aws_mqtt_topic_subscription {
struct aws_byte_cursor topic;
enum aws_mqtt_qos qos;
aws_mqtt_client_publish_received_fn *on_publish;
aws_mqtt_userdata_cleanup_fn *on_cleanup;
void *on_publish_ud;
};
/**
* host_name The server name to connect to. This resource may be freed immediately on return.
* port The port on the server to connect to
* client_id The clientid to place in the CONNECT packet.
* socket_options The socket options to pass to the aws_client_bootstrap functions.
* This is copied into the connection
* tls_options TLS settings to use when opening a connection.
* This is copied into the connection
* Pass NULL to connect without TLS (NOT RECOMMENDED)
* clean_session True to discard all server session data and start fresh
* keep_alive_time_secs The keep alive value to place in the CONNECT PACKET, a PING will automatically
* be sent at this interval as well. If you specify 0, defaults will be used
* and a ping will be sent once per 20 minutes.
* This duration must be longer than ping_timeout_ms.
* ping_timeout_ms Network connection is re-established if a ping response is not received
* within this amount of time (milliseconds). If you specify 0, a default value of 3 seconds
* is used. Alternatively, tcp keep-alive may be away to accomplish this in a more efficient
* (low-power) scenario, but keep-alive options may not work the same way on every platform
* and OS version. This duration must be shorter than keep_alive_time_secs.
* protocol_operation_timeout_ms
* Timeout when waiting for the response to some operation requires response by protocol.
* Set to zero to disable timeout. Otherwise, the operation will fail with error
* AWS_ERROR_MQTT_TIMEOUT if no response is received within this amount of time after
* the packet is written to the socket. The timer is reset if the connection is interrupted.
* It applied to PUBLISH (QoS>0) and UNSUBSCRIBE now.
* Note: While the MQTT 3 specification states that a broker MUST respond,
* some brokers are known to ignore publish packets in exceptional circumstances
* (e.g. AWS IoT Core will not respond if the publish quota is exceeded).
* on_connection_complete The callback to fire when the connection attempt completes
* user_data Passed to the userdata param of on_connection_complete
*/
struct aws_mqtt_connection_options {
struct aws_byte_cursor host_name;
uint32_t port;
struct aws_socket_options *socket_options;
struct aws_tls_connection_options *tls_options;
struct aws_byte_cursor client_id;
uint16_t keep_alive_time_secs;
uint32_t ping_timeout_ms;
uint32_t protocol_operation_timeout_ms;
aws_mqtt_client_on_connection_complete_fn *on_connection_complete;
void *user_data;
bool clean_session;
};
/**
* Contains some simple statistics about the current state of the connection's queue of operations
*/
struct aws_mqtt_connection_operation_statistics {
/**
* total number of operations submitted to the connection that have not yet been completed. Unacked operations
* are a subset of this.
*/
uint64_t incomplete_operation_count;
/**
* total packet size of operations submitted to the connection that have not yet been completed. Unacked operations
* are a subset of this.
*/
uint64_t incomplete_operation_size;
/**
* total number of operations that have been sent to the server and are waiting for a corresponding ACK before
* they can be completed.
*/
uint64_t unacked_operation_count;
/**
* total packet size of operations that have been sent to the server and are waiting for a corresponding ACK before
* they can be completed.
*/
uint64_t unacked_operation_size;
};
AWS_EXTERN_C_BEGIN
/**
* Creates an instance of aws_mqtt_client.
*
* \param[in] allocator The allocator the client will use for all future allocations
* \param[in] bootstrap The client bootstrap to use to initiate new socket connections
*
* \returns a new instance of an aws_mqtt_client if successful, NULL otherwise
*/
AWS_MQTT_API
struct aws_mqtt_client *aws_mqtt_client_new(struct aws_allocator *allocator, struct aws_client_bootstrap *bootstrap);
/**
* Increments the ref count to an mqtt client, allowing the caller to take a reference to it
*
* \param[in] client The client to increment the ref count on
*
* \returns the mqtt client
*/
AWS_MQTT_API
struct aws_mqtt_client *aws_mqtt_client_acquire(struct aws_mqtt_client *client);
/**
* Decrements the ref count on an mqtt client. If the ref count drops to zero, the client is cleaned up.
*
* \param[in] client The client to release a ref count on
*/
AWS_MQTT_API
void aws_mqtt_client_release(struct aws_mqtt_client *client);
/**
* Spawns a new connection object.
*
* \param[in] client The client to spawn the connection from
*
* \returns a new mqtt connection on success, NULL otherwise
*/
AWS_MQTT_API
struct aws_mqtt_client_connection *aws_mqtt_client_connection_new(struct aws_mqtt_client *client);
/**
* Creates a new MQTT311 connection object that uses an MQTT5 client under the hood
*
* \param[in] client The mqtt5 client to create the connection from
*
* \returns a new mqtt (311) connection on success, NULL otherwise
*/
AWS_MQTT_API
struct aws_mqtt_client_connection *aws_mqtt_client_connection_new_from_mqtt5_client(struct aws_mqtt5_client *client);
/**
* Increments the ref count to an mqtt client connection, allowing the caller to take a reference to it
*
* \param[in] connection The connection object
*
* \returns the mqtt connection
*/
AWS_MQTT_API
struct aws_mqtt_client_connection *aws_mqtt_client_connection_acquire(struct aws_mqtt_client_connection *connection);
/**
* Decrements the ref count on an mqtt connection. If the ref count drops to zero, the connection is cleaned up.
* Note: cannot call this with lock held, since it will start the destroy process and cause a dead lock.
*
* \param[in] connection The connection object
*/
AWS_MQTT_API
void aws_mqtt_client_connection_release(struct aws_mqtt_client_connection *connection);
/**
* Sets the will message to send with the CONNECT packet.
*
* \param[in] connection The connection object
* \param[in] topic The topic to publish the will on
* \param[in] qos The QoS to publish the will with
* \param[in] retain The retain flag to publish the will with
* \param[in] payload The data if the will message
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_will(
struct aws_mqtt_client_connection *connection,
const struct aws_byte_cursor *topic,
enum aws_mqtt_qos qos,
bool retain,
const struct aws_byte_cursor *payload);
/**
* Sets the username and/or password to send with the CONNECT packet.
*
* \param[in] connection The connection object
* \param[in] username The username to connect with
* \param[in] password [optional] The password to connect with
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_login(
struct aws_mqtt_client_connection *connection,
const struct aws_byte_cursor *username,
const struct aws_byte_cursor *password);
/**
* Use MQTT over websockets when connecting.
* Requires the MQTT_WITH_WEBSOCKETS build option.
*
* In this scenario, an HTTP connection is established, which is then upgraded to a websocket connection,
* which is then used to send MQTT data.
*
* \param[in] connection The connection object.
* \param[in] transformer [optional] Function that may transform the websocket handshake request.
* See `aws_mqtt_transform_websocket_handshake_fn` for more info.
* \param[in] transformer_ud [optional] Userdata for request_transformer.
* \param[in] validator [optional] Function that may reject the websocket handshake response.
* \param[in] validator_ud [optional] Userdata for response_validator.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_use_websockets(
struct aws_mqtt_client_connection *connection,
aws_mqtt_transform_websocket_handshake_fn *transformer,
void *transformer_ud,
aws_mqtt_validate_websocket_handshake_fn *validator,
void *validator_ud);
/**
* Set http proxy options for the connection.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_http_proxy_options(
struct aws_mqtt_client_connection *connection,
struct aws_http_proxy_options *proxy_options);
/**
* Set host resolution ooptions for the connection.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_host_resolution_options(
struct aws_mqtt_client_connection *connection,
const struct aws_host_resolution_config *host_resolution_config);
/**
* Sets the minimum and maximum reconnect timeouts.
*
* The time between reconnect attempts will start at min and multiply by 2 until max is reached.
*
* \param[in] connection The connection object
* \param[in] min_timeout The timeout to start with
* \param[in] max_timeout The highest allowable wait time between reconnect attempts
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_reconnect_timeout(
struct aws_mqtt_client_connection *connection,
uint64_t min_timeout,
uint64_t max_timeout);
/**
* Sets the callbacks to call when a connection succeeds or fails
*
* \param[in] connection The connection object
* \param[in] on_connection_success The function to call when a connection is successful or gets resumed
* \param[in] on_connection_success_ud Userdata for on_connection_success
* \param[in] on_connection_failure The function to call when a connection fails
* \param[in] on_connection_failure_ud Userdata for on_connection_failure
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_connection_result_handlers(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_on_connection_success_fn *on_connection_success,
void *on_connection_success_ud,
aws_mqtt_client_on_connection_failure_fn *on_connection_failure,
void *on_connection_failure_ud);
/**
* Sets the callbacks to call when a connection is interrupted and resumed.
*
* \param[in] connection The connection object
* \param[in] on_interrupted The function to call when a connection is lost
* \param[in] on_interrupted_ud Userdata for on_interrupted
* \param[in] on_resumed The function to call when a connection is resumed
(if clean_session is true, calling aws_mqtt_resubscribe_existing_topics is suggested)
* \param[in] on_resumed_ud Userdata for on_resumed
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_connection_interruption_handlers(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_on_connection_interrupted_fn *on_interrupted,
void *on_interrupted_ud,
aws_mqtt_client_on_connection_resumed_fn *on_resumed,
void *on_resumed_ud);
/**
* Sets the callback to call when the connection is closed normally by user request.
* This is different than the connection interrupted or lost, this only covers successful
* closure.
*
* \param[in] connection The connection object
* \param[in] on_closed The function to call when a connection is closed
* \param[in] on_closed_ud Userdata for on_closed
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_connection_closed_handler(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_on_connection_closed_fn *on_closed,
void *on_closed_ud);
/**
* Sets the callback to call whenever ANY publish packet is received. Only safe to set when connection is not connected.
*
* \param[in] connection The connection object
* \param[in] on_any_publish The function to call when a publish is received (pass NULL to unset)
* \param[in] on_any_publish_ud Userdata for on_any_publish
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_on_any_publish_handler(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_publish_received_fn *on_any_publish,
void *on_any_publish_ud);
/**
* Sets the callback to call on a connection destruction.
*
* \param[in] connection The connection object.
* \param[in] on_termination The function to call when a connection is destroyed.
* \param[in] on_termination_ud Userdata for on_termination.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_set_connection_termination_handler(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_on_connection_termination_fn *on_termination,
void *on_termination_ud);
/**
* Opens the actual connection defined by aws_mqtt_client_connection_new.
* Once the connection is opened, on_connack will be called. Only called when connection is disconnected.
*
* \param[in] connection The connection object
* \param[in] connection_options Configuration information for the connection attempt
*
* \returns AWS_OP_SUCCESS if the connection has been successfully initiated,
* otherwise AWS_OP_ERR and aws_last_error() will be set.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_connect(
struct aws_mqtt_client_connection *connection,
const struct aws_mqtt_connection_options *connection_options);
/**
* DEPRECATED
* Opens the actual connection defined by aws_mqtt_client_connection_new.
* Once the connection is opened, on_connack will be called.
*
* Must be called on a connection that has previously been open,
* as the parameters passed during the last connection will be reused.
*
* \param[in] connection The connection object
* \param[in] on_connection_complete The callback to fire when the connection attempt completes
* \param[in] userdata (nullable) Passed to the userdata param of on_connection_complete
*
* \returns AWS_OP_SUCCESS if the connection has been successfully initiated,
* otherwise AWS_OP_ERR and aws_last_error() will be set.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_reconnect(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_on_connection_complete_fn *on_connection_complete,
void *userdata);
/**
* Closes the connection asynchronously, calls the on_disconnect callback.
* All uncompleted requests (publish/subscribe/unsubscribe) will be cancelled, regardless to the status of
* clean_session. DISCONNECT packet will be sent, which deletes the will message from server.
*
* \param[in] connection The connection to close
* \param[in] on_disconnect (nullable) Callback function to invoke when the connection is completely disconnected.
* \param[in] userdata (nullable) passed to on_disconnect
*
* \returns AWS_OP_SUCCESS if the connection is open and is being shutdown,
* otherwise AWS_OP_ERR and aws_last_error() is set.
*/
AWS_MQTT_API
int aws_mqtt_client_connection_disconnect(
struct aws_mqtt_client_connection *connection,
aws_mqtt_client_on_disconnect_fn *on_disconnect,
void *userdata);
/**
* Subscribe to topic filters. on_publish will be called when a PUBLISH matching each topic_filter is received.
*
* \param[in] connection The connection to subscribe on
* \param[in] topic_filters An array_list of aws_mqtt_topic_subscription (NOT pointers) describing the requests.
* \param[in] on_suback (nullable) Called when a SUBACK has been received from the server and the subscription
* is complete. Broker may fail one of the topics, check the qos in
* aws_mqtt_topic_subscription from the callback
* \param[in] on_suback_ud (nullable) Passed to on_suback
*
* \returns The packet id of the subscribe packet if successfully sent, otherwise 0.
*/
AWS_MQTT_API
uint16_t aws_mqtt_client_connection_subscribe_multiple(
struct aws_mqtt_client_connection *connection,
const struct aws_array_list *topic_filters,
aws_mqtt_suback_multi_fn *on_suback,
void *on_suback_ud);
/**
* Subscribe to a single topic filter. on_publish will be called when a PUBLISH matching topic_filter is received.
*
* \param[in] connection The connection to subscribe on
* \param[in] topic_filter The topic filter to subscribe on. This resource must persist until on_suback.
* \param[in] qos The maximum QoS of messages to receive
* \param[in] on_publish (nullable) Called when a PUBLISH packet matching topic_filter is received
* \param[in] on_publish_ud (nullable) Passed to on_publish
* \param[in] on_ud_cleanup (nullable) Called when a subscription is removed, on_publish_ud is passed.
* \param[in] on_suback (nullable) Called when a SUBACK has been received from the server and the subscription is
* complete
* \param[in] on_suback_ud (nullable) Passed to on_suback
*
* \returns The packet id of the subscribe packet if successfully sent, otherwise 0.
*/
AWS_MQTT_API
uint16_t aws_mqtt_client_connection_subscribe(
struct aws_mqtt_client_connection *connection,
const struct aws_byte_cursor *topic_filter,
enum aws_mqtt_qos qos,
aws_mqtt_client_publish_received_fn *on_publish,
void *on_publish_ud,
aws_mqtt_userdata_cleanup_fn *on_ud_cleanup,
aws_mqtt_suback_fn *on_suback,
void *on_suback_ud);
/**
* Resubscribe to all topics currently subscribed to. This is to help when resuming a connection with a clean session.
*
* \param[in] connection The connection to subscribe on
* \param[in] on_suback (nullable) Called when a SUBACK has been received from the server and the subscription is
* complete
* \param[in] on_suback_ud (nullable) Passed to on_suback
*
* \returns The packet id of the subscribe packet if successfully sent, otherwise 0 (and aws_last_error() will be set).
*/
AWS_MQTT_API
uint16_t aws_mqtt_resubscribe_existing_topics(
struct aws_mqtt_client_connection *connection,
aws_mqtt_suback_multi_fn *on_suback,
void *on_suback_ud);
/**
* Unsubscribe to a topic filter.
*
* \param[in] connection The connection to unsubscribe on
* \param[in] topic_filter The topic filter to unsubscribe on. This resource must persist until on_unsuback.
* \param[in] on_unsuback (nullable) Called when a UNSUBACK has been received from the server and the subscription
* is removed
* \param[in] on_unsuback_ud (nullable) Passed to on_unsuback
*
* \returns The packet id of the unsubscribe packet if successfully sent, otherwise 0.
*/
AWS_MQTT_API
uint16_t aws_mqtt_client_connection_unsubscribe(
struct aws_mqtt_client_connection *connection,
const struct aws_byte_cursor *topic_filter,
aws_mqtt_op_complete_fn *on_unsuback,
void *on_unsuback_ud);
/**
* Send a PUBLISH packet over connection.
*
* \param[in] connection The connection to publish on
* \param[in] topic The topic to publish on
* \param[in] qos The requested QoS of the packet
* \param[in] retain True to have the server save the packet, and send to all new subscriptions matching topic
* \param[in] payload The data to send as the payload of the publish
* \param[in] on_complete (nullable) For QoS 0, called as soon as the packet is sent
* For QoS 1, called when PUBACK is received
* For QoS 2, called when PUBCOMP is received
* \param[in] user_data (nullable) Passed to on_complete
*
* \returns The packet id of the publish packet if successfully sent, otherwise 0.
*/
AWS_MQTT_API
uint16_t aws_mqtt_client_connection_publish(
struct aws_mqtt_client_connection *connection,
const struct aws_byte_cursor *topic,
enum aws_mqtt_qos qos,
bool retain,
const struct aws_byte_cursor *payload,
aws_mqtt_op_complete_fn *on_complete,
void *userdata);
/**
* Queries the connection's internal statistics for incomplete/unacked operations.
* \param connection connection to get statistics for
* \param stats set of incomplete/unacked operation statistics
* \returns AWS_OP_SUCCESS if getting the operation statistics were successful, AWS_OP_ERR otherwise
*/
AWS_MQTT_API
int aws_mqtt_client_connection_get_stats(
struct aws_mqtt_client_connection *connection,
struct aws_mqtt_connection_operation_statistics *stats);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_MQTT_CLIENT_H */

View File

@@ -0,0 +1,27 @@
#ifndef AWS_MQTT_EXPORTS_H
#define AWS_MQTT_EXPORTS_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#if defined(USE_WINDOWS_DLL_SEMANTICS) || defined(WIN32)
# ifdef AWS_MQTT_USE_IMPORT_EXPORT
# ifdef AWS_MQTT_EXPORTS
# define AWS_MQTT_API __declspec(dllexport)
# else
# define AWS_MQTT_API __declspec(dllimport)
# endif /* AWS_MQTT_EXPORTS */
# else
# define AWS_MQTT_API
# endif /* USE_IMPORT_EXPORT */
#else /* defined (USE_WINDOWS_DLL_SEMANTICS) || defined (WIN32) */
# if ((__GNUC__ >= 4) || defined(__clang__)) && defined(AWS_MQTT_USE_IMPORT_EXPORT) && defined(AWS_MQTT_EXPORTS)
# define AWS_MQTT_API __attribute__((visibility("default")))
# else
# define AWS_MQTT_API
# endif /* __GNUC__ >= 4 || defined(__clang__) */
#endif /* defined (USE_WINDOWS_DLL_SEMANTICS) || defined (WIN32) */
#endif /* AWS_MQTT_EXPORTS_H */

View File

@@ -0,0 +1,149 @@
#ifndef AWS_MQTT_MQTT_H
#define AWS_MQTT_MQTT_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/common/byte_buf.h>
#include <aws/common/logging.h>
#include <aws/mqtt/exports.h>
AWS_PUSH_SANE_WARNING_LEVEL
#define AWS_C_MQTT_PACKAGE_ID 5
/* Quality of Service associated with a publish action or subscription [MQTT-4.3]. */
enum aws_mqtt_qos {
AWS_MQTT_QOS_AT_MOST_ONCE = 0x0,
AWS_MQTT_QOS_AT_LEAST_ONCE = 0x1,
AWS_MQTT_QOS_EXACTLY_ONCE = 0x2,
/* reserved = 3 */
AWS_MQTT_QOS_FAILURE = 0x80, /* Only used in SUBACK packets */
};
/* Result of a connect request [MQTT-3.2.2.3]. */
enum aws_mqtt_connect_return_code {
AWS_MQTT_CONNECT_ACCEPTED,
AWS_MQTT_CONNECT_UNACCEPTABLE_PROTOCOL_VERSION,
AWS_MQTT_CONNECT_IDENTIFIER_REJECTED,
AWS_MQTT_CONNECT_SERVER_UNAVAILABLE,
AWS_MQTT_CONNECT_BAD_USERNAME_OR_PASSWORD,
AWS_MQTT_CONNECT_NOT_AUTHORIZED,
/* reserved = 6 - 255 */
};
enum aws_mqtt_error {
AWS_ERROR_MQTT_INVALID_RESERVED_BITS = AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_MQTT_PACKAGE_ID),
AWS_ERROR_MQTT_BUFFER_TOO_BIG,
AWS_ERROR_MQTT_INVALID_REMAINING_LENGTH,
AWS_ERROR_MQTT_UNSUPPORTED_PROTOCOL_NAME,
AWS_ERROR_MQTT_UNSUPPORTED_PROTOCOL_LEVEL,
AWS_ERROR_MQTT_INVALID_CREDENTIALS,
AWS_ERROR_MQTT_INVALID_QOS,
AWS_ERROR_MQTT_INVALID_PACKET_TYPE,
AWS_ERROR_MQTT_INVALID_TOPIC,
AWS_ERROR_MQTT_TIMEOUT,
AWS_ERROR_MQTT_PROTOCOL_ERROR,
AWS_ERROR_MQTT_NOT_CONNECTED,
AWS_ERROR_MQTT_ALREADY_CONNECTED,
AWS_ERROR_MQTT_BUILT_WITHOUT_WEBSOCKETS,
AWS_ERROR_MQTT_UNEXPECTED_HANGUP,
AWS_ERROR_MQTT_CONNECTION_SHUTDOWN,
AWS_ERROR_MQTT_CONNECTION_DESTROYED,
AWS_ERROR_MQTT_CONNECTION_DISCONNECTING,
AWS_ERROR_MQTT_CANCELLED_FOR_CLEAN_SESSION,
AWS_ERROR_MQTT_QUEUE_FULL,
AWS_ERROR_MQTT5_CLIENT_OPTIONS_VALIDATION,
AWS_ERROR_MQTT5_CONNECT_OPTIONS_VALIDATION,
AWS_ERROR_MQTT5_DISCONNECT_OPTIONS_VALIDATION,
AWS_ERROR_MQTT5_PUBLISH_OPTIONS_VALIDATION,
AWS_ERROR_MQTT5_SUBSCRIBE_OPTIONS_VALIDATION,
AWS_ERROR_MQTT5_UNSUBSCRIBE_OPTIONS_VALIDATION,
AWS_ERROR_MQTT5_USER_PROPERTY_VALIDATION,
AWS_ERROR_MQTT5_PACKET_VALIDATION,
AWS_ERROR_MQTT5_ENCODE_FAILURE,
AWS_ERROR_MQTT5_DECODE_PROTOCOL_ERROR,
AWS_ERROR_MQTT5_CONNACK_CONNECTION_REFUSED,
AWS_ERROR_MQTT5_CONNACK_TIMEOUT,
AWS_ERROR_MQTT5_PING_RESPONSE_TIMEOUT,
AWS_ERROR_MQTT5_USER_REQUESTED_STOP,
AWS_ERROR_MQTT5_DISCONNECT_RECEIVED,
AWS_ERROR_MQTT5_CLIENT_TERMINATED,
AWS_ERROR_MQTT5_OPERATION_FAILED_DUE_TO_OFFLINE_QUEUE_POLICY,
AWS_ERROR_MQTT5_ENCODE_SIZE_UNSUPPORTED_PACKET_TYPE,
AWS_ERROR_MQTT5_OPERATION_PROCESSING_FAILURE,
AWS_ERROR_MQTT5_INVALID_INBOUND_TOPIC_ALIAS,
AWS_ERROR_MQTT5_INVALID_OUTBOUND_TOPIC_ALIAS,
AWS_ERROR_MQTT5_INVALID_UTF8_STRING,
AWS_ERROR_MQTT_CONNECTION_RESET_FOR_ADAPTER_CONNECT,
AWS_ERROR_MQTT_CONNECTION_RESUBSCRIBE_NO_TOPICS,
AWS_ERROR_MQTT_CONNECTION_SUBSCRIBE_FAILURE,
AWS_ERROR_MQTT_ACK_REASON_CODE_FAILURE,
AWS_ERROR_MQTT_PROTOCOL_ADAPTER_FAILING_REASON_CODE,
AWS_ERROR_MQTT_REQUEST_RESPONSE_CLIENT_SHUT_DOWN,
AWS_ERROR_MQTT_REQUEST_RESPONSE_TIMEOUT,
AWS_ERROR_MQTT_REQUEST_RESPONSE_NO_SUBSCRIPTION_CAPACITY,
AWS_ERROR_MQTT_REQUEST_RESPONSE_SUBSCRIBE_FAILURE,
AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR,
AWS_ERROR_MQTT_REQUEST_RESPONSE_PUBLISH_FAILURE,
AWS_ERROR_MQTT_REUQEST_RESPONSE_STREAM_ALREADY_ACTIVATED,
AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR,
AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR,
AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH,
AWS_ERROR_END_MQTT_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_MQTT_PACKAGE_ID),
};
enum aws_mqtt_log_subject {
AWS_LS_MQTT_GENERAL = AWS_LOG_SUBJECT_BEGIN_RANGE(AWS_C_MQTT_PACKAGE_ID),
AWS_LS_MQTT_CLIENT,
AWS_LS_MQTT_TOPIC_TREE,
AWS_LS_MQTT5_GENERAL,
AWS_LS_MQTT5_CLIENT,
AWS_LS_MQTT5_CANARY,
AWS_LS_MQTT5_TO_MQTT3_ADAPTER,
AWS_LS_MQTT_REQUEST_RESPONSE,
};
/** Function called on cleanup of a userdata. */
typedef void(aws_mqtt_userdata_cleanup_fn)(void *userdata);
AWS_EXTERN_C_BEGIN
AWS_MQTT_API
bool aws_mqtt_is_valid_topic(const struct aws_byte_cursor *topic);
AWS_MQTT_API
bool aws_mqtt_is_valid_topic_filter(const struct aws_byte_cursor *topic_filter);
/**
* Validate utf-8 string under mqtt specs
*
* @param text
* @return AWS_OP_SUCCESS if the text is validate, otherwise AWS_OP_ERR
*/
AWS_MQTT_API int aws_mqtt_validate_utf8_text(struct aws_byte_cursor text);
/**
* Initializes internal datastructures used by aws-c-mqtt.
* Must be called before using any functionality in aws-c-mqtt.
*/
AWS_MQTT_API
void aws_mqtt_library_init(struct aws_allocator *allocator);
/**
* Shuts down the internal datastructures used by aws-c-mqtt.
*/
AWS_MQTT_API
void aws_mqtt_library_clean_up(void);
AWS_MQTT_API
void aws_mqtt_fatal_assert_library_initialized(void);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_MQTT_MQTT_H */

View File

@@ -0,0 +1,37 @@
#ifndef AWS_MQTT_CLIENT_TEST_HELPER_H
#define AWS_MQTT_CLIENT_TEST_HELPER_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/common/stdint.h>
#include <aws/mqtt/exports.h>
struct aws_allocator;
struct aws_byte_cursor;
struct aws_mqtt_client_connection_311_impl;
struct aws_string;
AWS_EXTERN_C_BEGIN
/** This is for testing applications sending MQTT payloads. Don't ever include this file outside of a unit test. */
/** result buffer will be initialized and payload will be written into it */
AWS_MQTT_API
int aws_mqtt_client_get_payload_for_outstanding_publish_packet(
struct aws_mqtt_client_connection *connection,
uint16_t packet_id,
struct aws_allocator *allocator,
struct aws_byte_buf *result);
AWS_MQTT_API
int aws_mqtt_client_get_topic_for_outstanding_publish_packet(
struct aws_mqtt_client_connection *connection,
uint16_t packet_id,
struct aws_allocator *allocator,
struct aws_string **result);
AWS_EXTERN_C_END
#endif // AWS_C_IOT_MQTT_CLIENT_TEST_HELPER_H

View File

@@ -0,0 +1,274 @@
#ifndef AWS_MQTT_REQUEST_RESPONSE_REQUEST_RESPONSE_CLIENT_H
#define AWS_MQTT_REQUEST_RESPONSE_REQUEST_RESPONSE_CLIENT_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/mqtt/mqtt.h>
struct aws_event_loop;
struct aws_mqtt_request_response_client;
struct aws_mqtt_client_connection;
struct aws_mqtt5_client;
/*
* A response path is a pair of values - MQTT topic and a JSON path - that describe where a response to
* an MQTT-based request may arrive. For a given request type, there may be multiple response paths and each
* one is associated with a separate JSON schema for the response body.
*/
struct aws_mqtt_request_operation_response_path {
/*
* MQTT topic that a response may arrive on.
*/
struct aws_byte_cursor topic;
/*
* JSON path for finding correlation tokens within payloads that arrive on this path's topic.
*/
struct aws_byte_cursor correlation_token_json_path;
};
/*
* Callback signature for request-response completion.
*
* Invariants:
* If error_code is non-zero then response_topic and payload will be NULL.
* If response_topic and payload are not NULL then error_code will be 0.
* response_topic and payload are either both set or both not set.
*/
typedef void(aws_mqtt_request_operation_completion_fn)(
const struct aws_byte_cursor *response_topic,
const struct aws_byte_cursor *payload,
int error_code,
void *user_data);
/*
* Configuration options for a request-response operation.
*/
struct aws_mqtt_request_operation_options {
/*
* Set of topic filters that should be subscribed to in order to cover all possible response paths. Sometimes
* we can use wildcards to cut down on the subscriptions needed; sometimes we can't.
*/
struct aws_byte_cursor *subscription_topic_filters;
size_t subscription_topic_filter_count;
/*
* Set of all possible response paths associated with this request type
*/
struct aws_mqtt_request_operation_response_path *response_paths;
size_t response_path_count;
/*
* Topic to publish the request to once response subscriptions have been established.
*/
struct aws_byte_cursor publish_topic;
/*
* Payload to publish in order to initiate the request
*/
struct aws_byte_cursor serialized_request;
/*
* Correlation token embedded in the request that must be found in a response message. This can be the
* empty cursor to support certain services which don't use correlation tokens. In this case, the client
* only allows one request at a time to use the associated subscriptions; no concurrency is possible. There
* are some optimizations we could make here but for now, they're not worth the complexity.
*/
struct aws_byte_cursor correlation_token;
/*
* Callback (and associated user data) to invoke when the request is completed.
*/
aws_mqtt_request_operation_completion_fn *completion_callback;
void *user_data;
};
/*
* Describes a change to the state of a streaming operation subscription
*/
enum aws_rr_streaming_subscription_event_type {
/*
* The streaming operation is successfully subscribed to its topic (filter)
*/
ARRSSET_SUBSCRIPTION_ESTABLISHED,
/*
* The streaming operation has temporarily lost its subscription to its topic (filter)
*/
ARRSSET_SUBSCRIPTION_LOST,
/*
* The streaming operation has entered a terminal state where it has given up trying to subscribe
* to its topic (filter). This is always due to user error (bad topic filter or IoT Core permission policy).
*/
ARRSSET_SUBSCRIPTION_HALTED,
};
/*
* Callback signature for when the subscription status of a streaming operation changes.
*/
typedef void(aws_mqtt_streaming_operation_subscription_status_fn)(
enum aws_rr_streaming_subscription_event_type status,
int error_code,
void *user_data);
/*
* Callback signature for when a publish arrives that matches a streaming operation's subscription
*/
typedef void(aws_mqtt_streaming_operation_incoming_publish_fn)(struct aws_byte_cursor payload, void *user_data);
/*
* Callback signature for when a streaming operation is fully destroyed and no more events will be emitted.
*/
typedef void(aws_mqtt_streaming_operation_terminated_fn)(void *user_data);
/*
* Configuration options for a streaming operation.
*/
struct aws_mqtt_streaming_operation_options {
/*
* Topic filter that the streaming operation should listen on
*/
struct aws_byte_cursor topic_filter;
/*
* Callback for subscription status events
*/
aws_mqtt_streaming_operation_subscription_status_fn *subscription_status_callback;
/*
* Callback for publish messages that match the operation's topic filter
*/
aws_mqtt_streaming_operation_incoming_publish_fn *incoming_publish_callback;
/*
* Callback for streaming operation final shutdown
*/
aws_mqtt_streaming_operation_terminated_fn *terminated_callback;
/*
* Data passed to all streaming operation callbacks
*/
void *user_data;
};
typedef void(aws_mqtt_request_response_client_initialized_callback_fn)(void *user_data);
typedef void(aws_mqtt_request_response_client_terminated_callback_fn)(void *user_data);
/*
* Request-response client configuration options
*/
struct aws_mqtt_request_response_client_options {
/*
* Maximum number of subscriptions that the client will concurrently use for request-response operations
*/
size_t max_request_response_subscriptions;
/*
* Maximum number of subscriptions that the client will concurrently use for streaming operations
*/
size_t max_streaming_subscriptions;
/*
* Duration, in seconds, that a request-response operation will wait for completion before giving up
*/
uint32_t operation_timeout_seconds;
/*
* Request-response client initialization is asynchronous. This callback is invoked when the client is fully
* initialized.
*
* Do not bind the initialized callback; it exists mostly for tests and should not be exposed
*/
aws_mqtt_request_response_client_initialized_callback_fn *initialized_callback;
/*
* Callback invoked when the client's asynchronous destruction process has fully completed.
*/
aws_mqtt_request_response_client_terminated_callback_fn *terminated_callback;
/*
* Arbitrary data to pass to the client callbacks
*/
void *user_data;
};
AWS_EXTERN_C_BEGIN
/*
* Create a new request-response client that uses an MQTT311 client.
*/
AWS_MQTT_API struct aws_mqtt_request_response_client *aws_mqtt_request_response_client_new_from_mqtt311_client(
struct aws_allocator *allocator,
struct aws_mqtt_client_connection *client,
const struct aws_mqtt_request_response_client_options *options);
/*
* Create a new request-response client that uses an MQTT5 client.
*/
AWS_MQTT_API struct aws_mqtt_request_response_client *aws_mqtt_request_response_client_new_from_mqtt5_client(
struct aws_allocator *allocator,
struct aws_mqtt5_client *client,
const struct aws_mqtt_request_response_client_options *options);
/*
* Add a reference to a request-response client
*/
AWS_MQTT_API struct aws_mqtt_request_response_client *aws_mqtt_request_response_client_acquire(
struct aws_mqtt_request_response_client *client);
/*
* Remove a reference from a request-response client
*/
AWS_MQTT_API struct aws_mqtt_request_response_client *aws_mqtt_request_response_client_release(
struct aws_mqtt_request_response_client *client);
/*
* Submits a request operation to the client
*/
AWS_MQTT_API int aws_mqtt_request_response_client_submit_request(
struct aws_mqtt_request_response_client *client,
const struct aws_mqtt_request_operation_options *request_options);
/*
* Creates a new streaming operation. Streaming operations start in an inactive state and must be
* activated before its subscription can be established.
*/
AWS_MQTT_API struct aws_mqtt_rr_client_operation *aws_mqtt_request_response_client_create_streaming_operation(
struct aws_mqtt_request_response_client *client,
const struct aws_mqtt_streaming_operation_options *streaming_options);
/*
* Returns the event loop used by the request-response client's protocol client
*/
AWS_MQTT_API struct aws_event_loop *aws_mqtt_request_response_client_get_event_loop(
struct aws_mqtt_request_response_client *client);
/*
* Initiates a streaming operation's subscription process.
*/
AWS_MQTT_API int aws_mqtt_rr_client_operation_activate(struct aws_mqtt_rr_client_operation *operation);
/*
* Add a reference to a streaming operation.
*/
AWS_MQTT_API struct aws_mqtt_rr_client_operation *aws_mqtt_rr_client_operation_acquire(
struct aws_mqtt_rr_client_operation *operation);
/*
* Remove a reference from a streaming operation
*/
AWS_MQTT_API struct aws_mqtt_rr_client_operation *aws_mqtt_rr_client_operation_release(
struct aws_mqtt_rr_client_operation *operation);
AWS_EXTERN_C_END
#endif /* AWS_MQTT_REQUEST_RESPONSE_REQUEST_RESPONSE_CLIENT_H */

View File

@@ -0,0 +1,814 @@
#ifndef AWS_MQTT_MQTT5_CLIENT_H
#define AWS_MQTT_MQTT5_CLIENT_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/mqtt/mqtt.h>
#include <aws/io/retry_strategy.h>
#include <aws/mqtt/v5/mqtt5_types.h>
AWS_PUSH_SANE_WARNING_LEVEL
struct aws_allocator;
struct aws_client_bootstrap;
struct aws_host_resolution_config;
struct aws_http_message;
struct aws_mqtt5_client;
struct aws_mqtt5_client_lifecycle_event;
struct aws_tls_connection_options;
struct aws_socket_options;
/* public client-related enums */
/**
* Controls how the mqtt client should behave with respect to mqtt sessions.
*/
enum aws_mqtt5_client_session_behavior_type {
/**
* Maps to AWS_MQTT5_CSBT_CLEAN
*/
AWS_MQTT5_CSBT_DEFAULT,
/**
* Always join a new, clean session
*/
AWS_MQTT5_CSBT_CLEAN,
/**
* Always attempt to rejoin an existing session after an initial connection success.
*/
AWS_MQTT5_CSBT_REJOIN_POST_SUCCESS,
/**
* Always attempt to rejoin an existing session. Since the client does not support durable session persistence,
* this option is not guaranteed to be spec compliant because any unacknowledged qos1 publishes (which are
* part of the client session state) will not be present on the initial connection. Until we support
* durable session resumption, this option is technically spec-breaking, but useful.
*/
AWS_MQTT5_CSBT_REJOIN_ALWAYS,
};
/**
* Outbound topic aliasing behavior is controlled by this type.
*
* Topic alias behavior is described in https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901113
*
* If the server allows topic aliasing, this setting controls how topic aliases are used on PUBLISH packets sent
* from the client to the server.
*
* If topic aliasing is not supported by the server, this setting has no effect and any attempts to directly
* manipulate the topic alias id in outbound publishes will be ignored.
*/
enum aws_mqtt5_client_outbound_topic_alias_behavior_type {
/**
* Maps to AWS_MQTT5_COTABT_DISABLED This keeps the client from being broken (by default) if the broker
* topic aliasing implementation has a problem.
*/
AWS_MQTT5_COTABT_DEFAULT,
/**
* Outbound aliasing is the user's responsibility. Client will cache and use
* previously-established aliases if they fall within the negotiated limits of the connection.
*
* The user must still always submit a full topic in their publishes because disconnections disrupt
* topic alias mappings unpredictably. The client will properly use the alias when the current connection
* has seen the alias binding already.
*/
AWS_MQTT5_COTABT_MANUAL,
/**
* Client ignores any user-specified topic aliasing and acts on the outbound alias set as an LRU cache.
*/
AWS_MQTT5_COTABT_LRU,
/**
* Completely disable outbound topic aliasing.
*/
AWS_MQTT5_COTABT_DISABLED
};
/**
* Inbound topic aliasing behavior is controlled by this type.
*
* Topic alias behavior is described in https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901113
*
* This setting controls whether or not the client will send a positive topic alias maximum to the server
* in its CONNECT packets.
*
* If topic aliasing is not supported by the server, this setting has no net effect.
*/
enum aws_mqtt5_client_inbound_topic_alias_behavior_type {
/**
* Maps to AWS_MQTT5_CITABT_DISABLED
*/
AWS_MQTT5_CITABT_DEFAULT,
/**
* Allow the server to send PUBLISH packets to the client that use topic aliasing
*/
AWS_MQTT5_CITABT_ENABLED,
/**
* Forbid the server from sending PUBLISH packets to the client that use topic aliasing
*/
AWS_MQTT5_CITABT_DISABLED
};
/**
* Configuration struct for all client topic aliasing behavior. If this is left null, then all default options
* (as it zeroed) will be used.
*/
struct aws_mqtt5_client_topic_alias_options {
/**
* Controls what kind of outbound topic aliasing behavior the client should attempt to use.
*/
enum aws_mqtt5_client_outbound_topic_alias_behavior_type outbound_topic_alias_behavior;
/**
* If outbound topic aliasing is set to LRU, this controls the maximum size of the cache. If outbound topic
* aliasing is set to LRU and this is zero, a sensible default is used (25). If outbound topic aliasing is not
* set to LRU, then this setting has no effect.
*
* The final size of the cache is determined by the minimum of this setting and the value of the
* topic_alias_maximum property of the received CONNACK. If the received CONNACK does not have an explicit
* positive value for that field, outbound topic aliasing is disabled for the duration of that connection.
*/
uint16_t outbound_alias_cache_max_size;
/**
* Controls what kind of inbound topic aliasing behavior the client should use.
*
* Even if inbound topic aliasing is enabled, it is up to the server to choose whether or not to use it.
*/
enum aws_mqtt5_client_inbound_topic_alias_behavior_type inbound_topic_alias_behavior;
/**
* If inbound topic aliasing is enabled, this will control the size of the inbound alias cache. If inbound
* aliases are enabled and this is zero, then a sensible default will be used (25). If inbound aliases are
* disabled, this setting has no effect.
*
* Behaviorally, this value overrides anything present in the topic_alias_maximum field of
* the CONNECT packet options.
*/
uint16_t inbound_alias_cache_size;
};
/**
* Extended validation and flow control options
*
* Potentially a point of expansion in the future. We could add custom controls letting people override
* the Aws IOT Core limits based on their account properties. We could, with IoT Core support, add dynamic
* limit recognition via user properties as well.
*/
enum aws_mqtt5_extended_validation_and_flow_control_options {
/**
* Do not do any additional validation or flow control outside of the MQTT5 spec
*/
AWS_MQTT5_EVAFCO_NONE,
/**
* Apply additional client-side operational flow control that respects the
* default AWS IoT Core limits.
*
* Applies the following flow control:
* (1) Outbound throughput throttled to 512KB/s
* (2) Outbound publish TPS throttled to 100
*/
AWS_MQTT5_EVAFCO_AWS_IOT_CORE_DEFAULTS,
};
/**
* Controls how disconnects affect the queued and in-progress operations submitted to the client. Also controls
* how operations are handled while the client is not connected. In particular, if the client is not connected,
* then any operation that would be failed on disconnect (according to these rules) will be rejected.
*/
enum aws_mqtt5_client_operation_queue_behavior_type {
/*
* Maps to AWS_MQTT5_COQBT_FAIL_QOS0_PUBLISH_ON_DISCONNECT
*/
AWS_MQTT5_COQBT_DEFAULT,
/*
* Requeues QoS 1+ publishes on disconnect; unacked publishes go to the front, unprocessed publishes stay
* in place. All other operations (QoS 0 publishes, subscribe, unsubscribe) are failed.
*/
AWS_MQTT5_COQBT_FAIL_NON_QOS1_PUBLISH_ON_DISCONNECT,
/*
* Qos 0 publishes that are not complete at the time of disconnection are failed. Unacked QoS 1+ publishes are
* requeued at the head of the line for immediate retransmission on a session resumption. All other operations
* are requeued in original order behind any retransmissions.
*/
AWS_MQTT5_COQBT_FAIL_QOS0_PUBLISH_ON_DISCONNECT,
/*
* All operations that are not complete at the time of disconnection are failed, except those operations that
* the mqtt 5 spec requires to be retransmitted (unacked qos1+ publishes).
*/
AWS_MQTT5_COQBT_FAIL_ALL_ON_DISCONNECT,
};
/**
* Type of a client lifecycle event
*/
enum aws_mqtt5_client_lifecycle_event_type {
/**
* Emitted when the client begins an attempt to connect to the remote endpoint.
*
* Mandatory event fields: client, user_data
*/
AWS_MQTT5_CLET_ATTEMPTING_CONNECT,
/**
* Emitted after the client connects to the remote endpoint and receives a successful CONNACK.
* Every ATTEMPTING_CONNECT will be followed by exactly one CONNECTION_SUCCESS or one CONNECTION_FAILURE.
*
* Mandatory event fields: client, user_data, connack_data, settings
*/
AWS_MQTT5_CLET_CONNECTION_SUCCESS,
/**
* Emitted at any point during the connection process when it has conclusively failed.
* Every ATTEMPTING_CONNECT will be followed by exactly one CONNECTION_SUCCESS or one CONNECTION_FAILURE.
*
* Mandatory event fields: client, user_data, error_code
* Conditional event fields: connack_data
*/
AWS_MQTT5_CLET_CONNECTION_FAILURE,
/**
* Lifecycle event containing information about a disconnect. Every CONNECTION_SUCCESS will eventually be
* followed by one and only one DISCONNECTION.
*
* Mandatory event fields: client, user_data, error_code
* Conditional event fields: disconnect_data
*/
AWS_MQTT5_CLET_DISCONNECTION,
/**
* Lifecycle event notifying the user that the client has entered the STOPPED state. Entering this state will
* cause the client to wipe all MQTT session state.
*
* Mandatory event fields: client, user_data
*/
AWS_MQTT5_CLET_STOPPED,
};
/* client-related callback function signatures */
/**
* Signature of the continuation function to be called after user-code transforms a websocket handshake request
*/
typedef void(aws_mqtt5_transform_websocket_handshake_complete_fn)(
struct aws_http_message *request,
int error_code,
void *complete_ctx);
/**
* Signature of the websocket handshake request transformation function. After transformation, the completion
* function must be invoked to send the request.
*/
typedef void(aws_mqtt5_transform_websocket_handshake_fn)(
struct aws_http_message *request,
void *user_data,
aws_mqtt5_transform_websocket_handshake_complete_fn *complete_fn,
void *complete_ctx);
/**
* Callback signature for mqtt5 client lifecycle events.
*/
typedef void(aws_mqtt5_client_connection_event_callback_fn)(const struct aws_mqtt5_client_lifecycle_event *event);
/**
* Signature of callback to invoke on Publish success/failure.
*/
typedef void(aws_mqtt5_publish_completion_fn)(
enum aws_mqtt5_packet_type packet_type,
const void *packet,
int error_code,
void *complete_ctx);
/**
* Signature of callback to invoke on Subscribe success/failure.
*/
typedef void(aws_mqtt5_subscribe_completion_fn)(
const struct aws_mqtt5_packet_suback_view *suback,
int error_code,
void *complete_ctx);
/**
* Signature of callback to invoke on Unsubscribe success/failure.
*/
typedef void(aws_mqtt5_unsubscribe_completion_fn)(
const struct aws_mqtt5_packet_unsuback_view *unsuback,
int error_code,
void *complete_ctx);
/**
* Signature of callback to invoke on Publish received
*/
typedef void(aws_mqtt5_publish_received_fn)(const struct aws_mqtt5_packet_publish_view *publish, void *user_data);
/**
* Signature of a listener publish received callback that returns an indicator whether or not the publish
* was handled by the listener.
*/
typedef bool(
aws_mqtt5_listener_publish_received_fn)(const struct aws_mqtt5_packet_publish_view *publish, void *user_data);
/**
* Signature of callback to invoke when a DISCONNECT is fully written to the socket (or fails to be)
*/
typedef void(aws_mqtt5_disconnect_completion_fn)(int error_code, void *complete_ctx);
/**
* Signature of callback invoked when a client has completely destroyed itself
*/
typedef void(aws_mqtt5_client_termination_completion_fn)(void *complete_ctx);
/* operation completion options structures */
/**
* Completion options for the Publish operation
*/
struct aws_mqtt5_publish_completion_options {
aws_mqtt5_publish_completion_fn *completion_callback;
void *completion_user_data;
/** Overrides the client's ack timeout with this value, for this operation only */
uint32_t ack_timeout_seconds_override;
};
/**
* Completion options for the Subscribe operation
*/
struct aws_mqtt5_subscribe_completion_options {
aws_mqtt5_subscribe_completion_fn *completion_callback;
void *completion_user_data;
/** Overrides the client's ack timeout with this value, for this operation only */
uint32_t ack_timeout_seconds_override;
};
/**
* Completion options for the Unsubscribe operation
*/
struct aws_mqtt5_unsubscribe_completion_options {
aws_mqtt5_unsubscribe_completion_fn *completion_callback;
void *completion_user_data;
/** Overrides the client's ack timeout with this value, for this operation only */
uint32_t ack_timeout_seconds_override;
};
/**
* Completion options for the a DISCONNECT operation
*/
struct aws_mqtt5_disconnect_completion_options {
aws_mqtt5_disconnect_completion_fn *completion_callback;
void *completion_user_data;
};
/**
* Mqtt behavior settings that are dynamically negotiated as part of the CONNECT/CONNACK exchange.
*/
struct aws_mqtt5_negotiated_settings {
/**
* The maximum QoS used between the server and client.
*/
enum aws_mqtt5_qos maximum_qos;
/**
* the amount of time in seconds the server will retain the session after a disconnect.
*/
uint32_t session_expiry_interval;
/**
* the number of QoS 1 and QoS2 publications the server is willing to process concurrently.
*/
uint16_t receive_maximum_from_server;
/**
* the maximum packet size the server is willing to accept.
*/
uint32_t maximum_packet_size_to_server;
/**
* the highest value that the server will accept as a Topic Alias sent by the client.
*/
uint16_t topic_alias_maximum_to_server;
/**
* the highest value that the client will accept as a Topic Alias sent by the server.
*/
uint16_t topic_alias_maximum_to_client;
/**
* the amount of time in seconds before the server will disconnect the client for inactivity.
*/
uint16_t server_keep_alive;
/**
* whether the server supports retained messages.
*/
bool retain_available;
/**
* whether the server supports wildcard subscriptions.
*/
bool wildcard_subscriptions_available;
/**
* whether the server supports subscription identifiers
*/
bool subscription_identifiers_available;
/**
* whether the server supports shared subscriptions
*/
bool shared_subscriptions_available;
/**
* whether the client has rejoined an existing session.
*/
bool rejoined_session;
struct aws_byte_buf client_id_storage;
};
/**
* Contains some simple statistics about the current state of the client's queue of operations
*/
struct aws_mqtt5_client_operation_statistics {
/*
* total number of operations submitted to the client that have not yet been completed. Unacked operations
* are a subset of this.
*/
uint64_t incomplete_operation_count;
/*
* total packet size of operations submitted to the client that have not yet been completed. Unacked operations
* are a subset of this.
*/
uint64_t incomplete_operation_size;
/*
* total number of operations that have been sent to the server and are waiting for a corresponding ACK before
* they can be completed.
*/
uint64_t unacked_operation_count;
/*
* total packet size of operations that have been sent to the server and are waiting for a corresponding ACK before
* they can be completed.
*/
uint64_t unacked_operation_size;
};
/**
* Details about a client lifecycle event.
*/
struct aws_mqtt5_client_lifecycle_event {
/**
* Type of event this is.
*/
enum aws_mqtt5_client_lifecycle_event_type event_type;
/**
* Client this event corresponds to. Necessary (can't be replaced with user data) because the client
* doesn't exist at the time the event callback user data is configured.
*/
struct aws_mqtt5_client *client;
/**
* Aws-c-* error code associated with the event
*/
int error_code;
/**
* User data associated with the client's lifecycle event handler. Set with client configuration.
*/
void *user_data;
/**
* If this event was caused by receiving a CONNACK, this will be a view of that packet.
*/
const struct aws_mqtt5_packet_connack_view *connack_data;
/**
* If this is a successful connection establishment, this will contain the negotiated mqtt5 behavioral settings
*/
const struct aws_mqtt5_negotiated_settings *settings;
/**
* If this event was caused by receiving a DISCONNECT, this will be a view of that packet.
*/
const struct aws_mqtt5_packet_disconnect_view *disconnect_data;
};
/**
* Basic mqtt5 client configuration struct.
*
* Contains desired connection properties
* Configuration that represents properties of the mqtt5 CONNECT packet go in the connect view (connect_options)
*/
struct aws_mqtt5_client_options {
/**
* Host to establish mqtt connections to
*/
struct aws_byte_cursor host_name;
/**
* Port to establish mqtt connections to
*/
uint32_t port;
/**
* Client bootstrap to use whenever this client establishes a connection
*/
struct aws_client_bootstrap *bootstrap;
/**
* Socket options to use whenever this client establishes a connection
*/
const struct aws_socket_options *socket_options;
/**
* (Optional) Tls options to use whenever this client establishes a connection
*/
const struct aws_tls_connection_options *tls_options;
/**
* (Optional) Http proxy options to use whenever this client establishes a connection
*/
const struct aws_http_proxy_options *http_proxy_options;
/**
* (Optional) Websocket handshake transformation function and user data. Websockets are used if the
* transformation function is non-null.
*/
aws_mqtt5_transform_websocket_handshake_fn *websocket_handshake_transform;
void *websocket_handshake_transform_user_data;
/**
* All CONNECT-related options, includes the will configuration, if desired
*/
const struct aws_mqtt5_packet_connect_view *connect_options;
/**
* Controls session rejoin behavior
*/
enum aws_mqtt5_client_session_behavior_type session_behavior;
/**
* Controls if any additional AWS-specific validation or flow control should be performed by the client.
*/
enum aws_mqtt5_extended_validation_and_flow_control_options extended_validation_and_flow_control_options;
/**
* Controls how the client treats queued/in-progress operations when the connection drops for any reason.
*/
enum aws_mqtt5_client_operation_queue_behavior_type offline_queue_behavior;
/**
* Controls the exponential backoff behavior when the client is waiting to reconnect.
*
* See: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
*/
enum aws_exponential_backoff_jitter_mode retry_jitter_mode;
/**
* Minimum amount of time in ms to wait before attempting to reconnect. If this is zero, a default of 1000 ms will
* be used.
*/
uint64_t min_reconnect_delay_ms;
/**
* Maximum amount of time in ms to wait before attempting to reconnect. If this is zero, a default of 120000 ms
* will be used.
*/
uint64_t max_reconnect_delay_ms;
/**
* Amount of time that must elapse with a good connection before the reconnect delay is reset to the minimum. If
* this zero, a default of 30000 ms will be used.
*/
uint64_t min_connected_time_to_reset_reconnect_delay_ms;
/**
* Time interval to wait after sending a PINGREQ for a PINGRESP to arrive. If one does not arrive, the connection
* will be shut down. If this is zero, a default of 30000 ms will be used.
*/
uint32_t ping_timeout_ms;
/**
* Time interval to wait after sending a CONNECT request for a CONNACK to arrive. If one does not arrive, the
* connection will be shut down. If this zero, a default of 20000 ms will be used.
*/
uint32_t connack_timeout_ms;
/**
* Time interval to wait for an ack after sending a SUBSCRIBE, UNSUBSCRIBE, or PUBLISH with QoS 1+ before
* failing the packet, notifying the client of failure, and removing it. If this is zero, a default of 60 seconds
* will be used.
*/
uint32_t ack_timeout_seconds;
/**
* Controls how the client uses mqtt5 topic aliasing. If NULL, zero-based defaults will be used.
*/
const struct aws_mqtt5_client_topic_alias_options *topic_aliasing_options;
/**
* Callback for received publish packets
*/
aws_mqtt5_publish_received_fn *publish_received_handler;
void *publish_received_handler_user_data;
/**
* Callback and user data for all client lifecycle events.
* Life cycle events include:
* ConnectionSuccess
* ConnectionFailure,
* Disconnect
* (client) Stopped
*
* Disconnect lifecycle events are 1-1 with -- strictly after -- ConnectionSuccess events.
*/
aws_mqtt5_client_connection_event_callback_fn *lifecycle_event_handler;
void *lifecycle_event_handler_user_data;
/**
* Callback for when the client has completely destroyed itself
*/
aws_mqtt5_client_termination_completion_fn *client_termination_handler;
void *client_termination_handler_user_data;
/**
* Options to override aspects of DNS resolution. If unspecified, use a default that matches the regular
* configuration but changes the refresh frequency to a value that prevents DNS pinging.
*/
struct aws_host_resolution_config *host_resolution_override;
};
AWS_EXTERN_C_BEGIN
/**
* Creates a new mqtt5 client using the supplied configuration
*
* @param allocator allocator to use with all memory operations related to this client's creation and operation
* @param options mqtt5 client configuration
* @return a new mqtt5 client or NULL
*/
AWS_MQTT_API
struct aws_mqtt5_client *aws_mqtt5_client_new(
struct aws_allocator *allocator,
const struct aws_mqtt5_client_options *options);
/**
* Acquires a reference to an mqtt5 client
*
* @param client client to acquire a reference to. May be NULL.
* @return what was passed in as the client (a client or NULL)
*/
AWS_MQTT_API
struct aws_mqtt5_client *aws_mqtt5_client_acquire(struct aws_mqtt5_client *client);
/**
* Release a reference to an mqtt5 client. When the client ref count drops to zero, the client will automatically
* trigger a stop and once the stop completes, the client will delete itself.
*
* @param client client to release a reference to. May be NULL.
* @return NULL
*/
AWS_MQTT_API
struct aws_mqtt5_client *aws_mqtt5_client_release(struct aws_mqtt5_client *client);
/**
* Asynchronous notify to the mqtt5 client that you want it to attempt to connect to the configured endpoint.
* The client will attempt to stay connected using the properties of the reconnect-related parameters
* in the mqtt5 client configuration.
*
* @param client mqtt5 client to start
* @return success/failure in the synchronous logic that kicks off the start process
*/
AWS_MQTT_API
int aws_mqtt5_client_start(struct aws_mqtt5_client *client);
/**
* Asynchronous notify to the mqtt5 client that you want it to transition to the stopped state. When the client
* reaches the stopped state, all session state is erased.
*
* @param client mqtt5 client to stop
* @param disconnect_options (optional) properties of a DISCONNECT packet to send as part of the shutdown process
* @return success/failure in the synchronous logic that kicks off the stop process
*/
AWS_MQTT_API
int aws_mqtt5_client_stop(
struct aws_mqtt5_client *client,
const struct aws_mqtt5_packet_disconnect_view *disconnect_options,
const struct aws_mqtt5_disconnect_completion_options *completion_options);
/**
* Queues a Publish operation in an mqtt5 client
*
* @param client mqtt5 client to queue a Publish for
* @param publish_options configuration options for the Publish operation
* @param completion_options completion callback configuration. Successful QoS 0 publishes invoke the callback when
* the data has been written to the socket. Successful QoS1+ publishes invoke the callback when the corresponding ack
* is received. Unsuccessful publishes invoke the callback at the point in time a failure condition is reached.
* @return success/failure in the synchronous logic that kicks off the publish operation
*/
AWS_MQTT_API
int aws_mqtt5_client_publish(
struct aws_mqtt5_client *client,
const struct aws_mqtt5_packet_publish_view *publish_options,
const struct aws_mqtt5_publish_completion_options *completion_options);
/**
* Queues a Subscribe operation in an mqtt5 client
*
* @param client mqtt5 client to queue a Subscribe for
* @param subscribe_options configuration options for the Subscribe operation
* @param completion_options Completion callback configuration. Invoked when the corresponding SUBACK is received or
* a failure condition is reached. An error code implies complete failure of the subscribe, while a success code
* implies the user must still check all of the SUBACK's reason codes for per-subscription feedback.
* @return success/failure in the synchronous logic that kicks off the Subscribe operation
*/
AWS_MQTT_API
int aws_mqtt5_client_subscribe(
struct aws_mqtt5_client *client,
const struct aws_mqtt5_packet_subscribe_view *subscribe_options,
const struct aws_mqtt5_subscribe_completion_options *completion_options);
/**
* Queues an Unsubscribe operation in an mqtt5 client
*
* @param client mqtt5 client to queue an Unsubscribe for
* @param unsubscribe_options configuration options for the Unsubscribe operation
* @param completion_options Completion callback configuration. Invoked when the corresponding UNSUBACK is received or
* a failure condition is reached. An error code implies complete failure of the unsubscribe, while a success code
* implies the user must still check all of the UNSUBACK's reason codes for per-topic-filter feedback.
* @return success/failure in the synchronous logic that kicks off the Unsubscribe operation
*/
AWS_MQTT_API
int aws_mqtt5_client_unsubscribe(
struct aws_mqtt5_client *client,
const struct aws_mqtt5_packet_unsubscribe_view *unsubscribe_options,
const struct aws_mqtt5_unsubscribe_completion_options *completion_options);
/**
* Queries the client's internal statistics for incomplete operations.
* @param client client to get statistics for
* @param stats set of incomplete operation statistics
*/
AWS_MQTT_API
void aws_mqtt5_client_get_stats(struct aws_mqtt5_client *client, struct aws_mqtt5_client_operation_statistics *stats);
/* Misc related type APIs */
/**
* Initializes the Client ID byte buf in negotiated settings
*
* @param allocator allocator to use for memory allocation
* @param negotiated_settings settings to apply client id to
* @param client_id client id to set
*/
AWS_MQTT_API int aws_mqtt5_negotiated_settings_init(
struct aws_allocator *allocator,
struct aws_mqtt5_negotiated_settings *negotiated_settings,
const struct aws_byte_cursor *client_id);
/**
* Makes an owning copy of a negotiated settings structure.
*
* @param source settings to copy from
* @param dest settings to copy into. Must be in a zeroed or initialized state because it gets clean up
* called on it as the first step of the copy process.
* @return success/failure
*
* Used in downstream.
*/
AWS_MQTT_API int aws_mqtt5_negotiated_settings_copy(
const struct aws_mqtt5_negotiated_settings *source,
struct aws_mqtt5_negotiated_settings *dest);
/**
* Clean up owned memory in negotiated_settings
*
* @param negotiated_settings settings to clean up
*/
AWS_MQTT_API void aws_mqtt5_negotiated_settings_clean_up(struct aws_mqtt5_negotiated_settings *negotiated_settings);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_MQTT_MQTT5_CLIENT_H */

View File

@@ -0,0 +1,88 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#ifndef AWS_MQTT_MQTT5_LISTENER_H
#define AWS_MQTT_MQTT5_LISTENER_H
#include <aws/mqtt/mqtt.h>
#include <aws/mqtt/v5/mqtt5_client.h>
AWS_PUSH_SANE_WARNING_LEVEL
/*
* Callback signature for when an mqtt5 listener has completely destroyed itself.
*/
typedef void(aws_mqtt5_listener_termination_completion_fn)(void *complete_ctx);
/**
* A record that tracks MQTT5 client callbacks which can be dynamically injected via a listener.
*/
struct aws_mqtt5_callback_set {
aws_mqtt5_listener_publish_received_fn *listener_publish_received_handler;
void *listener_publish_received_handler_user_data;
aws_mqtt5_client_connection_event_callback_fn *lifecycle_event_handler;
void *lifecycle_event_handler_user_data;
};
/**
* Configuration options for MQTT5 listener objects.
*/
struct aws_mqtt5_listener_config {
/**
* MQTT5 client to listen to events on
*/
struct aws_mqtt5_client *client;
/**
* Callbacks to invoke when events occur on the MQTT5 client
*/
struct aws_mqtt5_callback_set listener_callbacks;
/**
* Listener destruction is asynchronous and thus requires a termination callback and associated user data
* to notify the user that the listener has been fully destroyed and no further events will be received.
*/
aws_mqtt5_listener_termination_completion_fn *termination_callback;
void *termination_callback_user_data;
};
AWS_EXTERN_C_BEGIN
/**
* Creates a new MQTT5 listener object. For as long as the listener lives, incoming publishes and lifecycle events
* will be forwarded to the callbacks configured on the listener.
*
* @param allocator allocator to use
* @param config listener configuration
* @return a new aws_mqtt5_listener object
*/
AWS_MQTT_API struct aws_mqtt5_listener *aws_mqtt5_listener_new(
struct aws_allocator *allocator,
struct aws_mqtt5_listener_config *config);
/**
* Adds a reference to an mqtt5 listener.
*
* @param listener listener to add a reference to
* @return the listener object
*/
AWS_MQTT_API struct aws_mqtt5_listener *aws_mqtt5_listener_acquire(struct aws_mqtt5_listener *listener);
/**
* Removes a reference to an mqtt5 listener. When the reference count drops to zero, the listener's asynchronous
* destruction will be started.
*
* @param listener listener to remove a reference from
* @return NULL
*/
AWS_MQTT_API struct aws_mqtt5_listener *aws_mqtt5_listener_release(struct aws_mqtt5_listener *listener);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_MQTT_MQTT5_LISTENER_H */

View File

@@ -0,0 +1,331 @@
#ifndef AWS_MQTT_MQTT5_PACKET_STORAGE_H
#define AWS_MQTT_MQTT5_PACKET_STORAGE_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/mqtt/mqtt.h>
#include <aws/mqtt/v5/mqtt5_types.h>
AWS_PUSH_SANE_WARNING_LEVEL
struct aws_mqtt5_user_property_set {
struct aws_array_list properties;
};
struct aws_mqtt5_packet_connect_storage {
struct aws_allocator *allocator;
struct aws_mqtt5_packet_connect_view storage_view;
struct aws_byte_cursor username;
struct aws_byte_cursor password;
uint32_t session_expiry_interval_seconds;
uint8_t request_response_information;
uint8_t request_problem_information;
uint16_t receive_maximum;
uint16_t topic_alias_maximum;
uint32_t maximum_packet_size_bytes;
struct aws_mqtt5_packet_publish_storage *will;
uint32_t will_delay_interval_seconds;
struct aws_mqtt5_user_property_set user_properties;
struct aws_byte_cursor authentication_method;
struct aws_byte_cursor authentication_data;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_connack_storage {
struct aws_allocator *allocator;
struct aws_mqtt5_packet_connack_view storage_view;
uint32_t session_expiry_interval;
uint16_t receive_maximum;
enum aws_mqtt5_qos maximum_qos;
bool retain_available;
uint32_t maximum_packet_size;
struct aws_byte_cursor assigned_client_identifier;
uint16_t topic_alias_maximum;
struct aws_byte_cursor reason_string;
bool wildcard_subscriptions_available;
bool subscription_identifiers_available;
bool shared_subscriptions_available;
uint16_t server_keep_alive;
struct aws_byte_cursor response_information;
struct aws_byte_cursor server_reference;
struct aws_byte_cursor authentication_method;
struct aws_byte_cursor authentication_data;
struct aws_mqtt5_user_property_set user_properties;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_suback_storage {
struct aws_allocator *allocator;
struct aws_mqtt5_packet_suback_view storage_view;
struct aws_byte_cursor reason_string;
struct aws_mqtt5_user_property_set user_properties;
struct aws_array_list reason_codes;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_unsuback_storage {
struct aws_allocator *allocator;
struct aws_mqtt5_packet_unsuback_view storage_view;
struct aws_byte_cursor reason_string;
struct aws_mqtt5_user_property_set user_properties;
struct aws_array_list reason_codes;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_publish_storage {
struct aws_mqtt5_packet_publish_view storage_view;
enum aws_mqtt5_payload_format_indicator payload_format;
uint32_t message_expiry_interval_seconds;
uint16_t topic_alias;
struct aws_byte_cursor response_topic;
struct aws_byte_cursor correlation_data;
struct aws_byte_cursor content_type;
struct aws_mqtt5_user_property_set user_properties;
struct aws_array_list subscription_identifiers;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_puback_storage {
struct aws_mqtt5_packet_puback_view storage_view;
struct aws_byte_cursor reason_string;
struct aws_mqtt5_user_property_set user_properties;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_disconnect_storage {
struct aws_mqtt5_packet_disconnect_view storage_view;
uint32_t session_expiry_interval_seconds;
struct aws_byte_cursor reason_string;
struct aws_mqtt5_user_property_set user_properties;
struct aws_byte_cursor server_reference;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_subscribe_storage {
struct aws_mqtt5_packet_subscribe_view storage_view;
uint32_t subscription_identifier;
struct aws_array_list subscriptions;
struct aws_mqtt5_user_property_set user_properties;
struct aws_byte_buf storage;
};
struct aws_mqtt5_packet_unsubscribe_storage {
struct aws_mqtt5_packet_unsubscribe_view storage_view;
struct aws_array_list topic_filters;
struct aws_mqtt5_user_property_set user_properties;
struct aws_byte_buf storage;
};
AWS_EXTERN_C_BEGIN
/* User properties */
AWS_MQTT_API int aws_mqtt5_user_property_set_init_with_storage(
struct aws_mqtt5_user_property_set *property_set,
struct aws_allocator *allocator,
struct aws_byte_buf *storage_buffer,
size_t property_count,
const struct aws_mqtt5_user_property *properties);
AWS_MQTT_API void aws_mqtt5_user_property_set_clean_up(struct aws_mqtt5_user_property_set *property_set);
AWS_MQTT_API size_t aws_mqtt5_user_property_set_size(const struct aws_mqtt5_user_property_set *property_set);
/* Connect */
AWS_MQTT_API int aws_mqtt5_packet_connect_storage_init(
struct aws_mqtt5_packet_connect_storage *connect_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_connect_view *connect_options);
AWS_MQTT_API int aws_mqtt5_packet_connect_storage_init_from_external_storage(
struct aws_mqtt5_packet_connect_storage *connect_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_connect_storage_clean_up(struct aws_mqtt5_packet_connect_storage *connect_storage);
/* Connack */
AWS_MQTT_API int aws_mqtt5_packet_connack_storage_init(
struct aws_mqtt5_packet_connack_storage *connack_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_connack_view *connack_options);
AWS_MQTT_API int aws_mqtt5_packet_connack_storage_init_from_external_storage(
struct aws_mqtt5_packet_connack_storage *connack_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_connack_storage_clean_up(struct aws_mqtt5_packet_connack_storage *connack_storage);
/* Disconnect */
AWS_MQTT_API int aws_mqtt5_packet_disconnect_storage_init(
struct aws_mqtt5_packet_disconnect_storage *disconnect_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_disconnect_view *disconnect_options);
AWS_MQTT_API int aws_mqtt5_packet_disconnect_storage_init_from_external_storage(
struct aws_mqtt5_packet_disconnect_storage *disconnect_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_disconnect_storage_clean_up(
struct aws_mqtt5_packet_disconnect_storage *disconnect_storage);
/* Publish */
AWS_MQTT_API int aws_mqtt5_packet_publish_storage_init(
struct aws_mqtt5_packet_publish_storage *publish_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_publish_view *publish_options);
AWS_MQTT_API int aws_mqtt5_packet_publish_storage_init_from_external_storage(
struct aws_mqtt5_packet_publish_storage *publish_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_publish_storage_clean_up(struct aws_mqtt5_packet_publish_storage *publish_storage);
/* Puback */
AWS_MQTT_API int aws_mqtt5_packet_puback_storage_init(
struct aws_mqtt5_packet_puback_storage *puback_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_puback_view *puback_view);
AWS_MQTT_API int aws_mqtt5_packet_puback_storage_init_from_external_storage(
struct aws_mqtt5_packet_puback_storage *puback_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_puback_storage_clean_up(struct aws_mqtt5_packet_puback_storage *puback_storage);
/* Subscribe */
AWS_MQTT_API int aws_mqtt5_packet_subscribe_storage_init(
struct aws_mqtt5_packet_subscribe_storage *subscribe_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_subscribe_view *subscribe_options);
AWS_MQTT_API int aws_mqtt5_packet_subscribe_storage_init_from_external_storage(
struct aws_mqtt5_packet_subscribe_storage *subscribe_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_subscribe_storage_clean_up(
struct aws_mqtt5_packet_subscribe_storage *subscribe_storage);
/* Suback */
AWS_MQTT_API int aws_mqtt5_packet_suback_storage_init(
struct aws_mqtt5_packet_suback_storage *suback_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_suback_view *suback_view);
AWS_MQTT_API int aws_mqtt5_packet_suback_storage_init_from_external_storage(
struct aws_mqtt5_packet_suback_storage *suback_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_suback_storage_clean_up(struct aws_mqtt5_packet_suback_storage *suback_storage);
/* Unsubscribe */
AWS_MQTT_API int aws_mqtt5_packet_unsubscribe_storage_init(
struct aws_mqtt5_packet_unsubscribe_storage *unsubscribe_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_unsubscribe_view *unsubscribe_options);
AWS_MQTT_API int aws_mqtt5_packet_unsubscribe_storage_init_from_external_storage(
struct aws_mqtt5_packet_unsubscribe_storage *unsubscribe_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_unsubscribe_storage_clean_up(
struct aws_mqtt5_packet_unsubscribe_storage *unsubscribe_storage);
/* Unsuback */
AWS_MQTT_API int aws_mqtt5_packet_unsuback_storage_init(
struct aws_mqtt5_packet_unsuback_storage *unsuback_storage,
struct aws_allocator *allocator,
const struct aws_mqtt5_packet_unsuback_view *unsuback_view);
AWS_MQTT_API int aws_mqtt5_packet_unsuback_storage_init_from_external_storage(
struct aws_mqtt5_packet_unsuback_storage *unsuback_storage,
struct aws_allocator *allocator);
AWS_MQTT_API void aws_mqtt5_packet_unsuback_storage_clean_up(
struct aws_mqtt5_packet_unsuback_storage *unsuback_storage);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_MQTT_MQTT5_PACKET_STORAGE_H */

View File

@@ -0,0 +1,481 @@
#ifndef AWS_MQTT_MQTT5_TYPES_H
#define AWS_MQTT_MQTT5_TYPES_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/mqtt/mqtt.h>
#include <aws/common/array_list.h>
#include <aws/common/byte_buf.h>
AWS_PUSH_SANE_WARNING_LEVEL
/**
* Some artificial (non-MQTT spec specified) limits that we place on input packets (publish, subscribe, unsubscibe)
* which lets us safely do the various packet size calculations with a bare minimum of checked arithmetic.
*
* I don't see any conceivable use cases why you'd want more than this, but they are relaxable to some degree.
*
* TODO: Add some static assert calculations that verify that we can't possibly overflow against the maximum value
* of a variable length integer for relevant packet size encodings that are absolute worst-case against these limits.
*/
#define AWS_MQTT5_CLIENT_MAXIMUM_USER_PROPERTIES 1024
#define AWS_MQTT5_CLIENT_MAXIMUM_SUBSCRIPTIONS_PER_SUBSCRIBE 1024
#define AWS_MQTT5_CLIENT_MAXIMUM_TOPIC_FILTERS_PER_UNSUBSCRIBE 1024
/**
* Over-the-wire packet id as defined in the mqtt spec. Allocated at the point in time when the packet is
* is next to go down the channel and about to be encoded into an io message buffer.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901026
*/
typedef uint16_t aws_mqtt5_packet_id_t;
/**
* MQTT Message delivery quality of service.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901234
*/
enum aws_mqtt5_qos {
/** https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901235 */
AWS_MQTT5_QOS_AT_MOST_ONCE = 0x0,
/** https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901236 */
AWS_MQTT5_QOS_AT_LEAST_ONCE = 0x1,
/** https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901237 */
AWS_MQTT5_QOS_EXACTLY_ONCE = 0x2,
};
/**
* Server return code for CONNECT attempts.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901079
*/
enum aws_mqtt5_connect_reason_code {
AWS_MQTT5_CRC_SUCCESS = 0,
AWS_MQTT5_CRC_UNSPECIFIED_ERROR = 128,
AWS_MQTT5_CRC_MALFORMED_PACKET = 129,
AWS_MQTT5_CRC_PROTOCOL_ERROR = 130,
AWS_MQTT5_CRC_IMPLEMENTATION_SPECIFIC_ERROR = 131,
AWS_MQTT5_CRC_UNSUPPORTED_PROTOCOL_VERSION = 132,
AWS_MQTT5_CRC_CLIENT_IDENTIFIER_NOT_VALID = 133,
AWS_MQTT5_CRC_BAD_USERNAME_OR_PASSWORD = 134,
AWS_MQTT5_CRC_NOT_AUTHORIZED = 135,
AWS_MQTT5_CRC_SERVER_UNAVAILABLE = 136,
AWS_MQTT5_CRC_SERVER_BUSY = 137,
AWS_MQTT5_CRC_BANNED = 138,
AWS_MQTT5_CRC_BAD_AUTHENTICATION_METHOD = 140,
AWS_MQTT5_CRC_TOPIC_NAME_INVALID = 144,
AWS_MQTT5_CRC_PACKET_TOO_LARGE = 149,
AWS_MQTT5_CRC_QUOTA_EXCEEDED = 151,
AWS_MQTT5_CRC_PAYLOAD_FORMAT_INVALID = 153,
AWS_MQTT5_CRC_RETAIN_NOT_SUPPORTED = 154,
AWS_MQTT5_CRC_QOS_NOT_SUPPORTED = 155,
AWS_MQTT5_CRC_USE_ANOTHER_SERVER = 156,
AWS_MQTT5_CRC_SERVER_MOVED = 157,
AWS_MQTT5_CRC_CONNECTION_RATE_EXCEEDED = 159,
};
/**
* Reason code inside DISCONNECT packets.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901208
*/
enum aws_mqtt5_disconnect_reason_code {
AWS_MQTT5_DRC_NORMAL_DISCONNECTION = 0,
AWS_MQTT5_DRC_DISCONNECT_WITH_WILL_MESSAGE = 4,
AWS_MQTT5_DRC_UNSPECIFIED_ERROR = 128,
AWS_MQTT5_DRC_MALFORMED_PACKET = 129,
AWS_MQTT5_DRC_PROTOCOL_ERROR = 130,
AWS_MQTT5_DRC_IMPLEMENTATION_SPECIFIC_ERROR = 131,
AWS_MQTT5_DRC_NOT_AUTHORIZED = 135,
AWS_MQTT5_DRC_SERVER_BUSY = 137,
AWS_MQTT5_DRC_SERVER_SHUTTING_DOWN = 139,
AWS_MQTT5_DRC_KEEP_ALIVE_TIMEOUT = 141,
AWS_MQTT5_DRC_SESSION_TAKEN_OVER = 142,
AWS_MQTT5_DRC_TOPIC_FILTER_INVALID = 143,
AWS_MQTT5_DRC_TOPIC_NAME_INVALID = 144,
AWS_MQTT5_DRC_RECEIVE_MAXIMUM_EXCEEDED = 147,
AWS_MQTT5_DRC_TOPIC_ALIAS_INVALID = 148,
AWS_MQTT5_DRC_PACKET_TOO_LARGE = 149,
AWS_MQTT5_DRC_MESSAGE_RATE_TOO_HIGH = 150,
AWS_MQTT5_DRC_QUOTA_EXCEEDED = 151,
AWS_MQTT5_DRC_ADMINISTRATIVE_ACTION = 152,
AWS_MQTT5_DRC_PAYLOAD_FORMAT_INVALID = 153,
AWS_MQTT5_DRC_RETAIN_NOT_SUPPORTED = 154,
AWS_MQTT5_DRC_QOS_NOT_SUPPORTED = 155,
AWS_MQTT5_DRC_USE_ANOTHER_SERVER = 156,
AWS_MQTT5_DRC_SERVER_MOVED = 157,
AWS_MQTT5_DRC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158,
AWS_MQTT5_DRC_CONNECTION_RATE_EXCEEDED = 159,
AWS_MQTT5_DRC_MAXIMUM_CONNECT_TIME = 160,
AWS_MQTT5_DRC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161,
AWS_MQTT5_DRC_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162,
};
/**
* Reason code inside PUBACK packets.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124
*/
enum aws_mqtt5_puback_reason_code {
AWS_MQTT5_PARC_SUCCESS = 0,
AWS_MQTT5_PARC_NO_MATCHING_SUBSCRIBERS = 16,
AWS_MQTT5_PARC_UNSPECIFIED_ERROR = 128,
AWS_MQTT5_PARC_IMPLEMENTATION_SPECIFIC_ERROR = 131,
AWS_MQTT5_PARC_NOT_AUTHORIZED = 135,
AWS_MQTT5_PARC_TOPIC_NAME_INVALID = 144,
AWS_MQTT5_PARC_PACKET_IDENTIFIER_IN_USE = 145,
AWS_MQTT5_PARC_QUOTA_EXCEEDED = 151,
AWS_MQTT5_PARC_PAYLOAD_FORMAT_INVALID = 153,
};
/**
* Reason code inside SUBACK packet payloads.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901178
*/
enum aws_mqtt5_suback_reason_code {
AWS_MQTT5_SARC_GRANTED_QOS_0 = 0,
AWS_MQTT5_SARC_GRANTED_QOS_1 = 1,
AWS_MQTT5_SARC_GRANTED_QOS_2 = 2,
AWS_MQTT5_SARC_UNSPECIFIED_ERROR = 128,
AWS_MQTT5_SARC_IMPLEMENTATION_SPECIFIC_ERROR = 131,
AWS_MQTT5_SARC_NOT_AUTHORIZED = 135,
AWS_MQTT5_SARC_TOPIC_FILTER_INVALID = 143,
AWS_MQTT5_SARC_PACKET_IDENTIFIER_IN_USE = 145,
AWS_MQTT5_SARC_QUOTA_EXCEEDED = 151,
AWS_MQTT5_SARC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158,
AWS_MQTT5_SARC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161,
AWS_MQTT5_SARC_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162,
};
/**
* Reason code inside UNSUBACK packet payloads.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901194
*/
enum aws_mqtt5_unsuback_reason_code {
AWS_MQTT5_UARC_SUCCESS = 0,
AWS_MQTT5_UARC_NO_SUBSCRIPTION_EXISTED = 17,
AWS_MQTT5_UARC_UNSPECIFIED_ERROR = 128,
AWS_MQTT5_UARC_IMPLEMENTATION_SPECIFIC_ERROR = 131,
AWS_MQTT5_UARC_NOT_AUTHORIZED = 135,
AWS_MQTT5_UARC_TOPIC_FILTER_INVALID = 143,
AWS_MQTT5_UARC_PACKET_IDENTIFIER_IN_USE = 145,
};
/**
* Type of mqtt packet.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901022
*/
enum aws_mqtt5_packet_type {
/* internal indicator that the associated packet is null */
AWS_MQTT5_PT_NONE = -1,
AWS_MQTT5_PT_RESERVED = 0,
AWS_MQTT5_PT_CONNECT = 1,
AWS_MQTT5_PT_CONNACK = 2,
AWS_MQTT5_PT_PUBLISH = 3,
AWS_MQTT5_PT_PUBACK = 4,
AWS_MQTT5_PT_PUBREC = 5,
AWS_MQTT5_PT_PUBREL = 6,
AWS_MQTT5_PT_PUBCOMP = 7,
AWS_MQTT5_PT_SUBSCRIBE = 8,
AWS_MQTT5_PT_SUBACK = 9,
AWS_MQTT5_PT_UNSUBSCRIBE = 10,
AWS_MQTT5_PT_UNSUBACK = 11,
AWS_MQTT5_PT_PINGREQ = 12,
AWS_MQTT5_PT_PINGRESP = 13,
AWS_MQTT5_PT_DISCONNECT = 14,
AWS_MQTT5_PT_AUTH = 15,
};
/**
* Non-persistent representation of an mqtt5 user property.
*/
struct aws_mqtt5_user_property {
struct aws_byte_cursor name;
struct aws_byte_cursor value;
};
/**
* Optional property describing a message's payload format.
* Enum values match mqtt spec encoding values.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901063
*/
enum aws_mqtt5_payload_format_indicator {
AWS_MQTT5_PFI_BYTES = 0,
AWS_MQTT5_PFI_UTF8 = 1,
};
/**
* Configures how retained messages should be handled when subscribing with a topic filter that matches topics with
* associated retained messages.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169
*/
enum aws_mqtt5_retain_handling_type {
/**
* Server should send all retained messages on topics that match the subscription's filter.
*/
AWS_MQTT5_RHT_SEND_ON_SUBSCRIBE = 0x00,
/**
* Server should send all retained messages on topics that match the subscription's filter, where this is the
* first (relative to connection) subscription filter that matches the topic with a retained message.
*/
AWS_MQTT5_RHT_SEND_ON_SUBSCRIBE_IF_NEW = 0x01,
/**
* Subscribe must not trigger any retained message publishes from the server.
*/
AWS_MQTT5_RHT_DONT_SEND = 0x02,
};
/**
* Configures a single subscription within a Subscribe operation
*/
struct aws_mqtt5_subscription_view {
/**
* Topic filter to subscribe to
*/
struct aws_byte_cursor topic_filter;
/**
* Maximum QOS that the subscriber will accept messages for. Negotiated QoS may be different.
*/
enum aws_mqtt5_qos qos;
/**
* Should the server not send publishes to a client when that client was the one who sent the publish?
*/
bool no_local;
/**
* Should messages sent due to this subscription keep the retain flag preserved on the message?
*/
bool retain_as_published;
/**
* Should retained messages on matching topics be sent in reaction to this subscription?
*/
enum aws_mqtt5_retain_handling_type retain_handling_type;
};
/**
* Read-only snapshot of a DISCONNECT packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901205
*/
struct aws_mqtt5_packet_disconnect_view {
enum aws_mqtt5_disconnect_reason_code reason_code;
const uint32_t *session_expiry_interval_seconds;
const struct aws_byte_cursor *reason_string;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
const struct aws_byte_cursor *server_reference;
};
/**
* Read-only snapshot of a SUBSCRIBE packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161
*/
struct aws_mqtt5_packet_subscribe_view {
aws_mqtt5_packet_id_t packet_id;
size_t subscription_count;
const struct aws_mqtt5_subscription_view *subscriptions;
const uint32_t *subscription_identifier;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
};
/**
* Read-only snapshot of an UNSUBSCRIBE packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901179
*/
struct aws_mqtt5_packet_unsubscribe_view {
aws_mqtt5_packet_id_t packet_id;
size_t topic_filter_count;
const struct aws_byte_cursor *topic_filters;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
};
/**
* Read-only snapshot of a PUBLISH packet. Used both in configuration of a publish operation and callback
* data in message receipt.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901100
*/
struct aws_mqtt5_packet_publish_view {
struct aws_byte_cursor payload;
/* packet_id is only set for QoS 1 and QoS 2 */
aws_mqtt5_packet_id_t packet_id;
enum aws_mqtt5_qos qos;
/*
* Used to set the duplicate flag on QoS 1+ re-delivery attempts.
* Set to false on all first attempts or QoS 0. Set to true on any re-delivery.
*/
bool duplicate;
bool retain;
struct aws_byte_cursor topic;
const enum aws_mqtt5_payload_format_indicator *payload_format;
const uint32_t *message_expiry_interval_seconds;
const uint16_t *topic_alias;
const struct aws_byte_cursor *response_topic;
const struct aws_byte_cursor *correlation_data;
/* These are ignored when building publish operations */
size_t subscription_identifier_count;
const uint32_t *subscription_identifiers;
const struct aws_byte_cursor *content_type;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
};
/**
* Read-only snapshot of a CONNECT packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901033
*/
struct aws_mqtt5_packet_connect_view {
uint16_t keep_alive_interval_seconds;
struct aws_byte_cursor client_id;
const struct aws_byte_cursor *username;
const struct aws_byte_cursor *password;
bool clean_start;
const uint32_t *session_expiry_interval_seconds;
const uint8_t *request_response_information;
const uint8_t *request_problem_information;
const uint16_t *receive_maximum;
const uint16_t *topic_alias_maximum;
const uint32_t *maximum_packet_size_bytes;
const uint32_t *will_delay_interval_seconds;
const struct aws_mqtt5_packet_publish_view *will;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
/* Do not bind these. We don't support AUTH packets yet. For decode/encade testing purposes only. */
const struct aws_byte_cursor *authentication_method;
const struct aws_byte_cursor *authentication_data;
};
/**
* Read-only snapshot of a CONNACK packet.
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901074
*/
struct aws_mqtt5_packet_connack_view {
bool session_present;
enum aws_mqtt5_connect_reason_code reason_code;
const uint32_t *session_expiry_interval;
const uint16_t *receive_maximum;
const enum aws_mqtt5_qos *maximum_qos;
const bool *retain_available;
const uint32_t *maximum_packet_size;
const struct aws_byte_cursor *assigned_client_identifier;
const uint16_t *topic_alias_maximum;
const struct aws_byte_cursor *reason_string;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
const bool *wildcard_subscriptions_available;
const bool *subscription_identifiers_available;
const bool *shared_subscriptions_available;
const uint16_t *server_keep_alive;
const struct aws_byte_cursor *response_information;
const struct aws_byte_cursor *server_reference;
const struct aws_byte_cursor *authentication_method;
const struct aws_byte_cursor *authentication_data;
};
/**
* Read-only snapshot of a PUBACK packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901121
*/
struct aws_mqtt5_packet_puback_view {
aws_mqtt5_packet_id_t packet_id;
enum aws_mqtt5_puback_reason_code reason_code;
const struct aws_byte_cursor *reason_string;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
};
/**
* Read-only snapshot of a SUBACK packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901171
*/
struct aws_mqtt5_packet_suback_view {
aws_mqtt5_packet_id_t packet_id;
const struct aws_byte_cursor *reason_string;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
size_t reason_code_count;
const enum aws_mqtt5_suback_reason_code *reason_codes;
};
/**
* Read-only snapshot of an UNSUBACK packet
*
* https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901187
*/
struct aws_mqtt5_packet_unsuback_view {
aws_mqtt5_packet_id_t packet_id;
const struct aws_byte_cursor *reason_string;
size_t user_property_count;
const struct aws_mqtt5_user_property *user_properties;
size_t reason_code_count;
const enum aws_mqtt5_unsuback_reason_code *reason_codes;
};
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_MQTT_MQTT5_TYPES_H */