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 <jni.h>
6*3c7ae9deSAndroid Build Coastguard Worker
7*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/atomics.h>
8*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/condition_variable.h>
9*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/logging.h>
10*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/mutex.h>
11*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/string.h>
12*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/thread.h>
13*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/connection.h>
14*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/proxy.h>
15*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/request_response.h>
16*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/channel.h>
17*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/channel_bootstrap.h>
18*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/event_loop.h>
19*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/host_resolver.h>
20*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/socket.h>
21*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/socket_channel_handler.h>
22*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/tls_channel_handler.h>
23*3c7ae9deSAndroid Build Coastguard Worker #include <aws/mqtt/client.h>
24*3c7ae9deSAndroid Build Coastguard Worker
25*3c7ae9deSAndroid Build Coastguard Worker #include <ctype.h>
26*3c7ae9deSAndroid Build Coastguard Worker #include <string.h>
27*3c7ae9deSAndroid Build Coastguard Worker
28*3c7ae9deSAndroid Build Coastguard Worker #include "crt.h"
29*3c7ae9deSAndroid Build Coastguard Worker
30*3c7ae9deSAndroid Build Coastguard Worker #include "http_request_utils.h"
31*3c7ae9deSAndroid Build Coastguard Worker #include "java_class_ids.h"
32*3c7ae9deSAndroid Build Coastguard Worker #include "mqtt5_client_jni.h"
33*3c7ae9deSAndroid Build Coastguard Worker
34*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
35*3c7ae9deSAndroid Build Coastguard Worker * mqtt_jni_async_callback - carries an AsyncCallback around as user data to mqtt
36*3c7ae9deSAndroid Build Coastguard Worker * async ops, and is used to deliver callbacks. Also hangs on to JNI references
37*3c7ae9deSAndroid Build Coastguard Worker * to buffers and strings that need to outlive the request
38*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
39*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback {
40*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection;
41*3c7ae9deSAndroid Build Coastguard Worker jobject async_callback;
42*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_buf buffer; /* payloads or other pinned resources go in here, freed when callback is delivered */
43*3c7ae9deSAndroid Build Coastguard Worker };
44*3c7ae9deSAndroid Build Coastguard Worker
45*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
46*3c7ae9deSAndroid Build Coastguard Worker * mqtt_jni_connection - represents an aws_mqtt_client_connection to Java
47*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
48*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection {
49*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client *client; /* Provided to mqtt_connect */
50*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection;
51*3c7ae9deSAndroid Build Coastguard Worker struct aws_socket_options socket_options;
52*3c7ae9deSAndroid Build Coastguard Worker struct aws_tls_connection_options tls_options;
53*3c7ae9deSAndroid Build Coastguard Worker
54*3c7ae9deSAndroid Build Coastguard Worker JavaVM *jvm;
55*3c7ae9deSAndroid Build Coastguard Worker jweak java_mqtt_connection; /* MqttClientConnection instance */
56*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *on_message;
57*3c7ae9deSAndroid Build Coastguard Worker
58*3c7ae9deSAndroid Build Coastguard Worker struct aws_atomic_var ref_count;
59*3c7ae9deSAndroid Build Coastguard Worker };
60*3c7ae9deSAndroid Build Coastguard Worker
61*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
62*3c7ae9deSAndroid Build Coastguard Worker * mqtt_jni_ws_handshake - Data needed to perform the async websocket handshake
63*3c7ae9deSAndroid Build Coastguard Worker * transform operations. Destroyed when transform is complete.
64*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
65*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_ws_handshake {
66*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection;
67*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_message *http_request;
68*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_transform_websocket_handshake_complete_fn *complete_fn;
69*3c7ae9deSAndroid Build Coastguard Worker void *complete_ctx;
70*3c7ae9deSAndroid Build Coastguard Worker };
71*3c7ae9deSAndroid Build Coastguard Worker
72*3c7ae9deSAndroid Build Coastguard Worker static void s_mqtt_connection_destroy(JNIEnv *env, struct mqtt_jni_connection *connection);
73*3c7ae9deSAndroid Build Coastguard Worker
s_mqtt_jni_connection_acquire(struct mqtt_jni_connection * connection)74*3c7ae9deSAndroid Build Coastguard Worker static void s_mqtt_jni_connection_acquire(struct mqtt_jni_connection *connection) {
75*3c7ae9deSAndroid Build Coastguard Worker size_t old_value = aws_atomic_fetch_add(&connection->ref_count, 1);
76*3c7ae9deSAndroid Build Coastguard Worker
77*3c7ae9deSAndroid Build Coastguard Worker AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "mqtt_jni_connection acquire, ref count now = %d", (int)old_value + 1);
78*3c7ae9deSAndroid Build Coastguard Worker }
79*3c7ae9deSAndroid Build Coastguard Worker
80*3c7ae9deSAndroid Build Coastguard Worker static void s_on_shutdown_disconnect_complete(struct aws_mqtt_client_connection *connection, void *user_data);
81*3c7ae9deSAndroid Build Coastguard Worker
s_mqtt_jni_connection_release(struct mqtt_jni_connection * connection)82*3c7ae9deSAndroid Build Coastguard Worker static void s_mqtt_jni_connection_release(struct mqtt_jni_connection *connection) {
83*3c7ae9deSAndroid Build Coastguard Worker size_t old_value = aws_atomic_fetch_sub(&connection->ref_count, 1);
84*3c7ae9deSAndroid Build Coastguard Worker
85*3c7ae9deSAndroid Build Coastguard Worker AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "mqtt_jni_connection release, ref count now = %d", (int)old_value - 1);
86*3c7ae9deSAndroid Build Coastguard Worker }
87*3c7ae9deSAndroid Build Coastguard Worker
88*3c7ae9deSAndroid Build Coastguard Worker /* The destroy function is called on Java MqttClientConnection resource release. */
s_mqtt_jni_connection_destroy(struct mqtt_jni_connection * connection)89*3c7ae9deSAndroid Build Coastguard Worker static void s_mqtt_jni_connection_destroy(struct mqtt_jni_connection *connection) {
90*3c7ae9deSAndroid Build Coastguard Worker /* For mqtt311 client, we have to call aws_mqtt_client_connection_disconnect before releasing the underlying c
91*3c7ae9deSAndroid Build Coastguard Worker * connection.*/
92*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_disconnect(
93*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_shutdown_disconnect_complete, connection) != AWS_OP_SUCCESS) {
94*3c7ae9deSAndroid Build Coastguard Worker
95*3c7ae9deSAndroid Build Coastguard Worker /*
96*3c7ae9deSAndroid Build Coastguard Worker * This can happen under normal code paths if the client happens to be disconnected at cleanup/shutdown
97*3c7ae9deSAndroid Build Coastguard Worker * time. Log it (in case it was unexpected) and then shutdown the underlying connection manually.
98*3c7ae9deSAndroid Build Coastguard Worker */
99*3c7ae9deSAndroid Build Coastguard Worker AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "Client disconnect failed. Release the client connection.");
100*3c7ae9deSAndroid Build Coastguard Worker s_on_shutdown_disconnect_complete(connection->client_connection, NULL);
101*3c7ae9deSAndroid Build Coastguard Worker }
102*3c7ae9deSAndroid Build Coastguard Worker }
103*3c7ae9deSAndroid Build Coastguard Worker
s_mqtt_jni_async_callback_new(struct mqtt_jni_connection * connection,jobject async_callback,JNIEnv * env)104*3c7ae9deSAndroid Build Coastguard Worker static struct mqtt_jni_async_callback *s_mqtt_jni_async_callback_new(
105*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection,
106*3c7ae9deSAndroid Build Coastguard Worker jobject async_callback,
107*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env) {
108*3c7ae9deSAndroid Build Coastguard Worker
109*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
110*3c7ae9deSAndroid Build Coastguard Worker return NULL;
111*3c7ae9deSAndroid Build Coastguard Worker }
112*3c7ae9deSAndroid Build Coastguard Worker
113*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *allocator = aws_jni_get_allocator();
114*3c7ae9deSAndroid Build Coastguard Worker /* allocate cannot fail */
115*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *callback = aws_mem_calloc(allocator, 1, sizeof(struct mqtt_jni_async_callback));
116*3c7ae9deSAndroid Build Coastguard Worker callback->connection = connection;
117*3c7ae9deSAndroid Build Coastguard Worker callback->async_callback = async_callback ? (*env)->NewGlobalRef(env, async_callback) : NULL;
118*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_init(&callback->buffer, aws_jni_get_allocator(), 0);
119*3c7ae9deSAndroid Build Coastguard Worker
120*3c7ae9deSAndroid Build Coastguard Worker return callback;
121*3c7ae9deSAndroid Build Coastguard Worker }
122*3c7ae9deSAndroid Build Coastguard Worker
s_mqtt_jni_async_callback_destroy(struct mqtt_jni_async_callback * callback,JNIEnv * env)123*3c7ae9deSAndroid Build Coastguard Worker static void s_mqtt_jni_async_callback_destroy(struct mqtt_jni_async_callback *callback, JNIEnv *env) {
124*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(callback && callback->connection);
125*3c7ae9deSAndroid Build Coastguard Worker
126*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
127*3c7ae9deSAndroid Build Coastguard Worker return;
128*3c7ae9deSAndroid Build Coastguard Worker }
129*3c7ae9deSAndroid Build Coastguard Worker
130*3c7ae9deSAndroid Build Coastguard Worker if (callback->async_callback) {
131*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteGlobalRef(env, callback->async_callback);
132*3c7ae9deSAndroid Build Coastguard Worker }
133*3c7ae9deSAndroid Build Coastguard Worker
134*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_clean_up(&callback->buffer);
135*3c7ae9deSAndroid Build Coastguard Worker
136*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *allocator = aws_jni_get_allocator();
137*3c7ae9deSAndroid Build Coastguard Worker aws_mem_release(allocator, callback);
138*3c7ae9deSAndroid Build Coastguard Worker }
139*3c7ae9deSAndroid Build Coastguard Worker
s_new_mqtt_exception(JNIEnv * env,int error_code)140*3c7ae9deSAndroid Build Coastguard Worker static jobject s_new_mqtt_exception(JNIEnv *env, int error_code) {
141*3c7ae9deSAndroid Build Coastguard Worker jobject exception = (*env)->NewObject(
142*3c7ae9deSAndroid Build Coastguard Worker env, mqtt_exception_properties.jni_mqtt_exception, mqtt_exception_properties.jni_constructor, error_code);
143*3c7ae9deSAndroid Build Coastguard Worker return exception;
144*3c7ae9deSAndroid Build Coastguard Worker }
145*3c7ae9deSAndroid Build Coastguard Worker
146*3c7ae9deSAndroid Build Coastguard Worker /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
147*3c7ae9deSAndroid Build Coastguard Worker #if UINTPTR_MAX == 0xffffffff
148*3c7ae9deSAndroid Build Coastguard Worker # if defined(_MSC_VER)
149*3c7ae9deSAndroid Build Coastguard Worker # pragma warning(push)
150*3c7ae9deSAndroid Build Coastguard Worker # pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
151*3c7ae9deSAndroid Build Coastguard Worker # else
152*3c7ae9deSAndroid Build Coastguard Worker # pragma GCC diagnostic push
153*3c7ae9deSAndroid Build Coastguard Worker # pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
154*3c7ae9deSAndroid Build Coastguard Worker # pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
155*3c7ae9deSAndroid Build Coastguard Worker # endif
156*3c7ae9deSAndroid Build Coastguard Worker #endif
157*3c7ae9deSAndroid Build Coastguard Worker
158*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
159*3c7ae9deSAndroid Build Coastguard Worker * new
160*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
161*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_disconnected(struct aws_mqtt_client_connection *client_connection, void *user_data);
s_on_connection_complete(struct aws_mqtt_client_connection * client_connection,int error_code,enum aws_mqtt_connect_return_code return_code,bool session_present,void * user_data)162*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_complete(
163*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection,
164*3c7ae9deSAndroid Build Coastguard Worker int error_code,
165*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_connect_return_code return_code,
166*3c7ae9deSAndroid Build Coastguard Worker bool session_present,
167*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
168*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
169*3c7ae9deSAndroid Build Coastguard Worker (void)return_code;
170*3c7ae9deSAndroid Build Coastguard Worker
171*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *connect_callback = user_data;
172*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = connect_callback->connection;
173*3c7ae9deSAndroid Build Coastguard Worker
174*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
175*3c7ae9deSAndroid Build Coastguard Worker JavaVM *jvm = connection->jvm;
176*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(jvm);
177*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
178*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
179*3c7ae9deSAndroid Build Coastguard Worker return;
180*3c7ae9deSAndroid Build Coastguard Worker }
181*3c7ae9deSAndroid Build Coastguard Worker
182*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
183*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection != NULL) {
184*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(
185*3c7ae9deSAndroid Build Coastguard Worker env, mqtt_connection, mqtt_connection_properties.on_connection_complete, error_code, session_present);
186*3c7ae9deSAndroid Build Coastguard Worker
187*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
188*3c7ae9deSAndroid Build Coastguard Worker
189*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
190*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
191*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE EARLY OUT **********/
192*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_disconnect(client_connection, s_on_connection_disconnected, connect_callback);
193*3c7ae9deSAndroid Build Coastguard Worker return; /* callback and ref count will be cleaned up in s_on_connection_disconnected */
194*3c7ae9deSAndroid Build Coastguard Worker }
195*3c7ae9deSAndroid Build Coastguard Worker }
196*3c7ae9deSAndroid Build Coastguard Worker
197*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(connect_callback, env);
198*3c7ae9deSAndroid Build Coastguard Worker
199*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(jvm, env);
200*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
201*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_release(connection);
202*3c7ae9deSAndroid Build Coastguard Worker }
203*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_interrupted_internal(struct mqtt_jni_connection * connection,int error_code,jobject ack_callback,JNIEnv * env)204*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_interrupted_internal(
205*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection,
206*3c7ae9deSAndroid Build Coastguard Worker int error_code,
207*3c7ae9deSAndroid Build Coastguard Worker jobject ack_callback,
208*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env) {
209*3c7ae9deSAndroid Build Coastguard Worker
210*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(env);
211*3c7ae9deSAndroid Build Coastguard Worker
212*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
213*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection) {
214*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(
215*3c7ae9deSAndroid Build Coastguard Worker env, mqtt_connection, mqtt_connection_properties.on_connection_interrupted, error_code, ack_callback);
216*3c7ae9deSAndroid Build Coastguard Worker
217*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
218*3c7ae9deSAndroid Build Coastguard Worker
219*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
220*3c7ae9deSAndroid Build Coastguard Worker }
221*3c7ae9deSAndroid Build Coastguard Worker }
222*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_interrupted(struct aws_mqtt_client_connection * client_connection,int error_code,void * user_data)223*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_interrupted(
224*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection,
225*3c7ae9deSAndroid Build Coastguard Worker int error_code,
226*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
227*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
228*3c7ae9deSAndroid Build Coastguard Worker
229*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = user_data;
230*3c7ae9deSAndroid Build Coastguard Worker
231*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
232*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(connection->jvm);
233*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
234*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
235*3c7ae9deSAndroid Build Coastguard Worker return;
236*3c7ae9deSAndroid Build Coastguard Worker }
237*3c7ae9deSAndroid Build Coastguard Worker
238*3c7ae9deSAndroid Build Coastguard Worker s_on_connection_interrupted_internal(user_data, error_code, NULL, env);
239*3c7ae9deSAndroid Build Coastguard Worker
240*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
241*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
242*3c7ae9deSAndroid Build Coastguard Worker }
243*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_success(struct aws_mqtt_client_connection * client_connection,enum aws_mqtt_connect_return_code return_code,bool session_present,void * user_data)244*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_success(
245*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection,
246*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_connect_return_code return_code,
247*3c7ae9deSAndroid Build Coastguard Worker bool session_present,
248*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
249*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
250*3c7ae9deSAndroid Build Coastguard Worker (void)return_code;
251*3c7ae9deSAndroid Build Coastguard Worker
252*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = user_data;
253*3c7ae9deSAndroid Build Coastguard Worker
254*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
255*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(connection->jvm);
256*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
257*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
258*3c7ae9deSAndroid Build Coastguard Worker return;
259*3c7ae9deSAndroid Build Coastguard Worker }
260*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
261*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection) {
262*3c7ae9deSAndroid Build Coastguard Worker
263*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, mqtt_connection, mqtt_connection_properties.on_connection_success, session_present);
264*3c7ae9deSAndroid Build Coastguard Worker
265*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
266*3c7ae9deSAndroid Build Coastguard Worker
267*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
268*3c7ae9deSAndroid Build Coastguard Worker }
269*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
270*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
271*3c7ae9deSAndroid Build Coastguard Worker }
272*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_failure(struct aws_mqtt_client_connection * client_connection,int error_code,void * user_data)273*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_failure(
274*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection,
275*3c7ae9deSAndroid Build Coastguard Worker int error_code,
276*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
277*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
278*3c7ae9deSAndroid Build Coastguard Worker
279*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = user_data;
280*3c7ae9deSAndroid Build Coastguard Worker
281*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
282*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(connection->jvm);
283*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
284*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
285*3c7ae9deSAndroid Build Coastguard Worker return;
286*3c7ae9deSAndroid Build Coastguard Worker }
287*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
288*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection) {
289*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, mqtt_connection, mqtt_connection_properties.on_connection_failure, error_code);
290*3c7ae9deSAndroid Build Coastguard Worker
291*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
292*3c7ae9deSAndroid Build Coastguard Worker
293*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
294*3c7ae9deSAndroid Build Coastguard Worker }
295*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
296*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
297*3c7ae9deSAndroid Build Coastguard Worker }
298*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_resumed(struct aws_mqtt_client_connection * client_connection,enum aws_mqtt_connect_return_code return_code,bool session_present,void * user_data)299*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_resumed(
300*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection,
301*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_connect_return_code return_code,
302*3c7ae9deSAndroid Build Coastguard Worker bool session_present,
303*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
304*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
305*3c7ae9deSAndroid Build Coastguard Worker (void)return_code;
306*3c7ae9deSAndroid Build Coastguard Worker
307*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = user_data;
308*3c7ae9deSAndroid Build Coastguard Worker
309*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
310*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(connection->jvm);
311*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
312*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
313*3c7ae9deSAndroid Build Coastguard Worker return;
314*3c7ae9deSAndroid Build Coastguard Worker }
315*3c7ae9deSAndroid Build Coastguard Worker
316*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
317*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection) {
318*3c7ae9deSAndroid Build Coastguard Worker
319*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, mqtt_connection, mqtt_connection_properties.on_connection_resumed, session_present);
320*3c7ae9deSAndroid Build Coastguard Worker
321*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
322*3c7ae9deSAndroid Build Coastguard Worker
323*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
324*3c7ae9deSAndroid Build Coastguard Worker }
325*3c7ae9deSAndroid Build Coastguard Worker
326*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
327*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
328*3c7ae9deSAndroid Build Coastguard Worker }
329*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_disconnected(struct aws_mqtt_client_connection * client_connection,void * user_data)330*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_disconnected(struct aws_mqtt_client_connection *client_connection, void *user_data) {
331*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
332*3c7ae9deSAndroid Build Coastguard Worker
333*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *connect_callback = user_data;
334*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *jni_connection = connect_callback->connection;
335*3c7ae9deSAndroid Build Coastguard Worker
336*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
337*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(jni_connection->jvm);
338*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
339*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
340*3c7ae9deSAndroid Build Coastguard Worker return;
341*3c7ae9deSAndroid Build Coastguard Worker }
342*3c7ae9deSAndroid Build Coastguard Worker
343*3c7ae9deSAndroid Build Coastguard Worker s_on_connection_interrupted_internal(connect_callback->connection, 0, connect_callback->async_callback, env);
344*3c7ae9deSAndroid Build Coastguard Worker
345*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(connect_callback, env);
346*3c7ae9deSAndroid Build Coastguard Worker
347*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
348*3c7ae9deSAndroid Build Coastguard Worker
349*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(jni_connection->jvm, env);
350*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
351*3c7ae9deSAndroid Build Coastguard Worker
352*3c7ae9deSAndroid Build Coastguard Worker /* Do not call release here: s_on_connection_closed will (normally) be called
353*3c7ae9deSAndroid Build Coastguard Worker * right after and so we can call the release there instead. */
354*3c7ae9deSAndroid Build Coastguard Worker }
355*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_closed(struct aws_mqtt_client_connection * client_connection,struct on_connection_closed_data * data,void * user_data)356*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_closed(
357*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *client_connection,
358*3c7ae9deSAndroid Build Coastguard Worker struct on_connection_closed_data *data,
359*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
360*3c7ae9deSAndroid Build Coastguard Worker (void)client_connection;
361*3c7ae9deSAndroid Build Coastguard Worker (void)data;
362*3c7ae9deSAndroid Build Coastguard Worker
363*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = user_data;
364*3c7ae9deSAndroid Build Coastguard Worker
365*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
366*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(connection->jvm);
367*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
368*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
369*3c7ae9deSAndroid Build Coastguard Worker return;
370*3c7ae9deSAndroid Build Coastguard Worker }
371*3c7ae9deSAndroid Build Coastguard Worker
372*3c7ae9deSAndroid Build Coastguard Worker // Make sure the Java object has not been garbage collected
373*3c7ae9deSAndroid Build Coastguard Worker if (!(*env)->IsSameObject(env, connection->java_mqtt_connection, NULL)) {
374*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
375*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection) {
376*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, mqtt_connection, mqtt_connection_properties.on_connection_closed);
377*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
378*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
379*3c7ae9deSAndroid Build Coastguard Worker }
380*3c7ae9deSAndroid Build Coastguard Worker }
381*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
382*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
383*3c7ae9deSAndroid Build Coastguard Worker }
384*3c7ae9deSAndroid Build Coastguard Worker
s_on_connection_terminated(void * user_data)385*3c7ae9deSAndroid Build Coastguard Worker static void s_on_connection_terminated(void *user_data) {
386*3c7ae9deSAndroid Build Coastguard Worker
387*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *jni_connection = (struct mqtt_jni_connection *)user_data;
388*3c7ae9deSAndroid Build Coastguard Worker
389*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
390*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(jni_connection->jvm);
391*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
392*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
393*3c7ae9deSAndroid Build Coastguard Worker return;
394*3c7ae9deSAndroid Build Coastguard Worker }
395*3c7ae9deSAndroid Build Coastguard Worker
396*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, jni_connection->java_mqtt_connection);
397*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection != NULL) {
398*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, mqtt_connection, crt_resource_properties.release_references);
399*3c7ae9deSAndroid Build Coastguard Worker
400*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
401*3c7ae9deSAndroid Build Coastguard Worker
402*3c7ae9deSAndroid Build Coastguard Worker aws_jni_check_and_clear_exception(env);
403*3c7ae9deSAndroid Build Coastguard Worker }
404*3c7ae9deSAndroid Build Coastguard Worker
405*3c7ae9deSAndroid Build Coastguard Worker JavaVM *jvm = jni_connection->jvm;
406*3c7ae9deSAndroid Build Coastguard Worker
407*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_connection_destroy(env, jni_connection);
408*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(jvm, env);
409*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
410*3c7ae9deSAndroid Build Coastguard Worker }
411*3c7ae9deSAndroid Build Coastguard Worker
s_mqtt_connection_new(JNIEnv * env,struct aws_mqtt_client * client3,struct aws_mqtt5_client_java_jni * client5_jni,jobject java_mqtt_connection)412*3c7ae9deSAndroid Build Coastguard Worker static struct mqtt_jni_connection *s_mqtt_connection_new(
413*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
414*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client *client3,
415*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt5_client_java_jni *client5_jni,
416*3c7ae9deSAndroid Build Coastguard Worker jobject java_mqtt_connection) {
417*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *allocator = aws_jni_get_allocator();
418*3c7ae9deSAndroid Build Coastguard Worker
419*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = aws_mem_calloc(allocator, 1, sizeof(struct mqtt_jni_connection));
420*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
421*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
422*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqtt_connect: Out of memory allocating JNI connection");
423*3c7ae9deSAndroid Build Coastguard Worker return NULL;
424*3c7ae9deSAndroid Build Coastguard Worker }
425*3c7ae9deSAndroid Build Coastguard Worker
426*3c7ae9deSAndroid Build Coastguard Worker aws_atomic_store_int(&connection->ref_count, 1);
427*3c7ae9deSAndroid Build Coastguard Worker connection->java_mqtt_connection = (*env)->NewWeakGlobalRef(env, java_mqtt_connection);
428*3c7ae9deSAndroid Build Coastguard Worker jint jvmresult = (*env)->GetJavaVM(env, &connection->jvm);
429*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(jvmresult == 0);
430*3c7ae9deSAndroid Build Coastguard Worker
431*3c7ae9deSAndroid Build Coastguard Worker if (client3 != NULL) {
432*3c7ae9deSAndroid Build Coastguard Worker connection->client = client3;
433*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection = aws_mqtt_client_connection_new(client3);
434*3c7ae9deSAndroid Build Coastguard Worker } else if (client5_jni != NULL) {
435*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection = aws_mqtt_client_connection_new_from_mqtt5_client(client5_jni->client);
436*3c7ae9deSAndroid Build Coastguard Worker }
437*3c7ae9deSAndroid Build Coastguard Worker
438*3c7ae9deSAndroid Build Coastguard Worker if (!connection->client_connection) {
439*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
440*3c7ae9deSAndroid Build Coastguard Worker env,
441*3c7ae9deSAndroid Build Coastguard Worker "MqttClientConnection.mqtt_connect: aws_mqtt_client_connection_new failed, unable to create new "
442*3c7ae9deSAndroid Build Coastguard Worker "connection");
443*3c7ae9deSAndroid Build Coastguard Worker goto on_error;
444*3c7ae9deSAndroid Build Coastguard Worker }
445*3c7ae9deSAndroid Build Coastguard Worker
446*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_set_connection_termination_handler(
447*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_terminated, connection)) {
448*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
449*3c7ae9deSAndroid Build Coastguard Worker env,
450*3c7ae9deSAndroid Build Coastguard Worker "MqttClientConnection.mqtt_connect: aws_mqtt_client_connection_new failed, unable to set termination "
451*3c7ae9deSAndroid Build Coastguard Worker "callback");
452*3c7ae9deSAndroid Build Coastguard Worker goto on_error;
453*3c7ae9deSAndroid Build Coastguard Worker }
454*3c7ae9deSAndroid Build Coastguard Worker
455*3c7ae9deSAndroid Build Coastguard Worker return connection;
456*3c7ae9deSAndroid Build Coastguard Worker
457*3c7ae9deSAndroid Build Coastguard Worker on_error:
458*3c7ae9deSAndroid Build Coastguard Worker
459*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_release(connection);
460*3c7ae9deSAndroid Build Coastguard Worker
461*3c7ae9deSAndroid Build Coastguard Worker return NULL;
462*3c7ae9deSAndroid Build Coastguard Worker }
463*3c7ae9deSAndroid Build Coastguard Worker
s_mqtt_connection_destroy(JNIEnv * env,struct mqtt_jni_connection * connection)464*3c7ae9deSAndroid Build Coastguard Worker static void s_mqtt_connection_destroy(JNIEnv *env, struct mqtt_jni_connection *connection) {
465*3c7ae9deSAndroid Build Coastguard Worker if (connection == NULL) {
466*3c7ae9deSAndroid Build Coastguard Worker return;
467*3c7ae9deSAndroid Build Coastguard Worker }
468*3c7ae9deSAndroid Build Coastguard Worker
469*3c7ae9deSAndroid Build Coastguard Worker if (connection->on_message) {
470*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(connection->on_message, env);
471*3c7ae9deSAndroid Build Coastguard Worker }
472*3c7ae9deSAndroid Build Coastguard Worker
473*3c7ae9deSAndroid Build Coastguard Worker if (connection->java_mqtt_connection) {
474*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteWeakGlobalRef(env, connection->java_mqtt_connection);
475*3c7ae9deSAndroid Build Coastguard Worker }
476*3c7ae9deSAndroid Build Coastguard Worker
477*3c7ae9deSAndroid Build Coastguard Worker aws_tls_connection_options_clean_up(&connection->tls_options);
478*3c7ae9deSAndroid Build Coastguard Worker
479*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *allocator = aws_jni_get_allocator();
480*3c7ae9deSAndroid Build Coastguard Worker aws_mem_release(allocator, connection);
481*3c7ae9deSAndroid Build Coastguard Worker }
482*3c7ae9deSAndroid Build Coastguard Worker
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionNewFrom311Client(JNIEnv * env,jclass jni_class,jlong jni_client,jobject jni_mqtt_connection)483*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionNewFrom311Client(
484*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
485*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
486*3c7ae9deSAndroid Build Coastguard Worker jlong jni_client,
487*3c7ae9deSAndroid Build Coastguard Worker jobject jni_mqtt_connection) {
488*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
489*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
490*3c7ae9deSAndroid Build Coastguard Worker
491*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = NULL;
492*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client *client3 = (struct aws_mqtt_client *)jni_client;
493*3c7ae9deSAndroid Build Coastguard Worker if (!client3) {
494*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_new: Mqtt3 Client is invalid/null");
495*3c7ae9deSAndroid Build Coastguard Worker return (jlong)NULL;
496*3c7ae9deSAndroid Build Coastguard Worker }
497*3c7ae9deSAndroid Build Coastguard Worker
498*3c7ae9deSAndroid Build Coastguard Worker connection = s_mqtt_connection_new(env, client3, NULL, jni_mqtt_connection);
499*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
500*3c7ae9deSAndroid Build Coastguard Worker return (jlong)NULL;
501*3c7ae9deSAndroid Build Coastguard Worker }
502*3c7ae9deSAndroid Build Coastguard Worker
503*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_set_connection_result_handlers(
504*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_success, connection, s_on_connection_failure, connection);
505*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_set_connection_interruption_handlers(
506*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_interrupted, connection, s_on_connection_resumed, connection);
507*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_set_connection_closed_handler(
508*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_closed, connection);
509*3c7ae9deSAndroid Build Coastguard Worker
510*3c7ae9deSAndroid Build Coastguard Worker return (jlong)connection;
511*3c7ae9deSAndroid Build Coastguard Worker }
512*3c7ae9deSAndroid Build Coastguard Worker
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionNewFrom5Client(JNIEnv * env,jclass jni_class,jlong jni_client,jobject jni_mqtt_connection)513*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionNewFrom5Client(
514*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
515*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
516*3c7ae9deSAndroid Build Coastguard Worker jlong jni_client,
517*3c7ae9deSAndroid Build Coastguard Worker jobject jni_mqtt_connection) {
518*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
519*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
520*3c7ae9deSAndroid Build Coastguard Worker
521*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = NULL;
522*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt5_client_java_jni *client5_jni = (struct aws_mqtt5_client_java_jni *)jni_client;
523*3c7ae9deSAndroid Build Coastguard Worker if (!client5_jni) {
524*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_new: Mqtt5 Client is invalid/null");
525*3c7ae9deSAndroid Build Coastguard Worker return (jlong)NULL;
526*3c7ae9deSAndroid Build Coastguard Worker }
527*3c7ae9deSAndroid Build Coastguard Worker
528*3c7ae9deSAndroid Build Coastguard Worker connection = s_mqtt_connection_new(env, NULL, client5_jni, jni_mqtt_connection);
529*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
530*3c7ae9deSAndroid Build Coastguard Worker return (jlong)NULL;
531*3c7ae9deSAndroid Build Coastguard Worker }
532*3c7ae9deSAndroid Build Coastguard Worker
533*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_set_connection_result_handlers(
534*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_success, connection, s_on_connection_failure, connection);
535*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_set_connection_interruption_handlers(
536*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_interrupted, connection, s_on_connection_resumed, connection);
537*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_set_connection_closed_handler(
538*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_closed, connection);
539*3c7ae9deSAndroid Build Coastguard Worker
540*3c7ae9deSAndroid Build Coastguard Worker return (jlong)connection;
541*3c7ae9deSAndroid Build Coastguard Worker }
542*3c7ae9deSAndroid Build Coastguard Worker
543*3c7ae9deSAndroid Build Coastguard Worker /* The disconnect callback called on shutdown. We will release the underlying connection here, which should init the
544*3c7ae9deSAndroid Build Coastguard Worker ** client shutdown process. Then on termination callback, we will finally release all jni resources.
545*3c7ae9deSAndroid Build Coastguard Worker */
s_on_shutdown_disconnect_complete(struct aws_mqtt_client_connection * connection,void * user_data)546*3c7ae9deSAndroid Build Coastguard Worker static void s_on_shutdown_disconnect_complete(struct aws_mqtt_client_connection *connection, void *user_data) {
547*3c7ae9deSAndroid Build Coastguard Worker (void)user_data;
548*3c7ae9deSAndroid Build Coastguard Worker
549*3c7ae9deSAndroid Build Coastguard Worker AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "mqtt_jni_connection shutdown complete, releasing references");
550*3c7ae9deSAndroid Build Coastguard Worker
551*3c7ae9deSAndroid Build Coastguard Worker /* Release the underlying mqtt connection */
552*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_release(connection);
553*3c7ae9deSAndroid Build Coastguard Worker }
554*3c7ae9deSAndroid Build Coastguard Worker
555*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
556*3c7ae9deSAndroid Build Coastguard Worker * clean_up
557*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionDestroy(JNIEnv * env,jclass jni_class,jlong jni_connection)558*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionDestroy(
559*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
560*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
561*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection) {
562*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
563*3c7ae9deSAndroid Build Coastguard Worker (void)env;
564*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
565*3c7ae9deSAndroid Build Coastguard Worker
566*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
567*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_destroy(connection);
568*3c7ae9deSAndroid Build Coastguard Worker }
569*3c7ae9deSAndroid Build Coastguard Worker
570*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
571*3c7ae9deSAndroid Build Coastguard Worker * connect
572*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
573*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionConnect(JNIEnv * env,jclass jni_class,jlong jni_connection,jstring jni_endpoint,jint jni_port,jlong jni_socket_options,jlong jni_tls_ctx,jstring jni_client_id,jboolean jni_clean_session,jint keep_alive_secs,jshort ping_timeout_ms,jint protocol_operation_timeout_ms)574*3c7ae9deSAndroid Build Coastguard Worker void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionConnect(
575*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
576*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
577*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
578*3c7ae9deSAndroid Build Coastguard Worker jstring jni_endpoint,
579*3c7ae9deSAndroid Build Coastguard Worker jint jni_port,
580*3c7ae9deSAndroid Build Coastguard Worker jlong jni_socket_options,
581*3c7ae9deSAndroid Build Coastguard Worker jlong jni_tls_ctx,
582*3c7ae9deSAndroid Build Coastguard Worker jstring jni_client_id,
583*3c7ae9deSAndroid Build Coastguard Worker jboolean jni_clean_session,
584*3c7ae9deSAndroid Build Coastguard Worker jint keep_alive_secs,
585*3c7ae9deSAndroid Build Coastguard Worker jshort ping_timeout_ms,
586*3c7ae9deSAndroid Build Coastguard Worker jint protocol_operation_timeout_ms) {
587*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
588*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
589*3c7ae9deSAndroid Build Coastguard Worker
590*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
591*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
592*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_connect: Connection is invalid/null");
593*3c7ae9deSAndroid Build Coastguard Worker return;
594*3c7ae9deSAndroid Build Coastguard Worker }
595*3c7ae9deSAndroid Build Coastguard Worker
596*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor client_id;
597*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(client_id);
598*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor endpoint = aws_jni_byte_cursor_from_jstring_acquire(env, jni_endpoint);
599*3c7ae9deSAndroid Build Coastguard Worker uint32_t port = (uint32_t)jni_port;
600*3c7ae9deSAndroid Build Coastguard Worker if (!port) {
601*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
602*3c7ae9deSAndroid Build Coastguard Worker env,
603*3c7ae9deSAndroid Build Coastguard Worker "MqttClientConnection.mqtt_new: Endpoint should be in the format hostname:port and port must not be 0");
604*3c7ae9deSAndroid Build Coastguard Worker goto cleanup;
605*3c7ae9deSAndroid Build Coastguard Worker }
606*3c7ae9deSAndroid Build Coastguard Worker
607*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *connect_callback = s_mqtt_jni_async_callback_new(connection, NULL, env);
608*3c7ae9deSAndroid Build Coastguard Worker if (connect_callback == NULL) {
609*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_connect: Failed to create async callback");
610*3c7ae9deSAndroid Build Coastguard Worker goto cleanup;
611*3c7ae9deSAndroid Build Coastguard Worker }
612*3c7ae9deSAndroid Build Coastguard Worker
613*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_acquire(connection);
614*3c7ae9deSAndroid Build Coastguard Worker
615*3c7ae9deSAndroid Build Coastguard Worker struct aws_socket_options default_socket_options;
616*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(default_socket_options);
617*3c7ae9deSAndroid Build Coastguard Worker default_socket_options.type = AWS_SOCKET_STREAM;
618*3c7ae9deSAndroid Build Coastguard Worker default_socket_options.connect_timeout_ms = 3000;
619*3c7ae9deSAndroid Build Coastguard Worker struct aws_socket_options *socket_options = &default_socket_options;
620*3c7ae9deSAndroid Build Coastguard Worker if (jni_socket_options) {
621*3c7ae9deSAndroid Build Coastguard Worker socket_options = (struct aws_socket_options *)jni_socket_options;
622*3c7ae9deSAndroid Build Coastguard Worker }
623*3c7ae9deSAndroid Build Coastguard Worker memcpy(&connection->socket_options, socket_options, sizeof(struct aws_socket_options));
624*3c7ae9deSAndroid Build Coastguard Worker
625*3c7ae9deSAndroid Build Coastguard Worker /* if a tls_ctx was provided, initialize tls options */
626*3c7ae9deSAndroid Build Coastguard Worker struct aws_tls_ctx *tls_ctx = (struct aws_tls_ctx *)jni_tls_ctx;
627*3c7ae9deSAndroid Build Coastguard Worker struct aws_tls_connection_options *tls_options = NULL;
628*3c7ae9deSAndroid Build Coastguard Worker if (tls_ctx) {
629*3c7ae9deSAndroid Build Coastguard Worker tls_options = &connection->tls_options;
630*3c7ae9deSAndroid Build Coastguard Worker aws_tls_connection_options_init_from_ctx(tls_options, tls_ctx);
631*3c7ae9deSAndroid Build Coastguard Worker aws_tls_connection_options_set_server_name(tls_options, aws_jni_get_allocator(), &endpoint);
632*3c7ae9deSAndroid Build Coastguard Worker }
633*3c7ae9deSAndroid Build Coastguard Worker
634*3c7ae9deSAndroid Build Coastguard Worker client_id = aws_jni_byte_cursor_from_jstring_acquire(env, jni_client_id);
635*3c7ae9deSAndroid Build Coastguard Worker bool clean_session = jni_clean_session != 0;
636*3c7ae9deSAndroid Build Coastguard Worker
637*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_connection_options connect_options;
638*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(connect_options);
639*3c7ae9deSAndroid Build Coastguard Worker connect_options.host_name = endpoint;
640*3c7ae9deSAndroid Build Coastguard Worker connect_options.port = port;
641*3c7ae9deSAndroid Build Coastguard Worker connect_options.socket_options = &connection->socket_options;
642*3c7ae9deSAndroid Build Coastguard Worker connect_options.tls_options = tls_options;
643*3c7ae9deSAndroid Build Coastguard Worker connect_options.client_id = client_id;
644*3c7ae9deSAndroid Build Coastguard Worker connect_options.keep_alive_time_secs = (uint16_t)keep_alive_secs;
645*3c7ae9deSAndroid Build Coastguard Worker connect_options.ping_timeout_ms = ping_timeout_ms;
646*3c7ae9deSAndroid Build Coastguard Worker connect_options.protocol_operation_timeout_ms = protocol_operation_timeout_ms;
647*3c7ae9deSAndroid Build Coastguard Worker connect_options.clean_session = clean_session;
648*3c7ae9deSAndroid Build Coastguard Worker connect_options.on_connection_complete = s_on_connection_complete;
649*3c7ae9deSAndroid Build Coastguard Worker connect_options.user_data = connect_callback;
650*3c7ae9deSAndroid Build Coastguard Worker
651*3c7ae9deSAndroid Build Coastguard Worker int result = aws_mqtt_client_connection_connect(connection->client_connection, &connect_options);
652*3c7ae9deSAndroid Build Coastguard Worker if (result != AWS_OP_SUCCESS) {
653*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_release(connection);
654*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(connect_callback, env);
655*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
656*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqtt_connect: aws_mqtt_client_connection_connect failed");
657*3c7ae9deSAndroid Build Coastguard Worker }
658*3c7ae9deSAndroid Build Coastguard Worker
659*3c7ae9deSAndroid Build Coastguard Worker cleanup:
660*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_endpoint, endpoint);
661*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_client_id, client_id);
662*3c7ae9deSAndroid Build Coastguard Worker }
663*3c7ae9deSAndroid Build Coastguard Worker
664*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
665*3c7ae9deSAndroid Build Coastguard Worker * disconnect
666*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
667*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionDisconnect(JNIEnv * env,jclass jni_class,jlong jni_connection,jobject jni_ack)668*3c7ae9deSAndroid Build Coastguard Worker void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionDisconnect(
669*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
670*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
671*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
672*3c7ae9deSAndroid Build Coastguard Worker jobject jni_ack) {
673*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
674*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
675*3c7ae9deSAndroid Build Coastguard Worker
676*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
677*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
678*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_disconnect: Invalid connection");
679*3c7ae9deSAndroid Build Coastguard Worker return;
680*3c7ae9deSAndroid Build Coastguard Worker }
681*3c7ae9deSAndroid Build Coastguard Worker
682*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *disconnect_callback = s_mqtt_jni_async_callback_new(connection, jni_ack, env);
683*3c7ae9deSAndroid Build Coastguard Worker if (disconnect_callback == NULL) {
684*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_disconnect: Failed to create async callback");
685*3c7ae9deSAndroid Build Coastguard Worker return;
686*3c7ae9deSAndroid Build Coastguard Worker }
687*3c7ae9deSAndroid Build Coastguard Worker
688*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_disconnect(
689*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_connection_disconnected, disconnect_callback) != AWS_OP_SUCCESS) {
690*3c7ae9deSAndroid Build Coastguard Worker int error = aws_last_error();
691*3c7ae9deSAndroid Build Coastguard Worker /*
692*3c7ae9deSAndroid Build Coastguard Worker * Disconnect invoked on a disconnected connection can happen under normal circumstances. Invoke the callback
693*3c7ae9deSAndroid Build Coastguard Worker * manually since it won't get invoked otherwise.
694*3c7ae9deSAndroid Build Coastguard Worker */
695*3c7ae9deSAndroid Build Coastguard Worker AWS_LOGF_WARN(
696*3c7ae9deSAndroid Build Coastguard Worker AWS_LS_MQTT_CLIENT,
697*3c7ae9deSAndroid Build Coastguard Worker "MqttClientConnection.mqtt_disconnect: error calling disconnect - %d(%s)",
698*3c7ae9deSAndroid Build Coastguard Worker error,
699*3c7ae9deSAndroid Build Coastguard Worker aws_error_str(error));
700*3c7ae9deSAndroid Build Coastguard Worker s_on_connection_disconnected(connection->client_connection, disconnect_callback);
701*3c7ae9deSAndroid Build Coastguard Worker }
702*3c7ae9deSAndroid Build Coastguard Worker }
703*3c7ae9deSAndroid Build Coastguard Worker
704*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
705*3c7ae9deSAndroid Build Coastguard Worker * subscribe
706*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
707*3c7ae9deSAndroid Build Coastguard Worker /* called from any sub, unsub, or pub ack */
s_deliver_ack_success(struct mqtt_jni_async_callback * callback,JNIEnv * env)708*3c7ae9deSAndroid Build Coastguard Worker static void s_deliver_ack_success(struct mqtt_jni_async_callback *callback, JNIEnv *env) {
709*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(callback);
710*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(callback->connection);
711*3c7ae9deSAndroid Build Coastguard Worker
712*3c7ae9deSAndroid Build Coastguard Worker if (callback->async_callback) {
713*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, callback->async_callback, async_callback_properties.on_success);
714*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
715*3c7ae9deSAndroid Build Coastguard Worker }
716*3c7ae9deSAndroid Build Coastguard Worker }
717*3c7ae9deSAndroid Build Coastguard Worker
s_deliver_ack_failure(struct mqtt_jni_async_callback * callback,int error_code,JNIEnv * env)718*3c7ae9deSAndroid Build Coastguard Worker static void s_deliver_ack_failure(struct mqtt_jni_async_callback *callback, int error_code, JNIEnv *env) {
719*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(callback);
720*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(callback->connection);
721*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(env);
722*3c7ae9deSAndroid Build Coastguard Worker
723*3c7ae9deSAndroid Build Coastguard Worker if (callback->async_callback) {
724*3c7ae9deSAndroid Build Coastguard Worker jobject jni_reason = s_new_mqtt_exception(env, error_code);
725*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(env, callback->async_callback, async_callback_properties.on_failure, jni_reason);
726*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, jni_reason);
727*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
728*3c7ae9deSAndroid Build Coastguard Worker }
729*3c7ae9deSAndroid Build Coastguard Worker }
730*3c7ae9deSAndroid Build Coastguard Worker
s_on_op_complete(struct aws_mqtt_client_connection * connection,uint16_t packet_id,int error_code,void * user_data)731*3c7ae9deSAndroid Build Coastguard Worker static void s_on_op_complete(
732*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *connection,
733*3c7ae9deSAndroid Build Coastguard Worker uint16_t packet_id,
734*3c7ae9deSAndroid Build Coastguard Worker int error_code,
735*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
736*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(connection);
737*3c7ae9deSAndroid Build Coastguard Worker (void)packet_id;
738*3c7ae9deSAndroid Build Coastguard Worker
739*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *callback = user_data;
740*3c7ae9deSAndroid Build Coastguard Worker if (!callback) {
741*3c7ae9deSAndroid Build Coastguard Worker return;
742*3c7ae9deSAndroid Build Coastguard Worker }
743*3c7ae9deSAndroid Build Coastguard Worker
744*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
745*3c7ae9deSAndroid Build Coastguard Worker JavaVM *jvm = callback->connection->jvm;
746*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(jvm);
747*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
748*3c7ae9deSAndroid Build Coastguard Worker return;
749*3c7ae9deSAndroid Build Coastguard Worker }
750*3c7ae9deSAndroid Build Coastguard Worker
751*3c7ae9deSAndroid Build Coastguard Worker if (error_code) {
752*3c7ae9deSAndroid Build Coastguard Worker s_deliver_ack_failure(callback, error_code, env);
753*3c7ae9deSAndroid Build Coastguard Worker } else {
754*3c7ae9deSAndroid Build Coastguard Worker s_deliver_ack_success(callback, env);
755*3c7ae9deSAndroid Build Coastguard Worker }
756*3c7ae9deSAndroid Build Coastguard Worker
757*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(callback, env);
758*3c7ae9deSAndroid Build Coastguard Worker
759*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(jvm, env);
760*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
761*3c7ae9deSAndroid Build Coastguard Worker }
762*3c7ae9deSAndroid Build Coastguard Worker
s_is_qos_successful(enum aws_mqtt_qos qos)763*3c7ae9deSAndroid Build Coastguard Worker static bool s_is_qos_successful(enum aws_mqtt_qos qos) {
764*3c7ae9deSAndroid Build Coastguard Worker return qos < 128;
765*3c7ae9deSAndroid Build Coastguard Worker }
766*3c7ae9deSAndroid Build Coastguard Worker
s_on_ack(struct aws_mqtt_client_connection * connection,uint16_t packet_id,const struct aws_byte_cursor * topic,enum aws_mqtt_qos qos,int error_code,void * user_data)767*3c7ae9deSAndroid Build Coastguard Worker static void s_on_ack(
768*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *connection,
769*3c7ae9deSAndroid Build Coastguard Worker uint16_t packet_id,
770*3c7ae9deSAndroid Build Coastguard Worker const struct aws_byte_cursor *topic,
771*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_qos qos,
772*3c7ae9deSAndroid Build Coastguard Worker int error_code,
773*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
774*3c7ae9deSAndroid Build Coastguard Worker (void)topic;
775*3c7ae9deSAndroid Build Coastguard Worker
776*3c7ae9deSAndroid Build Coastguard Worker // Handle a case when the server processed SUBSCRIBE request successfully, but rejected a subscription for some
777*3c7ae9deSAndroid Build Coastguard Worker // reason, i.e. error_code is 0 and qos is 0x80.
778*3c7ae9deSAndroid Build Coastguard Worker // This mostly applies to mqtt5to3adapter, as MQTT3 client will be disconnected on unsuccessful subscribe.
779*3c7ae9deSAndroid Build Coastguard Worker if (error_code == 0 && !s_is_qos_successful(qos)) {
780*3c7ae9deSAndroid Build Coastguard Worker error_code = AWS_ERROR_MQTT_CONNECTION_SUBSCRIBE_FAILURE;
781*3c7ae9deSAndroid Build Coastguard Worker }
782*3c7ae9deSAndroid Build Coastguard Worker
783*3c7ae9deSAndroid Build Coastguard Worker s_on_op_complete(connection, packet_id, error_code, user_data);
784*3c7ae9deSAndroid Build Coastguard Worker }
785*3c7ae9deSAndroid Build Coastguard Worker
s_cleanup_handler(void * user_data)786*3c7ae9deSAndroid Build Coastguard Worker static void s_cleanup_handler(void *user_data) {
787*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *handler = user_data;
788*3c7ae9deSAndroid Build Coastguard Worker
789*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
790*3c7ae9deSAndroid Build Coastguard Worker JavaVM *jvm = handler->connection->jvm;
791*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(jvm);
792*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
793*3c7ae9deSAndroid Build Coastguard Worker return;
794*3c7ae9deSAndroid Build Coastguard Worker }
795*3c7ae9deSAndroid Build Coastguard Worker
796*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(handler, env);
797*3c7ae9deSAndroid Build Coastguard Worker
798*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(jvm, env);
799*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
800*3c7ae9deSAndroid Build Coastguard Worker }
801*3c7ae9deSAndroid Build Coastguard Worker
s_on_subscription_delivered(struct aws_mqtt_client_connection * connection,const struct aws_byte_cursor * topic,const struct aws_byte_cursor * payload,bool dup,enum aws_mqtt_qos qos,bool retain,void * user_data)802*3c7ae9deSAndroid Build Coastguard Worker static void s_on_subscription_delivered(
803*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_client_connection *connection,
804*3c7ae9deSAndroid Build Coastguard Worker const struct aws_byte_cursor *topic,
805*3c7ae9deSAndroid Build Coastguard Worker const struct aws_byte_cursor *payload,
806*3c7ae9deSAndroid Build Coastguard Worker bool dup,
807*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_qos qos,
808*3c7ae9deSAndroid Build Coastguard Worker bool retain,
809*3c7ae9deSAndroid Build Coastguard Worker void *user_data) {
810*3c7ae9deSAndroid Build Coastguard Worker
811*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(connection);
812*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(topic);
813*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(payload);
814*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(user_data);
815*3c7ae9deSAndroid Build Coastguard Worker
816*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *callback = user_data;
817*3c7ae9deSAndroid Build Coastguard Worker if (!callback->async_callback) {
818*3c7ae9deSAndroid Build Coastguard Worker return;
819*3c7ae9deSAndroid Build Coastguard Worker }
820*3c7ae9deSAndroid Build Coastguard Worker
821*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
822*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(callback->connection->jvm);
823*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
824*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
825*3c7ae9deSAndroid Build Coastguard Worker return;
826*3c7ae9deSAndroid Build Coastguard Worker }
827*3c7ae9deSAndroid Build Coastguard Worker
828*3c7ae9deSAndroid Build Coastguard Worker jbyteArray jni_payload = (*env)->NewByteArray(env, (jsize)payload->len);
829*3c7ae9deSAndroid Build Coastguard Worker (*env)->SetByteArrayRegion(env, jni_payload, 0, (jsize)payload->len, (const signed char *)payload->ptr);
830*3c7ae9deSAndroid Build Coastguard Worker
831*3c7ae9deSAndroid Build Coastguard Worker jstring jni_topic = aws_jni_string_from_cursor(env, topic);
832*3c7ae9deSAndroid Build Coastguard Worker
833*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(
834*3c7ae9deSAndroid Build Coastguard Worker env, callback->async_callback, message_handler_properties.deliver, jni_topic, jni_payload, dup, qos, retain);
835*3c7ae9deSAndroid Build Coastguard Worker
836*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, jni_payload);
837*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, jni_topic);
838*3c7ae9deSAndroid Build Coastguard Worker
839*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
840*3c7ae9deSAndroid Build Coastguard Worker
841*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(callback->connection->jvm, env);
842*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
843*3c7ae9deSAndroid Build Coastguard Worker }
844*3c7ae9deSAndroid Build Coastguard Worker
845*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSubscribe(JNIEnv * env,jclass jni_class,jlong jni_connection,jstring jni_topic,jint jni_qos,jobject jni_handler,jobject jni_ack)846*3c7ae9deSAndroid Build Coastguard Worker jshort JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSubscribe(
847*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
848*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
849*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
850*3c7ae9deSAndroid Build Coastguard Worker jstring jni_topic,
851*3c7ae9deSAndroid Build Coastguard Worker jint jni_qos,
852*3c7ae9deSAndroid Build Coastguard Worker jobject jni_handler,
853*3c7ae9deSAndroid Build Coastguard Worker jobject jni_ack) {
854*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
855*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
856*3c7ae9deSAndroid Build Coastguard Worker
857*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
858*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
859*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_subscribe: Invalid connection");
860*3c7ae9deSAndroid Build Coastguard Worker return 0;
861*3c7ae9deSAndroid Build Coastguard Worker }
862*3c7ae9deSAndroid Build Coastguard Worker
863*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *handler = s_mqtt_jni_async_callback_new(connection, jni_handler, env);
864*3c7ae9deSAndroid Build Coastguard Worker if (!handler) {
865*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_subscribe: Unable to allocate handler");
866*3c7ae9deSAndroid Build Coastguard Worker return 0;
867*3c7ae9deSAndroid Build Coastguard Worker }
868*3c7ae9deSAndroid Build Coastguard Worker
869*3c7ae9deSAndroid Build Coastguard Worker /* from here, any failure requires error_cleanup */
870*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *sub_ack = NULL;
871*3c7ae9deSAndroid Build Coastguard Worker if (jni_ack) {
872*3c7ae9deSAndroid Build Coastguard Worker sub_ack = s_mqtt_jni_async_callback_new(connection, jni_ack, env);
873*3c7ae9deSAndroid Build Coastguard Worker if (!sub_ack) {
874*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_subscribe: Unable to allocate sub ack");
875*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
876*3c7ae9deSAndroid Build Coastguard Worker }
877*3c7ae9deSAndroid Build Coastguard Worker }
878*3c7ae9deSAndroid Build Coastguard Worker
879*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor topic = aws_jni_byte_cursor_from_jstring_acquire(env, jni_topic);
880*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_qos qos = jni_qos;
881*3c7ae9deSAndroid Build Coastguard Worker
882*3c7ae9deSAndroid Build Coastguard Worker uint16_t msg_id = aws_mqtt_client_connection_subscribe(
883*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection,
884*3c7ae9deSAndroid Build Coastguard Worker &topic,
885*3c7ae9deSAndroid Build Coastguard Worker qos,
886*3c7ae9deSAndroid Build Coastguard Worker s_on_subscription_delivered,
887*3c7ae9deSAndroid Build Coastguard Worker handler,
888*3c7ae9deSAndroid Build Coastguard Worker s_cleanup_handler,
889*3c7ae9deSAndroid Build Coastguard Worker s_on_ack,
890*3c7ae9deSAndroid Build Coastguard Worker sub_ack);
891*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_topic, topic);
892*3c7ae9deSAndroid Build Coastguard Worker if (msg_id == 0) {
893*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
894*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqtt_subscribe: aws_mqtt_client_connection_subscribe failed");
895*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
896*3c7ae9deSAndroid Build Coastguard Worker }
897*3c7ae9deSAndroid Build Coastguard Worker
898*3c7ae9deSAndroid Build Coastguard Worker return msg_id;
899*3c7ae9deSAndroid Build Coastguard Worker
900*3c7ae9deSAndroid Build Coastguard Worker error_cleanup:
901*3c7ae9deSAndroid Build Coastguard Worker if (handler) {
902*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(handler, env);
903*3c7ae9deSAndroid Build Coastguard Worker }
904*3c7ae9deSAndroid Build Coastguard Worker
905*3c7ae9deSAndroid Build Coastguard Worker if (sub_ack) {
906*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(sub_ack, env);
907*3c7ae9deSAndroid Build Coastguard Worker }
908*3c7ae9deSAndroid Build Coastguard Worker
909*3c7ae9deSAndroid Build Coastguard Worker return 0;
910*3c7ae9deSAndroid Build Coastguard Worker }
911*3c7ae9deSAndroid Build Coastguard Worker
912*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionOnMessage(JNIEnv * env,jclass jni_class,jlong jni_connection,jobject jni_handler)913*3c7ae9deSAndroid Build Coastguard Worker void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionOnMessage(
914*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
915*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
916*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
917*3c7ae9deSAndroid Build Coastguard Worker jobject jni_handler) {
918*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
919*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
920*3c7ae9deSAndroid Build Coastguard Worker
921*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
922*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
923*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqttClientConnectionOnMessage: Invalid connection");
924*3c7ae9deSAndroid Build Coastguard Worker return;
925*3c7ae9deSAndroid Build Coastguard Worker }
926*3c7ae9deSAndroid Build Coastguard Worker
927*3c7ae9deSAndroid Build Coastguard Worker if (!jni_handler) {
928*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqttClientConnectionOnMessage: Invalid handler");
929*3c7ae9deSAndroid Build Coastguard Worker return;
930*3c7ae9deSAndroid Build Coastguard Worker }
931*3c7ae9deSAndroid Build Coastguard Worker
932*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *handler = s_mqtt_jni_async_callback_new(connection, jni_handler, env);
933*3c7ae9deSAndroid Build Coastguard Worker if (!handler) {
934*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
935*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqttClientConnectionOnMessage: Unable to allocate handler");
936*3c7ae9deSAndroid Build Coastguard Worker return;
937*3c7ae9deSAndroid Build Coastguard Worker }
938*3c7ae9deSAndroid Build Coastguard Worker
939*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_set_on_any_publish_handler(
940*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_on_subscription_delivered, handler)) {
941*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
942*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqttClientConnectionOnMessage: Failed to install on_any_publish_handler");
943*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
944*3c7ae9deSAndroid Build Coastguard Worker }
945*3c7ae9deSAndroid Build Coastguard Worker
946*3c7ae9deSAndroid Build Coastguard Worker if (connection->on_message) {
947*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(connection->on_message, env);
948*3c7ae9deSAndroid Build Coastguard Worker }
949*3c7ae9deSAndroid Build Coastguard Worker
950*3c7ae9deSAndroid Build Coastguard Worker connection->on_message = handler;
951*3c7ae9deSAndroid Build Coastguard Worker
952*3c7ae9deSAndroid Build Coastguard Worker return;
953*3c7ae9deSAndroid Build Coastguard Worker
954*3c7ae9deSAndroid Build Coastguard Worker error_cleanup:
955*3c7ae9deSAndroid Build Coastguard Worker if (handler) {
956*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(handler, env);
957*3c7ae9deSAndroid Build Coastguard Worker }
958*3c7ae9deSAndroid Build Coastguard Worker }
959*3c7ae9deSAndroid Build Coastguard Worker
960*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
961*3c7ae9deSAndroid Build Coastguard Worker * unsubscribe
962*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
963*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionUnsubscribe(JNIEnv * env,jclass jni_class,jlong jni_connection,jstring jni_topic,jobject jni_ack)964*3c7ae9deSAndroid Build Coastguard Worker jshort JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionUnsubscribe(
965*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
966*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
967*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
968*3c7ae9deSAndroid Build Coastguard Worker jstring jni_topic,
969*3c7ae9deSAndroid Build Coastguard Worker jobject jni_ack) {
970*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
971*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
972*3c7ae9deSAndroid Build Coastguard Worker
973*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
974*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
975*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_unsubscribe: Invalid connection");
976*3c7ae9deSAndroid Build Coastguard Worker return 0;
977*3c7ae9deSAndroid Build Coastguard Worker }
978*3c7ae9deSAndroid Build Coastguard Worker
979*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *unsub_ack = s_mqtt_jni_async_callback_new(connection, jni_ack, env);
980*3c7ae9deSAndroid Build Coastguard Worker if (!unsub_ack) {
981*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_unsubscribe: Unable to allocate unsub ack");
982*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
983*3c7ae9deSAndroid Build Coastguard Worker }
984*3c7ae9deSAndroid Build Coastguard Worker
985*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor topic = aws_jni_byte_cursor_from_jstring_acquire(env, jni_topic);
986*3c7ae9deSAndroid Build Coastguard Worker uint16_t msg_id =
987*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_unsubscribe(connection->client_connection, &topic, s_on_op_complete, unsub_ack);
988*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_topic, topic);
989*3c7ae9deSAndroid Build Coastguard Worker if (msg_id == 0) {
990*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
991*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqtt_unsubscribe: aws_mqtt_client_connection_unsubscribe failed");
992*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
993*3c7ae9deSAndroid Build Coastguard Worker }
994*3c7ae9deSAndroid Build Coastguard Worker
995*3c7ae9deSAndroid Build Coastguard Worker return msg_id;
996*3c7ae9deSAndroid Build Coastguard Worker
997*3c7ae9deSAndroid Build Coastguard Worker error_cleanup:
998*3c7ae9deSAndroid Build Coastguard Worker if (unsub_ack) {
999*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(unsub_ack, env);
1000*3c7ae9deSAndroid Build Coastguard Worker }
1001*3c7ae9deSAndroid Build Coastguard Worker return 0;
1002*3c7ae9deSAndroid Build Coastguard Worker }
1003*3c7ae9deSAndroid Build Coastguard Worker
1004*3c7ae9deSAndroid Build Coastguard Worker /*******************************************************************************
1005*3c7ae9deSAndroid Build Coastguard Worker * publish
1006*3c7ae9deSAndroid Build Coastguard Worker ******************************************************************************/
1007*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionPublish(JNIEnv * env,jclass jni_class,jlong jni_connection,jstring jni_topic,jint jni_qos,jboolean jni_retain,jbyteArray jni_payload,jobject jni_ack)1008*3c7ae9deSAndroid Build Coastguard Worker jshort JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionPublish(
1009*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1010*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1011*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
1012*3c7ae9deSAndroid Build Coastguard Worker jstring jni_topic,
1013*3c7ae9deSAndroid Build Coastguard Worker jint jni_qos,
1014*3c7ae9deSAndroid Build Coastguard Worker jboolean jni_retain,
1015*3c7ae9deSAndroid Build Coastguard Worker jbyteArray jni_payload,
1016*3c7ae9deSAndroid Build Coastguard Worker jobject jni_ack) {
1017*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1018*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1019*3c7ae9deSAndroid Build Coastguard Worker
1020*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1021*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
1022*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_publish: Invalid connection");
1023*3c7ae9deSAndroid Build Coastguard Worker return 0;
1024*3c7ae9deSAndroid Build Coastguard Worker }
1025*3c7ae9deSAndroid Build Coastguard Worker
1026*3c7ae9deSAndroid Build Coastguard Worker if (!jni_topic) {
1027*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_publish: Invalid/null topic");
1028*3c7ae9deSAndroid Build Coastguard Worker return 0;
1029*3c7ae9deSAndroid Build Coastguard Worker }
1030*3c7ae9deSAndroid Build Coastguard Worker
1031*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_async_callback *pub_ack = s_mqtt_jni_async_callback_new(connection, jni_ack, env);
1032*3c7ae9deSAndroid Build Coastguard Worker if (!pub_ack) {
1033*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_publish: Unable to allocate pub ack");
1034*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
1035*3c7ae9deSAndroid Build Coastguard Worker }
1036*3c7ae9deSAndroid Build Coastguard Worker
1037*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor topic = aws_jni_byte_cursor_from_jstring_acquire(env, jni_topic);
1038*3c7ae9deSAndroid Build Coastguard Worker
1039*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor payload;
1040*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(payload);
1041*3c7ae9deSAndroid Build Coastguard Worker if (jni_payload != NULL) {
1042*3c7ae9deSAndroid Build Coastguard Worker payload = aws_jni_byte_cursor_from_jbyteArray_acquire(env, jni_payload);
1043*3c7ae9deSAndroid Build Coastguard Worker }
1044*3c7ae9deSAndroid Build Coastguard Worker
1045*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_qos qos = jni_qos;
1046*3c7ae9deSAndroid Build Coastguard Worker bool retain = jni_retain != 0;
1047*3c7ae9deSAndroid Build Coastguard Worker
1048*3c7ae9deSAndroid Build Coastguard Worker uint16_t msg_id = aws_mqtt_client_connection_publish(
1049*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, &topic, qos, retain, &payload, s_on_op_complete, pub_ack);
1050*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_topic, topic);
1051*3c7ae9deSAndroid Build Coastguard Worker
1052*3c7ae9deSAndroid Build Coastguard Worker if (jni_payload != NULL) {
1053*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jbyteArray_release(env, jni_payload, payload);
1054*3c7ae9deSAndroid Build Coastguard Worker }
1055*3c7ae9deSAndroid Build Coastguard Worker
1056*3c7ae9deSAndroid Build Coastguard Worker if (msg_id == 0) {
1057*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1058*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqtt_publish: aws_mqtt_client_connection_publish failed");
1059*3c7ae9deSAndroid Build Coastguard Worker goto error_cleanup;
1060*3c7ae9deSAndroid Build Coastguard Worker }
1061*3c7ae9deSAndroid Build Coastguard Worker
1062*3c7ae9deSAndroid Build Coastguard Worker return msg_id;
1063*3c7ae9deSAndroid Build Coastguard Worker
1064*3c7ae9deSAndroid Build Coastguard Worker error_cleanup:
1065*3c7ae9deSAndroid Build Coastguard Worker if (pub_ack) {
1066*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_async_callback_destroy(pub_ack, env);
1067*3c7ae9deSAndroid Build Coastguard Worker }
1068*3c7ae9deSAndroid Build Coastguard Worker
1069*3c7ae9deSAndroid Build Coastguard Worker return 0;
1070*3c7ae9deSAndroid Build Coastguard Worker }
1071*3c7ae9deSAndroid Build Coastguard Worker
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetWill(JNIEnv * env,jclass jni_class,jlong jni_connection,jstring jni_topic,jint jni_qos,jboolean jni_retain,jbyteArray jni_payload)1072*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jboolean JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetWill(
1073*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1074*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1075*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
1076*3c7ae9deSAndroid Build Coastguard Worker jstring jni_topic,
1077*3c7ae9deSAndroid Build Coastguard Worker jint jni_qos,
1078*3c7ae9deSAndroid Build Coastguard Worker jboolean jni_retain,
1079*3c7ae9deSAndroid Build Coastguard Worker jbyteArray jni_payload) {
1080*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1081*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1082*3c7ae9deSAndroid Build Coastguard Worker
1083*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1084*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
1085*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_will: Invalid connection");
1086*3c7ae9deSAndroid Build Coastguard Worker return false;
1087*3c7ae9deSAndroid Build Coastguard Worker }
1088*3c7ae9deSAndroid Build Coastguard Worker
1089*3c7ae9deSAndroid Build Coastguard Worker if (jni_topic == NULL) {
1090*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_will: Topic must be non-null");
1091*3c7ae9deSAndroid Build Coastguard Worker return false;
1092*3c7ae9deSAndroid Build Coastguard Worker }
1093*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor topic = aws_jni_byte_cursor_from_jstring_acquire(env, jni_topic);
1094*3c7ae9deSAndroid Build Coastguard Worker
1095*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor payload;
1096*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(payload);
1097*3c7ae9deSAndroid Build Coastguard Worker if (jni_payload != NULL) {
1098*3c7ae9deSAndroid Build Coastguard Worker payload = aws_jni_byte_cursor_from_jbyteArray_acquire(env, jni_payload);
1099*3c7ae9deSAndroid Build Coastguard Worker }
1100*3c7ae9deSAndroid Build Coastguard Worker
1101*3c7ae9deSAndroid Build Coastguard Worker enum aws_mqtt_qos qos = jni_qos;
1102*3c7ae9deSAndroid Build Coastguard Worker bool retain = jni_retain != 0;
1103*3c7ae9deSAndroid Build Coastguard Worker
1104*3c7ae9deSAndroid Build Coastguard Worker int result = aws_mqtt_client_connection_set_will(connection->client_connection, &topic, qos, retain, &payload);
1105*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_topic, topic);
1106*3c7ae9deSAndroid Build Coastguard Worker
1107*3c7ae9deSAndroid Build Coastguard Worker if (jni_payload != NULL) {
1108*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jbyteArray_release(env, jni_payload, payload);
1109*3c7ae9deSAndroid Build Coastguard Worker }
1110*3c7ae9deSAndroid Build Coastguard Worker
1111*3c7ae9deSAndroid Build Coastguard Worker return (result == AWS_OP_SUCCESS);
1112*3c7ae9deSAndroid Build Coastguard Worker }
1113*3c7ae9deSAndroid Build Coastguard Worker
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetLogin(JNIEnv * env,jclass jni_class,jlong jni_connection,jstring jni_user,jstring jni_pass)1114*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetLogin(
1115*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1116*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1117*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
1118*3c7ae9deSAndroid Build Coastguard Worker jstring jni_user,
1119*3c7ae9deSAndroid Build Coastguard Worker jstring jni_pass) {
1120*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1121*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1122*3c7ae9deSAndroid Build Coastguard Worker
1123*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1124*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
1125*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_login: Invalid connection");
1126*3c7ae9deSAndroid Build Coastguard Worker return;
1127*3c7ae9deSAndroid Build Coastguard Worker }
1128*3c7ae9deSAndroid Build Coastguard Worker
1129*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor username = aws_jni_byte_cursor_from_jstring_acquire(env, jni_user);
1130*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor password;
1131*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor *password_ptr = NULL;
1132*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(password);
1133*3c7ae9deSAndroid Build Coastguard Worker if (jni_pass != NULL) {
1134*3c7ae9deSAndroid Build Coastguard Worker password = aws_jni_byte_cursor_from_jstring_acquire(env, jni_pass);
1135*3c7ae9deSAndroid Build Coastguard Worker password_ptr = &password;
1136*3c7ae9deSAndroid Build Coastguard Worker }
1137*3c7ae9deSAndroid Build Coastguard Worker
1138*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_set_login(connection->client_connection, &username, password_ptr)) {
1139*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_set_login: Failed to set login");
1140*3c7ae9deSAndroid Build Coastguard Worker }
1141*3c7ae9deSAndroid Build Coastguard Worker
1142*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_user, username);
1143*3c7ae9deSAndroid Build Coastguard Worker
1144*3c7ae9deSAndroid Build Coastguard Worker if (password.len > 0) {
1145*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_pass, password);
1146*3c7ae9deSAndroid Build Coastguard Worker }
1147*3c7ae9deSAndroid Build Coastguard Worker }
1148*3c7ae9deSAndroid Build Coastguard Worker
1149*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetReconnectTimeout(JNIEnv * env,jclass jni_class,jlong jni_connection,jlong jni_min_timeout,jlong jni_max_timeout)1150*3c7ae9deSAndroid Build Coastguard Worker Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetReconnectTimeout(
1151*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1152*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1153*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
1154*3c7ae9deSAndroid Build Coastguard Worker jlong jni_min_timeout,
1155*3c7ae9deSAndroid Build Coastguard Worker jlong jni_max_timeout) {
1156*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1157*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1158*3c7ae9deSAndroid Build Coastguard Worker
1159*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1160*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
1161*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.mqtt_reconnect_timeout: Invalid connection");
1162*3c7ae9deSAndroid Build Coastguard Worker return;
1163*3c7ae9deSAndroid Build Coastguard Worker }
1164*3c7ae9deSAndroid Build Coastguard Worker
1165*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_set_reconnect_timeout(
1166*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, jni_min_timeout, jni_max_timeout)) {
1167*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1168*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.mqtt_reconnect_timeout: Failed to set reconnect timeout");
1169*3c7ae9deSAndroid Build Coastguard Worker }
1170*3c7ae9deSAndroid Build Coastguard Worker }
1171*3c7ae9deSAndroid Build Coastguard Worker
1172*3c7ae9deSAndroid Build Coastguard Worker ///////
s_ws_handshake_destroy(struct mqtt_jni_ws_handshake * ws_handshake)1173*3c7ae9deSAndroid Build Coastguard Worker static void s_ws_handshake_destroy(struct mqtt_jni_ws_handshake *ws_handshake) {
1174*3c7ae9deSAndroid Build Coastguard Worker if (!ws_handshake) {
1175*3c7ae9deSAndroid Build Coastguard Worker return;
1176*3c7ae9deSAndroid Build Coastguard Worker }
1177*3c7ae9deSAndroid Build Coastguard Worker
1178*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_release(ws_handshake->connection);
1179*3c7ae9deSAndroid Build Coastguard Worker aws_mem_release(aws_jni_get_allocator(), ws_handshake);
1180*3c7ae9deSAndroid Build Coastguard Worker }
1181*3c7ae9deSAndroid Build Coastguard Worker
s_ws_handshake_transform(struct aws_http_message * request,void * user_data,aws_mqtt_transform_websocket_handshake_complete_fn * complete_fn,void * complete_ctx)1182*3c7ae9deSAndroid Build Coastguard Worker static void s_ws_handshake_transform(
1183*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_message *request,
1184*3c7ae9deSAndroid Build Coastguard Worker void *user_data,
1185*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_transform_websocket_handshake_complete_fn *complete_fn,
1186*3c7ae9deSAndroid Build Coastguard Worker void *complete_ctx) {
1187*3c7ae9deSAndroid Build Coastguard Worker
1188*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = user_data;
1189*3c7ae9deSAndroid Build Coastguard Worker
1190*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
1191*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(connection->jvm);
1192*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
1193*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
1194*3c7ae9deSAndroid Build Coastguard Worker complete_fn(request, AWS_ERROR_INVALID_STATE, complete_ctx);
1195*3c7ae9deSAndroid Build Coastguard Worker return;
1196*3c7ae9deSAndroid Build Coastguard Worker }
1197*3c7ae9deSAndroid Build Coastguard Worker
1198*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *alloc = aws_jni_get_allocator();
1199*3c7ae9deSAndroid Build Coastguard Worker
1200*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_ws_handshake *ws_handshake = aws_mem_calloc(alloc, 1, sizeof(struct mqtt_jni_ws_handshake));
1201*3c7ae9deSAndroid Build Coastguard Worker if (!ws_handshake) {
1202*3c7ae9deSAndroid Build Coastguard Worker goto error;
1203*3c7ae9deSAndroid Build Coastguard Worker }
1204*3c7ae9deSAndroid Build Coastguard Worker
1205*3c7ae9deSAndroid Build Coastguard Worker ws_handshake->connection = connection;
1206*3c7ae9deSAndroid Build Coastguard Worker s_mqtt_jni_connection_acquire(ws_handshake->connection);
1207*3c7ae9deSAndroid Build Coastguard Worker
1208*3c7ae9deSAndroid Build Coastguard Worker ws_handshake->complete_ctx = complete_ctx;
1209*3c7ae9deSAndroid Build Coastguard Worker ws_handshake->complete_fn = complete_fn;
1210*3c7ae9deSAndroid Build Coastguard Worker ws_handshake->http_request = request;
1211*3c7ae9deSAndroid Build Coastguard Worker
1212*3c7ae9deSAndroid Build Coastguard Worker jobject java_http_request = aws_java_http_request_from_native(env, request, NULL);
1213*3c7ae9deSAndroid Build Coastguard Worker if (!java_http_request) {
1214*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_UNKNOWN); /* TODO: given java exception, choose appropriate aws error code */
1215*3c7ae9deSAndroid Build Coastguard Worker goto error;
1216*3c7ae9deSAndroid Build Coastguard Worker }
1217*3c7ae9deSAndroid Build Coastguard Worker
1218*3c7ae9deSAndroid Build Coastguard Worker jobject mqtt_connection = (*env)->NewLocalRef(env, connection->java_mqtt_connection);
1219*3c7ae9deSAndroid Build Coastguard Worker if (mqtt_connection != NULL) {
1220*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallVoidMethod(
1221*3c7ae9deSAndroid Build Coastguard Worker env, mqtt_connection, mqtt_connection_properties.on_websocket_handshake, java_http_request, ws_handshake);
1222*3c7ae9deSAndroid Build Coastguard Worker
1223*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, mqtt_connection);
1224*3c7ae9deSAndroid Build Coastguard Worker
1225*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
1226*3c7ae9deSAndroid Build Coastguard Worker }
1227*3c7ae9deSAndroid Build Coastguard Worker
1228*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, java_http_request);
1229*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
1230*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE SUCCESS PATH **********/
1231*3c7ae9deSAndroid Build Coastguard Worker
1232*3c7ae9deSAndroid Build Coastguard Worker return;
1233*3c7ae9deSAndroid Build Coastguard Worker
1234*3c7ae9deSAndroid Build Coastguard Worker error:;
1235*3c7ae9deSAndroid Build Coastguard Worker
1236*3c7ae9deSAndroid Build Coastguard Worker int error_code = aws_last_error();
1237*3c7ae9deSAndroid Build Coastguard Worker s_ws_handshake_destroy(ws_handshake);
1238*3c7ae9deSAndroid Build Coastguard Worker complete_fn(request, error_code, complete_ctx);
1239*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(connection->jvm, env);
1240*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE FAILURE PATH **********/
1241*3c7ae9deSAndroid Build Coastguard Worker }
1242*3c7ae9deSAndroid Build Coastguard Worker
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionUseWebsockets(JNIEnv * env,jclass jni_class,jlong jni_connection)1243*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionUseWebsockets(
1244*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1245*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1246*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection) {
1247*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1248*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1249*3c7ae9deSAndroid Build Coastguard Worker
1250*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1251*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
1252*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1253*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.useWebsockets: Invalid connection");
1254*3c7ae9deSAndroid Build Coastguard Worker return;
1255*3c7ae9deSAndroid Build Coastguard Worker }
1256*3c7ae9deSAndroid Build Coastguard Worker
1257*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_use_websockets(
1258*3c7ae9deSAndroid Build Coastguard Worker connection->client_connection, s_ws_handshake_transform, connection, NULL, NULL)) {
1259*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.useWebsockets: Failed to use websockets");
1260*3c7ae9deSAndroid Build Coastguard Worker return;
1261*3c7ae9deSAndroid Build Coastguard Worker }
1262*3c7ae9deSAndroid Build Coastguard Worker }
1263*3c7ae9deSAndroid Build Coastguard Worker
1264*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionWebsocketHandshakeComplete(JNIEnv * env,jclass jni_class,jlong jni_connection,jbyteArray jni_marshalled_request,jobject jni_throwable,jlong jni_user_data)1265*3c7ae9deSAndroid Build Coastguard Worker void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionWebsocketHandshakeComplete(
1266*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1267*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1268*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
1269*3c7ae9deSAndroid Build Coastguard Worker jbyteArray jni_marshalled_request,
1270*3c7ae9deSAndroid Build Coastguard Worker jobject jni_throwable,
1271*3c7ae9deSAndroid Build Coastguard Worker jlong jni_user_data) {
1272*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1273*3c7ae9deSAndroid Build Coastguard Worker (void)jni_connection;
1274*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1275*3c7ae9deSAndroid Build Coastguard Worker
1276*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_ws_handshake *ws_handshake = (void *)jni_user_data;
1277*3c7ae9deSAndroid Build Coastguard Worker int error_code = AWS_ERROR_SUCCESS;
1278*3c7ae9deSAndroid Build Coastguard Worker
1279*3c7ae9deSAndroid Build Coastguard Worker if (jni_throwable != NULL) {
1280*3c7ae9deSAndroid Build Coastguard Worker if ((*env)->IsInstanceOf(env, jni_throwable, crt_runtime_exception_properties.crt_runtime_exception_class)) {
1281*3c7ae9deSAndroid Build Coastguard Worker error_code = (*env)->GetIntField(env, jni_throwable, crt_runtime_exception_properties.error_code_field_id);
1282*3c7ae9deSAndroid Build Coastguard Worker }
1283*3c7ae9deSAndroid Build Coastguard Worker
1284*3c7ae9deSAndroid Build Coastguard Worker if (error_code == AWS_ERROR_SUCCESS) {
1285*3c7ae9deSAndroid Build Coastguard Worker error_code = AWS_ERROR_UNKNOWN; /* is there anything more that could be done here? */
1286*3c7ae9deSAndroid Build Coastguard Worker }
1287*3c7ae9deSAndroid Build Coastguard Worker
1288*3c7ae9deSAndroid Build Coastguard Worker goto done;
1289*3c7ae9deSAndroid Build Coastguard Worker }
1290*3c7ae9deSAndroid Build Coastguard Worker
1291*3c7ae9deSAndroid Build Coastguard Worker if (aws_apply_java_http_request_changes_to_native_request(
1292*3c7ae9deSAndroid Build Coastguard Worker env, jni_marshalled_request, NULL, ws_handshake->http_request)) {
1293*3c7ae9deSAndroid Build Coastguard Worker error_code = aws_last_error();
1294*3c7ae9deSAndroid Build Coastguard Worker goto done;
1295*3c7ae9deSAndroid Build Coastguard Worker }
1296*3c7ae9deSAndroid Build Coastguard Worker
1297*3c7ae9deSAndroid Build Coastguard Worker done:
1298*3c7ae9deSAndroid Build Coastguard Worker ws_handshake->complete_fn(ws_handshake->http_request, error_code, ws_handshake->complete_ctx);
1299*3c7ae9deSAndroid Build Coastguard Worker s_ws_handshake_destroy(ws_handshake);
1300*3c7ae9deSAndroid Build Coastguard Worker }
1301*3c7ae9deSAndroid Build Coastguard Worker
1302*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetHttpProxyOptions(JNIEnv * env,jclass jni_class,jlong jni_connection,jint jni_proxy_connection_type,jstring jni_proxy_host,jint jni_proxy_port,jlong jni_proxy_tls_context,jint jni_proxy_authorization_type,jstring jni_proxy_authorization_username,jstring jni_proxy_authorization_password)1303*3c7ae9deSAndroid Build Coastguard Worker void JNICALL Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionSetHttpProxyOptions(
1304*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1305*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1306*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection,
1307*3c7ae9deSAndroid Build Coastguard Worker jint jni_proxy_connection_type,
1308*3c7ae9deSAndroid Build Coastguard Worker jstring jni_proxy_host,
1309*3c7ae9deSAndroid Build Coastguard Worker jint jni_proxy_port,
1310*3c7ae9deSAndroid Build Coastguard Worker jlong jni_proxy_tls_context,
1311*3c7ae9deSAndroid Build Coastguard Worker jint jni_proxy_authorization_type,
1312*3c7ae9deSAndroid Build Coastguard Worker jstring jni_proxy_authorization_username,
1313*3c7ae9deSAndroid Build Coastguard Worker jstring jni_proxy_authorization_password) {
1314*3c7ae9deSAndroid Build Coastguard Worker
1315*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1316*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1317*3c7ae9deSAndroid Build Coastguard Worker
1318*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1319*3c7ae9deSAndroid Build Coastguard Worker
1320*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_proxy_options proxy_options;
1321*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(proxy_options);
1322*3c7ae9deSAndroid Build Coastguard Worker
1323*3c7ae9deSAndroid Build Coastguard Worker if (!jni_proxy_host) {
1324*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.setHttpProxyOptions: proxyHost must not be null.");
1325*3c7ae9deSAndroid Build Coastguard Worker return;
1326*3c7ae9deSAndroid Build Coastguard Worker }
1327*3c7ae9deSAndroid Build Coastguard Worker
1328*3c7ae9deSAndroid Build Coastguard Worker proxy_options.connection_type = (enum aws_http_proxy_connection_type)jni_proxy_connection_type;
1329*3c7ae9deSAndroid Build Coastguard Worker
1330*3c7ae9deSAndroid Build Coastguard Worker proxy_options.host = aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_host);
1331*3c7ae9deSAndroid Build Coastguard Worker proxy_options.port = (uint32_t)jni_proxy_port;
1332*3c7ae9deSAndroid Build Coastguard Worker
1333*3c7ae9deSAndroid Build Coastguard Worker proxy_options.auth_type = (enum aws_http_proxy_authentication_type)jni_proxy_authorization_type;
1334*3c7ae9deSAndroid Build Coastguard Worker
1335*3c7ae9deSAndroid Build Coastguard Worker if (jni_proxy_authorization_username) {
1336*3c7ae9deSAndroid Build Coastguard Worker proxy_options.auth_username = aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_authorization_username);
1337*3c7ae9deSAndroid Build Coastguard Worker }
1338*3c7ae9deSAndroid Build Coastguard Worker
1339*3c7ae9deSAndroid Build Coastguard Worker if (jni_proxy_authorization_password) {
1340*3c7ae9deSAndroid Build Coastguard Worker proxy_options.auth_password = aws_jni_byte_cursor_from_jstring_acquire(env, jni_proxy_authorization_password);
1341*3c7ae9deSAndroid Build Coastguard Worker }
1342*3c7ae9deSAndroid Build Coastguard Worker
1343*3c7ae9deSAndroid Build Coastguard Worker struct aws_tls_connection_options proxy_tls_conn_options;
1344*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(proxy_tls_conn_options);
1345*3c7ae9deSAndroid Build Coastguard Worker
1346*3c7ae9deSAndroid Build Coastguard Worker if (jni_proxy_tls_context != 0) {
1347*3c7ae9deSAndroid Build Coastguard Worker struct aws_tls_ctx *proxy_tls_ctx = (struct aws_tls_ctx *)jni_proxy_tls_context;
1348*3c7ae9deSAndroid Build Coastguard Worker aws_tls_connection_options_init_from_ctx(&proxy_tls_conn_options, proxy_tls_ctx);
1349*3c7ae9deSAndroid Build Coastguard Worker aws_tls_connection_options_set_server_name(
1350*3c7ae9deSAndroid Build Coastguard Worker &proxy_tls_conn_options, aws_jni_get_allocator(), &proxy_options.host);
1351*3c7ae9deSAndroid Build Coastguard Worker proxy_options.tls_options = &proxy_tls_conn_options;
1352*3c7ae9deSAndroid Build Coastguard Worker }
1353*3c7ae9deSAndroid Build Coastguard Worker
1354*3c7ae9deSAndroid Build Coastguard Worker if (aws_mqtt_client_connection_set_http_proxy_options(connection->client_connection, &proxy_options)) {
1355*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.setHttpProxyOptions: Failed to set proxy options");
1356*3c7ae9deSAndroid Build Coastguard Worker }
1357*3c7ae9deSAndroid Build Coastguard Worker
1358*3c7ae9deSAndroid Build Coastguard Worker if (jni_proxy_authorization_password) {
1359*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_authorization_password, proxy_options.auth_password);
1360*3c7ae9deSAndroid Build Coastguard Worker }
1361*3c7ae9deSAndroid Build Coastguard Worker
1362*3c7ae9deSAndroid Build Coastguard Worker if (jni_proxy_authorization_username) {
1363*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_authorization_username, proxy_options.auth_username);
1364*3c7ae9deSAndroid Build Coastguard Worker }
1365*3c7ae9deSAndroid Build Coastguard Worker
1366*3c7ae9deSAndroid Build Coastguard Worker aws_jni_byte_cursor_from_jstring_release(env, jni_proxy_host, proxy_options.host);
1367*3c7ae9deSAndroid Build Coastguard Worker aws_tls_connection_options_clean_up(&proxy_tls_conn_options);
1368*3c7ae9deSAndroid Build Coastguard Worker }
1369*3c7ae9deSAndroid Build Coastguard Worker
1370*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jobject JNICALL
Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionGetOperationStatistics(JNIEnv * env,jclass jni_class,jlong jni_connection)1371*3c7ae9deSAndroid Build Coastguard Worker Java_software_amazon_awssdk_crt_mqtt_MqttClientConnection_mqttClientConnectionGetOperationStatistics(
1372*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
1373*3c7ae9deSAndroid Build Coastguard Worker jclass jni_class,
1374*3c7ae9deSAndroid Build Coastguard Worker jlong jni_connection) {
1375*3c7ae9deSAndroid Build Coastguard Worker (void)jni_class;
1376*3c7ae9deSAndroid Build Coastguard Worker aws_cache_jni_ids(env);
1377*3c7ae9deSAndroid Build Coastguard Worker
1378*3c7ae9deSAndroid Build Coastguard Worker struct mqtt_jni_connection *connection = (struct mqtt_jni_connection *)jni_connection;
1379*3c7ae9deSAndroid Build Coastguard Worker if (!connection) {
1380*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1381*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "MqttClientConnection.getOperationStatistics: Invalid connection");
1382*3c7ae9deSAndroid Build Coastguard Worker return NULL;
1383*3c7ae9deSAndroid Build Coastguard Worker }
1384*3c7ae9deSAndroid Build Coastguard Worker
1385*3c7ae9deSAndroid Build Coastguard Worker /* Construct Java object */
1386*3c7ae9deSAndroid Build Coastguard Worker jobject jni_operation_statistics = (*env)->NewObject(
1387*3c7ae9deSAndroid Build Coastguard Worker env,
1388*3c7ae9deSAndroid Build Coastguard Worker mqtt_connection_operation_statistics_properties.statistics_class,
1389*3c7ae9deSAndroid Build Coastguard Worker mqtt_connection_operation_statistics_properties.statistics_constructor_id);
1390*3c7ae9deSAndroid Build Coastguard Worker if (jni_operation_statistics == NULL) {
1391*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1392*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1393*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.getOperationStatistics: Could not create operation statistics object");
1394*3c7ae9deSAndroid Build Coastguard Worker return NULL;
1395*3c7ae9deSAndroid Build Coastguard Worker }
1396*3c7ae9deSAndroid Build Coastguard Worker
1397*3c7ae9deSAndroid Build Coastguard Worker struct aws_mqtt_connection_operation_statistics connection_stats;
1398*3c7ae9deSAndroid Build Coastguard Worker aws_mqtt_client_connection_get_stats(connection->client_connection, &connection_stats);
1399*3c7ae9deSAndroid Build Coastguard Worker
1400*3c7ae9deSAndroid Build Coastguard Worker (*env)->SetLongField(
1401*3c7ae9deSAndroid Build Coastguard Worker env,
1402*3c7ae9deSAndroid Build Coastguard Worker jni_operation_statistics,
1403*3c7ae9deSAndroid Build Coastguard Worker mqtt_connection_operation_statistics_properties.incomplete_operation_count_field_id,
1404*3c7ae9deSAndroid Build Coastguard Worker (jlong)connection_stats.incomplete_operation_count);
1405*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
1406*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1407*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1408*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.getOperationStatistics: could not create incomplete operation count");
1409*3c7ae9deSAndroid Build Coastguard Worker return NULL;
1410*3c7ae9deSAndroid Build Coastguard Worker }
1411*3c7ae9deSAndroid Build Coastguard Worker
1412*3c7ae9deSAndroid Build Coastguard Worker (*env)->SetLongField(
1413*3c7ae9deSAndroid Build Coastguard Worker env,
1414*3c7ae9deSAndroid Build Coastguard Worker jni_operation_statistics,
1415*3c7ae9deSAndroid Build Coastguard Worker mqtt_connection_operation_statistics_properties.incomplete_operation_size_field_id,
1416*3c7ae9deSAndroid Build Coastguard Worker (jlong)connection_stats.incomplete_operation_size);
1417*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
1418*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1419*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1420*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.getOperationStatistics: could not create incomplete operation size");
1421*3c7ae9deSAndroid Build Coastguard Worker return NULL;
1422*3c7ae9deSAndroid Build Coastguard Worker }
1423*3c7ae9deSAndroid Build Coastguard Worker
1424*3c7ae9deSAndroid Build Coastguard Worker (*env)->SetLongField(
1425*3c7ae9deSAndroid Build Coastguard Worker env,
1426*3c7ae9deSAndroid Build Coastguard Worker jni_operation_statistics,
1427*3c7ae9deSAndroid Build Coastguard Worker mqtt_connection_operation_statistics_properties.unacked_operation_count_field_id,
1428*3c7ae9deSAndroid Build Coastguard Worker (jlong)connection_stats.unacked_operation_count);
1429*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
1430*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1431*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1432*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.getOperationStatistics: could not create unacked operation count");
1433*3c7ae9deSAndroid Build Coastguard Worker return NULL;
1434*3c7ae9deSAndroid Build Coastguard Worker }
1435*3c7ae9deSAndroid Build Coastguard Worker
1436*3c7ae9deSAndroid Build Coastguard Worker (*env)->SetLongField(
1437*3c7ae9deSAndroid Build Coastguard Worker env,
1438*3c7ae9deSAndroid Build Coastguard Worker jni_operation_statistics,
1439*3c7ae9deSAndroid Build Coastguard Worker mqtt_connection_operation_statistics_properties.unacked_operation_size_field_id,
1440*3c7ae9deSAndroid Build Coastguard Worker (jlong)connection_stats.unacked_operation_size);
1441*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
1442*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_STATE);
1443*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
1444*3c7ae9deSAndroid Build Coastguard Worker env, "MqttClientConnection.getOperationStatistics: could not create unacked operation size");
1445*3c7ae9deSAndroid Build Coastguard Worker return NULL;
1446*3c7ae9deSAndroid Build Coastguard Worker }
1447*3c7ae9deSAndroid Build Coastguard Worker
1448*3c7ae9deSAndroid Build Coastguard Worker return jni_operation_statistics;
1449*3c7ae9deSAndroid Build Coastguard Worker }
1450*3c7ae9deSAndroid Build Coastguard Worker
1451*3c7ae9deSAndroid Build Coastguard Worker #if UINTPTR_MAX == 0xffffffff
1452*3c7ae9deSAndroid Build Coastguard Worker # if defined(_MSC_VER)
1453*3c7ae9deSAndroid Build Coastguard Worker # pragma warning(pop)
1454*3c7ae9deSAndroid Build Coastguard Worker # else
1455*3c7ae9deSAndroid Build Coastguard Worker # pragma GCC diagnostic pop
1456*3c7ae9deSAndroid Build Coastguard Worker # endif
1457*3c7ae9deSAndroid Build Coastguard Worker #endif
1458