From 1d8a7aa5e95afaa1eedc98ada51b9a0ad2ec15ed Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 30 Dec 2025 12:10:31 -0800 Subject: [PATCH 01/16] binding metrics. Custom Auth related test should fail --- crt/aws-c-common | 2 +- crt/aws-c-mqtt | 2 +- .../crt/internal/IoTDeviceSDKMetrics.java | 21 ++++ .../awssdk/crt/mqtt/MqttClientConnection.java | 8 ++ .../awssdk/crt/mqtt/MqttConnectionConfig.java | 22 +++++ .../awssdk/crt/mqtt5/Mqtt5ClientOptions.java | 42 ++++++++ src/native/crt.c | 8 ++ src/native/iot_device_sdk_metrics.c | 96 +++++++++++++++++++ src/native/iot_device_sdk_metrics.h | 31 ++++++ src/native/java_class_ids.c | 23 +++++ src/native/java_class_ids.h | 9 ++ src/native/mqtt5_client.c | 25 +++++ src/native/mqtt_connection.c | 24 +++++ 13 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java create mode 100644 src/native/iot_device_sdk_metrics.c create mode 100644 src/native/iot_device_sdk_metrics.h diff --git a/crt/aws-c-common b/crt/aws-c-common index 31578beb2..95515a8b1 160000 --- a/crt/aws-c-common +++ b/crt/aws-c-common @@ -1 +1 @@ -Subproject commit 31578beb2309330fece3fb3a66035a568a2641e7 +Subproject commit 95515a8b1ff40d5bb14f965ca4cbbe99ad1843df diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index 1d512d927..154e9c5dd 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit 1d512d92709f60b74e2cafa018e69a2e647f28e9 +Subproject commit 154e9c5dd19ec6d8d4cd690492d2a029f13e2035 diff --git a/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java b/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java new file mode 100644 index 000000000..2d396541d --- /dev/null +++ b/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java @@ -0,0 +1,21 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package software.amazon.awssdk.crt.internal; + +/** + * @internal + * IoT Device SDK Metrics Structure + */ +public class IoTDeviceSDKMetrics { + private String libraryName; + + public IoTDeviceSDKMetrics() { + this.libraryName = "IoTDeviceSDK/Java"; + } + + public String getLibraryName() { + return libraryName; + } +} \ No newline at end of file diff --git a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java index c4ac6af1f..376649280 100644 --- a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java +++ b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java @@ -17,6 +17,7 @@ import software.amazon.awssdk.crt.mqtt5.Mqtt5Client; import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions; import software.amazon.awssdk.crt.mqtt5.packets.ConnectPacket; +import software.amazon.awssdk.crt.internal.IoTDeviceSDKMetrics; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -162,6 +163,10 @@ private void SetupConfig(MqttConnectionConfig config) throws MqttException { mqttClientConnectionSetLogin(getNativeHandle(), config.getUsername(), config.getPassword()); } + if (config.getMetricsEnabled()) { + mqttClientConnectionSetMetrics(getNativeHandle(), new IoTDeviceSDKMetrics()); + } + if (config.getMinReconnectTimeoutSecs() != 0L && config.getMaxReconnectTimeoutSecs() != 0L) { mqttClientConnectionSetReconnectTimeout(getNativeHandle(), config.getMinReconnectTimeoutSecs(), config.getMaxReconnectTimeoutSecs()); @@ -502,6 +507,9 @@ private static native boolean mqttClientConnectionSetWill(long connection, Strin private static native void mqttClientConnectionSetLogin(long connection, String username, String password) throws CrtRuntimeException; + private static native void mqttClientConnectionSetMetrics(long connection, IoTDeviceSDKMetrics metrics) + throws CrtRuntimeException; + private static native void mqttClientConnectionSetReconnectTimeout(long connection, long minTimeout, long maxTimeout) throws CrtRuntimeException; diff --git a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttConnectionConfig.java b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttConnectionConfig.java index 255697852..6b6af1084 100644 --- a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttConnectionConfig.java +++ b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttConnectionConfig.java @@ -46,6 +46,9 @@ public final class MqttConnectionConfig extends CrtResource { private HttpProxyOptions proxyOptions; private Consumer websocketHandshakeTransform; + /* metrics */ + private boolean metricsEnabled = true; + public MqttConnectionConfig() {} @@ -538,6 +541,24 @@ public Consumer getWebsocketHandshakeTransform( return websocketHandshakeTransform; } + /** + * Enables or disables IoT Device SDK metrics collection + * + * @param enabled true to enable metrics, false to disable + */ + public void setMetricsEnabled(boolean enabled) { + this.metricsEnabled = enabled; + } + + /** + * Queries whether IoT Device SDK metrics collection is enabled + * + * @return true if metrics are enabled, false if disabled + */ + public boolean getMetricsEnabled() { + return metricsEnabled; + } + /** * Creates a (shallow) clone of this config object * @@ -567,6 +588,7 @@ public MqttConnectionConfig clone() { clone.setWebsocketHandshakeTransform(getWebsocketHandshakeTransform()); clone.setReconnectTimeoutSecs(getMinReconnectTimeoutSecs(), getMaxReconnectTimeoutSecs()); + clone.setMetricsEnabled(getMetricsEnabled()); // success, bump up the ref count so we can escape the try-with-resources block clone.addRef(); diff --git a/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java b/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java index acd18c8ac..b5829feb1 100644 --- a/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java +++ b/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java @@ -12,6 +12,7 @@ import software.amazon.awssdk.crt.mqtt5.packets.ConnectPacket; import software.amazon.awssdk.crt.mqtt.MqttConnectionConfig; +import software.amazon.awssdk.crt.internal.IoTDeviceSDKMetrics; import java.util.Map; import java.util.function.Function; @@ -45,6 +46,11 @@ public class Mqtt5ClientOptions { private Consumer websocketHandshakeTransform; private PublishEvents publishEvents; private TopicAliasingOptions topicAliasingOptions; + // Indicates whether AWS IoT Metrics are enabled for this client, default to true. + // We don't expose this setting in the builder for now. + private IoTDeviceSDKMetrics iotDeviceSDKMetrics; + private boolean metricsEnabled = true; + /** * Returns the host name of the MQTT server to connect to. @@ -263,6 +269,15 @@ public TopicAliasingOptions getTopicAliasingOptions() { return this.topicAliasingOptions; } + /** + * Enables or disables IoT Device SDK metrics collection + * + * @param enabled true to enable metrics, false to disable + */ + public void setMetricsEnabled(boolean enabled) { + this.metricsEnabled = enabled; + } + /** * Creates a Mqtt5ClientOptionsBuilder instance * @param builder The builder to get the Mqtt5ClientOptions values from @@ -289,6 +304,8 @@ public Mqtt5ClientOptions(Mqtt5ClientOptionsBuilder builder) { this.websocketHandshakeTransform = builder.websocketHandshakeTransform; this.publishEvents = builder.publishEvents; this.topicAliasingOptions = builder.topicAliasingOptions; + this.metricsEnabled = builder.metricsEnabled; + this.iotDeviceSDKMetrics = new IoTDeviceSDKMetrics(); } /******************************************************************************* @@ -583,6 +600,8 @@ static final public class Mqtt5ClientOptionsBuilder { private Consumer websocketHandshakeTransform; private PublishEvents publishEvents; private TopicAliasingOptions topicAliasingOptions; + private boolean enableAwsMetrics = true; + private boolean metricsEnabled = true; /** * Sets the host name of the MQTT server to connect to. @@ -850,6 +869,29 @@ public Mqtt5ClientOptionsBuilder withTopicAliasingOptions(TopicAliasingOptions o return this; } + /** + * Enable or disable AWS IoT specific metrics. The metrics will be set in username field of CONNECT packet. + * By default, the AWS IoT metrics are enabled. Disable it if you are connecting to a non-AWS IoT MQTT broker. + * + * @param enableAwsMetrics true to enable, false to disable + * @return The Mqtt5ClientOptionsBuilder after setting the AWS metrics option + */ + public Mqtt5ClientOptionsBuilder withAWSMetrics(boolean enableAwsMetrics) { + this.enableAwsMetrics = enableAwsMetrics; + return this; + } + + /** + * Enables or disables IoT Device SDK metrics collection + * + * @param enabled true to enable metrics, false to disable + * @return The Mqtt5ClientOptionsBuilder after setting the metrics option + */ + public Mqtt5ClientOptionsBuilder withMetricsEnabled(boolean enabled) { + this.metricsEnabled = enabled; + return this; + } + /** * Creates a new Mqtt5ClientOptionsBuilder instance * diff --git a/src/native/crt.c b/src/native/crt.c index 463f31e34..6ff618f29 100644 --- a/src/native/crt.c +++ b/src/native/crt.c @@ -707,6 +707,14 @@ jstring JNICALL Java_software_amazon_awssdk_crt_CRT_awsErrorName(JNIEnv *env, jc return (*env)->NewStringUTF(env, error_msg); } +JNIEXPORT +jstring JNICALL Java_software_amazon_awssdk_crt_CRT_awsPlatformBuildString(JNIEnv *env, jclass jni_crt_class) { + (void)jni_crt_class; + struct aws_byte_cursor platform_string = aws_get_platform_build_os_string(); + + return aws_jni_string_from_cursor(env, &platform_string); +} + JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_CRT_awsNativeMemory(JNIEnv *env, jclass jni_crt_class) { (void)env; diff --git a/src/native/iot_device_sdk_metrics.c b/src/native/iot_device_sdk_metrics.c new file mode 100644 index 000000000..35cb2fc00 --- /dev/null +++ b/src/native/iot_device_sdk_metrics.c @@ -0,0 +1,96 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include + +#include "iot_device_sdk_metrics.h" +#include "mqtt5_packets.h" +#include +#include +#include + +/* on 32-bit platforms, casting pointers to longs throws a warning we don't need */ +#if UINTPTR_MAX == 0xffffffff +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */ +# else +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +# pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +# endif +#endif + +static char s_iot_device_sdk_metrics_string[] = "IoTDeviceSDKMetrics"; + +void aws_mqtt_iot_sdk_metrics_java_jni_destroy( + JNIEnv *env, + struct aws_allocator *allocator, + struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics) { + (void)env; + + if (!java_metrics) { + return; + } + AWS_LOGF_DEBUG(AWS_LS_MQTT_GENERAL, "id=%p: Destroying IoTDeviceSDKMetrics", (void *)java_metrics); + + if (aws_byte_buf_is_valid(&java_metrics->library_name_buf)) { + aws_byte_buf_clean_up(&java_metrics->library_name_buf); + } + + aws_mem_release(allocator, java_metrics); +} + +struct aws_mqtt_iot_sdk_metrics_java_jni *aws_mqtt_iot_sdk_metrics_java_jni_create_from_java( + JNIEnv *env, + struct aws_allocator *allocator, + jobject java_iot_device_sdk_metrics) { + + struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics = + aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt_iot_sdk_metrics_java_jni)); + if (java_metrics == NULL) { + AWS_LOGF_ERROR( + AWS_LS_MQTT_GENERAL, "IoTDeviceSDKMetrics create_from_java: Creating new IoTDeviceSDKMetrics failed"); + return NULL; + } + + if (aws_get_string_from_jobject( + env, + java_iot_device_sdk_metrics, + iot_device_sdk_metrics_properties.library_name_field_id, + s_iot_device_sdk_metrics_string, + "library name", + &java_metrics->library_name_buf, + &java_metrics->library_name_cursor, + false, + NULL) == AWS_OP_ERR) { + AWS_LOGF_ERROR(AWS_LS_MQTT_GENERAL, "IoTDeviceSDKMetrics create_from_java: No library name found"); + goto on_error; + } + java_metrics->metrics.library_name = java_metrics->library_name_cursor; + + return java_metrics; + +on_error: + /* Clean up */ + aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, allocator, java_metrics); + return NULL; +} + +struct aws_mqtt_iot_sdk_metrics *aws_mqtt_iot_sdk_metrics_java_jni_get_metrics( + struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics) { + if (java_metrics) { + return &java_metrics->metrics; + } else { + return NULL; + } +} + +#if UINTPTR_MAX == 0xffffffff +# if defined(_MSC_VER) +# pragma warning(pop) +# else +# pragma GCC diagnostic pop +# endif +#endif diff --git a/src/native/iot_device_sdk_metrics.h b/src/native/iot_device_sdk_metrics.h new file mode 100644 index 000000000..552a01005 --- /dev/null +++ b/src/native/iot_device_sdk_metrics.h @@ -0,0 +1,31 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#ifndef AWS_JNI_IOT_DEVICE_SDK_METRICS_H +#define AWS_JNI_IOT_DEVICE_SDK_METRICS_H + +#include +#include +#include + +struct aws_mqtt_iot_sdk_metrics_java_jni { + struct aws_mqtt_iot_sdk_metrics metrics; + struct aws_byte_buf library_name_buf; + struct aws_byte_cursor library_name_cursor; +}; + +void aws_mqtt_iot_sdk_metrics_java_jni_destroy( + JNIEnv *env, + struct aws_allocator *allocator, + struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics); + +struct aws_mqtt_iot_sdk_metrics_java_jni *aws_mqtt_iot_sdk_metrics_java_jni_create_from_java( + JNIEnv *env, + struct aws_allocator *allocator, + jobject java_iot_device_sdk_metrics); + +struct aws_mqtt_iot_sdk_metrics *aws_mqtt_iot_sdk_metrics_java_jni_get_metrics( + struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics); + +#endif /* AWS_JNI_IOT_DEVICE_SDK_METRICS_H */ diff --git a/src/native/java_class_ids.c b/src/native/java_class_ids.c index 4cd3bcf65..28bcb42c4 100644 --- a/src/native/java_class_ids.c +++ b/src/native/java_class_ids.c @@ -1628,6 +1628,15 @@ static void s_cache_mqtt5_client_options(JNIEnv *env) { "topicAliasingOptions", "Lsoftware/amazon/awssdk/crt/mqtt5/TopicAliasingOptions;"); AWS_FATAL_ASSERT(mqtt5_client_options_properties.topic_aliasing_options_field_id); + mqtt5_client_options_properties.metrics_enabled_field_id = (*env)->GetFieldID( + env, mqtt5_client_options_properties.client_options_class, "metricsEnabled", "Z"); + AWS_FATAL_ASSERT(mqtt5_client_options_properties.metrics_enabled_field_id); + mqtt5_client_options_properties.iot_device_sdk_metrics_field_id = (*env)->GetFieldID( + env, + mqtt5_client_options_properties.client_options_class, + "iotDeviceSDKMetrics", + "Lsoftware/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics;"); + AWS_FATAL_ASSERT(mqtt5_client_options_properties.iot_device_sdk_metrics_field_id); } struct java_aws_mqtt5_topic_aliasing_options_properties mqtt5_topic_aliasing_options_properties; @@ -2515,6 +2524,19 @@ static void s_cache_cognito_credentials_provider(JNIEnv *env) { AWS_FATAL_ASSERT(cognito_credentials_provider_properties.create_chained_future_method_id != NULL); } +struct java_iot_device_sdk_metrics_properties iot_device_sdk_metrics_properties; + +static void s_cache_iot_device_sdk_metrics(JNIEnv *env) { + jclass cls = (*env)->FindClass(env, "software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics"); + AWS_FATAL_ASSERT(cls); + iot_device_sdk_metrics_properties.iot_device_sdk_metrics_class = (*env)->NewGlobalRef(env, cls); + AWS_FATAL_ASSERT(iot_device_sdk_metrics_properties.iot_device_sdk_metrics_class); + + iot_device_sdk_metrics_properties.library_name_field_id = (*env)->GetFieldID( + env, iot_device_sdk_metrics_properties.iot_device_sdk_metrics_class, "libraryName", "Ljava/lang/String;"); + AWS_FATAL_ASSERT(iot_device_sdk_metrics_properties.library_name_field_id); +} + static void s_cache_java_class_ids(void *user_data) { JNIEnv *env = user_data; s_cache_http_request_body_stream(env); @@ -2630,6 +2652,7 @@ static void s_cache_java_class_ids(void *user_data) { s_cache_consumer_properties(env); s_cache_cognito_login_token_source(env); s_cache_cognito_credentials_provider(env); + s_cache_iot_device_sdk_metrics(env); } static aws_thread_once s_cache_once_init = AWS_THREAD_ONCE_STATIC_INIT; diff --git a/src/native/java_class_ids.h b/src/native/java_class_ids.h index 97b42ef3b..8aad5766e 100644 --- a/src/native/java_class_ids.h +++ b/src/native/java_class_ids.h @@ -673,6 +673,8 @@ struct java_aws_mqtt5_client_options_properties { jfieldID publish_events_field_id; jfieldID lifecycle_events_field_id; jfieldID topic_aliasing_options_field_id; + jfieldID metrics_enabled_field_id; + jfieldID iot_device_sdk_metrics_field_id; }; extern struct java_aws_mqtt5_client_options_properties mqtt5_client_options_properties; @@ -1058,6 +1060,13 @@ struct java_cognito_credentials_provider_properties { extern struct java_cognito_credentials_provider_properties cognito_credentials_provider_properties; +/* IoTDeviceSDKMetrics */ +struct java_iot_device_sdk_metrics_properties { + jclass iot_device_sdk_metrics_class; + jfieldID library_name_field_id; +}; +extern struct java_iot_device_sdk_metrics_properties iot_device_sdk_metrics_properties; + /** * All functions bound to JNI MUST call this before doing anything else. * This caches all JNI IDs the first time it is called. Any further calls are no-op; it is thread-safe. diff --git a/src/native/mqtt5_client.c b/src/native/mqtt5_client.c index 5100ef3b8..6e125af61 100644 --- a/src/native/mqtt5_client.c +++ b/src/native/mqtt5_client.c @@ -16,6 +16,7 @@ #include #include #include +#include /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */ #if UINTPTR_MAX == 0xffffffff @@ -1692,6 +1693,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C struct aws_mqtt5_client_options client_options; AWS_ZERO_STRUCT(client_options); struct aws_http_proxy_options_java_jni *java_http_proxy_options = NULL; + struct aws_mqtt_iot_sdk_metrics_java_jni *iot_device_sdk_metrics = NULL; struct aws_byte_buf host_name_buf; /* Needed to track if optionals are set or not */ @@ -2106,6 +2108,28 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C client_options.client_termination_handler = &s_aws_mqtt5_client_java_termination; client_options.client_termination_handler_user_data = (void *)java_client; + /* Check if metrics are enabled and set metrics value */ + jboolean metrics_enabled = (*env)->GetBooleanField(env, jni_options, mqtt5_client_options_properties.metrics_enabled_field_id); + if (aws_jni_check_and_clear_exception(env)) { + s_aws_mqtt5_client_log_and_throw_exception( + env, "MQTT5 client new: error getting metrics enabled", AWS_ERROR_INVALID_STATE); + goto clean_up; + } + + if (metrics_enabled) { + jobject jni_iot_device_sdk_metrics = (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.iot_device_sdk_metrics_field_id); + if (aws_jni_check_and_clear_exception(env)) { + s_aws_mqtt5_client_log_and_throw_exception( + env, "MQTT5 client new: error getting IoT device SDK metrics", AWS_ERROR_INVALID_STATE); + goto clean_up; + } + + iot_device_sdk_metrics = aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); + client_options.metrics = &iot_device_sdk_metrics->metrics; + } + + + /* Make the MQTT5 client */ java_client->client = aws_mqtt5_client_new(allocator, &client_options); /* Did we successfully make a client? If not, then throw an exception */ @@ -2123,6 +2147,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C aws_mqtt5_packet_connect_view_java_destroy(env, allocator, connect_options); s_aws_mqtt5_http_proxy_options_java_destroy(env, allocator, java_http_proxy_options); + aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, allocator, iot_device_sdk_metrics); if (aws_byte_buf_is_valid(&host_name_buf)) { aws_byte_buf_clean_up(&host_name_buf); } diff --git a/src/native/mqtt_connection.c b/src/native/mqtt_connection.c index 5de927a71..295c88beb 100644 --- a/src/native/mqtt_connection.c +++ b/src/native/mqtt_connection.c @@ -31,6 +31,7 @@ #include "java_class_ids.h" #include "mqtt5_client_jni.h" #include "mqtt_connection.h" +#include "iot_device_sdk_metrics.h" /******************************************************************************* * mqtt_jni_ws_handshake - Data needed to perform the async websocket handshake @@ -1120,6 +1121,29 @@ JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection } } +JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetMetrics( + JNIEnv *env, + jclass jni_class, + jlong jni_connection, + jobject jni_metrics) { + (void)jni_class; + aws_cache_jni_ids(env); + + struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection; + if (!connection) { + aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_metrics: Invalid connection"); + return; + } + + struct aws_mqtt_iot_sdk_metrics_java_jni *iot_sdk_metrics_java_jni = aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, aws_jni_get_allocator(), jni_metrics); + + if (aws_mqtt_client_connection_set_metrics(connection->client_connection, &iot_sdk_metrics_java_jni->metrics)) { + aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_metrics: Failed to set metrics"); + } + + aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, aws_jni_get_allocator(), iot_sdk_metrics_java_jni); +} + JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetReconnectTimeout( JNIEnv *env, From 77814a69ce3cf8e9386f8cc670b222d7df7ec7f5 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 30 Dec 2025 13:47:32 -0800 Subject: [PATCH 02/16] update custome auth tests and adapter --- .../awssdk/crt/mqtt/MqttClientConnection.java | 1 + .../awssdk/crt/mqtt5/Mqtt5ClientOptions.java | 22 ++++------ src/native/iot_device_sdk_metrics.h | 2 +- src/native/java_class_ids.c | 4 +- src/native/mqtt5_client.c | 17 ++++---- src/native/mqtt_connection.c | 5 ++- .../awssdk/crt/test/CustomKeyOpsTest.java | 12 ++++-- .../awssdk/crt/test/IotServiceTest.java | 3 +- .../awssdk/crt/test/Mqtt5ClientTest.java | 11 +++-- .../crt/test/MqttClientConnectionFixture.java | 6 ++- .../test/MqttClientConnectionMethodTest.java | 41 ++++++++++++------- .../crt/test/MqttClientConnectionTest.java | 18 +++++--- .../amazon/awssdk/crt/test/PublishTest.java | 9 ++-- .../awssdk/crt/test/SelfPubSubTest.java | 6 ++- .../amazon/awssdk/crt/test/SubscribeTest.java | 3 +- .../amazon/awssdk/crt/test/WillTest.java | 9 ++-- 16 files changed, 104 insertions(+), 65 deletions(-) diff --git a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java index 376649280..6cec4bcd4 100644 --- a/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java +++ b/src/main/java/software/amazon/awssdk/crt/mqtt/MqttClientConnection.java @@ -78,6 +78,7 @@ private static MqttConnectionConfig s_toMqtt3ConnectionConfig(Mqtt5ClientOptions options.setProtocolOperationTimeoutMs(mqtt5options.getAckTimeoutSeconds() != null ? Math.toIntExact(mqtt5options.getAckTimeoutSeconds()) * 1000 : 0); + options.setMetricsEnabled(mqtt5options.getMetricsEnabled()); return options; } diff --git a/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java b/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java index b5829feb1..fdfdc8353 100644 --- a/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java +++ b/src/main/java/software/amazon/awssdk/crt/mqtt5/Mqtt5ClientOptions.java @@ -269,6 +269,15 @@ public TopicAliasingOptions getTopicAliasingOptions() { return this.topicAliasingOptions; } + /** + * Returns whether AWS IoT Device SDK metrics collection is enabled + * + * @return true if metrics are enabled, false otherwise + */ + public boolean getMetricsEnabled() { + return this.metricsEnabled; + } + /** * Enables or disables IoT Device SDK metrics collection * @@ -600,7 +609,6 @@ static final public class Mqtt5ClientOptionsBuilder { private Consumer websocketHandshakeTransform; private PublishEvents publishEvents; private TopicAliasingOptions topicAliasingOptions; - private boolean enableAwsMetrics = true; private boolean metricsEnabled = true; /** @@ -869,18 +877,6 @@ public Mqtt5ClientOptionsBuilder withTopicAliasingOptions(TopicAliasingOptions o return this; } - /** - * Enable or disable AWS IoT specific metrics. The metrics will be set in username field of CONNECT packet. - * By default, the AWS IoT metrics are enabled. Disable it if you are connecting to a non-AWS IoT MQTT broker. - * - * @param enableAwsMetrics true to enable, false to disable - * @return The Mqtt5ClientOptionsBuilder after setting the AWS metrics option - */ - public Mqtt5ClientOptionsBuilder withAWSMetrics(boolean enableAwsMetrics) { - this.enableAwsMetrics = enableAwsMetrics; - return this; - } - /** * Enables or disables IoT Device SDK metrics collection * diff --git a/src/native/iot_device_sdk_metrics.h b/src/native/iot_device_sdk_metrics.h index 552a01005..06108ebf6 100644 --- a/src/native/iot_device_sdk_metrics.h +++ b/src/native/iot_device_sdk_metrics.h @@ -5,9 +5,9 @@ #ifndef AWS_JNI_IOT_DEVICE_SDK_METRICS_H #define AWS_JNI_IOT_DEVICE_SDK_METRICS_H -#include #include #include +#include struct aws_mqtt_iot_sdk_metrics_java_jni { struct aws_mqtt_iot_sdk_metrics metrics; diff --git a/src/native/java_class_ids.c b/src/native/java_class_ids.c index 28bcb42c4..75691e9fe 100644 --- a/src/native/java_class_ids.c +++ b/src/native/java_class_ids.c @@ -1628,8 +1628,8 @@ static void s_cache_mqtt5_client_options(JNIEnv *env) { "topicAliasingOptions", "Lsoftware/amazon/awssdk/crt/mqtt5/TopicAliasingOptions;"); AWS_FATAL_ASSERT(mqtt5_client_options_properties.topic_aliasing_options_field_id); - mqtt5_client_options_properties.metrics_enabled_field_id = (*env)->GetFieldID( - env, mqtt5_client_options_properties.client_options_class, "metricsEnabled", "Z"); + mqtt5_client_options_properties.metrics_enabled_field_id = + (*env)->GetFieldID(env, mqtt5_client_options_properties.client_options_class, "metricsEnabled", "Z"); AWS_FATAL_ASSERT(mqtt5_client_options_properties.metrics_enabled_field_id); mqtt5_client_options_properties.iot_device_sdk_metrics_field_id = (*env)->GetFieldID( env, diff --git a/src/native/mqtt5_client.c b/src/native/mqtt5_client.c index 6e125af61..facf6072a 100644 --- a/src/native/mqtt5_client.c +++ b/src/native/mqtt5_client.c @@ -11,12 +11,12 @@ #include #include +#include #include #include #include #include #include -#include /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */ #if UINTPTR_MAX == 0xffffffff @@ -2109,27 +2109,28 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C client_options.client_termination_handler_user_data = (void *)java_client; /* Check if metrics are enabled and set metrics value */ - jboolean metrics_enabled = (*env)->GetBooleanField(env, jni_options, mqtt5_client_options_properties.metrics_enabled_field_id); + jboolean metrics_enabled = + (*env)->GetBooleanField(env, jni_options, mqtt5_client_options_properties.metrics_enabled_field_id); if (aws_jni_check_and_clear_exception(env)) { s_aws_mqtt5_client_log_and_throw_exception( env, "MQTT5 client new: error getting metrics enabled", AWS_ERROR_INVALID_STATE); goto clean_up; } - + if (metrics_enabled) { - jobject jni_iot_device_sdk_metrics = (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.iot_device_sdk_metrics_field_id); + jobject jni_iot_device_sdk_metrics = + (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.iot_device_sdk_metrics_field_id); if (aws_jni_check_and_clear_exception(env)) { s_aws_mqtt5_client_log_and_throw_exception( env, "MQTT5 client new: error getting IoT device SDK metrics", AWS_ERROR_INVALID_STATE); goto clean_up; } - - iot_device_sdk_metrics = aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); + + iot_device_sdk_metrics = + aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); client_options.metrics = &iot_device_sdk_metrics->metrics; } - - /* Make the MQTT5 client */ java_client->client = aws_mqtt5_client_new(allocator, &client_options); /* Did we successfully make a client? If not, then throw an exception */ diff --git a/src/native/mqtt_connection.c b/src/native/mqtt_connection.c index 295c88beb..a33d44125 100644 --- a/src/native/mqtt_connection.c +++ b/src/native/mqtt_connection.c @@ -28,10 +28,10 @@ #include "crt.h" #include "http_request_utils.h" +#include "iot_device_sdk_metrics.h" #include "java_class_ids.h" #include "mqtt5_client_jni.h" #include "mqtt_connection.h" -#include "iot_device_sdk_metrics.h" /******************************************************************************* * mqtt_jni_ws_handshake - Data needed to perform the async websocket handshake @@ -1135,7 +1135,8 @@ JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection return; } - struct aws_mqtt_iot_sdk_metrics_java_jni *iot_sdk_metrics_java_jni = aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, aws_jni_get_allocator(), jni_metrics); + struct aws_mqtt_iot_sdk_metrics_java_jni *iot_sdk_metrics_java_jni = + aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, aws_jni_get_allocator(), jni_metrics); if (aws_mqtt_client_connection_set_metrics(connection->client_connection, &iot_sdk_metrics_java_jni->metrics)) { aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_metrics: Failed to set metrics"); diff --git a/src/test/java/software/amazon/awssdk/crt/test/CustomKeyOpsTest.java b/src/test/java/software/amazon/awssdk/crt/test/CustomKeyOpsTest.java index 12da86cf3..a63dfcf5d 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/CustomKeyOpsTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/CustomKeyOpsTest.java @@ -147,7 +147,8 @@ private void doHappyPathTest() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -242,7 +243,8 @@ public void testExceptionFailurePath() { 8883, null, null, - null); + null, + true); } catch (Exception ex) { return; } finally { @@ -265,7 +267,8 @@ private void doExtraCompleteHappyTest() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -305,7 +308,8 @@ public void testExceptionExtraCompleteFailurePath() { 8883, null, null, - null); + null, + true); } catch (Exception ex) { return; } finally { diff --git a/src/test/java/software/amazon/awssdk/crt/test/IotServiceTest.java b/src/test/java/software/amazon/awssdk/crt/test/IotServiceTest.java index 91264fa4c..1f032927a 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/IotServiceTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/IotServiceTest.java @@ -43,7 +43,8 @@ private void doIotServiceTest() { port, null, null, - null); + null, + true); CompletableFuture subscribed = connection.subscribe(TEST_TOPIC, QualityOfService.AT_LEAST_ONCE, messageHandler); subscribed.thenApply(packetId -> subsAcked++); diff --git a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java index 06d81e503..e8786f0f4 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java @@ -264,7 +264,8 @@ public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) { }) .withRetryJitterMode(JitterMode.Default) .withSessionBehavior(ClientSessionBehavior.CLEAN) - .withSocketOptions(socketOptions); + .withSocketOptions(socketOptions) + .withMetricsEnabled(false); // Skip websocket and TLS options - those are all different tests HttpProxyOptions proxyOptions = new HttpProxyOptions(); @@ -330,6 +331,7 @@ private void doConnDC_UC2Test() { AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT)); builder.withLifecycleEvents(events); + builder.withMetricsEnabled(false); ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME).withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); @@ -510,7 +512,8 @@ public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) { }) .withRetryJitterMode(JitterMode.Default) .withSessionBehavior(ClientSessionBehavior.CLEAN) - .withSocketOptions(socketOptions); + .withSocketOptions(socketOptions) + .withMetricsEnabled(false); // Skip websocket, proxy options, and TLS options - those are all different tests try (Mqtt5Client client = new Mqtt5Client(builder.build())) { @@ -605,6 +608,7 @@ public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME).withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); builder.withConnectOptions(connectOptions.build()); + builder.withMetricsEnabled(false); try (Mqtt5Client client = new Mqtt5Client(builder.build())) { client.start(); @@ -772,7 +776,8 @@ public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) { }) .withRetryJitterMode(JitterMode.Default) .withSessionBehavior(ClientSessionBehavior.CLEAN) - .withSocketOptions(socketOptions); + .withSocketOptions(socketOptions) + .withMetricsEnabled(false); Consumer websocketTransform = new Consumer() { @Override diff --git a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionFixture.java b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionFixture.java index baed2d069..c11c95b89 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionFixture.java +++ b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionFixture.java @@ -176,7 +176,7 @@ void reset() { connectionEventsStatistics = new ConnectionEventsStatistics(); } - void connectDirect(TlsContext tlsContext, String endpoint, int port, String username, String password, HttpProxyOptions httpProxyOptions) throws Exception + void connectDirect(TlsContext tlsContext, String endpoint, int port, String username, String password, HttpProxyOptions httpProxyOptions, boolean metricsEnabled) throws Exception { reset(); @@ -236,6 +236,7 @@ public void onConnectionClosed(OnConnectionClosedReturn data) { config.setKeepAliveSecs(0); config.setProtocolOperationTimeoutMs(60000); config.setConnectionCallbacks(events); + config.setMetricsEnabled(metricsEnabled); if (httpProxyOptions != null) { config.setHttpProxyOptions(httpProxyOptions); @@ -262,7 +263,7 @@ public void onConnectionClosed(OnConnectionClosedReturn data) { } } - void connectWebsockets(CredentialsProvider credentialsProvider, String endpoint, int port, TlsContext tlsContext, String username, String password, HttpProxyOptions httpProxyOptions) throws Exception + void connectWebsockets(CredentialsProvider credentialsProvider, String endpoint, int port, TlsContext tlsContext, String username, String password, HttpProxyOptions httpProxyOptions, boolean metricsEnabled) throws Exception { String clientId = TEST_CLIENTID + (UUID.randomUUID()).toString(); @@ -313,6 +314,7 @@ public void onConnectionClosed(OnConnectionClosedReturn data) { config.setPort(port); config.setUseWebsockets(true); config.setConnectionCallbacks(events); + config.setMetricsEnabled(metricsEnabled); if (username != null) { config.setUsername(username); diff --git a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionMethodTest.java b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionMethodTest.java index c10cc1e95..f767de7fe 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionMethodTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionMethodTest.java @@ -60,7 +60,8 @@ private void doConnDC_Cred_UC1Test() { 8883, null, null, - null); + null, + true); disconnect(); } finally { close(); @@ -95,7 +96,8 @@ private void doConnDC_Cred_UC2Test() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -127,7 +129,8 @@ private void doConnDC_Cred_UC3Test() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -167,7 +170,8 @@ private void doConnDC_Cred_UC4Test() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -205,7 +209,7 @@ private void doWebsocketIotCoreConnectionTest(Function receivedFuture = new CompletableFuture<>(); Consumer messageHandler = (message) -> { @@ -128,7 +129,8 @@ private void doPubSubOnMessageTest() { 8883, null, null, - null); + null, + true); CompletableFuture subscribed = connection.subscribe(TEST_TOPIC, QualityOfService.AT_LEAST_ONCE); diff --git a/src/test/java/software/amazon/awssdk/crt/test/SubscribeTest.java b/src/test/java/software/amazon/awssdk/crt/test/SubscribeTest.java index e48233649..2c774c7f4 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/SubscribeTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/SubscribeTest.java @@ -49,7 +49,8 @@ private void doSubscribeUnsubscribeTest() { 8883, null, null, - null); + null, + true); Consumer messageHandler = (message) -> {}; CompletableFuture subscribed = connection.subscribe(TEST_TOPIC, QualityOfService.AT_LEAST_ONCE, diff --git a/src/test/java/software/amazon/awssdk/crt/test/WillTest.java b/src/test/java/software/amazon/awssdk/crt/test/WillTest.java index 059c1707d..cde308eef 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/WillTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/WillTest.java @@ -50,7 +50,8 @@ private void doWillTest() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -83,7 +84,8 @@ private void doEmptyWillTest() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); @@ -116,7 +118,8 @@ private void doNullWillTest() { 8883, null, null, - null); + null, + true); disconnect(); } catch (Exception ex) { throw new RuntimeException(ex); From a3376ed3682aebc5b4e8c0051478663a23d3f5ab Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 30 Dec 2025 14:08:43 -0800 Subject: [PATCH 03/16] update test for adapter --- .../amazon/awssdk/crt/test/Mqtt5to3AdapterConnectionTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5to3AdapterConnectionTest.java b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5to3AdapterConnectionTest.java index a94f8e63e..b69b9badf 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5to3AdapterConnectionTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5to3AdapterConnectionTest.java @@ -303,7 +303,8 @@ public void TestBasicAuthConnectThroughMqtt5() { connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME) .withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()) .withClientId("test/MQTT5to3Adapter" + UUID.randomUUID().toString()); - builder.withConnectOptions(connectOptions.build()); + builder.withConnectOptions(connectOptions.build()) + .withMetricsEnabled(false); try (Mqtt5Client client = new Mqtt5Client(builder.build()); MqttClientConnection connection = new MqttClientConnection(client, null);) { @@ -496,6 +497,7 @@ public void TestBasicAuthConnectThroughMqtt311() { AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT)); builder.withLifecycleEvents(events); + builder.withMetricsEnabled(false); ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME) From 129e2d176c9c019850b1d45313164bd595d00176 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 5 Jan 2026 09:27:03 -0800 Subject: [PATCH 04/16] cleanup --- src/native/crt.c | 8 -------- src/native/iot_device_sdk_metrics.c | 19 ------------------- 2 files changed, 27 deletions(-) diff --git a/src/native/crt.c b/src/native/crt.c index fd29bd62c..67c74e8eb 100644 --- a/src/native/crt.c +++ b/src/native/crt.c @@ -737,14 +737,6 @@ jstring JNICALL Java_software_amazon_awssdk_crt_CRT_awsErrorName(JNIEnv *env, jc return (*env)->NewStringUTF(env, error_msg); } -JNIEXPORT -jstring JNICALL Java_software_amazon_awssdk_crt_CRT_awsPlatformBuildString(JNIEnv *env, jclass jni_crt_class) { - (void)jni_crt_class; - struct aws_byte_cursor platform_string = aws_get_platform_build_os_string(); - - return aws_jni_string_from_cursor(env, &platform_string); -} - JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_CRT_awsNativeMemory(JNIEnv *env, jclass jni_crt_class) { (void)env; diff --git a/src/native/iot_device_sdk_metrics.c b/src/native/iot_device_sdk_metrics.c index 35cb2fc00..5f27edbfb 100644 --- a/src/native/iot_device_sdk_metrics.c +++ b/src/native/iot_device_sdk_metrics.c @@ -10,17 +10,6 @@ #include #include -/* on 32-bit platforms, casting pointers to longs throws a warning we don't need */ -#if UINTPTR_MAX == 0xffffffff -# if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */ -# else -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpointer-to-int-cast" -# pragma GCC diagnostic ignored "-Wint-to-pointer-cast" -# endif -#endif static char s_iot_device_sdk_metrics_string[] = "IoTDeviceSDKMetrics"; @@ -86,11 +75,3 @@ struct aws_mqtt_iot_sdk_metrics *aws_mqtt_iot_sdk_metrics_java_jni_get_metrics( return NULL; } } - -#if UINTPTR_MAX == 0xffffffff -# if defined(_MSC_VER) -# pragma warning(pop) -# else -# pragma GCC diagnostic pop -# endif -#endif From c52ba49013eb1263b9d7a58506454d03f22eaca1 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 5 Jan 2026 09:32:56 -0800 Subject: [PATCH 05/16] lint --- .../amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java | 2 +- src/native/iot_device_sdk_metrics.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java b/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java index 2d396541d..611bd1a1d 100644 --- a/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java +++ b/src/main/java/software/amazon/awssdk/crt/internal/IoTDeviceSDKMetrics.java @@ -18,4 +18,4 @@ public IoTDeviceSDKMetrics() { public String getLibraryName() { return libraryName; } -} \ No newline at end of file +} diff --git a/src/native/iot_device_sdk_metrics.c b/src/native/iot_device_sdk_metrics.c index 5f27edbfb..41b413f5c 100644 --- a/src/native/iot_device_sdk_metrics.c +++ b/src/native/iot_device_sdk_metrics.c @@ -10,7 +10,6 @@ #include #include - static char s_iot_device_sdk_metrics_string[] = "IoTDeviceSDKMetrics"; void aws_mqtt_iot_sdk_metrics_java_jni_destroy( From 9b506f3528ecf8018862230c62ffbbff20ff49dd Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 5 Jan 2026 12:29:48 -0800 Subject: [PATCH 06/16] update jni-config --- .../crt/aws-crt/jni-config.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/resources/META-INF/native-image/software.amazon.awssdk/crt/aws-crt/jni-config.json b/src/main/resources/META-INF/native-image/software.amazon.awssdk/crt/aws-crt/jni-config.json index 02134b607..92322c497 100644 --- a/src/main/resources/META-INF/native-image/software.amazon.awssdk/crt/aws-crt/jni-config.json +++ b/src/main/resources/META-INF/native-image/software.amazon.awssdk/crt/aws-crt/jni-config.json @@ -1256,6 +1256,14 @@ } ] }, + { + "name": "software.amazon.awssdk.crt.internal.IoTDeviceSDKMetrics", + "fields": [ + { + "name": "libraryName" + } + ] + }, { "name": "software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions", "fields": [ @@ -1306,6 +1314,12 @@ }, { "name": "topicAliasingOptions" + }, + { + "name": "iotDeviceSDKMetrics" + }, + { + "name": "metricsEnabled" } ], "methods": [ From a61572cdece0a330fd9e0625aae4d825337db329 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Fri, 16 Jan 2026 08:28:45 -0800 Subject: [PATCH 07/16] and retry From 63c143ddda3829300688dadc737bb7ab7d29491c Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Thu, 12 Feb 2026 14:46:04 -0800 Subject: [PATCH 08/16] set metrics should not fail the connection --- src/native/mqtt_connection.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/native/mqtt_connection.c b/src/native/mqtt_connection.c index aa98cd1d2..aba2a419d 100644 --- a/src/native/mqtt_connection.c +++ b/src/native/mqtt_connection.c @@ -1130,7 +1130,10 @@ JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, aws_jni_get_allocator(), jni_metrics); if (aws_mqtt_client_connection_set_metrics(connection->client_connection, &iot_sdk_metrics_java_jni->metrics)) { - aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_metrics: Failed to set metrics"); + error = aws_last_error(); + AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "MqttClientConnection.mqtt_set_metrics fail with error code %d(%s)", + error, + aws_error_str(error)); } aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, aws_jni_get_allocator(), iot_sdk_metrics_java_jni); From 2bbb3117efb0fb99f6c1b8c8ae42f64f889c6d0c Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Thu, 12 Feb 2026 14:46:19 -0800 Subject: [PATCH 09/16] set metrics should not fail the connection --- src/native/mqtt_connection.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/native/mqtt_connection.c b/src/native/mqtt_connection.c index aba2a419d..6a9812562 100644 --- a/src/native/mqtt_connection.c +++ b/src/native/mqtt_connection.c @@ -1131,7 +1131,9 @@ JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection if (aws_mqtt_client_connection_set_metrics(connection->client_connection, &iot_sdk_metrics_java_jni->metrics)) { error = aws_last_error(); - AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "MqttClientConnection.mqtt_set_metrics fail with error code %d(%s)", + AWS_LOGF_DEBUG( + AWS_LS_MQTT_CLIENT, + "MqttClientConnection.mqtt_set_metrics fail with error code %d(%s)", error, aws_error_str(error)); } From c8f12758d08a9e004aeed144ab36d24189220b7a Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Thu, 12 Feb 2026 15:58:03 -0800 Subject: [PATCH 10/16] set metrics should not fail the mqtt5 client --- src/native/mqtt5_client.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/native/mqtt5_client.c b/src/native/mqtt5_client.c index 1cc8f2422..60ad69d8c 100644 --- a/src/native/mqtt5_client.c +++ b/src/native/mqtt5_client.c @@ -2121,24 +2121,19 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C /* Check if metrics are enabled and set metrics value */ jboolean metrics_enabled = (*env)->GetBooleanField(env, jni_options, mqtt5_client_options_properties.metrics_enabled_field_id); - if (aws_jni_check_and_clear_exception(env)) { - s_aws_mqtt5_client_log_and_throw_exception( - env, "MQTT5 client new: error getting metrics enabled", AWS_ERROR_INVALID_STATE); - goto clean_up; - } + bool metrics_has_error = aws_jni_check_and_clear_exception(env); - if (metrics_enabled) { + if (!metrics_has_error && metrics_enabled) { jobject jni_iot_device_sdk_metrics = (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.iot_device_sdk_metrics_field_id); - if (aws_jni_check_and_clear_exception(env)) { - s_aws_mqtt5_client_log_and_throw_exception( - env, "MQTT5 client new: error getting IoT device SDK metrics", AWS_ERROR_INVALID_STATE); - goto clean_up; + if (!aws_jni_check_and_clear_exception(env)) { + iot_device_sdk_metrics = + aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); + client_options.metrics = iot_device_sdk_metrics ? &iot_device_sdk_metrics->metrics : NULL; + } else { + AWS_LOGF_DEBUG( + AWS_LS_MQTT5_CLIENT, "MQTT5 client new: Was unable to set metrics, continuing with no metrics."); } - - iot_device_sdk_metrics = - aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); - client_options.metrics = &iot_device_sdk_metrics->metrics; } /* Make the MQTT5 client */ From a0c5f34820ee23b0e42df6d6e05bff5d5579b54d Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Fri, 13 Feb 2026 10:18:25 -0800 Subject: [PATCH 11/16] update metrics naming --- crt/aws-c-mqtt | 2 +- src/native/iot_device_sdk_metrics.c | 16 ++++++++-------- src/native/iot_device_sdk_metrics.h | 14 +++++++------- src/native/mqtt5_client.c | 6 +++--- src/native/mqtt_connection.c | 10 +++++----- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index 154e9c5dd..29a2887fb 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit 154e9c5dd19ec6d8d4cd690492d2a029f13e2035 +Subproject commit 29a2887fb972cb2e9bbc022323f11542f2af2723 diff --git a/src/native/iot_device_sdk_metrics.c b/src/native/iot_device_sdk_metrics.c index 41b413f5c..cee93c9cb 100644 --- a/src/native/iot_device_sdk_metrics.c +++ b/src/native/iot_device_sdk_metrics.c @@ -12,10 +12,10 @@ static char s_iot_device_sdk_metrics_string[] = "IoTDeviceSDKMetrics"; -void aws_mqtt_iot_sdk_metrics_java_jni_destroy( +void aws_mqtt_iot_metrics_java_jni_destroy( JNIEnv *env, struct aws_allocator *allocator, - struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics) { + struct aws_mqtt_iot_metrics_java_jni *java_metrics) { (void)env; if (!java_metrics) { @@ -30,13 +30,13 @@ void aws_mqtt_iot_sdk_metrics_java_jni_destroy( aws_mem_release(allocator, java_metrics); } -struct aws_mqtt_iot_sdk_metrics_java_jni *aws_mqtt_iot_sdk_metrics_java_jni_create_from_java( +struct aws_mqtt_iot_metrics_java_jni *aws_mqtt_iot_metrics_java_jni_create_from_java( JNIEnv *env, struct aws_allocator *allocator, jobject java_iot_device_sdk_metrics) { - struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics = - aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt_iot_sdk_metrics_java_jni)); + struct aws_mqtt_iot_metrics_java_jni *java_metrics = + aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt_iot_metrics_java_jni)); if (java_metrics == NULL) { AWS_LOGF_ERROR( AWS_LS_MQTT_GENERAL, "IoTDeviceSDKMetrics create_from_java: Creating new IoTDeviceSDKMetrics failed"); @@ -62,12 +62,12 @@ struct aws_mqtt_iot_sdk_metrics_java_jni *aws_mqtt_iot_sdk_metrics_java_jni_crea on_error: /* Clean up */ - aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, allocator, java_metrics); + aws_mqtt_iot_metrics_java_jni_destroy(env, allocator, java_metrics); return NULL; } -struct aws_mqtt_iot_sdk_metrics *aws_mqtt_iot_sdk_metrics_java_jni_get_metrics( - struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics) { +struct aws_mqtt_iot_metrics *aws_mqtt_iot_metrics_java_jni_get_metrics( + struct aws_mqtt_iot_metrics_java_jni *java_metrics) { if (java_metrics) { return &java_metrics->metrics; } else { diff --git a/src/native/iot_device_sdk_metrics.h b/src/native/iot_device_sdk_metrics.h index 06108ebf6..5027925a3 100644 --- a/src/native/iot_device_sdk_metrics.h +++ b/src/native/iot_device_sdk_metrics.h @@ -9,23 +9,23 @@ #include #include -struct aws_mqtt_iot_sdk_metrics_java_jni { - struct aws_mqtt_iot_sdk_metrics metrics; +struct aws_mqtt_iot_metrics_java_jni { + struct aws_mqtt_iot_metrics metrics; struct aws_byte_buf library_name_buf; struct aws_byte_cursor library_name_cursor; }; -void aws_mqtt_iot_sdk_metrics_java_jni_destroy( +void aws_mqtt_iot_metrics_java_jni_destroy( JNIEnv *env, struct aws_allocator *allocator, - struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics); + struct aws_mqtt_iot_metrics_java_jni *java_metrics); -struct aws_mqtt_iot_sdk_metrics_java_jni *aws_mqtt_iot_sdk_metrics_java_jni_create_from_java( +struct aws_mqtt_iot_metrics_java_jni *aws_mqtt_iot_metrics_java_jni_create_from_java( JNIEnv *env, struct aws_allocator *allocator, jobject java_iot_device_sdk_metrics); -struct aws_mqtt_iot_sdk_metrics *aws_mqtt_iot_sdk_metrics_java_jni_get_metrics( - struct aws_mqtt_iot_sdk_metrics_java_jni *java_metrics); +struct aws_mqtt_iot_metrics *aws_mqtt_iot_metrics_java_jni_get_metrics( + struct aws_mqtt_iot_metrics_java_jni *java_metrics); #endif /* AWS_JNI_IOT_DEVICE_SDK_METRICS_H */ diff --git a/src/native/mqtt5_client.c b/src/native/mqtt5_client.c index 60ad69d8c..421444671 100644 --- a/src/native/mqtt5_client.c +++ b/src/native/mqtt5_client.c @@ -1703,7 +1703,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C struct aws_mqtt5_client_options client_options; AWS_ZERO_STRUCT(client_options); struct aws_http_proxy_options_java_jni *java_http_proxy_options = NULL; - struct aws_mqtt_iot_sdk_metrics_java_jni *iot_device_sdk_metrics = NULL; + struct aws_mqtt_iot_metrics_java_jni *iot_device_sdk_metrics = NULL; struct aws_byte_buf host_name_buf; /* Needed to track if optionals are set or not */ @@ -2128,7 +2128,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.iot_device_sdk_metrics_field_id); if (!aws_jni_check_and_clear_exception(env)) { iot_device_sdk_metrics = - aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); + aws_mqtt_iot_metrics_java_jni_create_from_java(env, allocator, jni_iot_device_sdk_metrics); client_options.metrics = iot_device_sdk_metrics ? &iot_device_sdk_metrics->metrics : NULL; } else { AWS_LOGF_DEBUG( @@ -2153,7 +2153,7 @@ JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5C aws_mqtt5_packet_connect_view_java_destroy(env, allocator, connect_options); s_aws_mqtt5_http_proxy_options_java_destroy(env, allocator, java_http_proxy_options); - aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, allocator, iot_device_sdk_metrics); + aws_mqtt_iot_metrics_java_jni_destroy(env, allocator, iot_device_sdk_metrics); if (aws_byte_buf_is_valid(&host_name_buf)) { aws_byte_buf_clean_up(&host_name_buf); } diff --git a/src/native/mqtt_connection.c b/src/native/mqtt_connection.c index 6a9812562..3d314c815 100644 --- a/src/native/mqtt_connection.c +++ b/src/native/mqtt_connection.c @@ -1126,11 +1126,11 @@ JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection return; } - struct aws_mqtt_iot_sdk_metrics_java_jni *iot_sdk_metrics_java_jni = - aws_mqtt_iot_sdk_metrics_java_jni_create_from_java(env, aws_jni_get_allocator(), jni_metrics); + struct aws_mqtt_iot_metrics_java_jni *iot_metrics_java_jni = + aws_mqtt_iot_metrics_java_jni_create_from_java(env, aws_jni_get_allocator(), jni_metrics); - if (aws_mqtt_client_connection_set_metrics(connection->client_connection, &iot_sdk_metrics_java_jni->metrics)) { - error = aws_last_error(); + if (aws_mqtt_client_connection_set_metrics(connection->client_connection, &iot_metrics_java_jni->metrics)) { + int error = aws_last_error(); AWS_LOGF_DEBUG( AWS_LS_MQTT_CLIENT, "MqttClientConnection.mqtt_set_metrics fail with error code %d(%s)", @@ -1138,7 +1138,7 @@ JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection aws_error_str(error)); } - aws_mqtt_iot_sdk_metrics_java_jni_destroy(env, aws_jni_get_allocator(), iot_sdk_metrics_java_jni); + aws_mqtt_iot_metrics_java_jni_destroy(env, aws_jni_get_allocator(), iot_metrics_java_jni); } JNIEXPORT void JNICALL From 21e2cb79df35b8a050280db5b089f4f084a53b08 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 17 Feb 2026 09:56:37 -0800 Subject: [PATCH 12/16] update mqtt library --- crt/aws-c-mqtt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index 29a2887fb..41b6a7d6d 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit 29a2887fb972cb2e9bbc022323f11542f2af2723 +Subproject commit 41b6a7d6d566a56eff69743df66c077d56a80c9d From 8ec2d38acfa43dd4559c819b1cb4048c0dbd56d4 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 2 Mar 2026 15:53:59 -0800 Subject: [PATCH 13/16] add metrics enabled tests --- .../awssdk/crt/test/Mqtt5ClientTest.java | 72 +++++++++++++++++++ .../crt/test/MqttClientConnectionTest.java | 43 +++++++++++ 2 files changed, 115 insertions(+) diff --git a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java index e8786f0f4..587237303 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java @@ -360,6 +360,78 @@ public void ConnDC_UC2() throws Exception { CrtResource.waitForNoResources(); } + /** + * ============================================================ + * METRICS TEST CASES + * ============================================================ + */ + + private void doConnDC_Metrics_EnabledTest() { + try { + LifecycleEvents_Futured events = new LifecycleEvents_Futured(); + + Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( + AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, + Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT)); + builder.withLifecycleEvents(events); + // Metrics are enabled by default (metricsEnabled = true) + // This should cause connection failure because metrics appends to username, + // corrupting basic auth credentials + + ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); + connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME).withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); + builder.withConnectOptions(connectOptions.build()); + + bool exceptionOccurred = false; + bool foundExpectedError = false; + + try (Mqtt5Client client = new Mqtt5Client(builder.build())) { + + client.start(); + + try { + events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); + } catch (Exception ex) { + exceptionOccurred = true; + if (events.connectFailureCode == 5150) { + foundExpectedError = true; + } else { + System.out.println("EXCEPTION: " + ex); + System.out.println(ex.getMessage() + " \n"); + } + } + + if (foundExpectedError == false) { + System.out.println("Error code was not AWS_ERROR_MQTT5_CONNACK_CONNECTION_REFUSED like expected! There was an exception though"); + } + if (exceptionOccurred == false) { + fail("No exception occurred!"); + } + + client.stop(); + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + /** + * Test that connection fails with basic auth when metrics are enabled (default). + * When metrics are enabled, the SDK appends metrics info to the username field, + * which corrupts basic authentication credentials and causes connection failure. + */ + @Test + public void ConnDC_Metrics_Enabled() throws Exception { + skipIfNetworkUnavailable(); + Assume.assumeNotNull( + AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT, + AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD); + + doConnDC_Metrics_EnabledTest(); + + CrtResource.waitForNoResources(); + } + private void doConnDC_UC3Test() { try (TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient()) { tlsOptions.withVerifyPeer(false); diff --git a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java index 0ef745fca..a6b7f9d0f 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java @@ -269,6 +269,49 @@ public void testConnectDisconnectEventsUnhappy() { } } + /** + * ============================================================ + * METRICS TEST CASES + * ============================================================ + */ + + /** + * Test that connection fails with basic auth when metrics are enabled (default). + * When metrics are enabled, the SDK appends metrics info to the username field, + * which corrupts basic authentication credentials and causes connection failure. + */ + @Test + public void testConnDC_Metrics_BasicAuth_Enabled() { + skipIfNetworkUnavailable(); + Assume.assumeNotNull( + AWS_TEST_MQTT311_DIRECT_MQTT_BASIC_AUTH_HOST, AWS_TEST_MQTT311_DIRECT_MQTT_BASIC_AUTH_PORT, + AWS_TEST_MQTT311_BASIC_AUTH_USERNAME, AWS_TEST_MQTT311_BASIC_AUTH_PASSWORD); + + boolean connectionFailed = false; + try { + // Metrics are enabled by default (metricsEnabled = true) + // This should cause connection failure because metrics appends to username, + // corrupting basic auth credentials + connectDirect( + null, // No TLS context for basic auth + AWS_TEST_MQTT311_DIRECT_MQTT_BASIC_AUTH_HOST, + Integer.parseInt(AWS_TEST_MQTT311_DIRECT_MQTT_BASIC_AUTH_PORT), + AWS_TEST_MQTT311_BASIC_AUTH_USERNAME, + AWS_TEST_MQTT311_BASIC_AUTH_PASSWORD, + null, + true); // Metrics enabled + } catch (Exception ex) { + // Expected - connection should fail with metrics enabled and basic auth + } + + OnConnectionFailureReturn result = waitForConnectFailure(); + assertTrue("Connection error callback was empty", result != null); + assertTrue("Error code was success when it should not be", result.getErrorCode() != 0); + + close(); + CrtResource.waitForNoResources(); + } + /* This scenario once led to memory leaks, so this test primarily checks that there is no memory leaks. */ @Test public void testMultipleFailedAttemptsOnSingleConnection() { From 20fa79838860e22bb381a8b4e00eccf4518ec505 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 2 Mar 2026 16:20:16 -0800 Subject: [PATCH 14/16] fix error --- .../java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java index 587237303..05ac2f493 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/Mqtt5ClientTest.java @@ -382,8 +382,8 @@ private void doConnDC_Metrics_EnabledTest() { connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME).withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); builder.withConnectOptions(connectOptions.build()); - bool exceptionOccurred = false; - bool foundExpectedError = false; + boolean exceptionOccurred = false; + boolean foundExpectedError = false; try (Mqtt5Client client = new Mqtt5Client(builder.build())) { From e67a0f4080a9872fed4e64cc301cb52fd284e720 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 2 Mar 2026 16:31:11 -0800 Subject: [PATCH 15/16] catch error for connection failure --- .../awssdk/crt/test/MqttClientConnectionTest.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java index a6b7f9d0f..60a4c19dd 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionTest.java @@ -304,9 +304,13 @@ public void testConnDC_Metrics_BasicAuth_Enabled() { // Expected - connection should fail with metrics enabled and basic auth } - OnConnectionFailureReturn result = waitForConnectFailure(); - assertTrue("Connection error callback was empty", result != null); - assertTrue("Error code was success when it should not be", result.getErrorCode() != 0); + try { + OnConnectionFailureReturn result = waitForConnectFailure(); + assertTrue("Connection error callback was empty", result != null); + assertTrue("Error code was success when it should not be", result.getErrorCode() != 0); + } catch (Exception ex) { + fail(ex.toString()); + } close(); CrtResource.waitForNoResources(); From 63510f3543efe46c783161e4303548543b70546f Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 3 Mar 2026 09:40:52 -0800 Subject: [PATCH 16/16] kick codebuild