Skip to content

Commit ef0e817

Browse files
committed
bring in mqtt3 changes
1 parent c1ab0e2 commit ef0e817

12 files changed

Lines changed: 862 additions & 4 deletions

include/aws/mqtt/client.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,21 @@ int aws_mqtt_client_connection_get_stats(
693693
struct aws_mqtt_client_connection *connection,
694694
struct aws_mqtt_connection_operation_statistics *stats);
695695

696+
/**
697+
* Sets IoT SDK metrics configuration for the connection.
698+
* These metrics will be appended to the username field during connection.
699+
*
700+
* NOTE: DO NOT USE METADATA. Metadata will not be set.
701+
*
702+
* \param connection The connection object
703+
* \param metrics The IoT SDK metrics configuration (pass NULL to disable metrics)
704+
* \returns AWS_OP_SUCCESS if successful, AWS_OP_ERR otherwise
705+
*/
706+
AWS_MQTT_API
707+
int aws_mqtt_client_connection_set_metrics(
708+
struct aws_mqtt_client_connection *connection,
709+
const struct aws_mqtt_iot_sdk_metrics *metrics);
710+
696711
AWS_EXTERN_C_END
697712
AWS_POP_SANE_WARNING_LEVEL
698713

include/aws/mqtt/mqtt.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,44 @@ enum aws_mqtt_log_subject {
111111
/** Function called on cleanup of a userdata. */
112112
typedef void(aws_mqtt_userdata_cleanup_fn)(void *userdata);
113113

114+
/**
115+
* Metadata entry for IoT SDK metrics
116+
*/
117+
struct aws_mqtt_metadata_entry {
118+
struct aws_byte_cursor key;
119+
struct aws_byte_cursor value;
120+
};
121+
122+
/**
123+
* IoT SDK metrics configuration structure
124+
*/
125+
struct aws_mqtt_iot_sdk_metrics {
126+
/**
127+
* TODO: This is a place holder for metadata entries.
128+
* The metadata_entries is not added to username yet.
129+
*
130+
* DO NOT USE.
131+
*
132+
* Array of metadata entries
133+
*/
134+
// struct aws_mqtt_metadata_entry *metadata_entries;
135+
136+
/**
137+
* TODO: This is a place holder for metadata entries.
138+
* The metadata_entries is not added to username yet.
139+
*
140+
* DO NOT USE.
141+
*
142+
* Number of metadata entries
143+
*/
144+
// size_t metadata_count;
145+
146+
/**
147+
* Library name string (SDK attribute)
148+
*/
149+
struct aws_byte_cursor library_name;
150+
};
151+
114152
AWS_EXTERN_C_BEGIN
115153

116154
AWS_MQTT_API

include/aws/mqtt/private/client_impl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,12 @@ struct aws_mqtt_client_connection_311_impl {
365365
* Statistics tracking operational state
366366
*/
367367
struct aws_mqtt_connection_operation_statistics_impl operation_statistics_impl;
368+
369+
/**
370+
* IoT SDK metrics configuration
371+
*/
372+
struct aws_mqtt_iot_sdk_metrics_storage *metrics;
373+
struct aws_byte_buf username_with_metrics_buf;
368374
};
369375

370376
struct aws_channel_handler_vtable *aws_mqtt_get_client_channel_vtable(void);

include/aws/mqtt/private/client_impl_shared.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ struct aws_mqtt_client_connection_vtable {
122122

123123
int (*get_stats_fn)(void *impl, struct aws_mqtt_connection_operation_statistics *stats);
124124

125+
int (*set_metrics_fn)(void *impl, const struct aws_mqtt_iot_sdk_metrics *metrics);
126+
125127
enum aws_mqtt311_impl_type (*get_impl_type)(const void *impl);
126128

127129
struct aws_event_loop *(*get_event_loop)(const void *impl);
@@ -132,6 +134,28 @@ struct aws_mqtt_client_connection {
132134
void *impl;
133135
};
134136

137+
struct aws_mqtt_iot_sdk_metrics_storage {
138+
struct aws_allocator *allocator;
139+
140+
struct aws_mqtt_iot_sdk_metrics storage_view;
141+
142+
struct aws_array_list metadata_entries;
143+
144+
struct aws_byte_cursor library_name;
145+
146+
struct aws_byte_buf storage;
147+
};
148+
149+
/* IoT SDK Metrics */
150+
AWS_MQTT_API int aws_mqtt_iot_sdk_metrics_storage_init(
151+
struct aws_mqtt_iot_sdk_metrics_storage *metrics_storage,
152+
struct aws_allocator *allocator,
153+
const struct aws_mqtt_iot_sdk_metrics *metrics_options);
154+
155+
AWS_MQTT_API size_t aws_mqtt_iot_sdk_metrics_compute_storage_size(const struct aws_mqtt_iot_sdk_metrics *metrics);
156+
157+
AWS_MQTT_API void aws_mqtt_iot_sdk_metrics_storage_clean_up(struct aws_mqtt_iot_sdk_metrics_storage *metrics_storage);
158+
135159
AWS_MQTT_API enum aws_mqtt311_impl_type aws_mqtt_client_connection_get_impl_type(
136160
const struct aws_mqtt_client_connection *connection);
137161

@@ -144,4 +168,38 @@ AWS_MQTT_API bool aws_mqtt_byte_cursor_hash_equality(const void *a, const void *
144168
AWS_MQTT_API struct aws_event_loop *aws_mqtt_client_connection_get_event_loop(
145169
const struct aws_mqtt_client_connection *connection);
146170

171+
/**
172+
* Appends SDK metrics to the username field
173+
*
174+
* @param original_username The original username
175+
* @param metrics The metrics configuration
176+
* @param output_username Buffer to store the modified username. If the function succeed, caller is responsible to
177+
* release the memory for output_username.
178+
*
179+
* @return AWS_OP_SUCCESS on success, AWS_OP_ERR on failure
180+
*/
181+
AWS_MQTT_API
182+
int aws_mqtt_append_sdk_metrics_to_username(
183+
struct aws_allocator *allocator,
184+
const struct aws_byte_cursor *original_username,
185+
const struct aws_mqtt_iot_sdk_metrics metrics,
186+
struct aws_byte_buf *output_username);
187+
188+
/**
189+
* Get final username length
190+
*/
191+
AWS_MQTT_API
192+
size_t aws_mqtt_append_sdk_metrics_to_username_size(
193+
const struct aws_byte_cursor *original_username,
194+
const struct aws_mqtt_iot_sdk_metrics metrics);
195+
196+
/**
197+
* Validates that all string fields in aws_mqtt_iot_sdk_metrics are valid UTF-8
198+
*
199+
* @param metrics The metrics structure to validate
200+
* @return AWS_OP_SUCCESS if all strings are valid UTF-8, AWS_OP_ERR otherwise
201+
*/
202+
AWS_MQTT_API
203+
int aws_mqtt_validate_iot_sdk_metrics_utf8(const struct aws_mqtt_iot_sdk_metrics *metrics);
204+
147205
#endif /* AWS_MQTT_PRIVATE_CLIENT_IMPL_SHARED_H */

source/client.c

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,32 @@ static void s_mqtt_client_init(
623623
&connect, topic_cur, connection->will.qos, connection->will.retain, payload_cur);
624624
}
625625

626-
if (connection->username) {
627-
struct aws_byte_cursor username_cur = aws_byte_cursor_from_string(connection->username);
626+
if (connection->username || connection->metrics) {
627+
struct aws_byte_cursor username_cur;
628+
if (connection->username) {
629+
username_cur = aws_byte_cursor_from_string(connection->username);
630+
} else {
631+
/* Create empty username cursor when username is null but metrics is set */
632+
username_cur = aws_byte_cursor_from_c_str("");
633+
}
634+
635+
aws_byte_buf_clean_up(&connection->username_with_metrics_buf);
636+
637+
/* Apply metrics to username if configured */
638+
if (connection->metrics) {
639+
if (aws_mqtt_append_sdk_metrics_to_username(
640+
connection->allocator,
641+
&username_cur,
642+
connection->metrics->storage_view,
643+
&connection->username_with_metrics_buf) == AWS_OP_SUCCESS) {
644+
username_cur = aws_byte_cursor_from_buf(&connection->username_with_metrics_buf);
645+
} else {
646+
AWS_LOGF_WARN(
647+
AWS_LS_MQTT_CLIENT,
648+
"id=%p: Failed to apply metrics to username, using original",
649+
(void *)connection);
650+
}
651+
}
628652

629653
AWS_LOGF_DEBUG(
630654
AWS_LS_MQTT_CLIENT,
@@ -844,6 +868,14 @@ static void s_mqtt_client_connection_destroy_final(struct aws_mqtt_client_connec
844868
connection->http_proxy_config = NULL;
845869
}
846870

871+
/* Clean up metrics */
872+
if (connection->metrics) {
873+
aws_mqtt_iot_sdk_metrics_storage_clean_up(connection->metrics);
874+
connection->metrics = NULL;
875+
}
876+
877+
aws_byte_buf_clean_up(&connection->username_with_metrics_buf);
878+
847879
aws_mqtt_client_release(connection->client);
848880

849881
/* Frees all allocated memory */
@@ -3341,6 +3373,46 @@ int aws_mqtt_client_connection_set_on_operation_statistics_handler(
33413373
return AWS_OP_SUCCESS;
33423374
}
33433375

3376+
static int s_aws_mqtt_client_connection_311_set_metrics(void *impl, const struct aws_mqtt_iot_sdk_metrics *metrics) {
3377+
3378+
struct aws_mqtt_client_connection_311_impl *connection = impl;
3379+
3380+
AWS_PRECONDITION(connection);
3381+
if (s_check_connection_state_for_configuration(connection)) {
3382+
return aws_raise_error(AWS_ERROR_INVALID_STATE);
3383+
}
3384+
3385+
if (metrics != NULL && aws_mqtt_validate_iot_sdk_metrics_utf8(metrics) == AWS_OP_ERR) {
3386+
AWS_LOGF_DEBUG(
3387+
AWS_LS_MQTT_CLIENT, "id=%p: Invalid utf8 or forbidden codepoints in metrics.", (void *)connection);
3388+
return aws_raise_error(AWS_ERROR_INVALID_UTF8);
3389+
}
3390+
3391+
// TODO: Validate metadata value, when we had metadata in place.
3392+
3393+
AWS_LOGF_TRACE(AWS_LS_MQTT_CLIENT, "id=%p: Setting IoT SDK metrics", (void *)connection);
3394+
3395+
/* Clean up existing metrics if any */
3396+
if (connection->metrics) {
3397+
aws_mqtt_iot_sdk_metrics_storage_clean_up(connection->metrics);
3398+
connection->metrics = NULL;
3399+
}
3400+
3401+
if (metrics) {
3402+
/* Allocate metrics storage */
3403+
connection->metrics = aws_mem_calloc(connection->allocator, 1, sizeof(struct aws_mqtt_iot_sdk_metrics_storage));
3404+
3405+
/* Initialize metrics storage */
3406+
if (aws_mqtt_iot_sdk_metrics_storage_init(connection->metrics, connection->allocator, metrics)) {
3407+
aws_mem_release(connection->allocator, connection->metrics);
3408+
connection->metrics = NULL;
3409+
return AWS_OP_ERR;
3410+
}
3411+
}
3412+
3413+
return AWS_OP_SUCCESS;
3414+
}
3415+
33443416
static struct aws_mqtt_client_connection *s_aws_mqtt_client_connection_311_acquire(void *impl) {
33453417
struct aws_mqtt_client_connection_311_impl *connection = impl;
33463418

@@ -3390,6 +3462,7 @@ static struct aws_mqtt_client_connection_vtable s_aws_mqtt_client_connection_311
33903462
.unsubscribe_fn = s_aws_mqtt_client_connection_311_unsubscribe,
33913463
.publish_fn = s_aws_mqtt_client_connection_311_publish,
33923464
.get_stats_fn = s_aws_mqtt_client_connection_311_get_stats,
3465+
.set_metrics_fn = s_aws_mqtt_client_connection_311_set_metrics,
33933466
.get_impl_type = s_aws_mqtt_client_connection_311_get_impl,
33943467
.get_event_loop = s_aws_mqtt_client_connection_311_get_event_loop,
33953468
};
@@ -3493,6 +3566,8 @@ struct aws_mqtt_client_connection *aws_mqtt_client_connection_new(struct aws_mqt
34933566
connection->handler.vtable = aws_mqtt_get_client_channel_vtable();
34943567
connection->handler.impl = connection;
34953568

3569+
aws_byte_buf_init(&connection->username_with_metrics_buf, connection->allocator, 0);
3570+
34963571
aws_mqtt311_callback_set_manager_init(&connection->callback_manager, connection->allocator, &connection->base);
34973572

34983573
return &connection->base;
@@ -3511,3 +3586,11 @@ struct aws_mqtt_client_connection *aws_mqtt_client_connection_new(struct aws_mqt
35113586

35123587
return NULL;
35133588
}
3589+
3590+
int aws_mqtt_client_connection_set_metrics(
3591+
struct aws_mqtt_client_connection *connection,
3592+
const struct aws_mqtt_iot_sdk_metrics *metrics) {
3593+
3594+
AWS_PRECONDITION(connection);
3595+
return connection->vtable->set_metrics_fn(connection->impl, metrics);
3596+
}

0 commit comments

Comments
 (0)