@@ -94,7 +94,6 @@ int s_build_username_query(
9494 return AWS_OP_SUCCESS ;
9595}
9696
97- // TODO Future Work: we ignored the metadata field for now, will add them in future support
9897int aws_mqtt_append_sdk_metrics_to_username (
9998 struct aws_allocator * allocator ,
10099 const struct aws_byte_cursor * original_username ,
@@ -133,10 +132,15 @@ int aws_mqtt_append_sdk_metrics_to_username(
133132 struct aws_byte_cursor question_mark_str = aws_byte_cursor_from_c_str ("?" );
134133 struct aws_byte_cursor sdk_str = aws_byte_cursor_from_c_str ("SDK" );
135134 struct aws_byte_cursor platform_str = aws_byte_cursor_from_c_str ("Platform" );
135+ struct aws_byte_cursor metadata_str = aws_byte_cursor_from_c_str ("Metadata" );
136136
137137 struct aws_array_list params_list ;
138138 aws_array_list_init_dynamic (& params_list , allocator , DEFAULT_QUERY_PARAM_COUNT , sizeof (struct aws_uri_param ));
139139
140+ /* Buffer to hold the metadata value string: (key1=value1;key2=value2;...) */
141+ struct aws_byte_buf metadata_value_buf ;
142+ AWS_ZERO_STRUCT (metadata_value_buf );
143+
140144 // Looking for any existing query in the original username
141145 if (local_original_username .len > 0 ) {
142146 struct aws_byte_cursor question_mark_find = local_original_username ;
@@ -193,6 +197,66 @@ int aws_mqtt_append_sdk_metrics_to_username(
193197 aws_array_list_push_back (& params_list , & platform_params );
194198 }
195199
200+ /* Build metadata value string and add to params_list if metadata entries exist */
201+ if (metrics -> metadata_entries != NULL && metrics -> metadata_count > 0 ) {
202+ struct aws_byte_cursor key_value_delim = aws_byte_cursor_from_c_str ("=" );
203+ struct aws_byte_cursor entry_delim = aws_byte_cursor_from_c_str (";" );
204+ struct aws_byte_cursor open_paren = aws_byte_cursor_from_c_str ("(" );
205+ struct aws_byte_cursor close_paren = aws_byte_cursor_from_c_str (")" );
206+
207+ /* Calculate size needed for metadata value: (key1=value1;key2=value2;...) */
208+ size_t metadata_value_size = open_paren .len + close_paren .len ;
209+ for (size_t i = 0 ; i < metrics -> metadata_count ; ++ i ) {
210+ const struct aws_mqtt_metadata_entry * entry = & metrics -> metadata_entries [i ];
211+ metadata_value_size += entry -> key .len + key_value_delim .len + entry -> value .len ;
212+ if (i < metrics -> metadata_count - 1 ) {
213+ metadata_value_size += entry_delim .len ; /* semicolon separator between entries */
214+ }
215+ }
216+
217+ /* Initialize buffer for metadata value */
218+ if (aws_byte_buf_init (& metadata_value_buf , allocator , metadata_value_size )) {
219+ goto cleanup ;
220+ }
221+
222+ /* Build metadata value: (key1=value1;key2=value2;...) */
223+ if (aws_byte_buf_append (& metadata_value_buf , & open_paren )) {
224+ goto cleanup ;
225+ }
226+
227+ for (size_t i = 0 ; i < metrics -> metadata_count ; ++ i ) {
228+ const struct aws_mqtt_metadata_entry * entry = & metrics -> metadata_entries [i ];
229+
230+ if (aws_byte_buf_append (& metadata_value_buf , & entry -> key )) {
231+ goto cleanup ;
232+ }
233+ if (aws_byte_buf_append (& metadata_value_buf , & key_value_delim )) {
234+ goto cleanup ;
235+ }
236+ if (aws_byte_buf_append (& metadata_value_buf , & entry -> value )) {
237+ goto cleanup ;
238+ }
239+
240+ /* Add semicolon separator between entries (not after the last one) */
241+ if (i < metrics -> metadata_count - 1 ) {
242+ if (aws_byte_buf_append (& metadata_value_buf , & entry_delim )) {
243+ goto cleanup ;
244+ }
245+ }
246+ }
247+
248+ if (aws_byte_buf_append (& metadata_value_buf , & close_paren )) {
249+ goto cleanup ;
250+ }
251+
252+ /* Add Metadata parameter to params_list */
253+ struct aws_uri_param metadata_params = {
254+ .key = metadata_str ,
255+ .value = aws_byte_cursor_from_buf (& metadata_value_buf ),
256+ };
257+ aws_array_list_push_back (& params_list , & metadata_params );
258+ }
259+
196260 // Rebuild metrics string from params_list
197261 // First parse to get final username size
198262 size_t total_size = 0 ;
@@ -218,6 +282,7 @@ int aws_mqtt_append_sdk_metrics_to_username(
218282 result = AWS_OP_SUCCESS ;
219283
220284cleanup :
285+ aws_byte_buf_clean_up (& metadata_value_buf );
221286 aws_array_list_clean_up (& params_list );
222287
223288 if (result == AWS_OP_ERR ) {
@@ -238,6 +303,15 @@ size_t aws_mqtt_iot_metrics_compute_storage_size(const struct aws_mqtt_iot_metri
238303 size_t storage_size = 0 ;
239304 storage_size += metrics -> library_name .len ;
240305
306+ /* Add storage for metadata entries */
307+ if (metrics -> metadata_entries != NULL && metrics -> metadata_count > 0 ) {
308+ for (size_t i = 0 ; i < metrics -> metadata_count ; ++ i ) {
309+ const struct aws_mqtt_metadata_entry * entry = & metrics -> metadata_entries [i ];
310+ storage_size += entry -> key .len ;
311+ storage_size += entry -> value .len ;
312+ }
313+ }
314+
241315 return storage_size ;
242316}
243317
@@ -270,13 +344,49 @@ struct aws_mqtt_iot_metrics_storage *aws_mqtt_iot_metrics_storage_new(
270344 storage_view -> library_name = metrics_storage -> library_name ;
271345 }
272346
347+ /* Copy metadata entries */
348+ if (metrics_options -> metadata_entries != NULL && metrics_options -> metadata_count > 0 ) {
349+ if (aws_array_list_init_dynamic (
350+ & metrics_storage -> metadata_entries ,
351+ allocator ,
352+ metrics_options -> metadata_count ,
353+ sizeof (struct aws_mqtt_metadata_entry ))) {
354+ goto cleanup_storage ;
355+ }
356+
357+ for (size_t i = 0 ; i < metrics_options -> metadata_count ; ++ i ) {
358+ struct aws_mqtt_metadata_entry entry ;
359+ entry .key = metrics_options -> metadata_entries [i ].key ;
360+ entry .value = metrics_options -> metadata_entries [i ].value ;
361+
362+ /* Copy key into storage buffer and update cursor */
363+ if (entry .key .len > 0 ) {
364+ if (aws_byte_buf_append_and_update (& metrics_storage -> storage , & entry .key )) {
365+ goto cleanup_storage ;
366+ }
367+ }
368+
369+ /* Copy value into storage buffer and update cursor */
370+ if (entry .value .len > 0 ) {
371+ if (aws_byte_buf_append_and_update (& metrics_storage -> storage , & entry .value )) {
372+ goto cleanup_storage ;
373+ }
374+ }
375+
376+ aws_array_list_push_back (& metrics_storage -> metadata_entries , & entry );
377+ }
378+
379+ /* Set storage_view to point to the metadata entries array */
380+ storage_view -> metadata_count = aws_array_list_length (& metrics_storage -> metadata_entries );
381+ storage_view -> metadata_entries = metrics_storage -> metadata_entries .data ;
382+ }
383+
273384 return metrics_storage ;
274385
275386cleanup_storage :
276- // TODO Future Work: add metadata entries once we implemented the metadata feature
277- // if (aws_array_list_is_valid(&metrics_storage->metadata_entries)) {
278- // aws_array_list_clean_up(&metrics_storage->metadata_entries);
279- // }
387+ if (aws_array_list_is_valid (& metrics_storage -> metadata_entries )) {
388+ aws_array_list_clean_up (& metrics_storage -> metadata_entries );
389+ }
280390
281391 aws_byte_buf_clean_up (& metrics_storage -> storage );
282392 aws_mem_release (allocator , metrics_storage );
@@ -288,6 +398,10 @@ void aws_mqtt_iot_metrics_storage_destroy(struct aws_mqtt_iot_metrics_storage *m
288398 return ;
289399 }
290400
401+ if (aws_array_list_is_valid (& metrics_storage -> metadata_entries )) {
402+ aws_array_list_clean_up (& metrics_storage -> metadata_entries );
403+ }
404+
291405 aws_byte_buf_clean_up (& metrics_storage -> storage );
292406
293407 aws_mem_release (metrics_storage -> allocator , metrics_storage );
@@ -302,5 +416,23 @@ int aws_mqtt_validate_iot_metrics(const struct aws_mqtt_iot_metrics *metrics) {
302416 return AWS_OP_ERR ;
303417 }
304418
419+ /* Validate metadata entries */
420+ if (metrics -> metadata_entries != NULL && metrics -> metadata_count > 0 ) {
421+ for (size_t i = 0 ; i < metrics -> metadata_count ; ++ i ) {
422+ if (aws_mqtt_validate_utf8_text (metrics -> metadata_entries [i ].key )) {
423+ return AWS_OP_ERR ;
424+ }
425+ if (aws_mqtt_validate_utf8_text (metrics -> metadata_entries [i ].value )) {
426+ return AWS_OP_ERR ;
427+ }
428+ }
429+ }
430+
305431 return AWS_OP_SUCCESS ;
306432}
433+
434+ bool aws_mqtt_has_non_empty_username (
435+ const struct aws_byte_cursor * username ,
436+ const struct aws_mqtt_iot_metrics_storage * metrics_storage ) {
437+ return (username != NULL && username -> len > 0 ) || metrics_storage != NULL ;
438+ }
0 commit comments