1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5 #include <jni.h>
6
7 #include <mqtt5_packets.h>
8
9 #include <aws/mqtt/v5/mqtt5_client.h>
10 #include <crt.h>
11
12 #include <java_class_ids.h>
13
14 /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
15 #if UINTPTR_MAX == 0xffffffff
16 # if defined(_MSC_VER)
17 # pragma warning(push)
18 # pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
19 # else
20 # pragma GCC diagnostic push
21 # pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
22 # pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
23 # endif
24 #endif
25
26 /*******************************************************************************
27 * STRUCT DEFINITIONS
28 ******************************************************************************/
29
30 struct aws_mqtt5_packet_connect_view_java_jni {
31 struct aws_mqtt5_packet_connect_view packet;
32
33 struct aws_byte_buf client_id_buf;
34 struct aws_byte_cursor client_id_cursor;
35 struct aws_byte_buf username_buf;
36 struct aws_byte_cursor username_cursor;
37 struct aws_byte_buf password_buf;
38 struct aws_byte_cursor password_cursor;
39 uint32_t session_expiry_interval_seconds;
40 uint8_t request_response_information;
41 uint8_t request_problem_information;
42 uint16_t receive_maximum;
43 uint16_t topic_alias_maximum;
44 uint32_t maximum_packet_size_bytes;
45 uint32_t will_delay_interval_seconds;
46 uint16_t keep_alive_interval_seconds;
47 /* Contains buffer_and_cursor_array_holder_struct pointers */
48 struct aws_array_list jni_user_properties_holder;
49 /* Contains aws_mqtt5_user_property pointers */
50 struct aws_array_list jni_user_properties_struct_holder;
51 struct aws_mqtt5_packet_publish_view_java_jni *will_publish_packet;
52 };
53
54 struct aws_mqtt5_packet_disconnect_view_java_jni {
55 struct aws_mqtt5_packet_disconnect_view packet;
56
57 struct aws_byte_buf reason_string_buf;
58 struct aws_byte_cursor reason_string_cursor;
59 struct aws_byte_buf server_reference_buf;
60 struct aws_byte_cursor server_reference_cursor;
61 uint32_t session_expiry_interval_seconds;
62 /* Contains buffer_and_cursor_array_holder_struct pointers */
63 struct aws_array_list jni_user_properties_holder;
64 /* Contains aws_mqtt5_user_property pointers */
65 struct aws_array_list jni_user_properties_struct_holder;
66 };
67
68 struct aws_mqtt5_packet_publish_view_java_jni {
69 struct aws_mqtt5_packet_publish_view packet;
70
71 struct aws_byte_buf payload_buf;
72 struct aws_byte_cursor payload_cursor;
73 struct aws_byte_buf topic_buf;
74 struct aws_byte_cursor topic_cursor;
75 enum aws_mqtt5_payload_format_indicator payload_format;
76 uint32_t message_expiry_interval_seconds;
77 uint16_t topic_alias;
78 struct aws_byte_buf response_topic_buf;
79 struct aws_byte_cursor response_topic_cursor;
80 struct aws_byte_buf correlation_data_buf;
81 struct aws_byte_cursor correlation_data_cursor;
82 struct aws_byte_buf content_type_buf;
83 struct aws_byte_cursor content_type_cursor;
84 /* Contains buffer_and_cursor_array_holder_struct pointers */
85 struct aws_array_list jni_user_properties_holder;
86 /* Contains aws_mqtt5_user_property pointers */
87 struct aws_array_list jni_user_properties_struct_holder;
88 };
89
90 struct aws_mqtt5_packet_subscribe_view_java_jni {
91 struct aws_mqtt5_packet_subscribe_view packet;
92
93 /* Contains aws_mqtt5_subscription_view pointers */
94 struct aws_array_list topic_filters;
95 /* Contains buffer_and_cursor_array_holder_struct pointers */
96 struct aws_array_list jni_subscription_topic_filters;
97 uint32_t subscription_identifier;
98 /* Contains buffer_and_cursor_array_holder_struct pointers */
99 struct aws_array_list jni_user_properties_holder;
100 /* Contains aws_mqtt5_user_property pointers */
101 struct aws_array_list jni_user_properties_struct_holder;
102 };
103
104 struct aws_mqtt5_packet_unsubscribe_view_java_jni {
105 struct aws_mqtt5_packet_unsubscribe_view packet;
106
107 /* Contains aws_byte_cursor pointers */
108 struct aws_array_list topic_filters;
109 /* Contains buffer_and_cursor_array_holder_struct pointers */
110 struct aws_array_list jni_topic_filters;
111 /* Contains buffer_and_cursor_array_holder_struct pointers */
112 struct aws_array_list jni_user_properties_holder;
113 /* Contains aws_mqtt5_user_property pointers */
114 struct aws_array_list jni_user_properties_struct_holder;
115 };
116
117 struct buffer_and_cursor_array_holder_struct {
118 struct aws_byte_cursor cursor;
119 struct aws_byte_buf buffer;
120 };
121
122 /*******************************************************************************
123 * HELPER FUNCTIONS
124 ******************************************************************************/
125
s_populate_user_properties(JNIEnv * env,jobject jni_user_properties_list,size_t java_packet_native_user_property_count,const struct aws_mqtt5_user_property ** java_packet_native_user_properties,struct aws_array_list * java_packet_user_properties_holder,struct aws_array_list * java_packet_user_properties_struct_holder)126 static int s_populate_user_properties(
127 JNIEnv *env,
128 jobject jni_user_properties_list,
129 size_t java_packet_native_user_property_count,
130 const struct aws_mqtt5_user_property **java_packet_native_user_properties,
131 /* Contains buffer_and_cursor_array_holder_struct pointers */
132 struct aws_array_list *java_packet_user_properties_holder,
133 /* Contains aws_mqtt5_user_property pointers */
134 struct aws_array_list *java_packet_user_properties_struct_holder) {
135
136 if (jni_user_properties_list) {
137 for (size_t i = 0; i < java_packet_native_user_property_count; i++) {
138 jobject jni_property =
139 (*env)->CallObjectMethod(env, jni_user_properties_list, boxed_list_properties.list_get_id, (jint)i);
140 if (!jni_property || aws_jni_check_and_clear_exception(env)) {
141 AWS_LOGF_ERROR(
142 AWS_LS_MQTT5_CLIENT,
143 "Could not populate user properties due to being unable to get property in list from Java");
144 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
145 }
146
147 jstring jni_property_key =
148 (jstring)(*env)->GetObjectField(env, jni_property, mqtt5_user_property_properties.property_key_id);
149 if (aws_jni_check_and_clear_exception(env) || !jni_property_key) {
150 AWS_LOGF_ERROR(
151 AWS_LS_MQTT5_CLIENT,
152 "Could not populate user properties due to exception when getting property key");
153 return aws_raise_error(AWS_ERROR_INVALID_STATE);
154 }
155 jstring jni_property_value =
156 (jstring)(*env)->GetObjectField(env, jni_property, mqtt5_user_property_properties.property_value_id);
157 if (aws_jni_check_and_clear_exception(env) || !jni_property_value) {
158 AWS_LOGF_ERROR(
159 AWS_LS_MQTT5_CLIENT,
160 "Could not populate user properties due to exception when getting property value");
161 return aws_raise_error(AWS_ERROR_INVALID_STATE);
162 }
163
164 if (!jni_property_key) {
165 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error reading a user property: Key in user property was NULL!");
166 return aws_raise_error(AWS_ERROR_INVALID_STATE);
167 }
168 if (!jni_property_value) {
169 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error reading a user property: Key in user property was NULL!");
170 return aws_raise_error(AWS_ERROR_INVALID_STATE);
171 }
172
173 // Get a temporary cursor from JNI, copy it, and then destroy the JNI version, leaving the byte_buffer copy.
174 // This gets around JNI stuff going out of scope.
175 struct buffer_and_cursor_array_holder_struct holder_property_key;
176 struct aws_byte_cursor tmp_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, jni_property_key);
177 aws_byte_buf_init_copy_from_cursor(&holder_property_key.buffer, aws_jni_get_allocator(), tmp_cursor);
178 holder_property_key.cursor = aws_byte_cursor_from_buf(&holder_property_key.buffer);
179 aws_jni_byte_cursor_from_jstring_release(env, jni_property_key, tmp_cursor);
180 jni_property_key = NULL;
181
182 // Get a temporary cursor from JNI, copy it, and then destroy the JNI version, leaving the byte_buffer copy.
183 // This gets around JNI stuff going out of scope.
184 struct buffer_and_cursor_array_holder_struct holder_property_value;
185 tmp_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, jni_property_value);
186 aws_byte_buf_init_copy_from_cursor(&holder_property_value.buffer, aws_jni_get_allocator(), tmp_cursor);
187 holder_property_value.cursor = aws_byte_cursor_from_buf(&holder_property_value.buffer);
188 aws_jni_byte_cursor_from_jstring_release(env, jni_property_value, tmp_cursor);
189 jni_property_value = NULL;
190
191 aws_array_list_push_back(java_packet_user_properties_holder, (void *)&holder_property_key);
192 aws_array_list_push_back(java_packet_user_properties_holder, (void *)&holder_property_value);
193
194 struct aws_mqtt5_user_property jni_property_struct = {
195 .name = holder_property_key.cursor,
196 .value = holder_property_value.cursor,
197 };
198 aws_array_list_push_back(java_packet_user_properties_struct_holder, (void *)&jni_property_struct);
199 }
200 *java_packet_native_user_properties =
201 (struct aws_mqtt5_user_property *)java_packet_user_properties_struct_holder->data;
202 }
203 return AWS_OP_SUCCESS;
204 }
205
s_allocate_user_properties_array_holders(struct aws_allocator * allocator,struct aws_array_list * holder_array,struct aws_array_list * user_property_array,size_t init_entries)206 static int s_allocate_user_properties_array_holders(
207 struct aws_allocator *allocator,
208 /* Contains buffer_and_cursor_array_holder_struct pointers */
209 struct aws_array_list *holder_array,
210 /* Contains aws_mqtt5_user_property pointers */
211 struct aws_array_list *user_property_array,
212 size_t init_entries) {
213
214 if (init_entries > 0) {
215 if (aws_array_list_init_dynamic(
216 holder_array, allocator, 2 * init_entries, sizeof(struct buffer_and_cursor_array_holder_struct)) !=
217 AWS_OP_SUCCESS ||
218 aws_array_list_init_dynamic(
219 user_property_array, allocator, 2 * init_entries, sizeof(struct aws_mqtt5_user_property)) !=
220 AWS_OP_SUCCESS) {
221 return aws_raise_error(AWS_ERROR_INVALID_STATE);
222 }
223 }
224 return AWS_OP_SUCCESS;
225 }
226
s_cleanup_two_aws_array(JNIEnv * env,struct aws_array_list * user_properties_holder,struct aws_array_list * user_properties_struct_holder)227 static void s_cleanup_two_aws_array(
228 JNIEnv *env,
229 struct aws_array_list *user_properties_holder,
230 struct aws_array_list *user_properties_struct_holder) {
231
232 (void)env;
233 if (aws_array_list_is_valid(user_properties_holder)) {
234 /**
235 * Note that this ONLY frees the array holders for the non-struct array.
236 * We want to keep the struct one in memory since it belongs to a packet or similar.
237 * If both need to be freed, then we assume whomever is calling this will handle it.
238 */
239 for (size_t i = 0; i < aws_array_list_length(user_properties_holder); i++) {
240 struct buffer_and_cursor_array_holder_struct holder;
241 aws_array_list_get_at(user_properties_holder, &holder, i);
242 if (aws_byte_buf_is_valid(&holder.buffer)) {
243 aws_byte_buf_clean_up(&holder.buffer);
244 }
245 }
246 aws_array_list_clean_up(user_properties_holder);
247 }
248 if (aws_array_list_is_valid(user_properties_struct_holder)) {
249 aws_array_list_clean_up(user_properties_struct_holder);
250 }
251 }
252
aws_get_uint16_from_jobject(JNIEnv * env,jobject object,jfieldID object_field,char * object_name,char * field_name,uint16_t * result,bool optional,bool * was_value_set)253 int aws_get_uint16_from_jobject(
254 JNIEnv *env,
255 jobject object,
256 jfieldID object_field,
257 char *object_name,
258 char *field_name,
259 uint16_t *result,
260 bool optional,
261 bool *was_value_set) {
262
263 if (was_value_set != NULL) {
264 *was_value_set = false;
265 }
266
267 jobject jlong_obj = (*env)->GetObjectField(env, object, object_field);
268 if (aws_jni_check_and_clear_exception(env)) {
269 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
270 return aws_raise_error(AWS_ERROR_INVALID_STATE);
271 }
272 if (jlong_obj) {
273 jlong jlong_value = (*env)->CallLongMethod(env, jlong_obj, boxed_long_properties.long_value_method_id);
274 if (aws_jni_check_and_clear_exception(env)) {
275 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
276 return aws_raise_error(AWS_ERROR_INVALID_STATE);
277 }
278 int64_t jlong_value_check = (int64_t)jlong_value;
279 if (jlong_value_check < 0) {
280 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: %s is less than 0", object_name, field_name);
281 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
282 } else if (jlong_value_check > UINT16_MAX) {
283 AWS_LOGF_ERROR(
284 AWS_LS_MQTT5_CLIENT, "%s create_from_java: %s is more than UINT16_MAX", object_name, field_name);
285 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
286 }
287 *result = (uint16_t)jlong_value;
288
289 if (was_value_set != NULL) {
290 *was_value_set = true;
291 }
292
293 if (!optional) {
294 return AWS_OP_SUCCESS;
295 }
296 }
297
298 if (optional) {
299 return AWS_OP_SUCCESS;
300 } else {
301 return AWS_OP_ERR;
302 }
303 }
304
aws_get_uint32_from_jobject(JNIEnv * env,jobject object,jfieldID object_field,char * object_name,char * field_name,uint32_t * result,bool optional,bool * was_value_set)305 int aws_get_uint32_from_jobject(
306 JNIEnv *env,
307 jobject object,
308 jfieldID object_field,
309 char *object_name,
310 char *field_name,
311 uint32_t *result,
312 bool optional,
313 bool *was_value_set) {
314
315 if (was_value_set != NULL) {
316 *was_value_set = false;
317 }
318
319 jobject jlong_obj = (*env)->GetObjectField(env, object, object_field);
320 if (aws_jni_check_and_clear_exception(env)) {
321 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
322 return aws_raise_error(AWS_ERROR_INVALID_STATE);
323 }
324 if (jlong_obj) {
325 jlong jlong_value = (*env)->CallLongMethod(env, jlong_obj, boxed_long_properties.long_value_method_id);
326 if (aws_jni_check_and_clear_exception(env)) {
327 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
328 return aws_raise_error(AWS_ERROR_INVALID_STATE);
329 }
330 int64_t jlong_value_check = (int64_t)jlong_value;
331 if (jlong_value_check < 0) {
332 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: %s is less than 0", object_name, field_name);
333 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
334 } else if (jlong_value_check > UINT32_MAX) {
335 AWS_LOGF_ERROR(
336 AWS_LS_MQTT5_CLIENT, "%s create_from_java: %s is more than UINT32_MAX", object_name, field_name);
337 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
338 }
339 *result = (uint32_t)jlong_value_check;
340
341 if (was_value_set != NULL) {
342 *was_value_set = true;
343 }
344
345 if (!optional) {
346 return AWS_OP_SUCCESS;
347 }
348 }
349
350 if (optional) {
351 return AWS_OP_SUCCESS;
352 } else {
353 return AWS_OP_ERR;
354 }
355 }
356
aws_get_uint64_from_jobject(JNIEnv * env,jobject object,jfieldID object_field,char * object_name,char * field_name,uint64_t * result,bool optional,bool * was_value_set)357 int aws_get_uint64_from_jobject(
358 JNIEnv *env,
359 jobject object,
360 jfieldID object_field,
361 char *object_name,
362 char *field_name,
363 uint64_t *result,
364 bool optional,
365 bool *was_value_set) {
366
367 if (was_value_set != NULL) {
368 *was_value_set = false;
369 }
370
371 jobject jlong_obj = (*env)->GetObjectField(env, object, object_field);
372 if (aws_jni_check_and_clear_exception(env)) {
373 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
374 return aws_raise_error(AWS_ERROR_INVALID_STATE);
375 }
376 if (jlong_obj) {
377 jlong jlong_value = (*env)->CallLongMethod(env, jlong_obj, boxed_long_properties.long_value_method_id);
378 if (aws_jni_check_and_clear_exception(env)) {
379 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
380 return aws_raise_error(AWS_ERROR_INVALID_STATE);
381 }
382 int64_t jlong_value_check = (int64_t)jlong_value;
383 if (jlong_value_check < 0) {
384 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: %s is less than 0", object_name, field_name);
385 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
386 }
387 *result = (uint64_t)jlong_value_check;
388
389 if (was_value_set != NULL) {
390 *was_value_set = true;
391 }
392
393 if (!optional) {
394 return AWS_OP_SUCCESS;
395 }
396 }
397
398 if (optional) {
399 return AWS_OP_SUCCESS;
400 } else {
401 return AWS_OP_ERR;
402 }
403 }
404
aws_get_string_from_jobject(JNIEnv * env,jobject object,jfieldID object_field,char * object_name,char * field_name,struct aws_byte_buf * result_buf,struct aws_byte_cursor * result_cursor,bool is_optional,bool * was_value_set)405 int aws_get_string_from_jobject(
406 JNIEnv *env,
407 jobject object,
408 jfieldID object_field,
409 char *object_name,
410 char *field_name,
411 struct aws_byte_buf *result_buf,
412 struct aws_byte_cursor *result_cursor,
413 bool is_optional,
414 bool *was_value_set) {
415
416 if (was_value_set != NULL) {
417 *was_value_set = false;
418 }
419
420 jstring jstring_value = (jstring)(*env)->GetObjectField(env, object, object_field);
421 if (aws_jni_check_and_clear_exception(env)) {
422 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
423 return aws_raise_error(AWS_ERROR_INVALID_STATE);
424 }
425 if (jstring_value) {
426 // Get the data, copy it, and then release the JNI stuff
427 struct aws_byte_cursor tmp_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, jstring_value);
428 aws_byte_buf_init_copy_from_cursor(result_buf, aws_jni_get_allocator(), tmp_cursor);
429 *result_cursor = aws_byte_cursor_from_buf(result_buf);
430 aws_jni_byte_cursor_from_jstring_release(env, jstring_value, tmp_cursor);
431
432 if (was_value_set != NULL) {
433 *was_value_set = true;
434 }
435
436 if (!is_optional) {
437 return AWS_OP_SUCCESS;
438 }
439 }
440 if (is_optional) {
441 return AWS_OP_SUCCESS;
442 } else {
443 return AWS_OP_ERR;
444 }
445 }
446
aws_get_byte_array_from_jobject(JNIEnv * env,jobject object,jfieldID object_field,char * object_name,char * field_name,struct aws_byte_buf * result_buf,struct aws_byte_cursor * result_cursor,bool optional,bool * was_value_set)447 int aws_get_byte_array_from_jobject(
448 JNIEnv *env,
449 jobject object,
450 jfieldID object_field,
451 char *object_name,
452 char *field_name,
453 struct aws_byte_buf *result_buf,
454 struct aws_byte_cursor *result_cursor,
455 bool optional,
456 bool *was_value_set) {
457
458 if (was_value_set != NULL) {
459 *was_value_set = false;
460 }
461
462 jbyteArray jbyte_array_value = (jbyteArray)(*env)->GetObjectField(env, object, object_field);
463 if (aws_jni_check_and_clear_exception(env)) {
464 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
465 return aws_raise_error(AWS_ERROR_INVALID_STATE);
466 }
467 if (jbyte_array_value) {
468 // Get the data, copy it, and then release the JNI stuff
469 struct aws_byte_cursor tmp_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, jbyte_array_value);
470 aws_byte_buf_init_copy_from_cursor(result_buf, aws_jni_get_allocator(), tmp_cursor);
471 *result_cursor = aws_byte_cursor_from_buf(result_buf);
472 aws_jni_byte_cursor_from_jbyteArray_release(env, jbyte_array_value, tmp_cursor);
473
474 if (was_value_set != NULL) {
475 *was_value_set = true;
476 }
477
478 if (!optional) {
479 return AWS_OP_SUCCESS;
480 }
481 }
482 if (optional) {
483 return AWS_OP_SUCCESS;
484 } else {
485 return AWS_OP_ERR;
486 }
487 }
488
aws_get_boolean_from_jobject(JNIEnv * env,jobject object,jfieldID object_field,char * object_name,char * field_name,uint8_t * result_boolean_int,bool optional,bool * was_value_set)489 int aws_get_boolean_from_jobject(
490 JNIEnv *env,
491 jobject object,
492 jfieldID object_field,
493 char *object_name,
494 char *field_name,
495 uint8_t *result_boolean_int,
496 bool optional,
497 bool *was_value_set) {
498
499 if (was_value_set != NULL) {
500 *was_value_set = false;
501 }
502
503 jobject jboolean_obj = (*env)->GetObjectField(env, object, object_field);
504 if (aws_jni_check_and_clear_exception(env)) {
505 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, field_name);
506 return aws_raise_error(AWS_ERROR_INVALID_STATE);
507 }
508 if (jboolean_obj) {
509 jboolean jboolean_value =
510 (*env)->CallBooleanMethod(env, jboolean_obj, boxed_boolean_properties.boolean_get_value_id);
511 if (aws_jni_check_and_clear_exception(env)) {
512 AWS_LOGF_ERROR(
513 AWS_LS_MQTT5_CLIENT,
514 "%s create_from_java: Error getting native value from %s",
515 object_name,
516 field_name);
517 return aws_raise_error(AWS_ERROR_INVALID_STATE);
518 }
519 *result_boolean_int = (uint8_t)jboolean_value;
520 if (was_value_set != NULL) {
521 *was_value_set = true;
522 }
523 if (!optional) {
524 return AWS_OP_SUCCESS;
525 }
526 }
527
528 if (optional) {
529 return AWS_OP_SUCCESS;
530 } else {
531 return AWS_OP_ERR;
532 }
533 }
534
aws_get_enum_from_jobject(JNIEnv * env,jobject object,jmethodID object_enum_field,char * object_name,char * enum_name,jmethodID enum_value_field,uint32_t * enum_value_destination,bool optional,bool * was_value_set)535 int aws_get_enum_from_jobject(
536 JNIEnv *env,
537 jobject object,
538 jmethodID object_enum_field,
539 char *object_name,
540 char *enum_name,
541 jmethodID enum_value_field,
542 uint32_t *enum_value_destination,
543 bool optional,
544 bool *was_value_set) {
545
546 if (was_value_set != NULL) {
547 *was_value_set = false;
548 }
549
550 if (enum_value_destination == NULL) {
551 AWS_LOGF_ERROR(
552 AWS_LS_MQTT5_CLIENT,
553 "%s create_from_java: Error getting %s due to null destination",
554 object_name,
555 enum_name);
556 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
557 }
558
559 jobject jni_retain_handling_type = (*env)->CallObjectMethod(env, object, object_enum_field);
560 if (aws_jni_check_and_clear_exception(env)) {
561 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting %s", object_name, enum_name);
562 return aws_raise_error(AWS_ERROR_INVALID_STATE);
563 }
564 if (jni_retain_handling_type) {
565 jint enum_value = (*env)->CallIntMethod(env, jni_retain_handling_type, enum_value_field);
566 if (aws_jni_check_and_clear_exception(env)) {
567 AWS_LOGF_ERROR(
568 AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting native value from %s", object_name, enum_name);
569 return aws_raise_error(AWS_ERROR_INVALID_STATE);
570 }
571 if (enum_value < 0) {
572 AWS_LOGF_ERROR(
573 AWS_LS_MQTT5_CLIENT,
574 "%s create_from_java: Native value from %s is less than 0",
575 object_name,
576 enum_name);
577 return aws_raise_error(AWS_ERROR_INVALID_STATE);
578 } else if ((int32_t)enum_value > UINT16_MAX) {
579 AWS_LOGF_ERROR(
580 AWS_LS_MQTT5_CLIENT,
581 "%s create_from_java: Native value from %s is more than UINT16_MAX",
582 object_name,
583 enum_name);
584 return aws_raise_error(AWS_ERROR_INVALID_STATE);
585 }
586 *enum_value_destination = (int32_t)enum_value;
587 if (was_value_set != NULL) {
588 *was_value_set = true;
589 }
590 if (!optional) {
591 return AWS_OP_SUCCESS;
592 }
593 }
594 if (optional) {
595 return AWS_OP_SUCCESS;
596 } else {
597 return AWS_OP_ERR;
598 }
599 }
600
s_get_user_properties_from_packet_optional(JNIEnv * env,jobject packet,jfieldID packet_field,char * packet_name,size_t * packet_user_property_count,struct aws_array_list * jni_user_properties_holder,struct aws_array_list * jni_user_properties_struct_holder,const struct aws_mqtt5_user_property ** packet_properties)601 static int s_get_user_properties_from_packet_optional(
602 JNIEnv *env,
603 jobject packet,
604 jfieldID packet_field,
605 char *packet_name,
606 size_t *packet_user_property_count,
607 /* Contains buffer_and_cursor_array_holder_struct pointers */
608 struct aws_array_list *jni_user_properties_holder,
609 /* Contains aws_mqtt5_user_property pointers */
610 struct aws_array_list *jni_user_properties_struct_holder,
611 const struct aws_mqtt5_user_property **packet_properties) {
612
613 struct aws_allocator *allocator = aws_jni_get_allocator();
614
615 jobject jni_list = (*env)->GetObjectField(env, packet, packet_field);
616 if (aws_jni_check_and_clear_exception(env)) {
617 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting user properties list", packet_name);
618 return aws_raise_error(AWS_ERROR_INVALID_STATE);
619 }
620 if (jni_list) {
621 jint jni_user_properties_size = (*env)->CallIntMethod(env, jni_list, boxed_list_properties.list_size_id);
622 if (aws_jni_check_and_clear_exception(env)) {
623 AWS_LOGF_ERROR(
624 AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting user properties list size", packet_name);
625 return aws_raise_error(AWS_ERROR_INVALID_STATE);
626 }
627 *packet_user_property_count = (size_t)jni_user_properties_size;
628 if (AWS_OP_SUCCESS != s_allocate_user_properties_array_holders(
629 allocator,
630 jni_user_properties_holder,
631 jni_user_properties_struct_holder,
632 *packet_user_property_count)) {
633 AWS_LOGF_ERROR(
634 AWS_LS_MQTT5_CLIENT, "%s create_from_java: Could not create user properties array", packet_name);
635 return aws_raise_error(AWS_ERROR_INVALID_STATE);
636 }
637 int populate_result = s_populate_user_properties(
638 env,
639 jni_list,
640 *packet_user_property_count,
641 packet_properties,
642 jni_user_properties_holder,
643 jni_user_properties_struct_holder);
644 if (populate_result != AWS_OP_SUCCESS) {
645 return aws_raise_error(AWS_ERROR_INVALID_STATE);
646 }
647 }
648 return AWS_OP_SUCCESS;
649 }
650
s_get_qos_from_packet(JNIEnv * env,jobject packet,jmethodID packet_field,char * packet_name,enum aws_mqtt5_qos * packet_qos,bool optional,bool * was_value_set)651 static int s_get_qos_from_packet(
652 JNIEnv *env,
653 jobject packet,
654 jmethodID packet_field,
655 char *packet_name,
656 enum aws_mqtt5_qos *packet_qos,
657 bool optional,
658 bool *was_value_set) {
659
660 if (was_value_set != NULL) {
661 *was_value_set = false;
662 }
663
664 jobject jni_qos = (*env)->CallObjectMethod(env, packet, packet_field);
665 if (aws_jni_check_and_clear_exception(env)) {
666 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting QoS", packet_name);
667 return AWS_OP_ERR;
668 }
669 if (jni_qos) {
670 jint jni_qos_value = (*env)->CallIntMethod(env, jni_qos, mqtt5_packet_qos_properties.qos_get_value_id);
671 if (aws_jni_check_and_clear_exception(env)) {
672 AWS_LOGF_ERROR(
673 AWS_LS_MQTT5_CLIENT, "%s create_from_java: Error getting native value from QoS", packet_name);
674 return aws_raise_error(AWS_ERROR_INVALID_STATE);
675 }
676 *packet_qos = (enum aws_mqtt5_qos)jni_qos_value;
677 if (was_value_set != NULL) {
678 *was_value_set = true;
679 }
680 if (!optional) {
681 return AWS_OP_SUCCESS;
682 }
683 } else {
684 if (!optional) {
685 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "%s create_from_java: QoS not found", packet_name);
686 return aws_raise_error(AWS_ERROR_INVALID_STATE);
687 }
688 }
689 if (optional) {
690 return AWS_OP_SUCCESS;
691 } else {
692 return AWS_OP_ERR;
693 }
694 }
695
696 static char s_connect_packet_string[] = "ConnectPacket";
697 static char s_disconnect_packet_string[] = "DisconnectPacket";
698 static char s_publish_packet_string[] = "PublishPacket";
699 static char s_subscribe_packet_string[] = "SubscribePacket";
700 static char s_unsubscribe_packet_string[] = "UnsubscribePacket";
701
702 /*******************************************************************************
703 * CONNECT PACKET FUNCTIONS
704 ******************************************************************************/
705
aws_mqtt5_packet_connect_view_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_packet_connect_view_java_jni * java_packet)706 void aws_mqtt5_packet_connect_view_java_destroy(
707 JNIEnv *env,
708 struct aws_allocator *allocator,
709 struct aws_mqtt5_packet_connect_view_java_jni *java_packet) {
710 if (!java_packet) {
711 return;
712 }
713 AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "id=%p: Destroying ConnectPacket", (void *)java_packet);
714
715 if (aws_byte_buf_is_valid(&java_packet->client_id_buf)) {
716 aws_byte_buf_clean_up(&java_packet->client_id_buf);
717 }
718 if (aws_byte_buf_is_valid(&java_packet->username_buf)) {
719 aws_byte_buf_clean_up(&java_packet->username_buf);
720 }
721 if (aws_byte_buf_is_valid(&java_packet->password_buf)) {
722 aws_byte_buf_clean_up(&java_packet->password_buf);
723 }
724 if (java_packet->will_publish_packet) {
725 aws_mqtt5_packet_publish_view_java_destroy(env, allocator, java_packet->will_publish_packet);
726 }
727
728 s_cleanup_two_aws_array(
729 env, &java_packet->jni_user_properties_holder, &java_packet->jni_user_properties_struct_holder);
730 aws_mem_release(allocator, java_packet);
731 }
732
733 /**
734 * Creates a JNI connack packet from the given Java connack packet and returns it. It creates a new packet but it does
735 * NOT free it. You will need to call aws_mqtt5_packet_connect_view_java_destroy when you are done with it.
736 */
aws_mqtt5_packet_connect_view_create_from_java(JNIEnv * env,struct aws_allocator * allocator,jobject java_connect_packet)737 struct aws_mqtt5_packet_connect_view_java_jni *aws_mqtt5_packet_connect_view_create_from_java(
738 JNIEnv *env,
739 struct aws_allocator *allocator,
740 jobject java_connect_packet) {
741 struct aws_mqtt5_packet_connect_view_java_jni *java_packet =
742 aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_packet_connect_view_java_jni));
743 if (java_packet == NULL) {
744 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "ConnectPacket create_from_java: Creating new ConnectPacket failed");
745 return NULL;
746 }
747
748 /* Needed to track if optionals are set or not */
749 bool was_value_set = false;
750
751 if (aws_get_uint16_from_jobject(
752 env,
753 java_connect_packet,
754 mqtt5_connect_packet_properties.connect_keep_alive_interval_seconds_field_id,
755 s_connect_packet_string,
756 "keep alive interval seconds",
757 &java_packet->keep_alive_interval_seconds,
758 true,
759 &was_value_set) == AWS_OP_ERR) {
760 goto on_error;
761 }
762 if (was_value_set) {
763 java_packet->packet.keep_alive_interval_seconds = java_packet->keep_alive_interval_seconds;
764 }
765
766 if (aws_get_string_from_jobject(
767 env,
768 java_connect_packet,
769 mqtt5_connect_packet_properties.connect_client_id_field_id,
770 s_connect_packet_string,
771 "client ID",
772 &java_packet->client_id_buf,
773 &java_packet->client_id_cursor,
774 true,
775 &was_value_set) == AWS_OP_ERR) {
776 goto on_error;
777 }
778 if (was_value_set) {
779 java_packet->packet.client_id = java_packet->client_id_cursor;
780 }
781
782 if (aws_get_string_from_jobject(
783 env,
784 java_connect_packet,
785 mqtt5_connect_packet_properties.connect_username_field_id,
786 s_connect_packet_string,
787 "username",
788 &java_packet->username_buf,
789 &java_packet->username_cursor,
790 true,
791 &was_value_set) == AWS_OP_ERR) {
792 goto on_error;
793 }
794 if (was_value_set) {
795 java_packet->packet.username = &java_packet->username_cursor;
796 }
797
798 if (aws_get_byte_array_from_jobject(
799 env,
800 java_connect_packet,
801 mqtt5_connect_packet_properties.connect_password_field_id,
802 s_connect_packet_string,
803 "password",
804 &java_packet->password_buf,
805 &java_packet->password_cursor,
806 true,
807 &was_value_set) == AWS_OP_ERR) {
808 goto on_error;
809 }
810 if (was_value_set) {
811 java_packet->packet.password = &java_packet->password_cursor;
812 }
813
814 if (aws_get_uint32_from_jobject(
815 env,
816 java_connect_packet,
817 mqtt5_connect_packet_properties.connect_session_expiry_interval_seconds_field_id,
818 s_connect_packet_string,
819 "session expiry interval seconds",
820 &java_packet->session_expiry_interval_seconds,
821 true,
822 &was_value_set) == AWS_OP_ERR) {
823 goto on_error;
824 }
825 if (was_value_set) {
826 java_packet->packet.session_expiry_interval_seconds = &java_packet->session_expiry_interval_seconds;
827 }
828
829 if (aws_get_boolean_from_jobject(
830 env,
831 java_connect_packet,
832 mqtt5_connect_packet_properties.connect_request_response_information_field_id,
833 s_connect_packet_string,
834 "request response information",
835 &java_packet->request_response_information,
836 true,
837 &was_value_set) == AWS_OP_ERR) {
838 goto on_error;
839 }
840 if (was_value_set) {
841 java_packet->packet.request_response_information = &java_packet->request_response_information;
842 }
843
844 if (aws_get_boolean_from_jobject(
845 env,
846 java_connect_packet,
847 mqtt5_connect_packet_properties.connect_request_problem_information_field_id,
848 s_connect_packet_string,
849 "request problem information",
850 &java_packet->request_problem_information,
851 true,
852 &was_value_set) == AWS_OP_ERR) {
853 goto on_error;
854 }
855 if (was_value_set) {
856 java_packet->packet.request_problem_information = &java_packet->request_problem_information;
857 }
858
859 if (aws_get_uint16_from_jobject(
860 env,
861 java_connect_packet,
862 mqtt5_connect_packet_properties.connect_receive_maximum_field_id,
863 s_connect_packet_string,
864 "receive maximum",
865 &java_packet->receive_maximum,
866 true,
867 &was_value_set) == AWS_OP_ERR) {
868 goto on_error;
869 }
870 if (was_value_set) {
871 java_packet->packet.receive_maximum = &java_packet->receive_maximum;
872 }
873
874 if (aws_get_uint32_from_jobject(
875 env,
876 java_connect_packet,
877 mqtt5_connect_packet_properties.connect_maximum_packet_size_bytes_field_id,
878 s_connect_packet_string,
879 "maximum packet size",
880 &java_packet->maximum_packet_size_bytes,
881 true,
882 &was_value_set) == AWS_OP_ERR) {
883 goto on_error;
884 }
885 if (was_value_set) {
886 java_packet->packet.maximum_packet_size_bytes = &java_packet->maximum_packet_size_bytes;
887 }
888
889 if (aws_get_uint32_from_jobject(
890 env,
891 java_connect_packet,
892 mqtt5_connect_packet_properties.connect_will_delay_interval_seconds_field_id,
893 s_connect_packet_string,
894 "will delay interval",
895 &java_packet->will_delay_interval_seconds,
896 true,
897 &was_value_set) == AWS_OP_ERR) {
898 goto on_error;
899 }
900 if (was_value_set) {
901 java_packet->packet.will_delay_interval_seconds = &java_packet->will_delay_interval_seconds;
902 }
903
904 jobject jni_will_packet =
905 (*env)->GetObjectField(env, java_connect_packet, mqtt5_connect_packet_properties.connect_will_field_id);
906 if (aws_jni_check_and_clear_exception(env)) {
907 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "ConnectPacket create_from_java: Error getting will packet");
908 goto on_error;
909 }
910 if (jni_will_packet) {
911 java_packet->will_publish_packet =
912 aws_mqtt5_packet_publish_view_create_from_java(env, allocator, jni_will_packet);
913 if (java_packet->will_publish_packet == NULL) {
914 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "ConnectPacket create_from_java: Error getting will packet");
915 goto on_error;
916 }
917 java_packet->packet.will = &java_packet->will_publish_packet->packet;
918 }
919
920 if (s_get_user_properties_from_packet_optional(
921 env,
922 java_connect_packet,
923 mqtt5_connect_packet_properties.connect_user_properties_field_id,
924 s_connect_packet_string,
925 &java_packet->packet.user_property_count,
926 &java_packet->jni_user_properties_holder,
927 &java_packet->jni_user_properties_struct_holder,
928 &java_packet->packet.user_properties) == AWS_OP_ERR) {
929 goto on_error;
930 }
931
932 return java_packet;
933
934 on_error:
935
936 /* Clean up */
937 aws_mqtt5_packet_connect_view_java_destroy(env, allocator, java_packet);
938 return NULL;
939 }
940
aws_mqtt5_packet_connect_view_get_packet(struct aws_mqtt5_packet_connect_view_java_jni * java_packet)941 struct aws_mqtt5_packet_connect_view *aws_mqtt5_packet_connect_view_get_packet(
942 struct aws_mqtt5_packet_connect_view_java_jni *java_packet) {
943 if (java_packet) {
944 return &java_packet->packet;
945 } else {
946 return NULL;
947 }
948 }
949
950 /*******************************************************************************
951 * PACKET DISCONNECT FUNCTIONS
952 ******************************************************************************/
953
aws_mqtt5_packet_disconnect_view_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_packet_disconnect_view_java_jni * java_packet)954 void aws_mqtt5_packet_disconnect_view_java_destroy(
955 JNIEnv *env,
956 struct aws_allocator *allocator,
957 struct aws_mqtt5_packet_disconnect_view_java_jni *java_packet) {
958 if (!java_packet) {
959 return;
960 }
961 AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "id=%p: Destroying DisconnectPacket", (void *)java_packet);
962
963 if (aws_byte_buf_is_valid(&java_packet->reason_string_buf)) {
964 aws_byte_buf_clean_up(&java_packet->reason_string_buf);
965 }
966 if (aws_byte_buf_is_valid(&java_packet->server_reference_buf)) {
967 aws_byte_buf_clean_up(&java_packet->server_reference_buf);
968 }
969
970 s_cleanup_two_aws_array(
971 env, &java_packet->jni_user_properties_holder, &java_packet->jni_user_properties_struct_holder);
972 aws_mem_release(allocator, java_packet);
973 }
974
aws_mqtt5_packet_disconnect_view_create_from_java(JNIEnv * env,struct aws_allocator * allocator,jobject java_disconnect_packet)975 struct aws_mqtt5_packet_disconnect_view_java_jni *aws_mqtt5_packet_disconnect_view_create_from_java(
976 JNIEnv *env,
977 struct aws_allocator *allocator,
978 jobject java_disconnect_packet) {
979
980 struct aws_mqtt5_packet_disconnect_view_java_jni *java_packet =
981 aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_packet_disconnect_view_java_jni));
982 if (java_packet == NULL) {
983 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "DisconnectPacket create_from_java: Creating new DisconnectPacket failed");
984 return NULL;
985 }
986
987 /* Needed to track if optionals are set or not */
988 bool was_value_set = false;
989
990 uint32_t reason_code_enum;
991 if (aws_get_enum_from_jobject(
992 env,
993 java_disconnect_packet,
994 mqtt5_disconnect_packet_properties.disconnect_get_reason_code_id,
995 s_disconnect_packet_string,
996 "reason code",
997 mqtt5_disconnect_reason_code_properties.code_get_value_id,
998 &reason_code_enum,
999 true,
1000 &was_value_set) == AWS_OP_ERR) {
1001 goto on_error;
1002 }
1003 if (was_value_set) {
1004 java_packet->packet.reason_code = (enum aws_mqtt5_disconnect_reason_code)reason_code_enum;
1005 }
1006
1007 if (aws_get_uint32_from_jobject(
1008 env,
1009 java_disconnect_packet,
1010 mqtt5_disconnect_packet_properties.disconnect_session_expiry_interval_seconds_field_id,
1011 s_disconnect_packet_string,
1012 "session expiry interval seconds",
1013 &java_packet->session_expiry_interval_seconds,
1014 true,
1015 &was_value_set) == AWS_OP_ERR) {
1016 goto on_error;
1017 }
1018 if (was_value_set) {
1019 java_packet->packet.session_expiry_interval_seconds = &java_packet->session_expiry_interval_seconds;
1020 }
1021
1022 if (aws_get_string_from_jobject(
1023 env,
1024 java_disconnect_packet,
1025 mqtt5_disconnect_packet_properties.disconnect_reason_string_field_id,
1026 s_disconnect_packet_string,
1027 "reason string",
1028 &java_packet->reason_string_buf,
1029 &java_packet->reason_string_cursor,
1030 true,
1031 &was_value_set) == AWS_OP_ERR) {
1032 goto on_error;
1033 }
1034 if (was_value_set) {
1035 java_packet->packet.reason_string = &java_packet->reason_string_cursor;
1036 }
1037
1038 if (aws_get_string_from_jobject(
1039 env,
1040 java_disconnect_packet,
1041 mqtt5_disconnect_packet_properties.disconnect_session_server_reference_field_id,
1042 s_disconnect_packet_string,
1043 "server reference",
1044 &java_packet->server_reference_buf,
1045 &java_packet->server_reference_cursor,
1046 true,
1047 &was_value_set) == AWS_OP_ERR) {
1048 goto on_error;
1049 }
1050 if (was_value_set) {
1051 java_packet->packet.server_reference = &java_packet->server_reference_cursor;
1052 }
1053
1054 if (s_get_user_properties_from_packet_optional(
1055 env,
1056 java_disconnect_packet,
1057 mqtt5_disconnect_packet_properties.disconnect_user_properties_field_id,
1058 s_disconnect_packet_string,
1059 &java_packet->packet.user_property_count,
1060 &java_packet->jni_user_properties_holder,
1061 &java_packet->jni_user_properties_struct_holder,
1062 &java_packet->packet.user_properties) == AWS_OP_ERR) {
1063 goto on_error;
1064 }
1065
1066 return java_packet;
1067
1068 on_error:
1069
1070 /* Clean up */
1071 aws_mqtt5_packet_disconnect_view_java_destroy(env, allocator, java_packet);
1072 return NULL;
1073 }
1074
aws_mqtt5_packet_disconnect_view_get_packet(struct aws_mqtt5_packet_disconnect_view_java_jni * java_packet)1075 struct aws_mqtt5_packet_disconnect_view *aws_mqtt5_packet_disconnect_view_get_packet(
1076 struct aws_mqtt5_packet_disconnect_view_java_jni *java_packet) {
1077 if (java_packet) {
1078 return &java_packet->packet;
1079 } else {
1080 return NULL;
1081 }
1082 }
1083
1084 /*******************************************************************************
1085 * PUBLISH PACKET FUNCTIONS
1086 ******************************************************************************/
1087
aws_mqtt5_packet_publish_view_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_packet_publish_view_java_jni * java_packet)1088 void aws_mqtt5_packet_publish_view_java_destroy(
1089 JNIEnv *env,
1090 struct aws_allocator *allocator,
1091 struct aws_mqtt5_packet_publish_view_java_jni *java_packet) {
1092 if (!java_packet) {
1093 return;
1094 }
1095 AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "id=%p: Destroying PublishPacket", (void *)java_packet);
1096
1097 if (aws_byte_buf_is_valid(&java_packet->payload_buf)) {
1098 aws_byte_buf_clean_up(&java_packet->payload_buf);
1099 }
1100 if (aws_byte_buf_is_valid(&java_packet->topic_buf)) {
1101 aws_byte_buf_clean_up(&java_packet->topic_buf);
1102 }
1103 if (aws_byte_buf_is_valid(&java_packet->response_topic_buf)) {
1104 aws_byte_buf_clean_up(&java_packet->response_topic_buf);
1105 }
1106 if (aws_byte_buf_is_valid(&java_packet->correlation_data_buf)) {
1107 aws_byte_buf_clean_up(&java_packet->correlation_data_buf);
1108 }
1109 if (aws_byte_buf_is_valid(&java_packet->content_type_buf)) {
1110 aws_byte_buf_clean_up(&java_packet->content_type_buf);
1111 }
1112
1113 s_cleanup_two_aws_array(
1114 env, &java_packet->jni_user_properties_holder, &java_packet->jni_user_properties_struct_holder);
1115 aws_mem_release(allocator, java_packet);
1116 }
1117
aws_mqtt5_packet_publish_view_create_from_java(JNIEnv * env,struct aws_allocator * allocator,jobject java_publish_packet)1118 struct aws_mqtt5_packet_publish_view_java_jni *aws_mqtt5_packet_publish_view_create_from_java(
1119 JNIEnv *env,
1120 struct aws_allocator *allocator,
1121 jobject java_publish_packet) {
1122
1123 struct aws_mqtt5_packet_publish_view_java_jni *java_packet =
1124 aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_packet_publish_view_java_jni));
1125 if (java_packet == NULL) {
1126 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishPacket create_from_java: Creating new PublishPacket failed");
1127 return NULL;
1128 }
1129
1130 /* Needed to track if optionals are set or not */
1131 bool was_value_set = false;
1132
1133 if (aws_get_byte_array_from_jobject(
1134 env,
1135 java_publish_packet,
1136 mqtt5_publish_packet_properties.publish_payload_field_id,
1137 s_publish_packet_string,
1138 "payload",
1139 &java_packet->correlation_data_buf,
1140 &java_packet->payload_cursor,
1141 true,
1142 &was_value_set) == AWS_OP_ERR) {
1143 goto on_error;
1144 }
1145 if (was_value_set) {
1146 java_packet->packet.payload = java_packet->payload_cursor;
1147 }
1148
1149 if (s_get_qos_from_packet(
1150 env,
1151 java_publish_packet,
1152 mqtt5_publish_packet_properties.publish_get_qos_id,
1153 s_publish_packet_string,
1154 &java_packet->packet.qos,
1155 false,
1156 NULL) == AWS_OP_ERR) {
1157 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishPacket create_from_java: QOS not found");
1158 goto on_error;
1159 }
1160
1161 uint8_t packet_retain;
1162 if (aws_get_boolean_from_jobject(
1163 env,
1164 java_publish_packet,
1165 mqtt5_publish_packet_properties.publish_retain_field_id,
1166 s_publish_packet_string,
1167 "retain",
1168 &packet_retain,
1169 true,
1170 &was_value_set) == AWS_OP_ERR) {
1171 goto on_error;
1172 }
1173 if (was_value_set) {
1174 java_packet->packet.retain = (bool)packet_retain;
1175 }
1176
1177 if (aws_get_string_from_jobject(
1178 env,
1179 java_publish_packet,
1180 mqtt5_publish_packet_properties.publish_topic_field_id,
1181 s_publish_packet_string,
1182 "topic",
1183 &java_packet->topic_buf,
1184 &java_packet->topic_cursor,
1185 false,
1186 NULL) == AWS_OP_ERR) {
1187 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "PublishPacket create_from_java: No topic found");
1188 goto on_error;
1189 }
1190 java_packet->packet.topic = java_packet->topic_cursor;
1191
1192 uint32_t format_enum;
1193 if (aws_get_enum_from_jobject(
1194 env,
1195 java_publish_packet,
1196 mqtt5_publish_packet_properties.publish_get_payload_format_id,
1197 s_publish_packet_string,
1198 "payload format",
1199 mqtt5_payload_format_indicator_properties.format_get_value_id,
1200 &format_enum,
1201 true,
1202 &was_value_set) == AWS_OP_ERR) {
1203 goto on_error;
1204 }
1205 if (was_value_set) {
1206 java_packet->payload_format = (enum aws_mqtt5_payload_format_indicator)format_enum;
1207 java_packet->packet.payload_format = &java_packet->payload_format;
1208 }
1209
1210 if (aws_get_uint32_from_jobject(
1211 env,
1212 java_publish_packet,
1213 mqtt5_publish_packet_properties.publish_message_expiry_interval_seconds_field_id,
1214 s_publish_packet_string,
1215 "message expiry interval seconds",
1216 &java_packet->message_expiry_interval_seconds,
1217 true,
1218 &was_value_set) == AWS_OP_ERR) {
1219 goto on_error;
1220 }
1221 if (was_value_set) {
1222 java_packet->packet.message_expiry_interval_seconds = &java_packet->message_expiry_interval_seconds;
1223 }
1224
1225 if (aws_get_uint16_from_jobject(
1226 env,
1227 java_publish_packet,
1228 mqtt5_publish_packet_properties.publish_topic_alias_field_id,
1229 s_publish_packet_string,
1230 "topic alias",
1231 &java_packet->topic_alias,
1232 true,
1233 &was_value_set) == AWS_OP_ERR) {
1234 goto on_error;
1235 }
1236 if (was_value_set) {
1237 java_packet->packet.topic_alias = &java_packet->topic_alias;
1238 }
1239
1240 if (aws_get_string_from_jobject(
1241 env,
1242 java_publish_packet,
1243 mqtt5_publish_packet_properties.publish_response_topic_field_id,
1244 s_publish_packet_string,
1245 "response topic",
1246 &java_packet->response_topic_buf,
1247 &java_packet->response_topic_cursor,
1248 true,
1249 &was_value_set) == AWS_OP_ERR) {
1250 goto on_error;
1251 }
1252 if (was_value_set) {
1253 java_packet->packet.response_topic = &java_packet->response_topic_cursor;
1254 }
1255
1256 if (aws_get_byte_array_from_jobject(
1257 env,
1258 java_publish_packet,
1259 mqtt5_publish_packet_properties.publish_correlation_data_field_id,
1260 s_publish_packet_string,
1261 "correlation data",
1262 &java_packet->correlation_data_buf,
1263 &java_packet->correlation_data_cursor,
1264 true,
1265 &was_value_set) == AWS_OP_ERR) {
1266 goto on_error;
1267 }
1268 if (was_value_set) {
1269 java_packet->packet.correlation_data = &java_packet->correlation_data_cursor;
1270 }
1271
1272 if (aws_get_string_from_jobject(
1273 env,
1274 java_publish_packet,
1275 mqtt5_publish_packet_properties.publish_content_type_field_id,
1276 s_publish_packet_string,
1277 "content type",
1278 &java_packet->content_type_buf,
1279 &java_packet->content_type_cursor,
1280 true,
1281 &was_value_set) == AWS_OP_ERR) {
1282 goto on_error;
1283 }
1284 if (was_value_set) {
1285 java_packet->packet.content_type = &java_packet->content_type_cursor;
1286 }
1287
1288 if (s_get_user_properties_from_packet_optional(
1289 env,
1290 java_publish_packet,
1291 mqtt5_publish_packet_properties.publish_user_properties_field_id,
1292 s_publish_packet_string,
1293 &java_packet->packet.user_property_count,
1294 &java_packet->jni_user_properties_holder,
1295 &java_packet->jni_user_properties_struct_holder,
1296 &java_packet->packet.user_properties) == AWS_OP_ERR) {
1297 goto on_error;
1298 }
1299
1300 return java_packet;
1301
1302 on_error:
1303
1304 /* Clean up */
1305 aws_mqtt5_packet_publish_view_java_destroy(env, allocator, java_packet);
1306 return NULL;
1307 }
1308
aws_mqtt5_packet_publish_view_get_packet(struct aws_mqtt5_packet_publish_view_java_jni * java_packet)1309 struct aws_mqtt5_packet_publish_view *aws_mqtt5_packet_publish_view_get_packet(
1310 struct aws_mqtt5_packet_publish_view_java_jni *java_packet) {
1311 if (java_packet) {
1312 return &java_packet->packet;
1313 } else {
1314 return NULL;
1315 }
1316 }
1317
1318 /*******************************************************************************
1319 * SUBSCRIBE PACKET FUNCTIONS
1320 ******************************************************************************/
1321
aws_mqtt5_packet_subscribe_view_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_packet_subscribe_view_java_jni * java_packet)1322 void aws_mqtt5_packet_subscribe_view_java_destroy(
1323 JNIEnv *env,
1324 struct aws_allocator *allocator,
1325 struct aws_mqtt5_packet_subscribe_view_java_jni *java_packet) {
1326 if (!java_packet) {
1327 return;
1328 }
1329 AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "id=%p: Destroying SubscribePacket", (void *)java_packet);
1330
1331 s_cleanup_two_aws_array(
1332 env, &java_packet->jni_user_properties_holder, &java_packet->jni_user_properties_struct_holder);
1333 s_cleanup_two_aws_array(env, &java_packet->jni_subscription_topic_filters, &java_packet->topic_filters);
1334 aws_mem_release(allocator, java_packet);
1335 }
1336
aws_mqtt5_packet_subscribe_view_create_from_java(JNIEnv * env,struct aws_allocator * allocator,jobject java_subscribe_packet)1337 struct aws_mqtt5_packet_subscribe_view_java_jni *aws_mqtt5_packet_subscribe_view_create_from_java(
1338 JNIEnv *env,
1339 struct aws_allocator *allocator,
1340 jobject java_subscribe_packet) {
1341
1342 jobject jni_subscriptions = (*env)->GetObjectField(
1343 env, java_subscribe_packet, mqtt5_subscribe_packet_properties.subscribe_subscriptions_field_id);
1344 if (aws_jni_check_and_clear_exception(env)) {
1345 return NULL;
1346 }
1347 if (!jni_subscriptions) {
1348 AWS_LOGF_ERROR(
1349 AWS_LS_MQTT5_CLIENT,
1350 "SubscribePacket create_from_java: Creating new SubscribePacket failed due to no subscriptions!");
1351 return NULL;
1352 }
1353 jint jni_subscriptions_size = (*env)->CallIntMethod(env, jni_subscriptions, boxed_list_properties.list_size_id);
1354 if (aws_jni_check_and_clear_exception(env)) {
1355 return NULL;
1356 }
1357 size_t subscriptions_filter_size = (size_t)jni_subscriptions_size;
1358
1359 if (subscriptions_filter_size <= 0) {
1360 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: subscriptions count is 0");
1361 return NULL;
1362 }
1363
1364 struct aws_mqtt5_packet_subscribe_view_java_jni *java_packet =
1365 aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_packet_subscribe_view_java_jni));
1366 if (java_packet == NULL) {
1367 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: Creating new SubscribePacket failed");
1368 return NULL;
1369 }
1370 int array_init = aws_array_list_init_dynamic(
1371 &java_packet->topic_filters, allocator, subscriptions_filter_size, sizeof(struct aws_mqtt5_subscription_view));
1372 if (array_init != AWS_OP_SUCCESS) {
1373 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: Creating new SubscribePacket failed");
1374 goto on_error;
1375 }
1376 int jni_array_init = aws_array_list_init_dynamic(
1377 &java_packet->jni_subscription_topic_filters,
1378 allocator,
1379 subscriptions_filter_size,
1380 sizeof(struct buffer_and_cursor_array_holder_struct));
1381 if (jni_array_init != AWS_OP_SUCCESS) {
1382 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: Creating new SubscribePacket failed");
1383 goto on_error;
1384 }
1385
1386 /* Needed to track if optionals are set or not */
1387 bool was_value_set = false;
1388
1389 if (aws_get_uint32_from_jobject(
1390 env,
1391 java_subscribe_packet,
1392 mqtt5_subscribe_packet_properties.subscribe_subscription_identifier_field_id,
1393 s_subscribe_packet_string,
1394 "subscription identifier",
1395 &java_packet->subscription_identifier,
1396 true,
1397 &was_value_set) == AWS_OP_ERR) {
1398 goto on_error;
1399 }
1400 if (was_value_set) {
1401 java_packet->packet.subscription_identifier = &java_packet->subscription_identifier;
1402 }
1403
1404 java_packet->packet.subscription_count = subscriptions_filter_size;
1405 for (size_t i = 0; i < subscriptions_filter_size; i++) {
1406 /* Populate */
1407 struct aws_mqtt5_subscription_view subscription_view;
1408 struct buffer_and_cursor_array_holder_struct holder;
1409
1410 jobject jni_packet_subscribe_subscription =
1411 (*env)->CallObjectMethod(env, jni_subscriptions, boxed_list_properties.list_get_id, (jint)i);
1412 if (aws_jni_check_and_clear_exception(env)) {
1413 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: Error getting topic filters");
1414 goto on_error;
1415 }
1416
1417 jstring jni_topic_filter = (jstring)(*env)->CallObjectMethod(
1418 env, jni_packet_subscribe_subscription, mqtt5_subscription_properties.subscribe_get_topic_filter_id);
1419 if (aws_jni_check_and_clear_exception(env)) {
1420 AWS_LOGF_ERROR(
1421 AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: Error getting subscription topic filter");
1422 goto on_error;
1423 }
1424 if (jni_topic_filter) {
1425 // Get a temporary cursor from JNI, copy it, and then destroy the JNI version, leaving the byte_buffer copy.
1426 // This gets around JNI stuff going out of scope.
1427 struct aws_byte_cursor tmp_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, jni_topic_filter);
1428 aws_byte_buf_init_copy_from_cursor(&holder.buffer, aws_jni_get_allocator(), tmp_cursor);
1429 holder.cursor = aws_byte_cursor_from_buf(&holder.buffer);
1430 aws_jni_byte_cursor_from_jstring_release(env, jni_topic_filter, tmp_cursor);
1431 subscription_view.topic_filter = holder.cursor;
1432 jni_topic_filter = NULL;
1433 } else {
1434 AWS_LOGF_ERROR(
1435 AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: subscription topic filter is required");
1436 goto on_error;
1437 }
1438
1439 if (s_get_qos_from_packet(
1440 env,
1441 jni_packet_subscribe_subscription,
1442 mqtt5_subscription_properties.subscribe_get_qos_id,
1443 s_subscribe_packet_string,
1444 &subscription_view.qos,
1445 false,
1446 NULL) == AWS_OP_ERR) {
1447 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "SubscribePacket create_from_java: subscription QoS is required");
1448 goto on_error;
1449 }
1450
1451 uint8_t subscription_no_local;
1452 if (aws_get_boolean_from_jobject(
1453 env,
1454 jni_packet_subscribe_subscription,
1455 mqtt5_subscription_properties.subscribe_no_local_field_id,
1456 s_subscribe_packet_string,
1457 "no local",
1458 &subscription_no_local,
1459 true,
1460 &was_value_set) != AWS_OP_SUCCESS) {
1461 goto on_error;
1462 }
1463 if (was_value_set) {
1464 subscription_view.no_local = (bool)subscription_no_local;
1465 }
1466
1467 uint8_t retain_as_published;
1468 if (aws_get_boolean_from_jobject(
1469 env,
1470 jni_packet_subscribe_subscription,
1471 mqtt5_subscription_properties.subscribe_retain_as_published_field_id,
1472 s_subscribe_packet_string,
1473 "retain as published",
1474 &retain_as_published,
1475 true,
1476 &was_value_set) != AWS_OP_SUCCESS) {
1477 goto on_error;
1478 }
1479 if (was_value_set) {
1480 subscription_view.retain_as_published = (bool)retain_as_published;
1481 }
1482
1483 uint32_t retain_enum;
1484 if (aws_get_enum_from_jobject(
1485 env,
1486 jni_packet_subscribe_subscription,
1487 mqtt5_subscription_properties.subscribe_get_retain_handling_type_id,
1488 s_subscribe_packet_string,
1489 "subscription retain handling type",
1490 mqtt5_retain_handling_type_properties.retain_get_value_id,
1491 &retain_enum,
1492 true,
1493 &was_value_set) == AWS_OP_ERR) {
1494 goto on_error;
1495 }
1496 if (was_value_set) {
1497 subscription_view.retain_handling_type = (enum aws_mqtt5_retain_handling_type)retain_enum;
1498 }
1499
1500 aws_array_list_push_back(&java_packet->topic_filters, (void *)&subscription_view);
1501 aws_array_list_push_back(&java_packet->jni_subscription_topic_filters, (void *)&holder);
1502 }
1503 java_packet->packet.subscriptions = (struct aws_mqtt5_subscription_view *)java_packet->topic_filters.data;
1504
1505 if (s_get_user_properties_from_packet_optional(
1506 env,
1507 java_subscribe_packet,
1508 mqtt5_subscribe_packet_properties.subscribe_user_properties_field_id,
1509 s_subscribe_packet_string,
1510 &java_packet->packet.user_property_count,
1511 &java_packet->jni_user_properties_holder,
1512 &java_packet->jni_user_properties_struct_holder,
1513 &java_packet->packet.user_properties) == AWS_OP_ERR) {
1514 goto on_error;
1515 }
1516
1517 return java_packet;
1518
1519 on_error:
1520
1521 /* Clean up */
1522 aws_mqtt5_packet_subscribe_view_java_destroy(env, allocator, java_packet);
1523 return NULL;
1524 }
1525
aws_mqtt5_packet_subscribe_view_get_packet(struct aws_mqtt5_packet_subscribe_view_java_jni * java_packet)1526 struct aws_mqtt5_packet_subscribe_view *aws_mqtt5_packet_subscribe_view_get_packet(
1527 struct aws_mqtt5_packet_subscribe_view_java_jni *java_packet) {
1528 if (java_packet) {
1529 return &java_packet->packet;
1530 } else {
1531 return NULL;
1532 }
1533 }
1534
1535 /*******************************************************************************
1536 * UNSUBSCRIBE PACKET FUNCTIONS
1537 ******************************************************************************/
1538
aws_mqtt5_packet_unsubscribe_view_java_destroy(JNIEnv * env,struct aws_allocator * allocator,struct aws_mqtt5_packet_unsubscribe_view_java_jni * java_packet)1539 void aws_mqtt5_packet_unsubscribe_view_java_destroy(
1540 JNIEnv *env,
1541 struct aws_allocator *allocator,
1542 struct aws_mqtt5_packet_unsubscribe_view_java_jni *java_packet) {
1543 if (!java_packet) {
1544 return;
1545 }
1546 AWS_LOGF_DEBUG(AWS_LS_MQTT5_CLIENT, "id=%p: Destroying UnsubscribePacket", (void *)java_packet);
1547
1548 s_cleanup_two_aws_array(
1549 env, &java_packet->jni_user_properties_holder, &java_packet->jni_user_properties_struct_holder);
1550 s_cleanup_two_aws_array(env, &java_packet->jni_topic_filters, &java_packet->topic_filters);
1551 aws_mem_release(allocator, java_packet);
1552 }
1553
aws_mqtt5_packet_unsubscribe_view_create_from_java(JNIEnv * env,struct aws_allocator * allocator,jobject java_unsubscribe_packet)1554 struct aws_mqtt5_packet_unsubscribe_view_java_jni *aws_mqtt5_packet_unsubscribe_view_create_from_java(
1555 JNIEnv *env,
1556 struct aws_allocator *allocator,
1557 jobject java_unsubscribe_packet) {
1558
1559 jobject jni_topic_filters = (*env)->GetObjectField(
1560 env, java_unsubscribe_packet, mqtt5_unsubscribe_packet_properties.unsubscribe_subscriptions_field_id);
1561 if (aws_jni_check_and_clear_exception(env)) {
1562 return NULL;
1563 }
1564 if (!jni_topic_filters) {
1565 AWS_LOGF_ERROR(
1566 AWS_LS_MQTT5_CLIENT,
1567 "UnsubscribePacket create_from_java: Creating new UnsubscribePacket failed due to no topic filters");
1568 return NULL;
1569 }
1570
1571 size_t topic_filter_size = 0;
1572 jint jni_topic_filter_size = (*env)->CallIntMethod(env, jni_topic_filters, boxed_list_properties.list_size_id);
1573 if (aws_jni_check_and_clear_exception(env)) {
1574 AWS_LOGF_ERROR(
1575 AWS_LS_MQTT5_CLIENT,
1576 "UnsubscribePacket create_from_java: Created new UnsubscribePacket failed due to no topic filters");
1577 return NULL;
1578 }
1579 int32_t jni_topic_filter_size_check = (int32_t)jni_topic_filter_size;
1580 if (jni_topic_filter_size_check < 0) {
1581 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "UnsubscribePacket create_from_java: No topic filters found");
1582 return NULL;
1583 } else {
1584 topic_filter_size = (size_t)jni_topic_filter_size;
1585 }
1586
1587 struct aws_mqtt5_packet_unsubscribe_view_java_jni *java_packet =
1588 aws_mem_calloc(allocator, 1, sizeof(struct aws_mqtt5_packet_unsubscribe_view_java_jni));
1589 if (java_packet == NULL) {
1590 AWS_LOGF_ERROR(
1591 AWS_LS_MQTT5_CLIENT, "UnsubscribePacket create_from_java: Creating new UnsubscribePacket failed");
1592 return NULL;
1593 }
1594 int array_init = aws_array_list_init_dynamic(
1595 &java_packet->topic_filters, allocator, topic_filter_size, sizeof(struct aws_byte_cursor));
1596 if (array_init != AWS_OP_SUCCESS) {
1597 AWS_LOGF_ERROR(
1598 AWS_LS_MQTT5_CLIENT, "UnsubscribePacket create_from_java: Creating new UnsubscribePacket failed");
1599 goto on_error;
1600 }
1601 int jni_array_init = aws_array_list_init_dynamic(
1602 &java_packet->jni_topic_filters,
1603 allocator,
1604 topic_filter_size,
1605 sizeof(struct buffer_and_cursor_array_holder_struct));
1606 if (jni_array_init != AWS_OP_SUCCESS) {
1607 AWS_LOGF_ERROR(
1608 AWS_LS_MQTT5_CLIENT, "UnsubscribePacket create_from_java: Creating new UnsubscribePacket failed");
1609 goto on_error;
1610 }
1611
1612 java_packet->packet.topic_filter_count = topic_filter_size;
1613
1614 for (size_t i = 0; i < topic_filter_size; i++) {
1615 /* Populate */
1616 struct buffer_and_cursor_array_holder_struct holder;
1617
1618 jstring jni_topic_filter =
1619 (jstring)(*env)->CallObjectMethod(env, jni_topic_filters, boxed_list_properties.list_get_id, (jint)i);
1620 if (aws_jni_check_and_clear_exception(env)) {
1621 AWS_LOGF_ERROR(
1622 AWS_LS_MQTT5_CLIENT, "UnsubscribePacket create_from_java: Error getting subscription topic filter");
1623 goto on_error;
1624 }
1625 if (jni_topic_filter) {
1626 // Get a temporary cursor from JNI, copy it, and then destroy the JNI version, leaving the byte_buffer copy.
1627 // This gets around JNI stuff going out of scope.
1628 struct aws_byte_cursor tmp_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, jni_topic_filter);
1629 aws_byte_buf_init_copy_from_cursor(&holder.buffer, aws_jni_get_allocator(), tmp_cursor);
1630 holder.cursor = aws_byte_cursor_from_buf(&holder.buffer);
1631 aws_jni_byte_cursor_from_jstring_release(env, jni_topic_filter, tmp_cursor);
1632 jni_topic_filter = NULL;
1633 }
1634 aws_array_list_push_back(&java_packet->topic_filters, (void *)&holder.cursor);
1635 aws_array_list_push_back(&java_packet->jni_topic_filters, (void *)&holder);
1636 }
1637 java_packet->packet.topic_filters = (struct aws_byte_cursor *)java_packet->topic_filters.data;
1638
1639 if (s_get_user_properties_from_packet_optional(
1640 env,
1641 java_unsubscribe_packet,
1642 mqtt5_unsubscribe_packet_properties.unsubscribe_user_properties_field_id,
1643 s_unsubscribe_packet_string,
1644 &java_packet->packet.user_property_count,
1645 &java_packet->jni_user_properties_holder,
1646 &java_packet->jni_user_properties_struct_holder,
1647 &java_packet->packet.user_properties) == AWS_OP_ERR) {
1648 goto on_error;
1649 }
1650
1651 return java_packet;
1652
1653 on_error:
1654
1655 /* Clean up */
1656 aws_mqtt5_packet_unsubscribe_view_java_destroy(env, allocator, java_packet);
1657 return NULL;
1658 }
1659
aws_mqtt5_packet_unsubscribe_view_get_packet(struct aws_mqtt5_packet_unsubscribe_view_java_jni * java_packet)1660 struct aws_mqtt5_packet_unsubscribe_view *aws_mqtt5_packet_unsubscribe_view_get_packet(
1661 struct aws_mqtt5_packet_unsubscribe_view_java_jni *java_packet) {
1662 if (java_packet) {
1663 return &java_packet->packet;
1664 } else {
1665 return NULL;
1666 }
1667 }
1668
1669 #if UINTPTR_MAX == 0xffffffff
1670 # if defined(_MSC_VER)
1671 # pragma warning(pop)
1672 # else
1673 # pragma GCC diagnostic pop
1674 # endif
1675 #endif
1676