xref: /aosp_15_r20/external/aws-crt-java/src/native/mqtt5_client.c (revision 3c7ae9de214676c52d19f01067dc1a404272dc11)
1*3c7ae9deSAndroid Build Coastguard Worker /**
2*3c7ae9deSAndroid Build Coastguard Worker  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3*3c7ae9deSAndroid Build Coastguard Worker  * SPDX-License-Identifier: Apache-2.0.
4*3c7ae9deSAndroid Build Coastguard Worker  */
5*3c7ae9deSAndroid Build Coastguard Worker #include <aws/mqtt/v5/mqtt5_client.h>
6*3c7ae9deSAndroid Build Coastguard Worker 
7*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/proxy.h>
8*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/event_loop.h>
9*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/socket.h>
10*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/tls_channel_handler.h>
11*3c7ae9deSAndroid Build Coastguard Worker 
12*3c7ae9deSAndroid Build Coastguard Worker #include <crt.h>
13*3c7ae9deSAndroid Build Coastguard Worker #include <http_request_utils.h>
14*3c7ae9deSAndroid Build Coastguard Worker #include <java_class_ids.h>
15*3c7ae9deSAndroid Build Coastguard Worker #include <jni.h>
16*3c7ae9deSAndroid Build Coastguard Worker #include <mqtt5_client_jni.h>
17*3c7ae9deSAndroid Build Coastguard Worker #include <mqtt5_packets.h>
18*3c7ae9deSAndroid Build Coastguard Worker #include <mqtt5_utils.h>
19*3c7ae9deSAndroid Build Coastguard Worker 
20*3c7ae9deSAndroid Build Coastguard Worker /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
21*3c7ae9deSAndroid Build Coastguard Worker #if UINTPTR_MAX == 0xffffffff
22*3c7ae9deSAndroid Build Coastguard Worker #    if defined(_MSC_VER)
23*3c7ae9deSAndroid Build Coastguard Worker #        pragma warning(push)
24*3c7ae9deSAndroid Build Coastguard Worker #        pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
25*3c7ae9deSAndroid Build Coastguard Worker #    else
26*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic push
27*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
28*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
29*3c7ae9deSAndroid Build Coastguard Worker #    endif
30*3c7ae9deSAndroid Build Coastguard Worker #endif
31*3c7ae9deSAndroid Build Coastguard Worker 
32*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
33*3c7ae9deSAndroid Build Coastguard Worker  * CLIENT ONLY STRUCTS
34*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
35*3c7ae9deSAndroid Build Coastguard Worker 
36*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt5_client_publish_return_data {
37*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client;
38*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_publish_future;
39*3c7ae9deSAndroid Build Coastguard Worker };
40*3c7ae9deSAndroid Build Coastguard Worker 
41*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt5_client_subscribe_return_data {
42*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client;
43*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_subscribe_future;
44*3c7ae9deSAndroid Build Coastguard Worker };
45*3c7ae9deSAndroid Build Coastguard Worker 
46*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt5_client_unsubscribe_return_data {
47*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client;
48*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_unsubscribe_future;
49*3c7ae9deSAndroid Build Coastguard Worker };
50*3c7ae9deSAndroid Build Coastguard Worker 
51*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_proxy_options_java_jni {
52*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_proxy_options options;
53*3c7ae9deSAndroid Build Coastguard Worker 
54*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_buf proxy_host_buf;
55*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_cursor proxy_host_cursor;
56*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_buf authorization_username_buf;
57*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_cursor authorization_username_cursor;
58*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_buf authorization_password_buf;
59*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_cursor authorization_password_cursor;
60*3c7ae9deSAndroid Build Coastguard Worker };
61*3c7ae9deSAndroid Build Coastguard Worker 
62*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
63*3c7ae9deSAndroid Build Coastguard Worker  * HELPER FUNCTION (LOGGING)
64*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
65*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_log_and_throw_exception(JNIEnv * env,const char * message,int error_code)66*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_log_and_throw_exception(JNIEnv *env, const char *message, int error_code) {
67*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s - error code: %i", message, error_code);
68*3c7ae9deSAndroid Build Coastguard Worker     // raise error to update the "last_error_code"
69*3c7ae9deSAndroid Build Coastguard Worker     aws_raise_error(error_code);
70*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_throw_runtime_exception(env, "%s - error code: %i", message, error_code);
71*3c7ae9deSAndroid Build Coastguard Worker }
72*3c7ae9deSAndroid Build Coastguard Worker 
73*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
74*3c7ae9deSAndroid Build Coastguard Worker  * HTTP PROXY FUNCTIONS
75*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
76*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_http_proxy_options_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_http_proxy_options_java_jni * http_options)77*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_http_proxy_options_java_destroy(
78*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
79*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator,
80*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_proxy_options_java_jni *http_options) {
81*3c7ae9deSAndroid Build Coastguard Worker     (void)env;
82*3c7ae9deSAndroid Build Coastguard Worker 
83*3c7ae9deSAndroid Build Coastguard Worker     if (!http_options) {
84*3c7ae9deSAndroid Build Coastguard Worker         return;
85*3c7ae9deSAndroid Build Coastguard Worker     }
86*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "id=%p: Destroying JavaHttpProxyOptions", (void *)http_options);
87*3c7ae9deSAndroid Build Coastguard Worker 
88*3c7ae9deSAndroid Build Coastguard Worker     if (aws_byte_buf_is_valid(&http_options->proxy_host_buf)) {
89*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_clean_up(&http_options->proxy_host_buf);
90*3c7ae9deSAndroid Build Coastguard Worker     }
91*3c7ae9deSAndroid Build Coastguard Worker     if (aws_byte_buf_is_valid(&http_options->authorization_username_buf)) {
92*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_clean_up(&http_options->authorization_username_buf);
93*3c7ae9deSAndroid Build Coastguard Worker     }
94*3c7ae9deSAndroid Build Coastguard Worker     if (aws_byte_buf_is_valid(&http_options->authorization_password_buf)) {
95*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_clean_up(&http_options->authorization_password_buf);
96*3c7ae9deSAndroid Build Coastguard Worker     }
97*3c7ae9deSAndroid Build Coastguard Worker 
98*3c7ae9deSAndroid Build Coastguard Worker     /* Frees all allocated memory */
99*3c7ae9deSAndroid Build Coastguard Worker     aws_mem_release(allocator, http_options);
100*3c7ae9deSAndroid Build Coastguard Worker }
101*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_http_proxy_options_create_from_java(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_client_java_jni * java_client,jobject java_http_proxy_options)102*3c7ae9deSAndroid Build Coastguard Worker static struct aws_http_proxy_options_java_jni *s_aws_mqtt5_http_proxy_options_create_from_java(
103*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
104*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator,
105*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client,
106*3c7ae9deSAndroid Build Coastguard Worker     jobject java_http_proxy_options) {
107*3c7ae9deSAndroid Build Coastguard Worker     /* Cannot fail */
108*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_proxy_options_java_jni *http_options =
109*3c7ae9deSAndroid Build Coastguard Worker         aws_mem_calloc(allocator, 1, sizeof(struct aws_http_proxy_options_java_jni));
110*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(
111*3c7ae9deSAndroid Build Coastguard Worker         AWS_LS_MQTT5_CLIENT, "JavaHttpProxyOptions=%p: Created new JavaHttpProxyOptions", (void *)http_options);
112*3c7ae9deSAndroid Build Coastguard Worker 
113*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_proxy_connection_type = (*env)->CallObjectMethod(
114*3c7ae9deSAndroid Build Coastguard Worker         env, java_http_proxy_options, http_proxy_options_properties.proxy_get_connection_type_id);
115*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
116*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
117*3c7ae9deSAndroid Build Coastguard Worker     }
118*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_connection_type) {
119*3c7ae9deSAndroid Build Coastguard Worker         jint jni_proxy_connection_type_value = (*env)->CallIntMethod(
120*3c7ae9deSAndroid Build Coastguard Worker             env, jni_proxy_connection_type, http_proxy_connection_type_properties.proxy_get_value_id);
121*3c7ae9deSAndroid Build Coastguard Worker         if (aws_jni_check_and_clear_exception(env)) {
122*3c7ae9deSAndroid Build Coastguard Worker             goto on_error;
123*3c7ae9deSAndroid Build Coastguard Worker         }
124*3c7ae9deSAndroid Build Coastguard Worker         if (jni_proxy_connection_type_value) {
125*3c7ae9deSAndroid Build Coastguard Worker             int32_t jni_proxy_connection_type_value_check = (int32_t)jni_proxy_connection_type_value;
126*3c7ae9deSAndroid Build Coastguard Worker             if (jni_proxy_connection_type_value_check < 0) {
127*3c7ae9deSAndroid Build Coastguard Worker                 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "HTTP Proxy Options connection type is less than 0");
128*3c7ae9deSAndroid Build Coastguard Worker                 goto on_error;
129*3c7ae9deSAndroid Build Coastguard Worker             } else if (jni_proxy_connection_type_value_check > AWS_HPCT_HTTP_TUNNEL) { /* The (current) maximum enum */
130*3c7ae9deSAndroid Build Coastguard Worker                                                                                        /* value */
131*3c7ae9deSAndroid Build Coastguard Worker                 AWS_LOGF_ERROR(
132*3c7ae9deSAndroid Build Coastguard Worker                     AWS_LS_MQTT5_CLIENT, "HTTP Proxy Options connection type is more than maximum allowed value");
133*3c7ae9deSAndroid Build Coastguard Worker                 goto on_error;
134*3c7ae9deSAndroid Build Coastguard Worker             } else {
135*3c7ae9deSAndroid Build Coastguard Worker                 http_options->options.connection_type =
136*3c7ae9deSAndroid Build Coastguard Worker                     (enum aws_http_proxy_connection_type)jni_proxy_connection_type_value;
137*3c7ae9deSAndroid Build Coastguard Worker             }
138*3c7ae9deSAndroid Build Coastguard Worker         }
139*3c7ae9deSAndroid Build Coastguard Worker     }
140*3c7ae9deSAndroid Build Coastguard Worker 
141*3c7ae9deSAndroid Build Coastguard Worker     jstring jni_proxy_host = (jstring)(*env)->CallObjectMethod(
142*3c7ae9deSAndroid Build Coastguard Worker         env, java_http_proxy_options, http_proxy_options_properties.proxy_get_proxy_host_id);
143*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
144*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
145*3c7ae9deSAndroid Build Coastguard Worker     }
146*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_host) {
147*3c7ae9deSAndroid Build Coastguard Worker         // Get the data, copy it, and then release the JNI stuff
148*3c7ae9deSAndroid Build Coastguard Worker         struct aws_byte_cursor tmp_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_host);
149*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_init_copy_from_cursor(&http_options->proxy_host_buf, aws_jni_get_allocator(), tmp_cursor);
150*3c7ae9deSAndroid Build Coastguard Worker         http_options->proxy_host_cursor = aws_byte_cursor_from_buf(&http_options->proxy_host_buf);
151*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_host, tmp_cursor);
152*3c7ae9deSAndroid Build Coastguard Worker 
153*3c7ae9deSAndroid Build Coastguard Worker         http_options->options.host = http_options->proxy_host_cursor;
154*3c7ae9deSAndroid Build Coastguard Worker     }
155*3c7ae9deSAndroid Build Coastguard Worker 
156*3c7ae9deSAndroid Build Coastguard Worker     jint jni_proxy_port =
157*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallIntMethod(env, java_http_proxy_options, http_proxy_options_properties.proxy_get_proxy_port_id);
158*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
159*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
160*3c7ae9deSAndroid Build Coastguard Worker     }
161*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_port) {
162*3c7ae9deSAndroid Build Coastguard Worker         http_options->options.port = (uint32_t)jni_proxy_port;
163*3c7ae9deSAndroid Build Coastguard Worker     }
164*3c7ae9deSAndroid Build Coastguard Worker 
165*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_proxy_tls_context = (*env)->CallObjectMethod(
166*3c7ae9deSAndroid Build Coastguard Worker         env, java_http_proxy_options, http_proxy_options_properties.proxy_get_proxy_tls_context_id);
167*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
168*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
169*3c7ae9deSAndroid Build Coastguard Worker     }
170*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_tls_context) {
171*3c7ae9deSAndroid Build Coastguard Worker         jlong jni_proxy_tls_context_long =
172*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallLongMethod(env, jni_proxy_tls_context, crt_resource_properties.get_native_handle_method_id);
173*3c7ae9deSAndroid Build Coastguard Worker 
174*3c7ae9deSAndroid Build Coastguard Worker         struct aws_tls_ctx *tls_ctx = (struct aws_tls_ctx *)jni_proxy_tls_context_long;
175*3c7ae9deSAndroid Build Coastguard Worker         if (tls_ctx) {
176*3c7ae9deSAndroid Build Coastguard Worker             aws_tls_connection_options_init_from_ctx(&java_client->http_proxy_tls_options, tls_ctx);
177*3c7ae9deSAndroid Build Coastguard Worker             aws_tls_connection_options_set_server_name(
178*3c7ae9deSAndroid Build Coastguard Worker                 &java_client->http_proxy_tls_options, allocator, &http_options->options.host);
179*3c7ae9deSAndroid Build Coastguard Worker             http_options->options.tls_options = &java_client->http_proxy_tls_options;
180*3c7ae9deSAndroid Build Coastguard Worker         }
181*3c7ae9deSAndroid Build Coastguard Worker     }
182*3c7ae9deSAndroid Build Coastguard Worker 
183*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_proxy_authorization_type = (*env)->CallObjectMethod(
184*3c7ae9deSAndroid Build Coastguard Worker         env, java_http_proxy_options, http_proxy_options_properties.proxy_get_proxy_authorization_type_id);
185*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
186*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
187*3c7ae9deSAndroid Build Coastguard Worker     }
188*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_authorization_type) {
189*3c7ae9deSAndroid Build Coastguard Worker         jint jni_proxy_authorization_type_value = (*env)->CallIntMethod(
190*3c7ae9deSAndroid Build Coastguard Worker             env, jni_proxy_authorization_type, http_proxy_connection_type_properties.proxy_get_value_id);
191*3c7ae9deSAndroid Build Coastguard Worker         if (aws_jni_check_and_clear_exception(env)) {
192*3c7ae9deSAndroid Build Coastguard Worker             goto on_error;
193*3c7ae9deSAndroid Build Coastguard Worker         }
194*3c7ae9deSAndroid Build Coastguard Worker         http_options->options.auth_type = (enum aws_http_proxy_authentication_type)jni_proxy_authorization_type_value;
195*3c7ae9deSAndroid Build Coastguard Worker     }
196*3c7ae9deSAndroid Build Coastguard Worker 
197*3c7ae9deSAndroid Build Coastguard Worker     jstring jni_proxy_authorization_username = (jstring)(*env)->CallObjectMethod(
198*3c7ae9deSAndroid Build Coastguard Worker         env, java_http_proxy_options, http_proxy_options_properties.proxy_get_authorization_username_id);
199*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
200*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
201*3c7ae9deSAndroid Build Coastguard Worker     }
202*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_authorization_username) {
203*3c7ae9deSAndroid Build Coastguard Worker         // Get the data, copy it, and then release the JNI stuff
204*3c7ae9deSAndroid Build Coastguard Worker         struct aws_byte_cursor tmp_cursor =
205*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_authorization_username);
206*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_init_copy_from_cursor(
207*3c7ae9deSAndroid Build Coastguard Worker             &http_options->authorization_username_buf, aws_jni_get_allocator(), tmp_cursor);
208*3c7ae9deSAndroid Build Coastguard Worker         http_options->authorization_username_cursor =
209*3c7ae9deSAndroid Build Coastguard Worker             aws_byte_cursor_from_buf(&http_options->authorization_username_buf);
210*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_authorization_username, tmp_cursor);
211*3c7ae9deSAndroid Build Coastguard Worker 
212*3c7ae9deSAndroid Build Coastguard Worker         http_options->options.auth_username = http_options->authorization_username_cursor;
213*3c7ae9deSAndroid Build Coastguard Worker     }
214*3c7ae9deSAndroid Build Coastguard Worker 
215*3c7ae9deSAndroid Build Coastguard Worker     jstring jni_proxy_authorization_password = (jstring)(*env)->CallObjectMethod(
216*3c7ae9deSAndroid Build Coastguard Worker         env, java_http_proxy_options, http_proxy_options_properties.proxy_get_authorization_password_id);
217*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
218*3c7ae9deSAndroid Build Coastguard Worker         goto on_error;
219*3c7ae9deSAndroid Build Coastguard Worker     }
220*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_authorization_password) {
221*3c7ae9deSAndroid Build Coastguard Worker         // Get the data, copy it, and then release the JNI stuff
222*3c7ae9deSAndroid Build Coastguard Worker         struct aws_byte_cursor tmp_cursor =
223*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_authorization_password);
224*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_init_copy_from_cursor(
225*3c7ae9deSAndroid Build Coastguard Worker             &http_options->authorization_password_buf, aws_jni_get_allocator(), tmp_cursor);
226*3c7ae9deSAndroid Build Coastguard Worker         http_options->authorization_password_cursor =
227*3c7ae9deSAndroid Build Coastguard Worker             aws_byte_cursor_from_buf(&http_options->authorization_password_buf);
228*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_authorization_password, tmp_cursor);
229*3c7ae9deSAndroid Build Coastguard Worker 
230*3c7ae9deSAndroid Build Coastguard Worker         http_options->options.auth_password = http_options->authorization_password_cursor;
231*3c7ae9deSAndroid Build Coastguard Worker     }
232*3c7ae9deSAndroid Build Coastguard Worker 
233*3c7ae9deSAndroid Build Coastguard Worker     return http_options;
234*3c7ae9deSAndroid Build Coastguard Worker 
235*3c7ae9deSAndroid Build Coastguard Worker on_error:
236*3c7ae9deSAndroid Build Coastguard Worker     s_aws_mqtt5_http_proxy_options_java_destroy(env, allocator, http_options);
237*3c7ae9deSAndroid Build Coastguard Worker     return NULL;
238*3c7ae9deSAndroid Build Coastguard Worker }
239*3c7ae9deSAndroid Build Coastguard Worker 
240*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
241*3c7ae9deSAndroid Build Coastguard Worker  * HELPER FUNCTIONS
242*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
243*3c7ae9deSAndroid Build Coastguard Worker 
aws_mqtt5_client_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_client_java_jni * java_client)244*3c7ae9deSAndroid Build Coastguard Worker static void aws_mqtt5_client_java_destroy(
245*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
246*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator,
247*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client) {
248*3c7ae9deSAndroid Build Coastguard Worker     AWS_PRECONDITION(java_client);
249*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
250*3c7ae9deSAndroid Build Coastguard Worker         return;
251*3c7ae9deSAndroid Build Coastguard Worker     }
252*3c7ae9deSAndroid Build Coastguard Worker 
253*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "java_client=%p: Destroying MQTT5 client", (void *)java_client);
254*3c7ae9deSAndroid Build Coastguard Worker 
255*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->jni_client) {
256*3c7ae9deSAndroid Build Coastguard Worker         (*env)->DeleteGlobalRef(env, java_client->jni_client);
257*3c7ae9deSAndroid Build Coastguard Worker     }
258*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->jni_publish_events) {
259*3c7ae9deSAndroid Build Coastguard Worker         (*env)->DeleteGlobalRef(env, java_client->jni_publish_events);
260*3c7ae9deSAndroid Build Coastguard Worker     }
261*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->jni_lifecycle_events) {
262*3c7ae9deSAndroid Build Coastguard Worker         (*env)->DeleteGlobalRef(env, java_client->jni_lifecycle_events);
263*3c7ae9deSAndroid Build Coastguard Worker     }
264*3c7ae9deSAndroid Build Coastguard Worker 
265*3c7ae9deSAndroid Build Coastguard Worker     aws_tls_connection_options_clean_up(&java_client->tls_options);
266*3c7ae9deSAndroid Build Coastguard Worker     aws_tls_connection_options_clean_up(&java_client->http_proxy_tls_options);
267*3c7ae9deSAndroid Build Coastguard Worker 
268*3c7ae9deSAndroid Build Coastguard Worker     /* Frees allocated memory */
269*3c7ae9deSAndroid Build Coastguard Worker     aws_mem_release(allocator, java_client);
270*3c7ae9deSAndroid Build Coastguard Worker }
271*3c7ae9deSAndroid Build Coastguard Worker 
s_complete_future_with_exception(JNIEnv * env,jobject * future,int error_code)272*3c7ae9deSAndroid Build Coastguard Worker static void s_complete_future_with_exception(JNIEnv *env, jobject *future, int error_code) {
273*3c7ae9deSAndroid Build Coastguard Worker     if (!env || !future) {
274*3c7ae9deSAndroid Build Coastguard Worker         return;
275*3c7ae9deSAndroid Build Coastguard Worker     }
276*3c7ae9deSAndroid Build Coastguard Worker 
277*3c7ae9deSAndroid Build Coastguard Worker     jobject crt_exception = aws_jni_new_crt_exception_from_error_code(env, error_code);
278*3c7ae9deSAndroid Build Coastguard Worker     (*env)->CallBooleanMethod(
279*3c7ae9deSAndroid Build Coastguard Worker         env, *future, completable_future_properties.complete_exceptionally_method_id, crt_exception);
280*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_check_and_clear_exception(env);
281*3c7ae9deSAndroid Build Coastguard Worker     (*env)->DeleteLocalRef(env, crt_exception);
282*3c7ae9deSAndroid Build Coastguard Worker }
283*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_count_allocation(const void * pointer,size_t * counter)284*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_count_allocation(const void *pointer, size_t *counter) {
285*3c7ae9deSAndroid Build Coastguard Worker     if (pointer != NULL) {
286*3c7ae9deSAndroid Build Coastguard Worker         *counter += 1;
287*3c7ae9deSAndroid Build Coastguard Worker     }
288*3c7ae9deSAndroid Build Coastguard Worker }
289*3c7ae9deSAndroid Build Coastguard Worker 
290*3c7ae9deSAndroid Build Coastguard Worker static char s_client_string[] = "MQTT5 Client";
291*3c7ae9deSAndroid Build Coastguard Worker 
292*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
293*3c7ae9deSAndroid Build Coastguard Worker  * MQTT5 CALLBACK FUNCTIONS
294*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
295*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_lifecycle_event(const struct aws_mqtt5_client_lifecycle_event * event)296*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_lifecycle_event(const struct aws_mqtt5_client_lifecycle_event *event) {
297*3c7ae9deSAndroid Build Coastguard Worker 
298*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)event->user_data;
299*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
300*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "LifecycleEvent: invalid client");
301*3c7ae9deSAndroid Build Coastguard Worker         return;
302*3c7ae9deSAndroid Build Coastguard Worker     }
303*3c7ae9deSAndroid Build Coastguard Worker 
304*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
305*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = java_client->jvm;
306*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = aws_jni_acquire_thread_env(jvm);
307*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
308*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
309*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "LifecycleEvent: could not get env");
310*3c7ae9deSAndroid Build Coastguard Worker         return;
311*3c7ae9deSAndroid Build Coastguard Worker     }
312*3c7ae9deSAndroid Build Coastguard Worker 
313*3c7ae9deSAndroid Build Coastguard Worker     /* Calculate the number of references needed (1 is always needed for the return struct) */
314*3c7ae9deSAndroid Build Coastguard Worker     size_t references_needed = 1;
315*3c7ae9deSAndroid Build Coastguard Worker     if (event->connack_data != NULL) {
316*3c7ae9deSAndroid Build Coastguard Worker         /* A ConnAck packet will need 2 references at minimum */
317*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 2;
318*3c7ae9deSAndroid Build Coastguard Worker         /* Optionals */
319*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->assigned_client_identifier, &references_needed);
320*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->authentication_data, &references_needed);
321*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->authentication_method, &references_needed);
322*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->maximum_packet_size, &references_needed);
323*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->maximum_qos, &references_needed);
324*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->reason_string, &references_needed);
325*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->receive_maximum, &references_needed);
326*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->response_information, &references_needed);
327*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->retain_available, &references_needed);
328*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->server_keep_alive, &references_needed);
329*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->server_reference, &references_needed);
330*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->session_expiry_interval, &references_needed);
331*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->shared_subscriptions_available, &references_needed);
332*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->subscription_identifiers_available, &references_needed);
333*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->topic_alias_maximum, &references_needed);
334*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->connack_data->wildcard_subscriptions_available, &references_needed);
335*3c7ae9deSAndroid Build Coastguard Worker         /* Add user properties */
336*3c7ae9deSAndroid Build Coastguard Worker         references_needed += event->connack_data->user_property_count * 2;
337*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 2; /* Add 2 for arrays to hold user properties */
338*3c7ae9deSAndroid Build Coastguard Worker     }
339*3c7ae9deSAndroid Build Coastguard Worker     if (event->disconnect_data != NULL) {
340*3c7ae9deSAndroid Build Coastguard Worker         /* A Disconnect packet will need 1 reference at a minimum */
341*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1;
342*3c7ae9deSAndroid Build Coastguard Worker         /* Optionals */
343*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->disconnect_data->reason_string, &references_needed);
344*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->disconnect_data->server_reference, &references_needed);
345*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(event->disconnect_data->session_expiry_interval_seconds, &references_needed);
346*3c7ae9deSAndroid Build Coastguard Worker         /* Add user properties */
347*3c7ae9deSAndroid Build Coastguard Worker         references_needed += event->disconnect_data->user_property_count * 2;
348*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 2; /* Add 1 for array to hold user properties */
349*3c7ae9deSAndroid Build Coastguard Worker     }
350*3c7ae9deSAndroid Build Coastguard Worker     if (event->settings != NULL) {
351*3c7ae9deSAndroid Build Coastguard Worker         /* Negotiated settings only need 2 references, one for the ClientID and another for the object */
352*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 2;
353*3c7ae9deSAndroid Build Coastguard Worker     }
354*3c7ae9deSAndroid Build Coastguard Worker 
355*3c7ae9deSAndroid Build Coastguard Worker     /* Make a local frame so we can clean memory */
356*3c7ae9deSAndroid Build Coastguard Worker     jint local_frame_result = (*env)->PushLocalFrame(env, (jint)references_needed);
357*3c7ae9deSAndroid Build Coastguard Worker     if (local_frame_result != 0) {
358*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
359*3c7ae9deSAndroid Build Coastguard Worker             env, "LifecycleEvent: could not push local JNI frame with 14 allocation minimum!", AWS_ERROR_INVALID_STATE);
360*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_release_thread_env(jvm, env);
361*3c7ae9deSAndroid Build Coastguard Worker         return;
362*3c7ae9deSAndroid Build Coastguard Worker     }
363*3c7ae9deSAndroid Build Coastguard Worker 
364*3c7ae9deSAndroid Build Coastguard Worker     jobject connack_data = NULL;
365*3c7ae9deSAndroid Build Coastguard Worker     if (event->connack_data != NULL) {
366*3c7ae9deSAndroid Build Coastguard Worker         connack_data = s_aws_mqtt5_client_create_jni_connack_packet_from_native(env, event->connack_data);
367*3c7ae9deSAndroid Build Coastguard Worker         if (connack_data == NULL) {
368*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "LifecycleEvent: creating ConnAck packet failed!");
369*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
370*3c7ae9deSAndroid Build Coastguard Worker         }
371*3c7ae9deSAndroid Build Coastguard Worker     }
372*3c7ae9deSAndroid Build Coastguard Worker 
373*3c7ae9deSAndroid Build Coastguard Worker     jobject disconnect_data = NULL;
374*3c7ae9deSAndroid Build Coastguard Worker     if (event->disconnect_data != NULL) {
375*3c7ae9deSAndroid Build Coastguard Worker         disconnect_data = s_aws_mqtt5_client_create_jni_disconnect_packet_from_native(env, event->disconnect_data);
376*3c7ae9deSAndroid Build Coastguard Worker         if (disconnect_data == NULL) {
377*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "LifecycleEvent: creating Disconnect packet failed!");
378*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
379*3c7ae9deSAndroid Build Coastguard Worker         }
380*3c7ae9deSAndroid Build Coastguard Worker     }
381*3c7ae9deSAndroid Build Coastguard Worker 
382*3c7ae9deSAndroid Build Coastguard Worker     jobject negotiated_settings_data = NULL;
383*3c7ae9deSAndroid Build Coastguard Worker     if (event->settings != NULL) {
384*3c7ae9deSAndroid Build Coastguard Worker         negotiated_settings_data = s_aws_mqtt5_client_create_jni_negotiated_settings_from_native(env, event->settings);
385*3c7ae9deSAndroid Build Coastguard Worker     }
386*3c7ae9deSAndroid Build Coastguard Worker 
387*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_lifecycle_events = java_client->jni_lifecycle_events;
388*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_lifecycle_events) {
389*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
390*3c7ae9deSAndroid Build Coastguard Worker             env, "LifecycleEvent: no lifecycle events found!", AWS_ERROR_INVALID_STATE);
391*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
392*3c7ae9deSAndroid Build Coastguard Worker     }
393*3c7ae9deSAndroid Build Coastguard Worker 
394*3c7ae9deSAndroid Build Coastguard Worker     jobject java_lifecycle_return_data;
395*3c7ae9deSAndroid Build Coastguard Worker 
396*3c7ae9deSAndroid Build Coastguard Worker     switch (event->event_type) {
397*3c7ae9deSAndroid Build Coastguard Worker         case AWS_MQTT5_CLET_ATTEMPTING_CONNECT:
398*3c7ae9deSAndroid Build Coastguard Worker 
399*3c7ae9deSAndroid Build Coastguard Worker             /* Make the OnAttemptingConnectReturn struct */
400*3c7ae9deSAndroid Build Coastguard Worker             java_lifecycle_return_data = (*env)->NewObject(
401*3c7ae9deSAndroid Build Coastguard Worker                 env,
402*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_attempting_connect_return_properties.return_class,
403*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_attempting_connect_return_properties.return_constructor_id);
404*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
405*3c7ae9deSAndroid Build Coastguard Worker 
406*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(
407*3c7ae9deSAndroid Build Coastguard Worker                 env,
408*3c7ae9deSAndroid Build Coastguard Worker                 jni_lifecycle_events,
409*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_lifecycle_events_properties.lifecycle_attempting_connect_id,
410*3c7ae9deSAndroid Build Coastguard Worker                 java_client->jni_client,
411*3c7ae9deSAndroid Build Coastguard Worker                 java_lifecycle_return_data);
412*3c7ae9deSAndroid Build Coastguard Worker             break;
413*3c7ae9deSAndroid Build Coastguard Worker         case AWS_MQTT5_CLET_CONNECTION_SUCCESS:
414*3c7ae9deSAndroid Build Coastguard Worker 
415*3c7ae9deSAndroid Build Coastguard Worker             /* Make the OnConnectionSuccessReturn struct */
416*3c7ae9deSAndroid Build Coastguard Worker             java_lifecycle_return_data = (*env)->NewObject(
417*3c7ae9deSAndroid Build Coastguard Worker                 env,
418*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_connection_success_return_properties.return_class,
419*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_connection_success_return_properties.return_constructor_id,
420*3c7ae9deSAndroid Build Coastguard Worker                 connack_data,
421*3c7ae9deSAndroid Build Coastguard Worker                 negotiated_settings_data);
422*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
423*3c7ae9deSAndroid Build Coastguard Worker 
424*3c7ae9deSAndroid Build Coastguard Worker             /* Set OnConnected BEFORE calling the callback so it is accurate in the callback itself. */
425*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(env, java_client->jni_client, mqtt5_client_properties.client_set_is_connected, true);
426*3c7ae9deSAndroid Build Coastguard Worker 
427*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(
428*3c7ae9deSAndroid Build Coastguard Worker                 env,
429*3c7ae9deSAndroid Build Coastguard Worker                 jni_lifecycle_events,
430*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_lifecycle_events_properties.lifecycle_connection_success_id,
431*3c7ae9deSAndroid Build Coastguard Worker                 java_client->jni_client,
432*3c7ae9deSAndroid Build Coastguard Worker                 java_lifecycle_return_data);
433*3c7ae9deSAndroid Build Coastguard Worker             break;
434*3c7ae9deSAndroid Build Coastguard Worker         case AWS_MQTT5_CLET_CONNECTION_FAILURE: {
435*3c7ae9deSAndroid Build Coastguard Worker             jint error_code = (jint)event->error_code;
436*3c7ae9deSAndroid Build Coastguard Worker 
437*3c7ae9deSAndroid Build Coastguard Worker             /* Make the OnConnectionFailureReturn struct */
438*3c7ae9deSAndroid Build Coastguard Worker             java_lifecycle_return_data = (*env)->NewObject(
439*3c7ae9deSAndroid Build Coastguard Worker                 env,
440*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_connection_failure_return_properties.return_class,
441*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_connection_failure_return_properties.return_constructor_id,
442*3c7ae9deSAndroid Build Coastguard Worker                 error_code,
443*3c7ae9deSAndroid Build Coastguard Worker                 connack_data);
444*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
445*3c7ae9deSAndroid Build Coastguard Worker 
446*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(
447*3c7ae9deSAndroid Build Coastguard Worker                 env,
448*3c7ae9deSAndroid Build Coastguard Worker                 jni_lifecycle_events,
449*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_lifecycle_events_properties.lifecycle_connection_failure_id,
450*3c7ae9deSAndroid Build Coastguard Worker                 java_client->jni_client,
451*3c7ae9deSAndroid Build Coastguard Worker                 java_lifecycle_return_data);
452*3c7ae9deSAndroid Build Coastguard Worker             break;
453*3c7ae9deSAndroid Build Coastguard Worker         }
454*3c7ae9deSAndroid Build Coastguard Worker         case AWS_MQTT5_CLET_DISCONNECTION: {
455*3c7ae9deSAndroid Build Coastguard Worker             jint error_code = (jint)event->error_code;
456*3c7ae9deSAndroid Build Coastguard Worker 
457*3c7ae9deSAndroid Build Coastguard Worker             /* Make the OnDisconnectionReturn struct */
458*3c7ae9deSAndroid Build Coastguard Worker             java_lifecycle_return_data = (*env)->NewObject(
459*3c7ae9deSAndroid Build Coastguard Worker                 env,
460*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_disconnection_return_properties.return_class,
461*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_disconnection_return_properties.return_constructor_id,
462*3c7ae9deSAndroid Build Coastguard Worker                 error_code,
463*3c7ae9deSAndroid Build Coastguard Worker                 disconnect_data);
464*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
465*3c7ae9deSAndroid Build Coastguard Worker 
466*3c7ae9deSAndroid Build Coastguard Worker             /* Set OnConnected BEFORE calling the callback so it is accurate in the callback itself. */
467*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(
468*3c7ae9deSAndroid Build Coastguard Worker                 env, java_client->jni_client, mqtt5_client_properties.client_set_is_connected, false);
469*3c7ae9deSAndroid Build Coastguard Worker 
470*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(
471*3c7ae9deSAndroid Build Coastguard Worker                 env,
472*3c7ae9deSAndroid Build Coastguard Worker                 jni_lifecycle_events,
473*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_lifecycle_events_properties.lifecycle_disconnection_id,
474*3c7ae9deSAndroid Build Coastguard Worker                 java_client->jni_client,
475*3c7ae9deSAndroid Build Coastguard Worker                 java_lifecycle_return_data);
476*3c7ae9deSAndroid Build Coastguard Worker             break;
477*3c7ae9deSAndroid Build Coastguard Worker         }
478*3c7ae9deSAndroid Build Coastguard Worker         case AWS_MQTT5_CLET_STOPPED:
479*3c7ae9deSAndroid Build Coastguard Worker 
480*3c7ae9deSAndroid Build Coastguard Worker             /* Make the OnStopped struct */
481*3c7ae9deSAndroid Build Coastguard Worker             java_lifecycle_return_data = (*env)->NewObject(
482*3c7ae9deSAndroid Build Coastguard Worker                 env,
483*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_stopped_return_properties.return_class,
484*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_on_stopped_return_properties.return_constructor_id);
485*3c7ae9deSAndroid Build Coastguard Worker             aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
486*3c7ae9deSAndroid Build Coastguard Worker 
487*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallVoidMethod(
488*3c7ae9deSAndroid Build Coastguard Worker                 env,
489*3c7ae9deSAndroid Build Coastguard Worker                 jni_lifecycle_events,
490*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_lifecycle_events_properties.lifecycle_stopped_id,
491*3c7ae9deSAndroid Build Coastguard Worker                 java_client->jni_client,
492*3c7ae9deSAndroid Build Coastguard Worker                 java_lifecycle_return_data);
493*3c7ae9deSAndroid Build Coastguard Worker             break;
494*3c7ae9deSAndroid Build Coastguard Worker         default:
495*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "LifecycleEvent: unsupported event type: %i", event->event_type);
496*3c7ae9deSAndroid Build Coastguard Worker     }
497*3c7ae9deSAndroid Build Coastguard Worker 
498*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
499*3c7ae9deSAndroid Build Coastguard Worker 
500*3c7ae9deSAndroid Build Coastguard Worker clean_up:
501*3c7ae9deSAndroid Build Coastguard Worker 
502*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
503*3c7ae9deSAndroid Build Coastguard Worker 
504*3c7ae9deSAndroid Build Coastguard Worker     (*env)->PopLocalFrame(env, NULL);
505*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE **********/
506*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(jvm, env);
507*3c7ae9deSAndroid Build Coastguard Worker }
508*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_publish_received(const struct aws_mqtt5_packet_publish_view * publish,void * user_data)509*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_publish_received(
510*3c7ae9deSAndroid Build Coastguard Worker     const struct aws_mqtt5_packet_publish_view *publish,
511*3c7ae9deSAndroid Build Coastguard Worker     void *user_data) {
512*3c7ae9deSAndroid Build Coastguard Worker 
513*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)user_data;
514*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
515*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "publishReceived function: invalid client");
516*3c7ae9deSAndroid Build Coastguard Worker         return;
517*3c7ae9deSAndroid Build Coastguard Worker     }
518*3c7ae9deSAndroid Build Coastguard Worker 
519*3c7ae9deSAndroid Build Coastguard Worker     if (!publish) {
520*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "publishReceived function: invalid publish packet");
521*3c7ae9deSAndroid Build Coastguard Worker         return;
522*3c7ae9deSAndroid Build Coastguard Worker     }
523*3c7ae9deSAndroid Build Coastguard Worker 
524*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
525*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = java_client->jvm;
526*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = aws_jni_acquire_thread_env(jvm);
527*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
528*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
529*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "publishReceived function: could not get env");
530*3c7ae9deSAndroid Build Coastguard Worker         return;
531*3c7ae9deSAndroid Build Coastguard Worker     }
532*3c7ae9deSAndroid Build Coastguard Worker 
533*3c7ae9deSAndroid Build Coastguard Worker     /* Calculate the number of references needed */
534*3c7ae9deSAndroid Build Coastguard Worker     size_t references_needed = 0;
535*3c7ae9deSAndroid Build Coastguard Worker     {
536*3c7ae9deSAndroid Build Coastguard Worker         /* One reference is needed for the PublishReturn */
537*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1;
538*3c7ae9deSAndroid Build Coastguard Worker 
539*3c7ae9deSAndroid Build Coastguard Worker         /* A Publish packet will need 5 references at minimum */
540*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 5;
541*3c7ae9deSAndroid Build Coastguard Worker         /* Optionals */
542*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(publish->content_type, &references_needed);
543*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(publish->correlation_data, &references_needed);
544*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(publish->message_expiry_interval_seconds, &references_needed);
545*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(publish->response_topic, &references_needed);
546*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(publish->topic_alias, &references_needed);
547*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(publish->payload_format, &references_needed);
548*3c7ae9deSAndroid Build Coastguard Worker         /* Add user properties and subscription identifiers */
549*3c7ae9deSAndroid Build Coastguard Worker         references_needed += publish->user_property_count * 2;
550*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1; /* Add 1 for array to hold user properties */
551*3c7ae9deSAndroid Build Coastguard Worker         if (publish->subscription_identifier_count > 0) {
552*3c7ae9deSAndroid Build Coastguard Worker             references_needed += publish->subscription_identifier_count;
553*3c7ae9deSAndroid Build Coastguard Worker             references_needed += 1; /* Add 1 for array */
554*3c7ae9deSAndroid Build Coastguard Worker         }
555*3c7ae9deSAndroid Build Coastguard Worker     }
556*3c7ae9deSAndroid Build Coastguard Worker 
557*3c7ae9deSAndroid Build Coastguard Worker     /**
558*3c7ae9deSAndroid Build Coastguard Worker      * Push a new local frame so any local references we make are tied to it. Then we can pop it to free memory.
559*3c7ae9deSAndroid Build Coastguard Worker      */
560*3c7ae9deSAndroid Build Coastguard Worker     jint local_frame_result = (*env)->PushLocalFrame(env, (jint)references_needed);
561*3c7ae9deSAndroid Build Coastguard Worker     if (local_frame_result != 0) {
562*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
563*3c7ae9deSAndroid Build Coastguard Worker             env,
564*3c7ae9deSAndroid Build Coastguard Worker             "publishReceived function: could not push local JNI frame with 12 allocation minimum!",
565*3c7ae9deSAndroid Build Coastguard Worker             AWS_ERROR_INVALID_STATE);
566*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
567*3c7ae9deSAndroid Build Coastguard Worker     }
568*3c7ae9deSAndroid Build Coastguard Worker 
569*3c7ae9deSAndroid Build Coastguard Worker     /* The return result */
570*3c7ae9deSAndroid Build Coastguard Worker     jobject publish_packet_return_data;
571*3c7ae9deSAndroid Build Coastguard Worker 
572*3c7ae9deSAndroid Build Coastguard Worker     /* Make the PublishPacket */
573*3c7ae9deSAndroid Build Coastguard Worker     jobject publish_packet_data = s_aws_mqtt5_client_create_jni_publish_packet_from_native(env, publish);
574*3c7ae9deSAndroid Build Coastguard Worker     if (publish_packet_data == NULL) {
575*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
576*3c7ae9deSAndroid Build Coastguard Worker     }
577*3c7ae9deSAndroid Build Coastguard Worker 
578*3c7ae9deSAndroid Build Coastguard Worker     /* Make the PublishReturn struct that will hold all of the data that is passed to Java */
579*3c7ae9deSAndroid Build Coastguard Worker     publish_packet_return_data = (*env)->NewObject(
580*3c7ae9deSAndroid Build Coastguard Worker         env,
581*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_publish_return_properties.return_class,
582*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_publish_return_properties.return_constructor_id,
583*3c7ae9deSAndroid Build Coastguard Worker         publish_packet_data);
584*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
585*3c7ae9deSAndroid Build Coastguard Worker 
586*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->jni_publish_events) {
587*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallVoidMethod(
588*3c7ae9deSAndroid Build Coastguard Worker             env,
589*3c7ae9deSAndroid Build Coastguard Worker             java_client->jni_publish_events,
590*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_publish_events_properties.publish_events_publish_received_id,
591*3c7ae9deSAndroid Build Coastguard Worker             java_client->jni_client,
592*3c7ae9deSAndroid Build Coastguard Worker             publish_packet_return_data);
593*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
594*3c7ae9deSAndroid Build Coastguard Worker     }
595*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
596*3c7ae9deSAndroid Build Coastguard Worker 
597*3c7ae9deSAndroid Build Coastguard Worker clean_up:
598*3c7ae9deSAndroid Build Coastguard Worker 
599*3c7ae9deSAndroid Build Coastguard Worker     (*env)->PopLocalFrame(env, NULL);
600*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE **********/
601*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(jvm, env);
602*3c7ae9deSAndroid Build Coastguard Worker }
603*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_publish_callback_destructor(JNIEnv * env,struct aws_mqtt5_client_publish_return_data * callback_return_data)604*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_publish_callback_destructor(
605*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
606*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_publish_return_data *callback_return_data) {
607*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
608*3c7ae9deSAndroid Build Coastguard Worker 
609*3c7ae9deSAndroid Build Coastguard Worker     if (callback_return_data != NULL) {
610*3c7ae9deSAndroid Build Coastguard Worker         if (callback_return_data->jni_publish_future && env != NULL) {
611*3c7ae9deSAndroid Build Coastguard Worker             (*env)->DeleteGlobalRef(env, callback_return_data->jni_publish_future);
612*3c7ae9deSAndroid Build Coastguard Worker         }
613*3c7ae9deSAndroid Build Coastguard Worker         aws_mem_release(allocator, callback_return_data);
614*3c7ae9deSAndroid Build Coastguard Worker     }
615*3c7ae9deSAndroid Build Coastguard Worker }
616*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_publish_completion(enum aws_mqtt5_packet_type packet_type,const void * packet,int error_code,void * user_data)617*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_publish_completion(
618*3c7ae9deSAndroid Build Coastguard Worker     enum aws_mqtt5_packet_type packet_type,
619*3c7ae9deSAndroid Build Coastguard Worker     const void *packet,
620*3c7ae9deSAndroid Build Coastguard Worker     int error_code,
621*3c7ae9deSAndroid Build Coastguard Worker     void *user_data) {
622*3c7ae9deSAndroid Build Coastguard Worker 
623*3c7ae9deSAndroid Build Coastguard Worker     int exception_error_code = error_code;
624*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = NULL;
625*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = NULL;
626*3c7ae9deSAndroid Build Coastguard Worker     bool has_pushed_frame = false;
627*3c7ae9deSAndroid Build Coastguard Worker 
628*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_publish_return_data *return_data = (struct aws_mqtt5_client_publish_return_data *)user_data;
629*3c7ae9deSAndroid Build Coastguard Worker     if (!return_data) {
630*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishCompletion function: invalid return data!");
631*3c7ae9deSAndroid Build Coastguard Worker         return;
632*3c7ae9deSAndroid Build Coastguard Worker     }
633*3c7ae9deSAndroid Build Coastguard Worker 
634*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = return_data->java_client;
635*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
636*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishCompletion function: invalid client");
637*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
638*3c7ae9deSAndroid Build Coastguard Worker     }
639*3c7ae9deSAndroid Build Coastguard Worker 
640*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
641*3c7ae9deSAndroid Build Coastguard Worker     jvm = java_client->jvm;
642*3c7ae9deSAndroid Build Coastguard Worker     env = aws_jni_acquire_thread_env(jvm);
643*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
644*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
645*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishCompletion function: could not get env");
646*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
647*3c7ae9deSAndroid Build Coastguard Worker     }
648*3c7ae9deSAndroid Build Coastguard Worker 
649*3c7ae9deSAndroid Build Coastguard Worker     /* Get the future for this specific publish and complete right away if there is an error */
650*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_publish_future = return_data->jni_publish_future;
651*3c7ae9deSAndroid Build Coastguard Worker     if (error_code != AWS_OP_SUCCESS) {
652*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
653*3c7ae9deSAndroid Build Coastguard Worker     }
654*3c7ae9deSAndroid Build Coastguard Worker 
655*3c7ae9deSAndroid Build Coastguard Worker     /* If this result is supposed to have a packet and does not, then error right away */
656*3c7ae9deSAndroid Build Coastguard Worker     if (packet_type != AWS_MQTT5_PT_NONE && packet == NULL) {
657*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishCompletion function: packet type but no packet!");
658*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
659*3c7ae9deSAndroid Build Coastguard Worker     }
660*3c7ae9deSAndroid Build Coastguard Worker 
661*3c7ae9deSAndroid Build Coastguard Worker     /* Calculate the number of references needed */
662*3c7ae9deSAndroid Build Coastguard Worker     size_t references_needed = 0;
663*3c7ae9deSAndroid Build Coastguard Worker     if (packet_type == AWS_MQTT5_PT_PUBACK) {
664*3c7ae9deSAndroid Build Coastguard Worker         struct aws_mqtt5_packet_puback_view *puback_packet = (struct aws_mqtt5_packet_puback_view *)packet;
665*3c7ae9deSAndroid Build Coastguard Worker         /* A PubAck packet will need 2 references at minimum */
666*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 2;
667*3c7ae9deSAndroid Build Coastguard Worker         /* Optionals */
668*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(puback_packet->reason_string, &references_needed);
669*3c7ae9deSAndroid Build Coastguard Worker         /* Add user properties */
670*3c7ae9deSAndroid Build Coastguard Worker         references_needed += puback_packet->user_property_count * 2;
671*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1; /* Add 1 for array to hold user properties */
672*3c7ae9deSAndroid Build Coastguard Worker     }
673*3c7ae9deSAndroid Build Coastguard Worker 
674*3c7ae9deSAndroid Build Coastguard Worker     /**
675*3c7ae9deSAndroid Build Coastguard Worker      * Push a new local frame so any local references we make are tied to it. Then we can pop it to free memory.
676*3c7ae9deSAndroid Build Coastguard Worker      */
677*3c7ae9deSAndroid Build Coastguard Worker     jint local_frame_result = (*env)->PushLocalFrame(env, (jint)references_needed);
678*3c7ae9deSAndroid Build Coastguard Worker     if (local_frame_result != 0) {
679*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(
680*3c7ae9deSAndroid Build Coastguard Worker             AWS_LS_MQTT5_CLIENT,
681*3c7ae9deSAndroid Build Coastguard Worker             "PublishCompletion function: could not push local JNI frame with 12 allocation minimum");
682*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = AWS_ERROR_INVALID_STATE;
683*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
684*3c7ae9deSAndroid Build Coastguard Worker     }
685*3c7ae9deSAndroid Build Coastguard Worker     has_pushed_frame = true;
686*3c7ae9deSAndroid Build Coastguard Worker 
687*3c7ae9deSAndroid Build Coastguard Worker     /* The result */
688*3c7ae9deSAndroid Build Coastguard Worker     jobject publish_packet_result_data;
689*3c7ae9deSAndroid Build Coastguard Worker 
690*3c7ae9deSAndroid Build Coastguard Worker     if (packet_type == AWS_MQTT5_PT_NONE) {
691*3c7ae9deSAndroid Build Coastguard Worker         /* QoS 0 */
692*3c7ae9deSAndroid Build Coastguard Worker         publish_packet_result_data = (*env)->NewObject(
693*3c7ae9deSAndroid Build Coastguard Worker             env, mqtt5_publish_result_properties.result_class, mqtt5_publish_result_properties.result_constructor_id);
694*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
695*3c7ae9deSAndroid Build Coastguard Worker 
696*3c7ae9deSAndroid Build Coastguard Worker     } else if (packet_type == AWS_MQTT5_PT_PUBACK) {
697*3c7ae9deSAndroid Build Coastguard Worker         /* QoS 1 */
698*3c7ae9deSAndroid Build Coastguard Worker         struct aws_mqtt5_packet_puback_view *puback_packet = (struct aws_mqtt5_packet_puback_view *)packet;
699*3c7ae9deSAndroid Build Coastguard Worker 
700*3c7ae9deSAndroid Build Coastguard Worker         /* Make the PubAck packet */
701*3c7ae9deSAndroid Build Coastguard Worker         jobject puback_packet_data = s_aws_mqtt5_client_create_jni_puback_packet_from_native(env, puback_packet);
702*3c7ae9deSAndroid Build Coastguard Worker         if (puback_packet_data == NULL) {
703*3c7ae9deSAndroid Build Coastguard Worker             exception_error_code = AWS_ERROR_INVALID_STATE;
704*3c7ae9deSAndroid Build Coastguard Worker             goto exception;
705*3c7ae9deSAndroid Build Coastguard Worker         }
706*3c7ae9deSAndroid Build Coastguard Worker 
707*3c7ae9deSAndroid Build Coastguard Worker         /* Make the result and populate it with data made above */
708*3c7ae9deSAndroid Build Coastguard Worker         publish_packet_result_data = (*env)->NewObject(
709*3c7ae9deSAndroid Build Coastguard Worker             env,
710*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_publish_result_properties.result_class,
711*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_publish_result_properties.result_puback_constructor_id,
712*3c7ae9deSAndroid Build Coastguard Worker             puback_packet_data);
713*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
714*3c7ae9deSAndroid Build Coastguard Worker 
715*3c7ae9deSAndroid Build Coastguard Worker     } else {
716*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishCompletion function called with unknown packet type!");
717*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = AWS_ERROR_INVALID_STATE;
718*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
719*3c7ae9deSAndroid Build Coastguard Worker     }
720*3c7ae9deSAndroid Build Coastguard Worker 
721*3c7ae9deSAndroid Build Coastguard Worker     /* Complete the future */
722*3c7ae9deSAndroid Build Coastguard Worker     (*env)->CallBooleanMethod(
723*3c7ae9deSAndroid Build Coastguard Worker         env, jni_publish_future, completable_future_properties.complete_method_id, publish_packet_result_data);
724*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
725*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishCompletion function: exception when completing future");
726*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
727*3c7ae9deSAndroid Build Coastguard Worker     }
728*3c7ae9deSAndroid Build Coastguard Worker 
729*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
730*3c7ae9deSAndroid Build Coastguard Worker 
731*3c7ae9deSAndroid Build Coastguard Worker exception:
732*3c7ae9deSAndroid Build Coastguard Worker     s_complete_future_with_exception(env, &jni_publish_future, exception_error_code);
733*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
734*3c7ae9deSAndroid Build Coastguard Worker 
735*3c7ae9deSAndroid Build Coastguard Worker clean_up:
736*3c7ae9deSAndroid Build Coastguard Worker     s_aws_mqtt5_client_java_publish_callback_destructor(env, return_data);
737*3c7ae9deSAndroid Build Coastguard Worker     if (env != NULL) {
738*3c7ae9deSAndroid Build Coastguard Worker         if (has_pushed_frame) {
739*3c7ae9deSAndroid Build Coastguard Worker             (*env)->PopLocalFrame(env, NULL);
740*3c7ae9deSAndroid Build Coastguard Worker         }
741*3c7ae9deSAndroid Build Coastguard Worker         /********** JNI ENV RELEASE **********/
742*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_release_thread_env(jvm, env);
743*3c7ae9deSAndroid Build Coastguard Worker     }
744*3c7ae9deSAndroid Build Coastguard Worker     return;
745*3c7ae9deSAndroid Build Coastguard Worker }
746*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_subscribe_callback_destructor(JNIEnv * env,struct aws_mqtt5_client_subscribe_return_data * callback_return_data)747*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_subscribe_callback_destructor(
748*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
749*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_subscribe_return_data *callback_return_data) {
750*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
751*3c7ae9deSAndroid Build Coastguard Worker 
752*3c7ae9deSAndroid Build Coastguard Worker     if (callback_return_data != NULL) {
753*3c7ae9deSAndroid Build Coastguard Worker         if (callback_return_data->jni_subscribe_future && env != NULL) {
754*3c7ae9deSAndroid Build Coastguard Worker             (*env)->DeleteGlobalRef(env, callback_return_data->jni_subscribe_future);
755*3c7ae9deSAndroid Build Coastguard Worker         }
756*3c7ae9deSAndroid Build Coastguard Worker         aws_mem_release(allocator, callback_return_data);
757*3c7ae9deSAndroid Build Coastguard Worker     }
758*3c7ae9deSAndroid Build Coastguard Worker }
759*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_subscribe_completion(const struct aws_mqtt5_packet_suback_view * suback,int error_code,void * user_data)760*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_subscribe_completion(
761*3c7ae9deSAndroid Build Coastguard Worker     const struct aws_mqtt5_packet_suback_view *suback,
762*3c7ae9deSAndroid Build Coastguard Worker     int error_code,
763*3c7ae9deSAndroid Build Coastguard Worker     void *user_data) {
764*3c7ae9deSAndroid Build Coastguard Worker 
765*3c7ae9deSAndroid Build Coastguard Worker     int exception_error_code = error_code;
766*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = NULL;
767*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = NULL;
768*3c7ae9deSAndroid Build Coastguard Worker     bool has_pushed_frame = false;
769*3c7ae9deSAndroid Build Coastguard Worker 
770*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_subscribe_return_data *return_data =
771*3c7ae9deSAndroid Build Coastguard Worker         (struct aws_mqtt5_client_subscribe_return_data *)user_data;
772*3c7ae9deSAndroid Build Coastguard Worker     if (!return_data) {
773*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribeCompletion: invalid return data!");
774*3c7ae9deSAndroid Build Coastguard Worker         return;
775*3c7ae9deSAndroid Build Coastguard Worker     }
776*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = return_data->java_client;
777*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
778*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribeCompletion: invalid client");
779*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
780*3c7ae9deSAndroid Build Coastguard Worker     }
781*3c7ae9deSAndroid Build Coastguard Worker 
782*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
783*3c7ae9deSAndroid Build Coastguard Worker     jvm = java_client->jvm;
784*3c7ae9deSAndroid Build Coastguard Worker     env = aws_jni_acquire_thread_env(jvm);
785*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
786*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
787*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribeCompletion: could not get env");
788*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
789*3c7ae9deSAndroid Build Coastguard Worker     }
790*3c7ae9deSAndroid Build Coastguard Worker 
791*3c7ae9deSAndroid Build Coastguard Worker     /* Get the future for this specific subscribe */
792*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_subscribe_future = return_data->jni_subscribe_future;
793*3c7ae9deSAndroid Build Coastguard Worker 
794*3c7ae9deSAndroid Build Coastguard Worker     if (error_code != AWS_OP_SUCCESS) {
795*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = error_code;
796*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
797*3c7ae9deSAndroid Build Coastguard Worker     }
798*3c7ae9deSAndroid Build Coastguard Worker 
799*3c7ae9deSAndroid Build Coastguard Worker     /* Calculate the number of references needed */
800*3c7ae9deSAndroid Build Coastguard Worker     size_t references_needed = 0;
801*3c7ae9deSAndroid Build Coastguard Worker     if (suback != NULL) {
802*3c7ae9deSAndroid Build Coastguard Worker         /* A SubAck packet will need 1 references at minimum */
803*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1;
804*3c7ae9deSAndroid Build Coastguard Worker         /* Optionals */
805*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(suback->reason_string, &references_needed);
806*3c7ae9deSAndroid Build Coastguard Worker         /* Add user properties and reason codes */
807*3c7ae9deSAndroid Build Coastguard Worker         references_needed += (suback->user_property_count) * 2;
808*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1; /* Add 1 for arrays to hold user properties */
809*3c7ae9deSAndroid Build Coastguard Worker         if (suback->reason_code_count > 0) {
810*3c7ae9deSAndroid Build Coastguard Worker             references_needed += suback->reason_code_count;
811*3c7ae9deSAndroid Build Coastguard Worker             references_needed += 1; /* Add 1 for arrays to hold reason codes */
812*3c7ae9deSAndroid Build Coastguard Worker         }
813*3c7ae9deSAndroid Build Coastguard Worker     }
814*3c7ae9deSAndroid Build Coastguard Worker 
815*3c7ae9deSAndroid Build Coastguard Worker     /**
816*3c7ae9deSAndroid Build Coastguard Worker      * Push a new local frame so any local references we make are tied to it. Then we can pop it to free memory.
817*3c7ae9deSAndroid Build Coastguard Worker      */
818*3c7ae9deSAndroid Build Coastguard Worker     jint local_frame_result = (*env)->PushLocalFrame(env, (jint)references_needed);
819*3c7ae9deSAndroid Build Coastguard Worker     if (local_frame_result != 0) {
820*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(
821*3c7ae9deSAndroid Build Coastguard Worker             AWS_LS_MQTT5_CLIENT, "SubscribeCompletion: could not push local JNI frame with 4 allocation minimum");
822*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = AWS_ERROR_INVALID_STATE;
823*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
824*3c7ae9deSAndroid Build Coastguard Worker     }
825*3c7ae9deSAndroid Build Coastguard Worker     has_pushed_frame = true;
826*3c7ae9deSAndroid Build Coastguard Worker 
827*3c7ae9deSAndroid Build Coastguard Worker     /* The SubAck to return (if present) */
828*3c7ae9deSAndroid Build Coastguard Worker     jobject suback_packet_data = NULL;
829*3c7ae9deSAndroid Build Coastguard Worker 
830*3c7ae9deSAndroid Build Coastguard Worker     if (suback != NULL) {
831*3c7ae9deSAndroid Build Coastguard Worker         suback_packet_data = (*env)->NewObject(
832*3c7ae9deSAndroid Build Coastguard Worker             env,
833*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_suback_packet_properties.suback_packet_class,
834*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_suback_packet_properties.suback_constructor_id);
835*3c7ae9deSAndroid Build Coastguard Worker 
836*3c7ae9deSAndroid Build Coastguard Worker         if (s_set_jni_string_field_in_packet(
837*3c7ae9deSAndroid Build Coastguard Worker                 env,
838*3c7ae9deSAndroid Build Coastguard Worker                 suback->reason_string,
839*3c7ae9deSAndroid Build Coastguard Worker                 suback_packet_data,
840*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_suback_packet_properties.suback_reason_string_field_id,
841*3c7ae9deSAndroid Build Coastguard Worker                 "reason string",
842*3c7ae9deSAndroid Build Coastguard Worker                 true) != AWS_OP_SUCCESS) {
843*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
844*3c7ae9deSAndroid Build Coastguard Worker         }
845*3c7ae9deSAndroid Build Coastguard Worker 
846*3c7ae9deSAndroid Build Coastguard Worker         if (suback->reason_codes != NULL) {
847*3c7ae9deSAndroid Build Coastguard Worker             if (suback->reason_code_count > 0) {
848*3c7ae9deSAndroid Build Coastguard Worker                 for (size_t i = 0; i < suback->reason_code_count; ++i) {
849*3c7ae9deSAndroid Build Coastguard Worker                     const enum aws_mqtt5_suback_reason_code *reason_code_data = &suback->reason_codes[i];
850*3c7ae9deSAndroid Build Coastguard Worker                     if (s_set_int_enum_in_packet(
851*3c7ae9deSAndroid Build Coastguard Worker                             env,
852*3c7ae9deSAndroid Build Coastguard Worker                             (int *)reason_code_data,
853*3c7ae9deSAndroid Build Coastguard Worker                             suback_packet_data,
854*3c7ae9deSAndroid Build Coastguard Worker                             mqtt5_suback_packet_properties.suback_native_add_suback_code_id,
855*3c7ae9deSAndroid Build Coastguard Worker                             false) != AWS_OP_SUCCESS) {
856*3c7ae9deSAndroid Build Coastguard Worker                         AWS_LOGF_ERROR(
857*3c7ae9deSAndroid Build Coastguard Worker                             AWS_LS_MQTT5_CLIENT,
858*3c7ae9deSAndroid Build Coastguard Worker                             "Error when creating SubAckPacket from native: Could not set reason code");
859*3c7ae9deSAndroid Build Coastguard Worker                         exception_error_code = AWS_ERROR_INVALID_STATE;
860*3c7ae9deSAndroid Build Coastguard Worker                         goto exception;
861*3c7ae9deSAndroid Build Coastguard Worker                     }
862*3c7ae9deSAndroid Build Coastguard Worker                 }
863*3c7ae9deSAndroid Build Coastguard Worker             }
864*3c7ae9deSAndroid Build Coastguard Worker         }
865*3c7ae9deSAndroid Build Coastguard Worker 
866*3c7ae9deSAndroid Build Coastguard Worker         if (s_set_user_properties_field(
867*3c7ae9deSAndroid Build Coastguard Worker                 env,
868*3c7ae9deSAndroid Build Coastguard Worker                 suback->user_property_count,
869*3c7ae9deSAndroid Build Coastguard Worker                 suback->user_properties,
870*3c7ae9deSAndroid Build Coastguard Worker                 suback_packet_data,
871*3c7ae9deSAndroid Build Coastguard Worker                 mqtt5_suback_packet_properties.suback_user_properties_field_id) == AWS_OP_ERR) {
872*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "When creating PubAckPacket from native could not add user property!");
873*3c7ae9deSAndroid Build Coastguard Worker             exception_error_code = AWS_ERROR_INVALID_STATE;
874*3c7ae9deSAndroid Build Coastguard Worker             goto exception;
875*3c7ae9deSAndroid Build Coastguard Worker         }
876*3c7ae9deSAndroid Build Coastguard Worker     }
877*3c7ae9deSAndroid Build Coastguard Worker 
878*3c7ae9deSAndroid Build Coastguard Worker     /* Complete the promise */
879*3c7ae9deSAndroid Build Coastguard Worker     (*env)->CallBooleanMethod(
880*3c7ae9deSAndroid Build Coastguard Worker         env, jni_subscribe_future, completable_future_properties.complete_method_id, suback_packet_data);
881*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
882*3c7ae9deSAndroid Build Coastguard Worker 
883*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
884*3c7ae9deSAndroid Build Coastguard Worker 
885*3c7ae9deSAndroid Build Coastguard Worker exception:
886*3c7ae9deSAndroid Build Coastguard Worker     s_complete_future_with_exception(env, &jni_subscribe_future, exception_error_code);
887*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
888*3c7ae9deSAndroid Build Coastguard Worker 
889*3c7ae9deSAndroid Build Coastguard Worker clean_up:
890*3c7ae9deSAndroid Build Coastguard Worker     s_aws_mqtt5_client_java_subscribe_callback_destructor(env, return_data);
891*3c7ae9deSAndroid Build Coastguard Worker     if (env != NULL) {
892*3c7ae9deSAndroid Build Coastguard Worker         if (has_pushed_frame) {
893*3c7ae9deSAndroid Build Coastguard Worker             (*env)->PopLocalFrame(env, NULL);
894*3c7ae9deSAndroid Build Coastguard Worker         }
895*3c7ae9deSAndroid Build Coastguard Worker         /********** JNI ENV RELEASE **********/
896*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_release_thread_env(jvm, env);
897*3c7ae9deSAndroid Build Coastguard Worker     }
898*3c7ae9deSAndroid Build Coastguard Worker }
899*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_unsubscribe_callback_destructor(JNIEnv * env,struct aws_mqtt5_client_unsubscribe_return_data * callback_return_data)900*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_unsubscribe_callback_destructor(
901*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
902*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_unsubscribe_return_data *callback_return_data) {
903*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
904*3c7ae9deSAndroid Build Coastguard Worker 
905*3c7ae9deSAndroid Build Coastguard Worker     if (callback_return_data != NULL) {
906*3c7ae9deSAndroid Build Coastguard Worker         if (callback_return_data->jni_unsubscribe_future && env != NULL) {
907*3c7ae9deSAndroid Build Coastguard Worker             (*env)->DeleteGlobalRef(env, callback_return_data->jni_unsubscribe_future);
908*3c7ae9deSAndroid Build Coastguard Worker         }
909*3c7ae9deSAndroid Build Coastguard Worker         aws_mem_release(allocator, callback_return_data);
910*3c7ae9deSAndroid Build Coastguard Worker     }
911*3c7ae9deSAndroid Build Coastguard Worker }
912*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_unsubscribe_completion(const struct aws_mqtt5_packet_unsuback_view * unsuback,int error_code,void * user_data)913*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_unsubscribe_completion(
914*3c7ae9deSAndroid Build Coastguard Worker     const struct aws_mqtt5_packet_unsuback_view *unsuback,
915*3c7ae9deSAndroid Build Coastguard Worker     int error_code,
916*3c7ae9deSAndroid Build Coastguard Worker     void *user_data) {
917*3c7ae9deSAndroid Build Coastguard Worker 
918*3c7ae9deSAndroid Build Coastguard Worker     int exception_error_code = error_code;
919*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = NULL;
920*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = NULL;
921*3c7ae9deSAndroid Build Coastguard Worker     bool has_pushed_frame = false;
922*3c7ae9deSAndroid Build Coastguard Worker 
923*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_unsubscribe_return_data *return_data =
924*3c7ae9deSAndroid Build Coastguard Worker         (struct aws_mqtt5_client_unsubscribe_return_data *)user_data;
925*3c7ae9deSAndroid Build Coastguard Worker     if (!return_data) {
926*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "UnsubscribeCompletion: invalid return data!");
927*3c7ae9deSAndroid Build Coastguard Worker         return;
928*3c7ae9deSAndroid Build Coastguard Worker     }
929*3c7ae9deSAndroid Build Coastguard Worker 
930*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = return_data->java_client;
931*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
932*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "UnsubscribeCompletion: invalid client");
933*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
934*3c7ae9deSAndroid Build Coastguard Worker     }
935*3c7ae9deSAndroid Build Coastguard Worker 
936*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
937*3c7ae9deSAndroid Build Coastguard Worker     jvm = java_client->jvm;
938*3c7ae9deSAndroid Build Coastguard Worker     env = aws_jni_acquire_thread_env(jvm);
939*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
940*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
941*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "UnsubscribeCompletion: could not get env");
942*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
943*3c7ae9deSAndroid Build Coastguard Worker     }
944*3c7ae9deSAndroid Build Coastguard Worker 
945*3c7ae9deSAndroid Build Coastguard Worker     /* Get the future for this specific unsubscribe */
946*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_unsubscribe_future = return_data->jni_unsubscribe_future;
947*3c7ae9deSAndroid Build Coastguard Worker 
948*3c7ae9deSAndroid Build Coastguard Worker     /* Calculate the number of references needed */
949*3c7ae9deSAndroid Build Coastguard Worker     size_t references_needed = 0;
950*3c7ae9deSAndroid Build Coastguard Worker     if (unsuback != NULL) {
951*3c7ae9deSAndroid Build Coastguard Worker         /* A UnsubAck packet will need 1 reference at minimum */
952*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1;
953*3c7ae9deSAndroid Build Coastguard Worker         /* Optionals */
954*3c7ae9deSAndroid Build Coastguard Worker         s_aws_count_allocation(unsuback->reason_string, &references_needed);
955*3c7ae9deSAndroid Build Coastguard Worker         /* Add user properties and reason codes */
956*3c7ae9deSAndroid Build Coastguard Worker         references_needed += (unsuback->user_property_count) * 2;
957*3c7ae9deSAndroid Build Coastguard Worker         references_needed += 1; /* Add 1 for array to hold user properties */
958*3c7ae9deSAndroid Build Coastguard Worker         if (unsuback->reason_code_count > 0) {
959*3c7ae9deSAndroid Build Coastguard Worker             references_needed += unsuback->reason_code_count;
960*3c7ae9deSAndroid Build Coastguard Worker             references_needed += 1; /* Add 1 for array to hold reason codes */
961*3c7ae9deSAndroid Build Coastguard Worker         }
962*3c7ae9deSAndroid Build Coastguard Worker     }
963*3c7ae9deSAndroid Build Coastguard Worker 
964*3c7ae9deSAndroid Build Coastguard Worker     /**
965*3c7ae9deSAndroid Build Coastguard Worker      * Push a new local frame so any local allocations we make are tied to it. Then we can pop it to free memory.
966*3c7ae9deSAndroid Build Coastguard Worker      */
967*3c7ae9deSAndroid Build Coastguard Worker     jint local_frame_result = (*env)->PushLocalFrame(env, (jint)references_needed);
968*3c7ae9deSAndroid Build Coastguard Worker     if (local_frame_result != 0) {
969*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(
970*3c7ae9deSAndroid Build Coastguard Worker             AWS_LS_MQTT5_CLIENT, "UnsubscribeCompletion: could not push local JNI frame with 4 allocation minimum");
971*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = AWS_ERROR_INVALID_STATE;
972*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
973*3c7ae9deSAndroid Build Coastguard Worker     }
974*3c7ae9deSAndroid Build Coastguard Worker     has_pushed_frame = true;
975*3c7ae9deSAndroid Build Coastguard Worker 
976*3c7ae9deSAndroid Build Coastguard Worker     if (error_code != AWS_OP_SUCCESS) {
977*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = error_code;
978*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
979*3c7ae9deSAndroid Build Coastguard Worker     }
980*3c7ae9deSAndroid Build Coastguard Worker 
981*3c7ae9deSAndroid Build Coastguard Worker     jobject unsuback_packet_data = (*env)->NewObject(
982*3c7ae9deSAndroid Build Coastguard Worker         env,
983*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_unsuback_packet_properties.unsuback_packet_class,
984*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_unsuback_packet_properties.unsuback_constructor_id);
985*3c7ae9deSAndroid Build Coastguard Worker 
986*3c7ae9deSAndroid Build Coastguard Worker     if (s_set_jni_string_field_in_packet(
987*3c7ae9deSAndroid Build Coastguard Worker             env,
988*3c7ae9deSAndroid Build Coastguard Worker             unsuback->reason_string,
989*3c7ae9deSAndroid Build Coastguard Worker             unsuback_packet_data,
990*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_unsuback_packet_properties.unsuback_reason_string_field_id,
991*3c7ae9deSAndroid Build Coastguard Worker             "reason string",
992*3c7ae9deSAndroid Build Coastguard Worker             true) != AWS_OP_SUCCESS) {
993*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
994*3c7ae9deSAndroid Build Coastguard Worker     }
995*3c7ae9deSAndroid Build Coastguard Worker 
996*3c7ae9deSAndroid Build Coastguard Worker     if (unsuback->reason_codes) {
997*3c7ae9deSAndroid Build Coastguard Worker         if (unsuback->reason_code_count > 0) {
998*3c7ae9deSAndroid Build Coastguard Worker             for (size_t i = 0; i < unsuback->reason_code_count; ++i) {
999*3c7ae9deSAndroid Build Coastguard Worker                 const enum aws_mqtt5_unsuback_reason_code *reason_code_data = &unsuback->reason_codes[i];
1000*3c7ae9deSAndroid Build Coastguard Worker                 if (s_set_int_enum_in_packet(
1001*3c7ae9deSAndroid Build Coastguard Worker                         env,
1002*3c7ae9deSAndroid Build Coastguard Worker                         (int *)reason_code_data,
1003*3c7ae9deSAndroid Build Coastguard Worker                         unsuback_packet_data,
1004*3c7ae9deSAndroid Build Coastguard Worker                         mqtt5_unsuback_packet_properties.unsuback_native_add_unsuback_code_id,
1005*3c7ae9deSAndroid Build Coastguard Worker                         false) != AWS_OP_SUCCESS) {
1006*3c7ae9deSAndroid Build Coastguard Worker                     AWS_LOGF_ERROR(
1007*3c7ae9deSAndroid Build Coastguard Worker                         AWS_LS_MQTT5_CLIENT,
1008*3c7ae9deSAndroid Build Coastguard Worker                         "Error when creating UnsubAckPacket from native: Could not set reason code");
1009*3c7ae9deSAndroid Build Coastguard Worker                     exception_error_code = AWS_ERROR_INVALID_STATE;
1010*3c7ae9deSAndroid Build Coastguard Worker                     goto exception;
1011*3c7ae9deSAndroid Build Coastguard Worker                 }
1012*3c7ae9deSAndroid Build Coastguard Worker             }
1013*3c7ae9deSAndroid Build Coastguard Worker         }
1014*3c7ae9deSAndroid Build Coastguard Worker     }
1015*3c7ae9deSAndroid Build Coastguard Worker 
1016*3c7ae9deSAndroid Build Coastguard Worker     if (s_set_user_properties_field(
1017*3c7ae9deSAndroid Build Coastguard Worker             env,
1018*3c7ae9deSAndroid Build Coastguard Worker             unsuback->user_property_count,
1019*3c7ae9deSAndroid Build Coastguard Worker             unsuback->user_properties,
1020*3c7ae9deSAndroid Build Coastguard Worker             unsuback_packet_data,
1021*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_unsuback_packet_properties.unsuback_user_properties_field_id) == AWS_OP_ERR) {
1022*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "When creating UnsubAckPacket from native could not add user property!");
1023*3c7ae9deSAndroid Build Coastguard Worker         exception_error_code = AWS_ERROR_INVALID_STATE;
1024*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1025*3c7ae9deSAndroid Build Coastguard Worker     }
1026*3c7ae9deSAndroid Build Coastguard Worker 
1027*3c7ae9deSAndroid Build Coastguard Worker     /* Complete the promise */
1028*3c7ae9deSAndroid Build Coastguard Worker     (*env)->CallBooleanMethod(
1029*3c7ae9deSAndroid Build Coastguard Worker         env, jni_unsubscribe_future, completable_future_properties.complete_method_id, unsuback_packet_data);
1030*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
1031*3c7ae9deSAndroid Build Coastguard Worker 
1032*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
1033*3c7ae9deSAndroid Build Coastguard Worker 
1034*3c7ae9deSAndroid Build Coastguard Worker exception:
1035*3c7ae9deSAndroid Build Coastguard Worker     s_complete_future_with_exception(env, &jni_unsubscribe_future, exception_error_code);
1036*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
1037*3c7ae9deSAndroid Build Coastguard Worker 
1038*3c7ae9deSAndroid Build Coastguard Worker clean_up:
1039*3c7ae9deSAndroid Build Coastguard Worker     s_aws_mqtt5_client_java_unsubscribe_callback_destructor(env, return_data);
1040*3c7ae9deSAndroid Build Coastguard Worker     if (env != NULL) {
1041*3c7ae9deSAndroid Build Coastguard Worker         if (has_pushed_frame) {
1042*3c7ae9deSAndroid Build Coastguard Worker             (*env)->PopLocalFrame(env, NULL);
1043*3c7ae9deSAndroid Build Coastguard Worker         }
1044*3c7ae9deSAndroid Build Coastguard Worker         /********** JNI ENV RELEASE **********/
1045*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_release_thread_env(jvm, env);
1046*3c7ae9deSAndroid Build Coastguard Worker     }
1047*3c7ae9deSAndroid Build Coastguard Worker }
1048*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_termination(void * complete_ctx)1049*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_termination(void *complete_ctx) {
1050*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)complete_ctx;
1051*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1052*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(
1053*3c7ae9deSAndroid Build Coastguard Worker             AWS_LS_MQTT5_CLIENT, "MQTT5 client termination function in JNI called, but with invalid java_client");
1054*3c7ae9deSAndroid Build Coastguard Worker         return;
1055*3c7ae9deSAndroid Build Coastguard Worker     }
1056*3c7ae9deSAndroid Build Coastguard Worker 
1057*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
1058*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = java_client->jvm;
1059*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = aws_jni_acquire_thread_env(jvm);
1060*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
1061*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
1062*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "MQTT5 client termination function in JNI called, but could not get env");
1063*3c7ae9deSAndroid Build Coastguard Worker         return;
1064*3c7ae9deSAndroid Build Coastguard Worker     }
1065*3c7ae9deSAndroid Build Coastguard Worker 
1066*3c7ae9deSAndroid Build Coastguard Worker     (*env)->CallVoidMethod(env, java_client->jni_client, crt_resource_properties.release_references);
1067*3c7ae9deSAndroid Build Coastguard Worker     java_client->client = NULL;
1068*3c7ae9deSAndroid Build Coastguard Worker 
1069*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
1070*3c7ae9deSAndroid Build Coastguard Worker     aws_mqtt5_client_java_destroy(env, allocator, java_client);
1071*3c7ae9deSAndroid Build Coastguard Worker 
1072*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE **********/
1073*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(jvm, env);
1074*3c7ae9deSAndroid Build Coastguard Worker }
1075*3c7ae9deSAndroid Build Coastguard Worker 
1076*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
1077*3c7ae9deSAndroid Build Coastguard Worker  * MQTT5 CLIENT FUNCTIONS
1078*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
1079*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalStart(JNIEnv * env,jclass jni_class,jlong jni_client)1080*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalStart(
1081*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1082*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1083*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client) {
1084*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1085*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1086*3c7ae9deSAndroid Build Coastguard Worker 
1087*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_client;
1088*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1089*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1090*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.start: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
1091*3c7ae9deSAndroid Build Coastguard Worker         return;
1092*3c7ae9deSAndroid Build Coastguard Worker     }
1093*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->client) {
1094*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1095*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.start: Invalid/null native client", AWS_ERROR_INVALID_ARGUMENT);
1096*3c7ae9deSAndroid Build Coastguard Worker         return;
1097*3c7ae9deSAndroid Build Coastguard Worker     }
1098*3c7ae9deSAndroid Build Coastguard Worker     int return_result = aws_mqtt5_client_start(java_client->client);
1099*3c7ae9deSAndroid Build Coastguard Worker 
1100*3c7ae9deSAndroid Build Coastguard Worker     if (return_result != AWS_OP_SUCCESS) {
1101*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1102*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.start: aws_mqtt5_client_start returned a non AWS_OP_SUCCESS code!", aws_last_error());
1103*3c7ae9deSAndroid Build Coastguard Worker     }
1104*3c7ae9deSAndroid Build Coastguard Worker }
1105*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalStop(JNIEnv * env,jclass jni_class,jlong jni_client,jobject jni_disconnect_packet)1106*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalStop(
1107*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1108*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1109*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client,
1110*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_disconnect_packet) {
1111*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1112*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1113*3c7ae9deSAndroid Build Coastguard Worker 
1114*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
1115*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_client;
1116*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1117*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1118*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.stop: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
1119*3c7ae9deSAndroid Build Coastguard Worker         return;
1120*3c7ae9deSAndroid Build Coastguard Worker     }
1121*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->client) {
1122*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1123*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.stop: Invalid/null native client", AWS_ERROR_INVALID_ARGUMENT);
1124*3c7ae9deSAndroid Build Coastguard Worker         return;
1125*3c7ae9deSAndroid Build Coastguard Worker     }
1126*3c7ae9deSAndroid Build Coastguard Worker 
1127*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_packet_disconnect_view_java_jni *java_disconnect_packet = NULL;
1128*3c7ae9deSAndroid Build Coastguard Worker     int return_result = AWS_OP_ERR;
1129*3c7ae9deSAndroid Build Coastguard Worker 
1130*3c7ae9deSAndroid Build Coastguard Worker     if (jni_disconnect_packet) {
1131*3c7ae9deSAndroid Build Coastguard Worker         java_disconnect_packet =
1132*3c7ae9deSAndroid Build Coastguard Worker             aws_mqtt5_packet_disconnect_view_create_from_java(env, allocator, jni_disconnect_packet);
1133*3c7ae9deSAndroid Build Coastguard Worker         if (!java_disconnect_packet) {
1134*3c7ae9deSAndroid Build Coastguard Worker             s_aws_mqtt5_client_log_and_throw_exception(
1135*3c7ae9deSAndroid Build Coastguard Worker                 env, "Mqtt5Client.stop: Invalid/null disconnect packet", aws_last_error());
1136*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
1137*3c7ae9deSAndroid Build Coastguard Worker         }
1138*3c7ae9deSAndroid Build Coastguard Worker     }
1139*3c7ae9deSAndroid Build Coastguard Worker 
1140*3c7ae9deSAndroid Build Coastguard Worker     return_result = aws_mqtt5_client_stop(
1141*3c7ae9deSAndroid Build Coastguard Worker         java_client->client, aws_mqtt5_packet_disconnect_view_get_packet(java_disconnect_packet), NULL);
1142*3c7ae9deSAndroid Build Coastguard Worker     if (return_result != AWS_OP_SUCCESS) {
1143*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1144*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.stop: aws_mqtt5_client_stop returned a non AWS_OP_SUCCESS code!", return_result);
1145*3c7ae9deSAndroid Build Coastguard Worker     }
1146*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
1147*3c7ae9deSAndroid Build Coastguard Worker 
1148*3c7ae9deSAndroid Build Coastguard Worker clean_up:
1149*3c7ae9deSAndroid Build Coastguard Worker     if (java_disconnect_packet) {
1150*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_disconnect_view_java_destroy(env, allocator, java_disconnect_packet);
1151*3c7ae9deSAndroid Build Coastguard Worker     }
1152*3c7ae9deSAndroid Build Coastguard Worker     return;
1153*3c7ae9deSAndroid Build Coastguard Worker }
1154*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalPublish(JNIEnv * env,jclass jni_class,jlong jni_client,jobject jni_publish_packet,jobject jni_publish_future)1155*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalPublish(
1156*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1157*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1158*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client,
1159*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_publish_packet,
1160*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_publish_future) {
1161*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1162*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1163*3c7ae9deSAndroid Build Coastguard Worker 
1164*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
1165*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_packet_publish_view_java_jni *java_publish_packet = NULL;
1166*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_publish_return_data *return_data = NULL;
1167*3c7ae9deSAndroid Build Coastguard Worker     int error_code = 0;
1168*3c7ae9deSAndroid Build Coastguard Worker 
1169*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_client;
1170*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1171*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1172*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.publish: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
1173*3c7ae9deSAndroid Build Coastguard Worker         return;
1174*3c7ae9deSAndroid Build Coastguard Worker     }
1175*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_publish_future) {
1176*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1177*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.publish: Invalid/null publish future", AWS_ERROR_INVALID_ARGUMENT);
1178*3c7ae9deSAndroid Build Coastguard Worker         return;
1179*3c7ae9deSAndroid Build Coastguard Worker     }
1180*3c7ae9deSAndroid Build Coastguard Worker 
1181*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->client) {
1182*3c7ae9deSAndroid Build Coastguard Worker         error_code = AWS_ERROR_INVALID_ARGUMENT;
1183*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.publish: Invalid/null native client");
1184*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1185*3c7ae9deSAndroid Build Coastguard Worker     }
1186*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_publish_packet) {
1187*3c7ae9deSAndroid Build Coastguard Worker         error_code = AWS_ERROR_INVALID_ARGUMENT;
1188*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.publish: Invalid/Null publish packet!");
1189*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1190*3c7ae9deSAndroid Build Coastguard Worker     }
1191*3c7ae9deSAndroid Build Coastguard Worker 
1192*3c7ae9deSAndroid Build Coastguard Worker     /* Cannot fail */
1193*3c7ae9deSAndroid Build Coastguard Worker     return_data = aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_client_publish_return_data));
1194*3c7ae9deSAndroid Build Coastguard Worker     return_data->java_client = java_client;
1195*3c7ae9deSAndroid Build Coastguard Worker     return_data->jni_publish_future = (*env)->NewGlobalRef(env, jni_publish_future);
1196*3c7ae9deSAndroid Build Coastguard Worker 
1197*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_publish_completion_options completion_options = {
1198*3c7ae9deSAndroid Build Coastguard Worker         .completion_callback = &s_aws_mqtt5_client_java_publish_completion,
1199*3c7ae9deSAndroid Build Coastguard Worker         .completion_user_data = return_data,
1200*3c7ae9deSAndroid Build Coastguard Worker     };
1201*3c7ae9deSAndroid Build Coastguard Worker 
1202*3c7ae9deSAndroid Build Coastguard Worker     java_publish_packet = aws_mqtt5_packet_publish_view_create_from_java(env, allocator, jni_publish_packet);
1203*3c7ae9deSAndroid Build Coastguard Worker     if (!java_publish_packet) {
1204*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1205*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.publish: Could not create native publish packet!");
1206*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1207*3c7ae9deSAndroid Build Coastguard Worker     }
1208*3c7ae9deSAndroid Build Coastguard Worker 
1209*3c7ae9deSAndroid Build Coastguard Worker     int return_result = aws_mqtt5_client_publish(
1210*3c7ae9deSAndroid Build Coastguard Worker         java_client->client, aws_mqtt5_packet_publish_view_get_packet(java_publish_packet), &completion_options);
1211*3c7ae9deSAndroid Build Coastguard Worker     if (return_result != AWS_OP_SUCCESS) {
1212*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1213*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(
1214*3c7ae9deSAndroid Build Coastguard Worker             AWS_LS_MQTT5_CLIENT, "Mqtt5Client.publish: Could not publish packet! Error code: %i", return_result);
1215*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1216*3c7ae9deSAndroid Build Coastguard Worker     }
1217*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
1218*3c7ae9deSAndroid Build Coastguard Worker 
1219*3c7ae9deSAndroid Build Coastguard Worker exception:
1220*3c7ae9deSAndroid Build Coastguard Worker     s_complete_future_with_exception(
1221*3c7ae9deSAndroid Build Coastguard Worker         env,
1222*3c7ae9deSAndroid Build Coastguard Worker         &jni_publish_future,
1223*3c7ae9deSAndroid Build Coastguard Worker         (error_code == AWS_ERROR_SUCCESS) ? AWS_ERROR_MQTT5_OPERATION_PROCESSING_FAILURE : error_code);
1224*3c7ae9deSAndroid Build Coastguard Worker     if (java_publish_packet) {
1225*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_publish_view_java_destroy(env, allocator, java_publish_packet);
1226*3c7ae9deSAndroid Build Coastguard Worker     }
1227*3c7ae9deSAndroid Build Coastguard Worker     if (return_data) {
1228*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_java_publish_callback_destructor(env, return_data);
1229*3c7ae9deSAndroid Build Coastguard Worker     }
1230*3c7ae9deSAndroid Build Coastguard Worker     return;
1231*3c7ae9deSAndroid Build Coastguard Worker 
1232*3c7ae9deSAndroid Build Coastguard Worker clean_up:
1233*3c7ae9deSAndroid Build Coastguard Worker     if (java_publish_packet) {
1234*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_publish_view_java_destroy(env, allocator, java_publish_packet);
1235*3c7ae9deSAndroid Build Coastguard Worker     }
1236*3c7ae9deSAndroid Build Coastguard Worker }
1237*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalSubscribe(JNIEnv * env,jclass jni_class,jlong jni_client,jobject jni_subscribe_packet,jobject jni_subscribe_future)1238*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalSubscribe(
1239*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1240*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1241*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client,
1242*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_subscribe_packet,
1243*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_subscribe_future) {
1244*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1245*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1246*3c7ae9deSAndroid Build Coastguard Worker 
1247*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
1248*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_subscribe_return_data *return_data = NULL;
1249*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_packet_subscribe_view_java_jni *java_subscribe_packet = NULL;
1250*3c7ae9deSAndroid Build Coastguard Worker     int error_code = AWS_ERROR_SUCCESS;
1251*3c7ae9deSAndroid Build Coastguard Worker 
1252*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_client;
1253*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1254*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1255*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.subscribe: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
1256*3c7ae9deSAndroid Build Coastguard Worker         return;
1257*3c7ae9deSAndroid Build Coastguard Worker     }
1258*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_subscribe_future) {
1259*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1260*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.subscribe: Invalid/null subscribe future", AWS_ERROR_INVALID_ARGUMENT);
1261*3c7ae9deSAndroid Build Coastguard Worker         return;
1262*3c7ae9deSAndroid Build Coastguard Worker     }
1263*3c7ae9deSAndroid Build Coastguard Worker 
1264*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->client) {
1265*3c7ae9deSAndroid Build Coastguard Worker         error_code = AWS_ERROR_INVALID_ARGUMENT;
1266*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.subscribe: Invalid/null native client");
1267*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1268*3c7ae9deSAndroid Build Coastguard Worker     }
1269*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_subscribe_packet) {
1270*3c7ae9deSAndroid Build Coastguard Worker         error_code = AWS_ERROR_INVALID_ARGUMENT;
1271*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.subscribe: Invalid/Null subscribe packet!");
1272*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1273*3c7ae9deSAndroid Build Coastguard Worker     }
1274*3c7ae9deSAndroid Build Coastguard Worker 
1275*3c7ae9deSAndroid Build Coastguard Worker     /* Cannot fail */
1276*3c7ae9deSAndroid Build Coastguard Worker     return_data = aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_client_subscribe_return_data));
1277*3c7ae9deSAndroid Build Coastguard Worker     return_data->java_client = java_client;
1278*3c7ae9deSAndroid Build Coastguard Worker     return_data->jni_subscribe_future = (*env)->NewGlobalRef(env, jni_subscribe_future);
1279*3c7ae9deSAndroid Build Coastguard Worker 
1280*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_subscribe_completion_options completion_options = {
1281*3c7ae9deSAndroid Build Coastguard Worker         .completion_callback = &s_aws_mqtt5_client_java_subscribe_completion,
1282*3c7ae9deSAndroid Build Coastguard Worker         .completion_user_data = return_data,
1283*3c7ae9deSAndroid Build Coastguard Worker     };
1284*3c7ae9deSAndroid Build Coastguard Worker 
1285*3c7ae9deSAndroid Build Coastguard Worker     java_subscribe_packet = aws_mqtt5_packet_subscribe_view_create_from_java(env, allocator, jni_subscribe_packet);
1286*3c7ae9deSAndroid Build Coastguard Worker     if (java_subscribe_packet == NULL) {
1287*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1288*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.subscribe: Could not create native subscribe packet!");
1289*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1290*3c7ae9deSAndroid Build Coastguard Worker     }
1291*3c7ae9deSAndroid Build Coastguard Worker 
1292*3c7ae9deSAndroid Build Coastguard Worker     int return_result = aws_mqtt5_client_subscribe(
1293*3c7ae9deSAndroid Build Coastguard Worker         java_client->client, aws_mqtt5_packet_subscribe_view_get_packet(java_subscribe_packet), &completion_options);
1294*3c7ae9deSAndroid Build Coastguard Worker     if (return_result != AWS_OP_SUCCESS) {
1295*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1296*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.subscribe: Subscribe failed! Error code: %i", return_result);
1297*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1298*3c7ae9deSAndroid Build Coastguard Worker     }
1299*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
1300*3c7ae9deSAndroid Build Coastguard Worker 
1301*3c7ae9deSAndroid Build Coastguard Worker exception:
1302*3c7ae9deSAndroid Build Coastguard Worker     s_complete_future_with_exception(
1303*3c7ae9deSAndroid Build Coastguard Worker         env,
1304*3c7ae9deSAndroid Build Coastguard Worker         &jni_subscribe_future,
1305*3c7ae9deSAndroid Build Coastguard Worker         (error_code == AWS_ERROR_SUCCESS) ? AWS_ERROR_MQTT5_OPERATION_PROCESSING_FAILURE : error_code);
1306*3c7ae9deSAndroid Build Coastguard Worker     if (java_subscribe_packet) {
1307*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_subscribe_view_java_destroy(env, allocator, java_subscribe_packet);
1308*3c7ae9deSAndroid Build Coastguard Worker     }
1309*3c7ae9deSAndroid Build Coastguard Worker     if (return_data) {
1310*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_java_subscribe_callback_destructor(env, return_data);
1311*3c7ae9deSAndroid Build Coastguard Worker     }
1312*3c7ae9deSAndroid Build Coastguard Worker     return;
1313*3c7ae9deSAndroid Build Coastguard Worker 
1314*3c7ae9deSAndroid Build Coastguard Worker clean_up:
1315*3c7ae9deSAndroid Build Coastguard Worker     if (java_subscribe_packet) {
1316*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_subscribe_view_java_destroy(env, allocator, java_subscribe_packet);
1317*3c7ae9deSAndroid Build Coastguard Worker     }
1318*3c7ae9deSAndroid Build Coastguard Worker }
1319*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalUnsubscribe(JNIEnv * env,jclass jni_class,jlong jni_client,jobject jni_unsubscribe_packet,jobject jni_unsubscribe_future)1320*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalUnsubscribe(
1321*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1322*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1323*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client,
1324*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_unsubscribe_packet,
1325*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_unsubscribe_future) {
1326*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1327*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1328*3c7ae9deSAndroid Build Coastguard Worker 
1329*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
1330*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_unsubscribe_return_data *return_data = NULL;
1331*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_packet_unsubscribe_view_java_jni *java_unsubscribe_packet = NULL;
1332*3c7ae9deSAndroid Build Coastguard Worker     int error_code = AWS_ERROR_SUCCESS;
1333*3c7ae9deSAndroid Build Coastguard Worker 
1334*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_client;
1335*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1336*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1337*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.unsubscribe: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
1338*3c7ae9deSAndroid Build Coastguard Worker         return;
1339*3c7ae9deSAndroid Build Coastguard Worker     }
1340*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_unsubscribe_future) {
1341*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1342*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.unsubscribe: Invalid/null unsubscribe future", AWS_ERROR_INVALID_ARGUMENT);
1343*3c7ae9deSAndroid Build Coastguard Worker         return;
1344*3c7ae9deSAndroid Build Coastguard Worker     }
1345*3c7ae9deSAndroid Build Coastguard Worker 
1346*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->client) {
1347*3c7ae9deSAndroid Build Coastguard Worker         error_code = AWS_ERROR_INVALID_ARGUMENT;
1348*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.unsubscribe: Invalid/null native client");
1349*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1350*3c7ae9deSAndroid Build Coastguard Worker     }
1351*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_unsubscribe_packet) {
1352*3c7ae9deSAndroid Build Coastguard Worker         error_code = AWS_ERROR_INVALID_ARGUMENT;
1353*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.unsubscribe: Invalid/Null unsubscribe packet!");
1354*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1355*3c7ae9deSAndroid Build Coastguard Worker     }
1356*3c7ae9deSAndroid Build Coastguard Worker 
1357*3c7ae9deSAndroid Build Coastguard Worker     /* Cannot fail */
1358*3c7ae9deSAndroid Build Coastguard Worker     return_data = aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_client_unsubscribe_return_data));
1359*3c7ae9deSAndroid Build Coastguard Worker     return_data->java_client = java_client;
1360*3c7ae9deSAndroid Build Coastguard Worker     return_data->jni_unsubscribe_future = (*env)->NewGlobalRef(env, jni_unsubscribe_future);
1361*3c7ae9deSAndroid Build Coastguard Worker 
1362*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_unsubscribe_completion_options completion_options = {
1363*3c7ae9deSAndroid Build Coastguard Worker         .completion_callback = &s_aws_mqtt5_client_java_unsubscribe_completion,
1364*3c7ae9deSAndroid Build Coastguard Worker         .completion_user_data = return_data,
1365*3c7ae9deSAndroid Build Coastguard Worker     };
1366*3c7ae9deSAndroid Build Coastguard Worker 
1367*3c7ae9deSAndroid Build Coastguard Worker     java_unsubscribe_packet =
1368*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_unsubscribe_view_create_from_java(env, allocator, jni_unsubscribe_packet);
1369*3c7ae9deSAndroid Build Coastguard Worker     if (!java_unsubscribe_packet) {
1370*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1371*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Mqtt5Client.unsubscribe: Could not create native unsubscribe packet!");
1372*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1373*3c7ae9deSAndroid Build Coastguard Worker     }
1374*3c7ae9deSAndroid Build Coastguard Worker 
1375*3c7ae9deSAndroid Build Coastguard Worker     int return_result = aws_mqtt5_client_unsubscribe(
1376*3c7ae9deSAndroid Build Coastguard Worker         java_client->client,
1377*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_unsubscribe_view_get_packet(java_unsubscribe_packet),
1378*3c7ae9deSAndroid Build Coastguard Worker         &completion_options);
1379*3c7ae9deSAndroid Build Coastguard Worker     if (return_result != AWS_OP_SUCCESS) {
1380*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1381*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(
1382*3c7ae9deSAndroid Build Coastguard Worker             AWS_LS_MQTT5_CLIENT, "Mqtt5Client.unsubscribe: Unsubscribe failed! Error code: %i", return_result);
1383*3c7ae9deSAndroid Build Coastguard Worker         goto exception;
1384*3c7ae9deSAndroid Build Coastguard Worker     }
1385*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
1386*3c7ae9deSAndroid Build Coastguard Worker 
1387*3c7ae9deSAndroid Build Coastguard Worker exception:
1388*3c7ae9deSAndroid Build Coastguard Worker     s_complete_future_with_exception(
1389*3c7ae9deSAndroid Build Coastguard Worker         env,
1390*3c7ae9deSAndroid Build Coastguard Worker         &jni_unsubscribe_future,
1391*3c7ae9deSAndroid Build Coastguard Worker         (error_code == AWS_ERROR_SUCCESS) ? AWS_ERROR_MQTT5_OPERATION_PROCESSING_FAILURE : error_code);
1392*3c7ae9deSAndroid Build Coastguard Worker     if (java_unsubscribe_packet) {
1393*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_unsubscribe_view_java_destroy(env, allocator, java_unsubscribe_packet);
1394*3c7ae9deSAndroid Build Coastguard Worker     }
1395*3c7ae9deSAndroid Build Coastguard Worker     if (return_data) {
1396*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_java_unsubscribe_callback_destructor(env, return_data);
1397*3c7ae9deSAndroid Build Coastguard Worker     }
1398*3c7ae9deSAndroid Build Coastguard Worker     return;
1399*3c7ae9deSAndroid Build Coastguard Worker 
1400*3c7ae9deSAndroid Build Coastguard Worker clean_up:
1401*3c7ae9deSAndroid Build Coastguard Worker     if (java_unsubscribe_packet) {
1402*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_packet_unsubscribe_view_java_destroy(env, allocator, java_unsubscribe_packet);
1403*3c7ae9deSAndroid Build Coastguard Worker     }
1404*3c7ae9deSAndroid Build Coastguard Worker }
1405*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalGetOperationStatistics(JNIEnv * env,jclass jni_class,jlong jni_client)1406*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jobject JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalGetOperationStatistics(
1407*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1408*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1409*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client) {
1410*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1411*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1412*3c7ae9deSAndroid Build Coastguard Worker 
1413*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_client;
1414*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1415*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1416*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.getOperationStatistics: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
1417*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1418*3c7ae9deSAndroid Build Coastguard Worker     }
1419*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->client) {
1420*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1421*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.getOperationStatistics: Invalid/null native client", AWS_ERROR_INVALID_ARGUMENT);
1422*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1423*3c7ae9deSAndroid Build Coastguard Worker     }
1424*3c7ae9deSAndroid Build Coastguard Worker 
1425*3c7ae9deSAndroid Build Coastguard Worker     /* Construct Java object */
1426*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_operation_statistics = (*env)->NewObject(
1427*3c7ae9deSAndroid Build Coastguard Worker         env,
1428*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_client_operation_statistics_properties.statistics_class,
1429*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_client_operation_statistics_properties.statistics_constructor_id);
1430*3c7ae9deSAndroid Build Coastguard Worker     if (jni_operation_statistics == NULL) {
1431*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1432*3c7ae9deSAndroid Build Coastguard Worker     }
1433*3c7ae9deSAndroid Build Coastguard Worker 
1434*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_operation_statistics client_stats;
1435*3c7ae9deSAndroid Build Coastguard Worker     aws_mqtt5_client_get_stats(java_client->client, &client_stats);
1436*3c7ae9deSAndroid Build Coastguard Worker 
1437*3c7ae9deSAndroid Build Coastguard Worker     (*env)->SetLongField(
1438*3c7ae9deSAndroid Build Coastguard Worker         env,
1439*3c7ae9deSAndroid Build Coastguard Worker         jni_operation_statistics,
1440*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_client_operation_statistics_properties.incomplete_operation_count_field_id,
1441*3c7ae9deSAndroid Build Coastguard Worker         (jlong)client_stats.incomplete_operation_count);
1442*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1443*3c7ae9deSAndroid Build Coastguard Worker         aws_raise_error(AWS_ERROR_INVALID_STATE);
1444*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(
1445*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.getOperationStatistics: could not create incomplete operation count");
1446*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1447*3c7ae9deSAndroid Build Coastguard Worker     }
1448*3c7ae9deSAndroid Build Coastguard Worker 
1449*3c7ae9deSAndroid Build Coastguard Worker     (*env)->SetLongField(
1450*3c7ae9deSAndroid Build Coastguard Worker         env,
1451*3c7ae9deSAndroid Build Coastguard Worker         jni_operation_statistics,
1452*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_client_operation_statistics_properties.incomplete_operation_size_field_id,
1453*3c7ae9deSAndroid Build Coastguard Worker         (jlong)client_stats.incomplete_operation_size);
1454*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1455*3c7ae9deSAndroid Build Coastguard Worker         aws_raise_error(AWS_ERROR_INVALID_STATE);
1456*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(
1457*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.getOperationStatistics: could not create incomplete operation size");
1458*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1459*3c7ae9deSAndroid Build Coastguard Worker     }
1460*3c7ae9deSAndroid Build Coastguard Worker 
1461*3c7ae9deSAndroid Build Coastguard Worker     (*env)->SetLongField(
1462*3c7ae9deSAndroid Build Coastguard Worker         env,
1463*3c7ae9deSAndroid Build Coastguard Worker         jni_operation_statistics,
1464*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_client_operation_statistics_properties.unacked_operation_count_field_id,
1465*3c7ae9deSAndroid Build Coastguard Worker         (jlong)client_stats.unacked_operation_count);
1466*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1467*3c7ae9deSAndroid Build Coastguard Worker         aws_raise_error(AWS_ERROR_INVALID_STATE);
1468*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(
1469*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.getOperationStatistics: could not create unacked operation count");
1470*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1471*3c7ae9deSAndroid Build Coastguard Worker     }
1472*3c7ae9deSAndroid Build Coastguard Worker 
1473*3c7ae9deSAndroid Build Coastguard Worker     (*env)->SetLongField(
1474*3c7ae9deSAndroid Build Coastguard Worker         env,
1475*3c7ae9deSAndroid Build Coastguard Worker         jni_operation_statistics,
1476*3c7ae9deSAndroid Build Coastguard Worker         mqtt5_client_operation_statistics_properties.unacked_operation_size_field_id,
1477*3c7ae9deSAndroid Build Coastguard Worker         (jlong)client_stats.unacked_operation_size);
1478*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1479*3c7ae9deSAndroid Build Coastguard Worker         aws_raise_error(AWS_ERROR_INVALID_STATE);
1480*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(
1481*3c7ae9deSAndroid Build Coastguard Worker             env, "Mqtt5Client.getOperationStatistics: could not create unacked operation size");
1482*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
1483*3c7ae9deSAndroid Build Coastguard Worker     }
1484*3c7ae9deSAndroid Build Coastguard Worker 
1485*3c7ae9deSAndroid Build Coastguard Worker     return jni_operation_statistics;
1486*3c7ae9deSAndroid Build Coastguard Worker }
1487*3c7ae9deSAndroid Build Coastguard Worker 
1488*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
1489*3c7ae9deSAndroid Build Coastguard Worker  * WEBSOCKET FUNCTIONS
1490*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
1491*3c7ae9deSAndroid Build Coastguard Worker struct mqtt5_jni_ws_handshake {
1492*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client;
1493*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_message *http_request;
1494*3c7ae9deSAndroid Build Coastguard Worker     aws_mqtt5_transform_websocket_handshake_complete_fn *complete_fn;
1495*3c7ae9deSAndroid Build Coastguard Worker     void *complete_ctx;
1496*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator;
1497*3c7ae9deSAndroid Build Coastguard Worker };
1498*3c7ae9deSAndroid Build Coastguard Worker 
s_ws_handshake_destroy(struct mqtt5_jni_ws_handshake * ws_handshake)1499*3c7ae9deSAndroid Build Coastguard Worker static void s_ws_handshake_destroy(struct mqtt5_jni_ws_handshake *ws_handshake) {
1500*3c7ae9deSAndroid Build Coastguard Worker     if (!ws_handshake) {
1501*3c7ae9deSAndroid Build Coastguard Worker         return;
1502*3c7ae9deSAndroid Build Coastguard Worker     }
1503*3c7ae9deSAndroid Build Coastguard Worker     aws_mem_release(ws_handshake->allocator, ws_handshake);
1504*3c7ae9deSAndroid Build Coastguard Worker }
1505*3c7ae9deSAndroid Build Coastguard Worker 
s_aws_mqtt5_client_java_websocket_handshake_transform(struct aws_http_message * request,void * user_data,aws_mqtt5_transform_websocket_handshake_complete_fn * complete_fn,void * complete_ctx)1506*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_mqtt5_client_java_websocket_handshake_transform(
1507*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_message *request,
1508*3c7ae9deSAndroid Build Coastguard Worker     void *user_data,
1509*3c7ae9deSAndroid Build Coastguard Worker     aws_mqtt5_transform_websocket_handshake_complete_fn *complete_fn,
1510*3c7ae9deSAndroid Build Coastguard Worker     void *complete_ctx) {
1511*3c7ae9deSAndroid Build Coastguard Worker 
1512*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)user_data;
1513*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
1514*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Websocket handshake function in JNI called without valid client");
1515*3c7ae9deSAndroid Build Coastguard Worker         return;
1516*3c7ae9deSAndroid Build Coastguard Worker     }
1517*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client->jni_client || !java_client->client) {
1518*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Websocket handshake function in JNI called with already freed client");
1519*3c7ae9deSAndroid Build Coastguard Worker         return;
1520*3c7ae9deSAndroid Build Coastguard Worker     }
1521*3c7ae9deSAndroid Build Coastguard Worker 
1522*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
1523*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = aws_jni_acquire_thread_env(java_client->jvm);
1524*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
1525*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
1526*3c7ae9deSAndroid Build Coastguard Worker         complete_fn(request, AWS_ERROR_INVALID_STATE, complete_ctx);
1527*3c7ae9deSAndroid Build Coastguard Worker         return;
1528*3c7ae9deSAndroid Build Coastguard Worker     }
1529*3c7ae9deSAndroid Build Coastguard Worker 
1530*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *alloc = aws_jni_get_allocator();
1531*3c7ae9deSAndroid Build Coastguard Worker 
1532*3c7ae9deSAndroid Build Coastguard Worker     /* Cannot fail */
1533*3c7ae9deSAndroid Build Coastguard Worker     struct mqtt5_jni_ws_handshake *ws_handshake = aws_mem_calloc(alloc, 1, sizeof(struct mqtt5_jni_ws_handshake));
1534*3c7ae9deSAndroid Build Coastguard Worker 
1535*3c7ae9deSAndroid Build Coastguard Worker     ws_handshake->java_client = java_client;
1536*3c7ae9deSAndroid Build Coastguard Worker     ws_handshake->complete_ctx = complete_ctx;
1537*3c7ae9deSAndroid Build Coastguard Worker     ws_handshake->complete_fn = complete_fn;
1538*3c7ae9deSAndroid Build Coastguard Worker     ws_handshake->http_request = request;
1539*3c7ae9deSAndroid Build Coastguard Worker     ws_handshake->allocator = alloc;
1540*3c7ae9deSAndroid Build Coastguard Worker 
1541*3c7ae9deSAndroid Build Coastguard Worker     jobject java_http_request = aws_java_http_request_from_native(env, request, NULL);
1542*3c7ae9deSAndroid Build Coastguard Worker     if (!java_http_request) {
1543*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not create a HttpRequest for Java in MQTT5 client");
1544*3c7ae9deSAndroid Build Coastguard Worker         aws_raise_error(AWS_ERROR_UNKNOWN);
1545*3c7ae9deSAndroid Build Coastguard Worker         goto error;
1546*3c7ae9deSAndroid Build Coastguard Worker     }
1547*3c7ae9deSAndroid Build Coastguard Worker 
1548*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->jni_client) {
1549*3c7ae9deSAndroid Build Coastguard Worker         jobject jni_client = java_client->jni_client;
1550*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallVoidMethod(
1551*3c7ae9deSAndroid Build Coastguard Worker             env, jni_client, mqtt5_client_properties.client_on_websocket_handshake_id, java_http_request, ws_handshake);
1552*3c7ae9deSAndroid Build Coastguard Worker         AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
1553*3c7ae9deSAndroid Build Coastguard Worker     }
1554*3c7ae9deSAndroid Build Coastguard Worker 
1555*3c7ae9deSAndroid Build Coastguard Worker     (*env)->DeleteLocalRef(env, java_http_request);
1556*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(java_client->jvm, env);
1557*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE SUCCESS PATH **********/
1558*3c7ae9deSAndroid Build Coastguard Worker 
1559*3c7ae9deSAndroid Build Coastguard Worker     return;
1560*3c7ae9deSAndroid Build Coastguard Worker 
1561*3c7ae9deSAndroid Build Coastguard Worker error:;
1562*3c7ae9deSAndroid Build Coastguard Worker     int error_code = aws_last_error();
1563*3c7ae9deSAndroid Build Coastguard Worker     s_ws_handshake_destroy(ws_handshake);
1564*3c7ae9deSAndroid Build Coastguard Worker     complete_fn(request, error_code, complete_ctx);
1565*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(java_client->jvm, env);
1566*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE FAILURE PATH **********/
1567*3c7ae9deSAndroid Build Coastguard Worker }
1568*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalWebsocketHandshakeComplete(JNIEnv * env,jclass jni_class,jlong jni_connection,jbyteArray jni_marshalled_request,jobject jni_throwable,jlong jni_user_data)1569*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientInternalWebsocketHandshakeComplete(
1570*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1571*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1572*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_connection,
1573*3c7ae9deSAndroid Build Coastguard Worker     jbyteArray jni_marshalled_request,
1574*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_throwable,
1575*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_user_data) {
1576*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1577*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_connection;
1578*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1579*3c7ae9deSAndroid Build Coastguard Worker 
1580*3c7ae9deSAndroid Build Coastguard Worker     struct mqtt5_jni_ws_handshake *ws_handshake = (void *)jni_user_data;
1581*3c7ae9deSAndroid Build Coastguard Worker     int error_code = AWS_ERROR_SUCCESS;
1582*3c7ae9deSAndroid Build Coastguard Worker 
1583*3c7ae9deSAndroid Build Coastguard Worker     if (!ws_handshake) {
1584*3c7ae9deSAndroid Build Coastguard Worker         AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Websocket handshake complete function in JNI called without handshake");
1585*3c7ae9deSAndroid Build Coastguard Worker         return;
1586*3c7ae9deSAndroid Build Coastguard Worker     }
1587*3c7ae9deSAndroid Build Coastguard Worker 
1588*3c7ae9deSAndroid Build Coastguard Worker     if (jni_throwable != NULL) {
1589*3c7ae9deSAndroid Build Coastguard Worker         if ((*env)->IsInstanceOf(env, jni_throwable, crt_runtime_exception_properties.crt_runtime_exception_class)) {
1590*3c7ae9deSAndroid Build Coastguard Worker             error_code = (*env)->GetIntField(env, jni_throwable, crt_runtime_exception_properties.error_code_field_id);
1591*3c7ae9deSAndroid Build Coastguard Worker         }
1592*3c7ae9deSAndroid Build Coastguard Worker         if (error_code == AWS_ERROR_SUCCESS) {
1593*3c7ae9deSAndroid Build Coastguard Worker             error_code = AWS_ERROR_UNKNOWN; /* is there anything more that could be done here? */
1594*3c7ae9deSAndroid Build Coastguard Worker         }
1595*3c7ae9deSAndroid Build Coastguard Worker         goto done;
1596*3c7ae9deSAndroid Build Coastguard Worker     }
1597*3c7ae9deSAndroid Build Coastguard Worker 
1598*3c7ae9deSAndroid Build Coastguard Worker     if (aws_apply_java_http_request_changes_to_native_request(
1599*3c7ae9deSAndroid Build Coastguard Worker             env, jni_marshalled_request, NULL, ws_handshake->http_request)) {
1600*3c7ae9deSAndroid Build Coastguard Worker         error_code = aws_last_error();
1601*3c7ae9deSAndroid Build Coastguard Worker         goto done;
1602*3c7ae9deSAndroid Build Coastguard Worker     }
1603*3c7ae9deSAndroid Build Coastguard Worker 
1604*3c7ae9deSAndroid Build Coastguard Worker done:
1605*3c7ae9deSAndroid Build Coastguard Worker     ws_handshake->complete_fn(ws_handshake->http_request, error_code, ws_handshake->complete_ctx);
1606*3c7ae9deSAndroid Build Coastguard Worker     s_ws_handshake_destroy(ws_handshake);
1607*3c7ae9deSAndroid Build Coastguard Worker }
1608*3c7ae9deSAndroid Build Coastguard Worker 
s_initialize_topic_aliasing_options(JNIEnv * env,struct aws_mqtt5_client_topic_alias_options * topic_aliasing_options,jobject jni_topic_aliasing_options)1609*3c7ae9deSAndroid Build Coastguard Worker static int s_initialize_topic_aliasing_options(
1610*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1611*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_topic_alias_options *topic_aliasing_options,
1612*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_topic_aliasing_options) {
1613*3c7ae9deSAndroid Build Coastguard Worker 
1614*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_outbound_behavior = (*env)->GetObjectField(
1615*3c7ae9deSAndroid Build Coastguard Worker         env, jni_topic_aliasing_options, mqtt5_topic_aliasing_options_properties.outbound_behavior_field_id);
1616*3c7ae9deSAndroid Build Coastguard Worker     if (jni_outbound_behavior != NULL) {
1617*3c7ae9deSAndroid Build Coastguard Worker         jint enum_value = (*env)->CallIntMethod(
1618*3c7ae9deSAndroid Build Coastguard Worker             env, jni_outbound_behavior, mqtt5_outbound_topic_alias_behavior_type_properties.get_value_method_id);
1619*3c7ae9deSAndroid Build Coastguard Worker         if (aws_jni_check_and_clear_exception(env)) {
1620*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error getting native value from OutboundTopicAliasBehaviorType");
1621*3c7ae9deSAndroid Build Coastguard Worker             return aws_raise_error(AWS_ERROR_INVALID_STATE);
1622*3c7ae9deSAndroid Build Coastguard Worker         }
1623*3c7ae9deSAndroid Build Coastguard Worker 
1624*3c7ae9deSAndroid Build Coastguard Worker         topic_aliasing_options->outbound_topic_alias_behavior =
1625*3c7ae9deSAndroid Build Coastguard Worker             (enum aws_mqtt5_client_outbound_topic_alias_behavior_type)enum_value;
1626*3c7ae9deSAndroid Build Coastguard Worker     }
1627*3c7ae9deSAndroid Build Coastguard Worker 
1628*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_outbound_cache_max_size = (*env)->GetObjectField(
1629*3c7ae9deSAndroid Build Coastguard Worker         env, jni_topic_aliasing_options, mqtt5_topic_aliasing_options_properties.outbound_cache_max_size_field_id);
1630*3c7ae9deSAndroid Build Coastguard Worker     if (jni_outbound_cache_max_size != NULL) {
1631*3c7ae9deSAndroid Build Coastguard Worker         jint int_value =
1632*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallIntMethod(env, jni_outbound_cache_max_size, boxed_integer_properties.integer_get_value_id);
1633*3c7ae9deSAndroid Build Coastguard Worker 
1634*3c7ae9deSAndroid Build Coastguard Worker         if (int_value < 0 || int_value > UINT16_MAX) {
1635*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Invalid outbound cache size value: %d", int_value);
1636*3c7ae9deSAndroid Build Coastguard Worker             return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
1637*3c7ae9deSAndroid Build Coastguard Worker         }
1638*3c7ae9deSAndroid Build Coastguard Worker 
1639*3c7ae9deSAndroid Build Coastguard Worker         topic_aliasing_options->outbound_alias_cache_max_size = (uint16_t)int_value;
1640*3c7ae9deSAndroid Build Coastguard Worker     }
1641*3c7ae9deSAndroid Build Coastguard Worker 
1642*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_inbound_behavior = (*env)->GetObjectField(
1643*3c7ae9deSAndroid Build Coastguard Worker         env, jni_topic_aliasing_options, mqtt5_topic_aliasing_options_properties.inbound_behavior_field_id);
1644*3c7ae9deSAndroid Build Coastguard Worker     if (jni_inbound_behavior != NULL) {
1645*3c7ae9deSAndroid Build Coastguard Worker         jint enum_value = (*env)->CallIntMethod(
1646*3c7ae9deSAndroid Build Coastguard Worker             env, jni_inbound_behavior, mqtt5_inbound_topic_alias_behavior_type_properties.get_value_method_id);
1647*3c7ae9deSAndroid Build Coastguard Worker         if (aws_jni_check_and_clear_exception(env)) {
1648*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error getting native value from InboundTopicAliasBehaviorType");
1649*3c7ae9deSAndroid Build Coastguard Worker             return aws_raise_error(AWS_ERROR_INVALID_STATE);
1650*3c7ae9deSAndroid Build Coastguard Worker         }
1651*3c7ae9deSAndroid Build Coastguard Worker 
1652*3c7ae9deSAndroid Build Coastguard Worker         topic_aliasing_options->inbound_topic_alias_behavior =
1653*3c7ae9deSAndroid Build Coastguard Worker             (enum aws_mqtt5_client_inbound_topic_alias_behavior_type)enum_value;
1654*3c7ae9deSAndroid Build Coastguard Worker     }
1655*3c7ae9deSAndroid Build Coastguard Worker 
1656*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_inbound_cache_max_size = (*env)->GetObjectField(
1657*3c7ae9deSAndroid Build Coastguard Worker         env, jni_topic_aliasing_options, mqtt5_topic_aliasing_options_properties.inbound_cache_max_size_field_id);
1658*3c7ae9deSAndroid Build Coastguard Worker     if (jni_inbound_cache_max_size != NULL) {
1659*3c7ae9deSAndroid Build Coastguard Worker         jint int_value =
1660*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallIntMethod(env, jni_inbound_cache_max_size, boxed_integer_properties.integer_get_value_id);
1661*3c7ae9deSAndroid Build Coastguard Worker 
1662*3c7ae9deSAndroid Build Coastguard Worker         if (int_value < 0 || int_value > UINT16_MAX) {
1663*3c7ae9deSAndroid Build Coastguard Worker             AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Invalid inbound cache size value: %d", int_value);
1664*3c7ae9deSAndroid Build Coastguard Worker             return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
1665*3c7ae9deSAndroid Build Coastguard Worker         }
1666*3c7ae9deSAndroid Build Coastguard Worker 
1667*3c7ae9deSAndroid Build Coastguard Worker         topic_aliasing_options->inbound_alias_cache_size = (uint16_t)int_value;
1668*3c7ae9deSAndroid Build Coastguard Worker     }
1669*3c7ae9deSAndroid Build Coastguard Worker 
1670*3c7ae9deSAndroid Build Coastguard Worker     return AWS_OP_SUCCESS;
1671*3c7ae9deSAndroid Build Coastguard Worker }
1672*3c7ae9deSAndroid Build Coastguard Worker 
1673*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
1674*3c7ae9deSAndroid Build Coastguard Worker  * JNI FUNCTIONS
1675*3c7ae9deSAndroid Build Coastguard Worker  ******************************************************************************/
1676*3c7ae9deSAndroid Build Coastguard Worker 
1677*3c7ae9deSAndroid Build Coastguard Worker /* Create and Destroy
1678*3c7ae9deSAndroid Build Coastguard Worker **************************************/
1679*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientNew(JNIEnv * env,jclass jni_class,jobject jni_options,jobject jni_connect_options,jobject jni_bootstrap,jobject jni_client)1680*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientNew(
1681*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
1682*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
1683*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_options,
1684*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_connect_options,
1685*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_bootstrap,
1686*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_client) {
1687*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
1688*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
1689*3c7ae9deSAndroid Build Coastguard Worker 
1690*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
1691*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_packet_connect_view_java_jni *connect_options = NULL;
1692*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_options client_options;
1693*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(client_options);
1694*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_proxy_options_java_jni *java_http_proxy_options = NULL;
1695*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_buf host_name_buf;
1696*3c7ae9deSAndroid Build Coastguard Worker 
1697*3c7ae9deSAndroid Build Coastguard Worker     /* Needed to track if optionals are set or not */
1698*3c7ae9deSAndroid Build Coastguard Worker     bool was_value_set = false;
1699*3c7ae9deSAndroid Build Coastguard Worker 
1700*3c7ae9deSAndroid Build Coastguard Worker     /**
1701*3c7ae9deSAndroid Build Coastguard Worker      * Push a new local frame so any local allocations we make are tied to it. Then we can pop it to free memory.
1702*3c7ae9deSAndroid Build Coastguard Worker      * In Java JNI allocations here, we have 21 allocations so we need at least that many.
1703*3c7ae9deSAndroid Build Coastguard Worker      * It should expand if we use more.
1704*3c7ae9deSAndroid Build Coastguard Worker      * (NOTE: We cannot get the exact here because we are pulling from Java objects and we have no way to know how many
1705*3c7ae9deSAndroid Build Coastguard Worker      * that will need)
1706*3c7ae9deSAndroid Build Coastguard Worker      */
1707*3c7ae9deSAndroid Build Coastguard Worker     jint local_frame_result = (*env)->PushLocalFrame(env, (jint)21);
1708*3c7ae9deSAndroid Build Coastguard Worker     if (local_frame_result != 0) {
1709*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1710*3c7ae9deSAndroid Build Coastguard Worker             env,
1711*3c7ae9deSAndroid Build Coastguard Worker             "MQTT5 client new: could not push local JNI frame with 21 allocation minimum",
1712*3c7ae9deSAndroid Build Coastguard Worker             AWS_ERROR_INVALID_STATE);
1713*3c7ae9deSAndroid Build Coastguard Worker         return (jlong)NULL;
1714*3c7ae9deSAndroid Build Coastguard Worker     }
1715*3c7ae9deSAndroid Build Coastguard Worker 
1716*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client =
1717*3c7ae9deSAndroid Build Coastguard Worker         aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_client_java_jni));
1718*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "java_client=%p: Initializing MQTT5 client", (void *)java_client);
1719*3c7ae9deSAndroid Build Coastguard Worker     if (java_client == NULL) {
1720*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1721*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: could not initialize new client", AWS_ERROR_INVALID_STATE);
1722*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1723*3c7ae9deSAndroid Build Coastguard Worker     }
1724*3c7ae9deSAndroid Build Coastguard Worker 
1725*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_string_from_jobject(
1726*3c7ae9deSAndroid Build Coastguard Worker             env,
1727*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1728*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.options_host_name_field_id,
1729*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1730*3c7ae9deSAndroid Build Coastguard Worker             "Host Name",
1731*3c7ae9deSAndroid Build Coastguard Worker             &host_name_buf,
1732*3c7ae9deSAndroid Build Coastguard Worker             &client_options.host_name,
1733*3c7ae9deSAndroid Build Coastguard Worker             false,
1734*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
1735*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1736*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get host name from options", AWS_ERROR_INVALID_STATE);
1737*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1738*3c7ae9deSAndroid Build Coastguard Worker     }
1739*3c7ae9deSAndroid Build Coastguard Worker 
1740*3c7ae9deSAndroid Build Coastguard Worker     uint32_t port = 0;
1741*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint32_from_jobject(
1742*3c7ae9deSAndroid Build Coastguard Worker             env,
1743*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1744*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.options_port_field_id,
1745*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1746*3c7ae9deSAndroid Build Coastguard Worker             "port",
1747*3c7ae9deSAndroid Build Coastguard Worker             &port,
1748*3c7ae9deSAndroid Build Coastguard Worker             false,
1749*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
1750*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1751*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get port from options", AWS_ERROR_INVALID_STATE);
1752*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1753*3c7ae9deSAndroid Build Coastguard Worker     }
1754*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1755*3c7ae9deSAndroid Build Coastguard Worker         client_options.port = port;
1756*3c7ae9deSAndroid Build Coastguard Worker     }
1757*3c7ae9deSAndroid Build Coastguard Worker 
1758*3c7ae9deSAndroid Build Coastguard Worker     if (!jni_bootstrap) {
1759*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1760*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: no bootstrap found", AWS_ERROR_INVALID_ARGUMENT);
1761*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1762*3c7ae9deSAndroid Build Coastguard Worker     }
1763*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_bootstrap_pointer =
1764*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallLongMethod(env, jni_bootstrap, crt_resource_properties.get_native_handle_method_id);
1765*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1766*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1767*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: could not get native handle for bootstrap", AWS_ERROR_INVALID_ARGUMENT);
1768*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1769*3c7ae9deSAndroid Build Coastguard Worker     }
1770*3c7ae9deSAndroid Build Coastguard Worker     struct aws_client_bootstrap *bootstrap = (struct aws_client_bootstrap *)jni_bootstrap_pointer;
1771*3c7ae9deSAndroid Build Coastguard Worker     client_options.bootstrap = bootstrap;
1772*3c7ae9deSAndroid Build Coastguard Worker 
1773*3c7ae9deSAndroid Build Coastguard Worker     struct aws_socket_options *socket_options = NULL;
1774*3c7ae9deSAndroid Build Coastguard Worker     struct aws_socket_options tmp_socket_options;
1775*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_socket_options =
1776*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallObjectMethod(env, jni_options, mqtt5_client_options_properties.options_get_socket_options_id);
1777*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1778*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1779*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: error getting socket options", AWS_ERROR_INVALID_STATE);
1780*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1781*3c7ae9deSAndroid Build Coastguard Worker     }
1782*3c7ae9deSAndroid Build Coastguard Worker     if (jni_socket_options) {
1783*3c7ae9deSAndroid Build Coastguard Worker         jlong jni_socket_options_pointer =
1784*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallLongMethod(env, jni_socket_options, crt_resource_properties.get_native_handle_method_id);
1785*3c7ae9deSAndroid Build Coastguard Worker         if (aws_jni_check_and_clear_exception(env)) {
1786*3c7ae9deSAndroid Build Coastguard Worker             s_aws_mqtt5_client_log_and_throw_exception(
1787*3c7ae9deSAndroid Build Coastguard Worker                 env, "MQTT5 client new: could not get native handle for socket options", AWS_ERROR_INVALID_ARGUMENT);
1788*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
1789*3c7ae9deSAndroid Build Coastguard Worker         }
1790*3c7ae9deSAndroid Build Coastguard Worker         socket_options = (struct aws_socket_options *)jni_socket_options_pointer;
1791*3c7ae9deSAndroid Build Coastguard Worker     }
1792*3c7ae9deSAndroid Build Coastguard Worker     if (socket_options == NULL) {
1793*3c7ae9deSAndroid Build Coastguard Worker         tmp_socket_options.type = AWS_SOCKET_STREAM;
1794*3c7ae9deSAndroid Build Coastguard Worker         tmp_socket_options.domain = AWS_SOCKET_IPV4;
1795*3c7ae9deSAndroid Build Coastguard Worker         tmp_socket_options.connect_timeout_ms = 10000;
1796*3c7ae9deSAndroid Build Coastguard Worker         client_options.socket_options = &tmp_socket_options;
1797*3c7ae9deSAndroid Build Coastguard Worker     } else {
1798*3c7ae9deSAndroid Build Coastguard Worker         client_options.socket_options = socket_options;
1799*3c7ae9deSAndroid Build Coastguard Worker     }
1800*3c7ae9deSAndroid Build Coastguard Worker 
1801*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_tls_options =
1802*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallObjectMethod(env, jni_options, mqtt5_client_options_properties.options_get_tls_options_id);
1803*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1804*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1805*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: error getting tls options", AWS_ERROR_INVALID_STATE);
1806*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1807*3c7ae9deSAndroid Build Coastguard Worker     }
1808*3c7ae9deSAndroid Build Coastguard Worker     if (jni_tls_options) {
1809*3c7ae9deSAndroid Build Coastguard Worker         jlong jni_tls_pointer =
1810*3c7ae9deSAndroid Build Coastguard Worker             (*env)->CallLongMethod(env, jni_tls_options, crt_resource_properties.get_native_handle_method_id);
1811*3c7ae9deSAndroid Build Coastguard Worker         if (aws_jni_check_and_clear_exception(env)) {
1812*3c7ae9deSAndroid Build Coastguard Worker             s_aws_mqtt5_client_log_and_throw_exception(
1813*3c7ae9deSAndroid Build Coastguard Worker                 env, "MQTT5 client new: could not get native handle for tls options", AWS_ERROR_INVALID_ARGUMENT);
1814*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
1815*3c7ae9deSAndroid Build Coastguard Worker         }
1816*3c7ae9deSAndroid Build Coastguard Worker         struct aws_tls_ctx *tls_ctx = (struct aws_tls_ctx *)jni_tls_pointer;
1817*3c7ae9deSAndroid Build Coastguard Worker         if (tls_ctx) {
1818*3c7ae9deSAndroid Build Coastguard Worker             aws_tls_connection_options_init_from_ctx(&java_client->tls_options, tls_ctx);
1819*3c7ae9deSAndroid Build Coastguard Worker             aws_tls_connection_options_set_server_name(&java_client->tls_options, allocator, &client_options.host_name);
1820*3c7ae9deSAndroid Build Coastguard Worker             client_options.tls_options = &java_client->tls_options;
1821*3c7ae9deSAndroid Build Coastguard Worker         }
1822*3c7ae9deSAndroid Build Coastguard Worker     } else {
1823*3c7ae9deSAndroid Build Coastguard Worker         client_options.tls_options = NULL;
1824*3c7ae9deSAndroid Build Coastguard Worker     }
1825*3c7ae9deSAndroid Build Coastguard Worker 
1826*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_http_proxy_options =
1827*3c7ae9deSAndroid Build Coastguard Worker         (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.http_proxy_options_field_id);
1828*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
1829*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1830*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: error getting http proxy options", AWS_ERROR_INVALID_STATE);
1831*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1832*3c7ae9deSAndroid Build Coastguard Worker     }
1833*3c7ae9deSAndroid Build Coastguard Worker     if (jni_http_proxy_options) {
1834*3c7ae9deSAndroid Build Coastguard Worker         java_http_proxy_options =
1835*3c7ae9deSAndroid Build Coastguard Worker             s_aws_mqtt5_http_proxy_options_create_from_java(env, allocator, java_client, jni_http_proxy_options);
1836*3c7ae9deSAndroid Build Coastguard Worker         client_options.http_proxy_options = &java_http_proxy_options->options;
1837*3c7ae9deSAndroid Build Coastguard Worker 
1838*3c7ae9deSAndroid Build Coastguard Worker         if (client_options.http_proxy_options->connection_type != AWS_HPCT_HTTP_TUNNEL) {
1839*3c7ae9deSAndroid Build Coastguard Worker             s_aws_mqtt5_client_log_and_throw_exception(
1840*3c7ae9deSAndroid Build Coastguard Worker                 env, "MQTT5 client new: http proxy connection type has to be set to tunnel", AWS_ERROR_INVALID_STATE);
1841*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
1842*3c7ae9deSAndroid Build Coastguard Worker         }
1843*3c7ae9deSAndroid Build Coastguard Worker     }
1844*3c7ae9deSAndroid Build Coastguard Worker 
1845*3c7ae9deSAndroid Build Coastguard Worker     if (jni_connect_options) {
1846*3c7ae9deSAndroid Build Coastguard Worker         connect_options = aws_mqtt5_packet_connect_view_create_from_java(env, allocator, jni_connect_options);
1847*3c7ae9deSAndroid Build Coastguard Worker         if (connect_options != NULL || aws_jni_check_and_clear_exception(env)) {
1848*3c7ae9deSAndroid Build Coastguard Worker             client_options.connect_options = aws_mqtt5_packet_connect_view_get_packet(connect_options);
1849*3c7ae9deSAndroid Build Coastguard Worker         } else {
1850*3c7ae9deSAndroid Build Coastguard Worker             s_aws_mqtt5_client_log_and_throw_exception(
1851*3c7ae9deSAndroid Build Coastguard Worker                 env, "MQTT5 client new: error getting connect options", AWS_ERROR_INVALID_STATE);
1852*3c7ae9deSAndroid Build Coastguard Worker             goto clean_up;
1853*3c7ae9deSAndroid Build Coastguard Worker         }
1854*3c7ae9deSAndroid Build Coastguard Worker     }
1855*3c7ae9deSAndroid Build Coastguard Worker 
1856*3c7ae9deSAndroid Build Coastguard Worker     uint32_t session_behavior = UINT32_MAX;
1857*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_enum_from_jobject(
1858*3c7ae9deSAndroid Build Coastguard Worker             env,
1859*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1860*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.options_get_session_behavior_id,
1861*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1862*3c7ae9deSAndroid Build Coastguard Worker             "session behavior",
1863*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_session_behavior_properties.client_get_value_id,
1864*3c7ae9deSAndroid Build Coastguard Worker             &session_behavior,
1865*3c7ae9deSAndroid Build Coastguard Worker             true,
1866*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) == AWS_OP_ERR) {
1867*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1868*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get session behavior from options", AWS_ERROR_INVALID_STATE);
1869*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1870*3c7ae9deSAndroid Build Coastguard Worker     }
1871*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1872*3c7ae9deSAndroid Build Coastguard Worker         client_options.session_behavior = (enum aws_mqtt5_client_session_behavior_type)session_behavior;
1873*3c7ae9deSAndroid Build Coastguard Worker     }
1874*3c7ae9deSAndroid Build Coastguard Worker 
1875*3c7ae9deSAndroid Build Coastguard Worker     uint32_t extended_validation_and_flow_control_options = UINT32_MAX;
1876*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_enum_from_jobject(
1877*3c7ae9deSAndroid Build Coastguard Worker             env,
1878*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1879*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.options_get_extended_validation_and_flow_control_options_id,
1880*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1881*3c7ae9deSAndroid Build Coastguard Worker             "extended validation and flow control",
1882*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_extended_validation_and_flow_control_options.client_get_value_id,
1883*3c7ae9deSAndroid Build Coastguard Worker             &extended_validation_and_flow_control_options,
1884*3c7ae9deSAndroid Build Coastguard Worker             true,
1885*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) == AWS_OP_ERR) {
1886*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1887*3c7ae9deSAndroid Build Coastguard Worker             env,
1888*3c7ae9deSAndroid Build Coastguard Worker             "MQTT5 client new: Could not extended validation and flow control from options",
1889*3c7ae9deSAndroid Build Coastguard Worker             AWS_ERROR_INVALID_STATE);
1890*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1891*3c7ae9deSAndroid Build Coastguard Worker     }
1892*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1893*3c7ae9deSAndroid Build Coastguard Worker         client_options.extended_validation_and_flow_control_options =
1894*3c7ae9deSAndroid Build Coastguard Worker             (enum aws_mqtt5_extended_validation_and_flow_control_options)extended_validation_and_flow_control_options;
1895*3c7ae9deSAndroid Build Coastguard Worker     }
1896*3c7ae9deSAndroid Build Coastguard Worker 
1897*3c7ae9deSAndroid Build Coastguard Worker     uint32_t offline_queue_enum = UINT32_MAX;
1898*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_enum_from_jobject(
1899*3c7ae9deSAndroid Build Coastguard Worker             env,
1900*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1901*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.options_get_offline_queue_behavior_id,
1902*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1903*3c7ae9deSAndroid Build Coastguard Worker             "offline queue behavior",
1904*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_offline_queue_behavior_type_properties.client_get_value_id,
1905*3c7ae9deSAndroid Build Coastguard Worker             &offline_queue_enum,
1906*3c7ae9deSAndroid Build Coastguard Worker             true,
1907*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) == AWS_OP_ERR) {
1908*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1909*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get offline queue behavior from options", AWS_ERROR_INVALID_STATE);
1910*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1911*3c7ae9deSAndroid Build Coastguard Worker     }
1912*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1913*3c7ae9deSAndroid Build Coastguard Worker         client_options.offline_queue_behavior = (enum aws_mqtt5_client_operation_queue_behavior_type)offline_queue_enum;
1914*3c7ae9deSAndroid Build Coastguard Worker     }
1915*3c7ae9deSAndroid Build Coastguard Worker 
1916*3c7ae9deSAndroid Build Coastguard Worker     uint32_t retry_jitter_enum = UINT32_MAX;
1917*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_enum_from_jobject(
1918*3c7ae9deSAndroid Build Coastguard Worker             env,
1919*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1920*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.options_get_retry_jitter_mode_id,
1921*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1922*3c7ae9deSAndroid Build Coastguard Worker             "retry jitter mode",
1923*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_jitter_mode_properties.client_get_value_id,
1924*3c7ae9deSAndroid Build Coastguard Worker             &retry_jitter_enum,
1925*3c7ae9deSAndroid Build Coastguard Worker             true,
1926*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) == AWS_OP_ERR) {
1927*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1928*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get retry jitter mode from options", AWS_ERROR_INVALID_STATE);
1929*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1930*3c7ae9deSAndroid Build Coastguard Worker     }
1931*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1932*3c7ae9deSAndroid Build Coastguard Worker         client_options.retry_jitter_mode = (enum aws_exponential_backoff_jitter_mode)retry_jitter_enum;
1933*3c7ae9deSAndroid Build Coastguard Worker     }
1934*3c7ae9deSAndroid Build Coastguard Worker 
1935*3c7ae9deSAndroid Build Coastguard Worker     uint64_t min_reconnect_delay_ms = 0;
1936*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint64_from_jobject(
1937*3c7ae9deSAndroid Build Coastguard Worker             env,
1938*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1939*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.min_reconnect_delay_ms_field_id,
1940*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1941*3c7ae9deSAndroid Build Coastguard Worker             "minimum reconnect delay",
1942*3c7ae9deSAndroid Build Coastguard Worker             &min_reconnect_delay_ms,
1943*3c7ae9deSAndroid Build Coastguard Worker             true,
1944*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
1945*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1946*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get minimum reconnect delay from options", AWS_ERROR_INVALID_STATE);
1947*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1948*3c7ae9deSAndroid Build Coastguard Worker     }
1949*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1950*3c7ae9deSAndroid Build Coastguard Worker         client_options.min_reconnect_delay_ms = min_reconnect_delay_ms;
1951*3c7ae9deSAndroid Build Coastguard Worker     }
1952*3c7ae9deSAndroid Build Coastguard Worker 
1953*3c7ae9deSAndroid Build Coastguard Worker     uint64_t max_reconnect_delay_ms = 0;
1954*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint64_from_jobject(
1955*3c7ae9deSAndroid Build Coastguard Worker             env,
1956*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1957*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.max_reconnect_delay_ms_field_id,
1958*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1959*3c7ae9deSAndroid Build Coastguard Worker             "maximum reconnect delay",
1960*3c7ae9deSAndroid Build Coastguard Worker             &max_reconnect_delay_ms,
1961*3c7ae9deSAndroid Build Coastguard Worker             true,
1962*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
1963*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1964*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get maximum reconnect delay from options", AWS_ERROR_INVALID_STATE);
1965*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1966*3c7ae9deSAndroid Build Coastguard Worker     }
1967*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1968*3c7ae9deSAndroid Build Coastguard Worker         client_options.max_reconnect_delay_ms = max_reconnect_delay_ms;
1969*3c7ae9deSAndroid Build Coastguard Worker     }
1970*3c7ae9deSAndroid Build Coastguard Worker 
1971*3c7ae9deSAndroid Build Coastguard Worker     uint64_t min_connected_time_to_reset_reconnect_delay_ms = 0;
1972*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint64_from_jobject(
1973*3c7ae9deSAndroid Build Coastguard Worker             env,
1974*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1975*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.min_connected_time_to_reset_reconnect_delay_ms_field_id,
1976*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1977*3c7ae9deSAndroid Build Coastguard Worker             "minimum connected time to reset reconnect delay",
1978*3c7ae9deSAndroid Build Coastguard Worker             &min_connected_time_to_reset_reconnect_delay_ms,
1979*3c7ae9deSAndroid Build Coastguard Worker             true,
1980*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
1981*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
1982*3c7ae9deSAndroid Build Coastguard Worker             env,
1983*3c7ae9deSAndroid Build Coastguard Worker             "MQTT5 client new: Could not get minimum connected time to reset reconnect delay from options",
1984*3c7ae9deSAndroid Build Coastguard Worker             AWS_ERROR_INVALID_STATE);
1985*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
1986*3c7ae9deSAndroid Build Coastguard Worker     }
1987*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
1988*3c7ae9deSAndroid Build Coastguard Worker         client_options.min_connected_time_to_reset_reconnect_delay_ms = min_connected_time_to_reset_reconnect_delay_ms;
1989*3c7ae9deSAndroid Build Coastguard Worker     }
1990*3c7ae9deSAndroid Build Coastguard Worker 
1991*3c7ae9deSAndroid Build Coastguard Worker     uint32_t ping_timeout = 0;
1992*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint32_from_jobject(
1993*3c7ae9deSAndroid Build Coastguard Worker             env,
1994*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
1995*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.ping_timeout_ms_field_id,
1996*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
1997*3c7ae9deSAndroid Build Coastguard Worker             "ping timeout",
1998*3c7ae9deSAndroid Build Coastguard Worker             &ping_timeout,
1999*3c7ae9deSAndroid Build Coastguard Worker             true,
2000*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
2001*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2002*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get ping timeout from options", AWS_ERROR_INVALID_STATE);
2003*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2004*3c7ae9deSAndroid Build Coastguard Worker     }
2005*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
2006*3c7ae9deSAndroid Build Coastguard Worker         client_options.ping_timeout_ms = ping_timeout;
2007*3c7ae9deSAndroid Build Coastguard Worker     }
2008*3c7ae9deSAndroid Build Coastguard Worker 
2009*3c7ae9deSAndroid Build Coastguard Worker     uint32_t connack_timeout = 0;
2010*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint32_from_jobject(
2011*3c7ae9deSAndroid Build Coastguard Worker             env,
2012*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
2013*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.connack_timeout_ms_field_id,
2014*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
2015*3c7ae9deSAndroid Build Coastguard Worker             "ConnAck timeout",
2016*3c7ae9deSAndroid Build Coastguard Worker             &connack_timeout,
2017*3c7ae9deSAndroid Build Coastguard Worker             true,
2018*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
2019*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2020*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get ConnAck timeout from options", AWS_ERROR_INVALID_STATE);
2021*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2022*3c7ae9deSAndroid Build Coastguard Worker     }
2023*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
2024*3c7ae9deSAndroid Build Coastguard Worker         client_options.connack_timeout_ms = connack_timeout;
2025*3c7ae9deSAndroid Build Coastguard Worker     }
2026*3c7ae9deSAndroid Build Coastguard Worker 
2027*3c7ae9deSAndroid Build Coastguard Worker     uint32_t ack_timeout = 0;
2028*3c7ae9deSAndroid Build Coastguard Worker     if (aws_get_uint32_from_jobject(
2029*3c7ae9deSAndroid Build Coastguard Worker             env,
2030*3c7ae9deSAndroid Build Coastguard Worker             jni_options,
2031*3c7ae9deSAndroid Build Coastguard Worker             mqtt5_client_options_properties.ack_timeout_seconds_field_id,
2032*3c7ae9deSAndroid Build Coastguard Worker             s_client_string,
2033*3c7ae9deSAndroid Build Coastguard Worker             "Ack timeout",
2034*3c7ae9deSAndroid Build Coastguard Worker             &ack_timeout,
2035*3c7ae9deSAndroid Build Coastguard Worker             true,
2036*3c7ae9deSAndroid Build Coastguard Worker             &was_value_set) != AWS_OP_SUCCESS) {
2037*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2038*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: Could not get Ack timeout from options", AWS_ERROR_INVALID_STATE);
2039*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2040*3c7ae9deSAndroid Build Coastguard Worker     }
2041*3c7ae9deSAndroid Build Coastguard Worker     if (was_value_set) {
2042*3c7ae9deSAndroid Build Coastguard Worker         client_options.ack_timeout_seconds = ack_timeout;
2043*3c7ae9deSAndroid Build Coastguard Worker     }
2044*3c7ae9deSAndroid Build Coastguard Worker 
2045*3c7ae9deSAndroid Build Coastguard Worker     jint jvmresult = (*env)->GetJavaVM(env, &java_client->jvm);
2046*3c7ae9deSAndroid Build Coastguard Worker     if (jvmresult != 0) {
2047*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(env, "MQTT5 client new: Unable to get JVM", AWS_ERROR_INVALID_STATE);
2048*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2049*3c7ae9deSAndroid Build Coastguard Worker     }
2050*3c7ae9deSAndroid Build Coastguard Worker     java_client->jni_client = (*env)->NewGlobalRef(env, jni_client);
2051*3c7ae9deSAndroid Build Coastguard Worker 
2052*3c7ae9deSAndroid Build Coastguard Worker     client_options.lifecycle_event_handler = &s_aws_mqtt5_client_java_lifecycle_event;
2053*3c7ae9deSAndroid Build Coastguard Worker     client_options.lifecycle_event_handler_user_data = (void *)java_client;
2054*3c7ae9deSAndroid Build Coastguard Worker 
2055*3c7ae9deSAndroid Build Coastguard Worker     client_options.publish_received_handler = &s_aws_mqtt5_client_java_publish_received;
2056*3c7ae9deSAndroid Build Coastguard Worker     client_options.publish_received_handler_user_data = (void *)java_client;
2057*3c7ae9deSAndroid Build Coastguard Worker 
2058*3c7ae9deSAndroid Build Coastguard Worker     /* Are we using websockets? */
2059*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_websocket_handshake =
2060*3c7ae9deSAndroid Build Coastguard Worker         (*env)->GetObjectField(env, jni_client, mqtt5_client_properties.websocket_handshake_field_id);
2061*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
2062*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2063*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: error getting websocket handshake transform", AWS_ERROR_INVALID_STATE);
2064*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2065*3c7ae9deSAndroid Build Coastguard Worker     }
2066*3c7ae9deSAndroid Build Coastguard Worker     if (jni_websocket_handshake) {
2067*3c7ae9deSAndroid Build Coastguard Worker         client_options.websocket_handshake_transform = &s_aws_mqtt5_client_java_websocket_handshake_transform;
2068*3c7ae9deSAndroid Build Coastguard Worker         client_options.websocket_handshake_transform_user_data = (void *)java_client;
2069*3c7ae9deSAndroid Build Coastguard Worker     }
2070*3c7ae9deSAndroid Build Coastguard Worker 
2071*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_publish_events =
2072*3c7ae9deSAndroid Build Coastguard Worker         (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.publish_events_field_id);
2073*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
2074*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2075*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: error getting publish events", AWS_ERROR_INVALID_STATE);
2076*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2077*3c7ae9deSAndroid Build Coastguard Worker     }
2078*3c7ae9deSAndroid Build Coastguard Worker     if (jni_publish_events != NULL) {
2079*3c7ae9deSAndroid Build Coastguard Worker         java_client->jni_publish_events = (*env)->NewGlobalRef(env, jni_publish_events);
2080*3c7ae9deSAndroid Build Coastguard Worker     }
2081*3c7ae9deSAndroid Build Coastguard Worker 
2082*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_lifecycle_events =
2083*3c7ae9deSAndroid Build Coastguard Worker         (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.lifecycle_events_field_id);
2084*3c7ae9deSAndroid Build Coastguard Worker     if (aws_jni_check_and_clear_exception(env)) {
2085*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2086*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client new: error getting lifecycle events", AWS_ERROR_INVALID_STATE);
2087*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2088*3c7ae9deSAndroid Build Coastguard Worker     }
2089*3c7ae9deSAndroid Build Coastguard Worker     if (jni_lifecycle_events != NULL) {
2090*3c7ae9deSAndroid Build Coastguard Worker         java_client->jni_lifecycle_events = (*env)->NewGlobalRef(env, jni_lifecycle_events);
2091*3c7ae9deSAndroid Build Coastguard Worker     }
2092*3c7ae9deSAndroid Build Coastguard Worker 
2093*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_topic_alias_options topic_aliasing_options;
2094*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(topic_aliasing_options);
2095*3c7ae9deSAndroid Build Coastguard Worker     jobject jni_topic_aliasing_options =
2096*3c7ae9deSAndroid Build Coastguard Worker         (*env)->GetObjectField(env, jni_options, mqtt5_client_options_properties.topic_aliasing_options_field_id);
2097*3c7ae9deSAndroid Build Coastguard Worker 
2098*3c7ae9deSAndroid Build Coastguard Worker     if (jni_topic_aliasing_options != NULL) {
2099*3c7ae9deSAndroid Build Coastguard Worker         if (s_initialize_topic_aliasing_options(env, &topic_aliasing_options, jni_topic_aliasing_options) ==
2100*3c7ae9deSAndroid Build Coastguard Worker             AWS_OP_SUCCESS) {
2101*3c7ae9deSAndroid Build Coastguard Worker             client_options.topic_aliasing_options = &topic_aliasing_options;
2102*3c7ae9deSAndroid Build Coastguard Worker         }
2103*3c7ae9deSAndroid Build Coastguard Worker     }
2104*3c7ae9deSAndroid Build Coastguard Worker 
2105*3c7ae9deSAndroid Build Coastguard Worker     client_options.client_termination_handler = &s_aws_mqtt5_client_java_termination;
2106*3c7ae9deSAndroid Build Coastguard Worker     client_options.client_termination_handler_user_data = (void *)java_client;
2107*3c7ae9deSAndroid Build Coastguard Worker 
2108*3c7ae9deSAndroid Build Coastguard Worker     /* Make the MQTT5 client */
2109*3c7ae9deSAndroid Build Coastguard Worker     java_client->client = aws_mqtt5_client_new(allocator, &client_options);
2110*3c7ae9deSAndroid Build Coastguard Worker     /* Did we successfully make a client? If not, then throw an exception */
2111*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->client == NULL) {
2112*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2113*3c7ae9deSAndroid Build Coastguard Worker             env,
2114*3c7ae9deSAndroid Build Coastguard Worker             "MQTT5 client new: Was unable to create client due to option configuration! Enable error logging to see "
2115*3c7ae9deSAndroid Build Coastguard Worker             "reason",
2116*3c7ae9deSAndroid Build Coastguard Worker             AWS_ERROR_MQTT5_CLIENT_OPTIONS_VALIDATION);
2117*3c7ae9deSAndroid Build Coastguard Worker         goto clean_up;
2118*3c7ae9deSAndroid Build Coastguard Worker     }
2119*3c7ae9deSAndroid Build Coastguard Worker     goto clean_up;
2120*3c7ae9deSAndroid Build Coastguard Worker 
2121*3c7ae9deSAndroid Build Coastguard Worker clean_up:
2122*3c7ae9deSAndroid Build Coastguard Worker 
2123*3c7ae9deSAndroid Build Coastguard Worker     aws_mqtt5_packet_connect_view_java_destroy(env, allocator, connect_options);
2124*3c7ae9deSAndroid Build Coastguard Worker     s_aws_mqtt5_http_proxy_options_java_destroy(env, allocator, java_http_proxy_options);
2125*3c7ae9deSAndroid Build Coastguard Worker     if (aws_byte_buf_is_valid(&host_name_buf)) {
2126*3c7ae9deSAndroid Build Coastguard Worker         aws_byte_buf_clean_up(&host_name_buf);
2127*3c7ae9deSAndroid Build Coastguard Worker     }
2128*3c7ae9deSAndroid Build Coastguard Worker     (*env)->PopLocalFrame(env, NULL);
2129*3c7ae9deSAndroid Build Coastguard Worker 
2130*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->client != NULL) {
2131*3c7ae9deSAndroid Build Coastguard Worker         return (jlong)java_client;
2132*3c7ae9deSAndroid Build Coastguard Worker     }
2133*3c7ae9deSAndroid Build Coastguard Worker 
2134*3c7ae9deSAndroid Build Coastguard Worker     aws_mqtt5_client_java_destroy(env, allocator, java_client);
2135*3c7ae9deSAndroid Build Coastguard Worker     return (jlong)NULL;
2136*3c7ae9deSAndroid Build Coastguard Worker }
2137*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientDestroy(JNIEnv * env,jclass jni_class,jlong jni_mqtt_client)2138*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt5_Mqtt5Client_mqtt5ClientDestroy(
2139*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
2140*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
2141*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_mqtt_client) {
2142*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
2143*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
2144*3c7ae9deSAndroid Build Coastguard Worker 
2145*3c7ae9deSAndroid Build Coastguard Worker     struct aws_mqtt5_client_java_jni *java_client = (struct aws_mqtt5_client_java_jni *)jni_mqtt_client;
2146*3c7ae9deSAndroid Build Coastguard Worker     if (!java_client) {
2147*3c7ae9deSAndroid Build Coastguard Worker         s_aws_mqtt5_client_log_and_throw_exception(
2148*3c7ae9deSAndroid Build Coastguard Worker             env, "MQTT5 client destroy: Invalid/null client", AWS_ERROR_INVALID_ARGUMENT);
2149*3c7ae9deSAndroid Build Coastguard Worker         return;
2150*3c7ae9deSAndroid Build Coastguard Worker     }
2151*3c7ae9deSAndroid Build Coastguard Worker 
2152*3c7ae9deSAndroid Build Coastguard Worker     // If the client is NOT null it can be shut down normally
2153*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
2154*3c7ae9deSAndroid Build Coastguard Worker     if (java_client->client) {
2155*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_client_release(java_client->client);
2156*3c7ae9deSAndroid Build Coastguard Worker     } else {
2157*3c7ae9deSAndroid Build Coastguard Worker         aws_mqtt5_client_java_destroy(env, allocator, java_client);
2158*3c7ae9deSAndroid Build Coastguard Worker     }
2159*3c7ae9deSAndroid Build Coastguard Worker }
2160*3c7ae9deSAndroid Build Coastguard Worker 
2161*3c7ae9deSAndroid Build Coastguard Worker #if UINTPTR_MAX == 0xffffffff
2162*3c7ae9deSAndroid Build Coastguard Worker #    if defined(_MSC_VER)
2163*3c7ae9deSAndroid Build Coastguard Worker #        pragma warning(pop)
2164*3c7ae9deSAndroid Build Coastguard Worker #    else
2165*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic pop
2166*3c7ae9deSAndroid Build Coastguard Worker #    endif
2167*3c7ae9deSAndroid Build Coastguard Worker #endif
2168