1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5
6 #include <jni.h>
7
8 #include <crt.h>
9 #include <java_class_ids.h>
10 #include <mqtt5_packets.h>
11 #include <mqtt5_utils.h>
12
13 /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
14 #if UINTPTR_MAX == 0xffffffff
15 # if defined(_MSC_VER)
16 # pragma warning(push)
17 # pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
18 # else
19 # pragma GCC diagnostic push
20 # pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
21 # pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
22 # endif
23 #endif
24
s_set_jni_uint32_t_field_in_packet(JNIEnv * env,const uint32_t * native_integer,jobject packet,jfieldID field_id,char * field_name,bool optional)25 int s_set_jni_uint32_t_field_in_packet(
26 JNIEnv *env,
27 const uint32_t *native_integer,
28 jobject packet,
29 jfieldID field_id,
30 char *field_name,
31 bool optional) {
32
33 if (native_integer != NULL) {
34 jobject jni_long = (*env)->NewObject(
35 env, boxed_long_properties.long_class, boxed_long_properties.constructor, (jlong)*native_integer);
36 if (aws_jni_check_and_clear_exception(env)) {
37 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not create uint32 field %s", field_name);
38 return AWS_OP_ERR;
39 }
40 (*env)->SetObjectField(env, packet, field_id, jni_long);
41 if (aws_jni_check_and_clear_exception(env)) {
42 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not set uint32 field %s", field_name);
43 return AWS_OP_ERR;
44 }
45 if (!optional) {
46 return AWS_OP_SUCCESS;
47 }
48 }
49 if (optional) {
50 return AWS_OP_SUCCESS;
51 } else {
52 return AWS_OP_ERR;
53 }
54 }
55
s_set_jni_uint16_t_field_in_packet(JNIEnv * env,const uint16_t * native_integer,jobject packet,jfieldID field_id,char * field_name,bool optional)56 int s_set_jni_uint16_t_field_in_packet(
57 JNIEnv *env,
58 const uint16_t *native_integer,
59 jobject packet,
60 jfieldID field_id,
61 char *field_name,
62 bool optional) {
63 if (native_integer != NULL) {
64 jobject jni_int = (*env)->NewObject(
65 env,
66 boxed_integer_properties.integer_class,
67 boxed_integer_properties.integer_constructor_id,
68 (jint)*native_integer);
69 if (aws_jni_check_and_clear_exception(env)) {
70 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not create uint16 field %s", field_name);
71 return AWS_OP_ERR;
72 }
73 (*env)->SetObjectField(env, packet, field_id, jni_int);
74 if (aws_jni_check_and_clear_exception(env)) {
75 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not set uint16 field %s", field_name);
76 return AWS_OP_ERR;
77 }
78 if (!optional) {
79 return AWS_OP_SUCCESS;
80 }
81 }
82 if (optional) {
83 return AWS_OP_SUCCESS;
84 } else {
85 return AWS_OP_ERR;
86 }
87 }
88
s_set_jni_bool_field_in_packet(JNIEnv * env,const bool * native_boolean,jobject packet,jfieldID field_id,char * field_name,bool optional)89 int s_set_jni_bool_field_in_packet(
90 JNIEnv *env,
91 const bool *native_boolean,
92 jobject packet,
93 jfieldID field_id,
94 char *field_name,
95 bool optional) {
96 if (native_boolean != NULL) {
97 jobject jni_boolean = (*env)->NewObject(
98 env,
99 boxed_boolean_properties.boolean_class,
100 boxed_boolean_properties.boolean_constructor_id,
101 (jboolean)*native_boolean);
102 if (aws_jni_check_and_clear_exception(env)) {
103 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not create boolean field %s", field_name);
104 return AWS_OP_ERR;
105 }
106
107 (*env)->SetObjectField(env, packet, field_id, jni_boolean);
108 if (aws_jni_check_and_clear_exception(env)) {
109 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not set boolean field %s", field_name);
110 return AWS_OP_ERR;
111 }
112
113 if (!optional) {
114 return AWS_OP_SUCCESS;
115 }
116 }
117 if (optional) {
118 return AWS_OP_SUCCESS;
119 } else {
120 return AWS_OP_ERR;
121 }
122 }
123
s_set_jni_string_field_in_packet(JNIEnv * env,const struct aws_byte_cursor * native_cursor,jobject packet,jfieldID field_id,char * field_name,bool optional)124 int s_set_jni_string_field_in_packet(
125 JNIEnv *env,
126 const struct aws_byte_cursor *native_cursor,
127 jobject packet,
128 jfieldID field_id,
129 char *field_name,
130 bool optional) {
131 if (native_cursor != NULL) {
132 jstring jni_string = aws_jni_string_from_cursor(env, native_cursor);
133 (*env)->SetObjectField(env, packet, field_id, jni_string);
134 if (aws_jni_check_and_clear_exception(env)) {
135 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not set string field %s", field_name);
136 return AWS_OP_ERR;
137 }
138 if (!optional) {
139 return AWS_OP_SUCCESS;
140 }
141 }
142 if (optional) {
143 return AWS_OP_SUCCESS;
144 } else {
145 return AWS_OP_ERR;
146 }
147 }
148
s_set_jni_byte_array_field_in_packet(JNIEnv * env,const struct aws_byte_cursor * native_cursor,jobject packet,jfieldID field_id,char * field_name,bool optional)149 int s_set_jni_byte_array_field_in_packet(
150 JNIEnv *env,
151 const struct aws_byte_cursor *native_cursor,
152 jobject packet,
153 jfieldID field_id,
154 char *field_name,
155 bool optional) {
156 if (native_cursor != NULL) {
157 jbyteArray jni_byte = aws_jni_byte_array_from_cursor(env, native_cursor);
158 (*env)->SetObjectField(env, packet, field_id, jni_byte);
159 if (aws_jni_check_and_clear_exception(env)) {
160 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not set string field %s", field_name);
161 return AWS_OP_ERR;
162 }
163 if (!optional) {
164 return AWS_OP_SUCCESS;
165 }
166 }
167 if (optional) {
168 return AWS_OP_SUCCESS;
169 } else {
170 return AWS_OP_ERR;
171 }
172 }
173
s_set_user_properties_field(JNIEnv * env,const size_t user_property_count,const struct aws_mqtt5_user_property * packet_properties,jobject packet,jfieldID user_property_field_id)174 int s_set_user_properties_field(
175 JNIEnv *env,
176 const size_t user_property_count,
177 const struct aws_mqtt5_user_property *packet_properties,
178 jobject packet,
179 jfieldID user_property_field_id) {
180 /* No properties - nothing to do */
181 if (packet_properties == NULL) {
182 return AWS_OP_SUCCESS;
183 }
184
185 if (user_property_count > 0) {
186 jobject jni_user_properties_list = (*env)->NewObject(
187 env, boxed_array_list_properties.list_class, boxed_array_list_properties.list_constructor_id);
188 if (aws_jni_check_and_clear_exception(env)) {
189 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not make new user properties list");
190 return AWS_OP_ERR;
191 }
192
193 (*env)->SetObjectField(env, packet, user_property_field_id, jni_user_properties_list);
194 if (aws_jni_check_and_clear_exception(env)) {
195 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not set new user properties list");
196 return AWS_OP_ERR;
197 }
198
199 for (size_t i = 0; i < user_property_count; ++i) {
200 const struct aws_mqtt5_user_property *property = &packet_properties[i];
201 jstring jni_new_property_name = aws_jni_string_from_cursor(env, &property->name);
202 jstring jni_new_property_value = aws_jni_string_from_cursor(env, &property->value);
203
204 jobject jni_new_property = (*env)->NewObject(
205 env,
206 mqtt5_user_property_properties.user_property_class,
207 mqtt5_user_property_properties.property_constructor_id,
208 jni_new_property_name,
209 jni_new_property_value);
210 if (aws_jni_check_and_clear_exception(env)) {
211 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not make new user property");
212 return AWS_OP_ERR;
213 }
214
215 jboolean jni_add_result = (*env)->CallBooleanMethod(
216 env, jni_user_properties_list, boxed_list_properties.list_add_id, jni_new_property);
217 if (aws_jni_check_and_clear_exception(env)) {
218 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Could not add new user property");
219 return AWS_OP_ERR;
220 }
221
222 if ((bool)jni_add_result == false) {
223 return AWS_OP_ERR;
224 }
225 }
226 }
227 return AWS_OP_SUCCESS;
228 }
229
s_set_int_enum_in_packet(JNIEnv * env,const int * int_enum,jobject packet,jmethodID set_enum_field_id,bool optional)230 int s_set_int_enum_in_packet(
231 JNIEnv *env,
232 const int *int_enum,
233 jobject packet,
234 jmethodID set_enum_field_id,
235 bool optional) {
236
237 if (int_enum) {
238 if (*int_enum < 0) {
239 return AWS_OP_ERR;
240 }
241 (*env)->CallVoidMethod(env, packet, set_enum_field_id, (jint)*int_enum);
242 if (aws_jni_check_and_clear_exception(env)) {
243 return AWS_OP_ERR;
244 }
245
246 if (!optional) {
247 return AWS_OP_SUCCESS;
248 }
249 }
250
251 if (optional) {
252 return AWS_OP_SUCCESS;
253 } else {
254 return AWS_OP_ERR;
255 }
256 }
257
s_aws_mqtt5_client_create_jni_connack_packet_from_native(JNIEnv * env,const struct aws_mqtt5_packet_connack_view * native_connack_data)258 jobject s_aws_mqtt5_client_create_jni_connack_packet_from_native(
259 JNIEnv *env,
260 const struct aws_mqtt5_packet_connack_view *native_connack_data) {
261
262 jobject connack_data = (*env)->NewObject(
263 env,
264 mqtt5_connack_packet_properties.connack_packet_class,
265 mqtt5_connack_packet_properties.connack_constructor_id);
266
267 (*env)->SetBooleanField(
268 env,
269 connack_data,
270 mqtt5_connack_packet_properties.connack_session_present_field_id,
271 (jboolean)native_connack_data->session_present);
272
273 int reason_code_int = (int)native_connack_data->reason_code;
274 if (reason_code_int < 0) {
275 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error when creating ConnAckPacket from native: Reason code is negative!");
276 return NULL;
277 }
278 (*env)->CallVoidMethod(
279 env, connack_data, mqtt5_connack_packet_properties.connack_native_add_reason_code_id, (jint)reason_code_int);
280
281 /* Set all of the optional data in Java classes */
282 if (s_set_jni_uint32_t_field_in_packet(
283 env,
284 native_connack_data->session_expiry_interval,
285 connack_data,
286 mqtt5_connack_packet_properties.connack_session_expiry_interval_field_id,
287 "session expiry interval",
288 true) != AWS_OP_SUCCESS) {
289 return NULL;
290 }
291 if (s_set_jni_uint16_t_field_in_packet(
292 env,
293 native_connack_data->receive_maximum,
294 connack_data,
295 mqtt5_connack_packet_properties.connack_receive_maximum_field_id,
296 "receive maximum",
297 true) != AWS_OP_SUCCESS) {
298 return NULL;
299 };
300
301 if (native_connack_data->maximum_qos) {
302 int *maximum_qos_int = (int *)native_connack_data->maximum_qos;
303 if (s_set_int_enum_in_packet(
304 env,
305 maximum_qos_int,
306 connack_data,
307 mqtt5_connack_packet_properties.connack_native_add_maximum_qos_id,
308 true) != AWS_OP_SUCCESS) {
309 AWS_LOGF_ERROR(
310 AWS_LS_MQTT5_CLIENT, "Error when creating ConnAckPacket from native: Could not set maximum QOS");
311 return NULL;
312 }
313 }
314
315 if (s_set_jni_bool_field_in_packet(
316 env,
317 native_connack_data->retain_available,
318 connack_data,
319 mqtt5_connack_packet_properties.connack_retain_available_field_id,
320 "retain available",
321 true) != AWS_OP_SUCCESS) {
322 return NULL;
323 }
324 if (s_set_jni_uint32_t_field_in_packet(
325 env,
326 native_connack_data->maximum_packet_size,
327 connack_data,
328 mqtt5_connack_packet_properties.connack_maximum_packet_size_field_id,
329 "maximum packet size",
330 true) != AWS_OP_SUCCESS) {
331 return NULL;
332 }
333 if (s_set_jni_string_field_in_packet(
334 env,
335 native_connack_data->assigned_client_identifier,
336 connack_data,
337 mqtt5_connack_packet_properties.connack_assigned_client_identifier_field_id,
338 "assigned client identifier",
339 true) != AWS_OP_SUCCESS) {
340 return NULL;
341 }
342 if (s_set_jni_uint16_t_field_in_packet(
343 env,
344 native_connack_data->topic_alias_maximum,
345 connack_data,
346 mqtt5_connack_packet_properties.connack_topic_alias_maximum_field_id,
347 "topic alias maximum",
348 true) != AWS_OP_SUCCESS) {
349 return NULL;
350 };
351 if (s_set_jni_string_field_in_packet(
352 env,
353 native_connack_data->reason_string,
354 connack_data,
355 mqtt5_connack_packet_properties.connack_reason_string_field_id,
356 "reason string",
357 true) != AWS_OP_SUCCESS) {
358 return NULL;
359 }
360 if (s_set_jni_bool_field_in_packet(
361 env,
362 native_connack_data->wildcard_subscriptions_available,
363 connack_data,
364 mqtt5_connack_packet_properties.connack_wildcard_subscriptions_available_field_id,
365 "wildcard subscriptions available",
366 true) != AWS_OP_SUCCESS) {
367 return NULL;
368 };
369 if (s_set_jni_bool_field_in_packet(
370 env,
371 native_connack_data->subscription_identifiers_available,
372 connack_data,
373 mqtt5_connack_packet_properties.connack_subscription_identifiers_available_field_id,
374 "subscription identifiers available",
375 true) != AWS_OP_SUCCESS) {
376 return NULL;
377 };
378 if (s_set_jni_bool_field_in_packet(
379 env,
380 native_connack_data->shared_subscriptions_available,
381 connack_data,
382 mqtt5_connack_packet_properties.connack_shared_subscriptions_available_field_id,
383 "shared subscriptions available",
384 true) != AWS_OP_SUCCESS) {
385 return NULL;
386 };
387 if (s_set_jni_uint16_t_field_in_packet(
388 env,
389 native_connack_data->server_keep_alive,
390 connack_data,
391 mqtt5_connack_packet_properties.connack_server_keep_alive_field_id,
392 "server keep alive",
393 true) != AWS_OP_SUCCESS) {
394 return NULL;
395 };
396 if (s_set_jni_string_field_in_packet(
397 env,
398 native_connack_data->response_information,
399 connack_data,
400 mqtt5_connack_packet_properties.connack_response_information_field_id,
401 "response information",
402 true) != AWS_OP_SUCCESS) {
403 return NULL;
404 }
405 if (s_set_jni_string_field_in_packet(
406 env,
407 native_connack_data->server_reference,
408 connack_data,
409 mqtt5_connack_packet_properties.connack_server_reference_field_id,
410 "server reference",
411 true) != AWS_OP_SUCCESS) {
412 return NULL;
413 }
414
415 if (s_set_user_properties_field(
416 env,
417 native_connack_data->user_property_count,
418 native_connack_data->user_properties,
419 connack_data,
420 mqtt5_connack_packet_properties.connack_user_properties_field_id) != AWS_OP_SUCCESS) {
421 AWS_LOGF_ERROR(
422 AWS_LS_MQTT5_CLIENT, "Error when creating ConnAckPacket from native: could not add user property!");
423 return NULL;
424 }
425
426 return connack_data;
427 }
428
s_aws_mqtt5_client_create_jni_disconnect_packet_from_native(JNIEnv * env,const struct aws_mqtt5_packet_disconnect_view * native_disconnect_data)429 jobject s_aws_mqtt5_client_create_jni_disconnect_packet_from_native(
430 JNIEnv *env,
431 const struct aws_mqtt5_packet_disconnect_view *native_disconnect_data) {
432
433 jobject disconnect_packet_data = (*env)->NewObject(
434 env,
435 mqtt5_disconnect_packet_properties.disconnect_packet_class,
436 mqtt5_disconnect_packet_properties.disconnect_constructor_id);
437
438 int reason_code_int = (int)native_disconnect_data->reason_code;
439 if (s_set_int_enum_in_packet(
440 env,
441 &reason_code_int,
442 disconnect_packet_data,
443 mqtt5_disconnect_packet_properties.disconnect_native_add_disconnect_reason_code_id,
444 false) != AWS_OP_SUCCESS) {
445 AWS_LOGF_ERROR(
446 AWS_LS_MQTT5_CLIENT, "Error when creating DisconnectPacket from native: Could not set reason code");
447 return NULL;
448 }
449
450 if (s_set_jni_uint32_t_field_in_packet(
451 env,
452 native_disconnect_data->session_expiry_interval_seconds,
453 disconnect_packet_data,
454 mqtt5_disconnect_packet_properties.disconnect_session_expiry_interval_seconds_field_id,
455 "session expiry interval seconds",
456 true) != AWS_OP_SUCCESS) {
457 return NULL;
458 }
459 if (s_set_jni_string_field_in_packet(
460 env,
461 native_disconnect_data->reason_string,
462 disconnect_packet_data,
463 mqtt5_disconnect_packet_properties.disconnect_reason_string_field_id,
464 "reason string",
465 true) != AWS_OP_SUCCESS) {
466 return NULL;
467 }
468 if (s_set_jni_string_field_in_packet(
469 env,
470 native_disconnect_data->server_reference,
471 disconnect_packet_data,
472 mqtt5_disconnect_packet_properties.disconnect_session_server_reference_field_id,
473 "server reference",
474 true) != AWS_OP_SUCCESS) {
475 return NULL;
476 }
477
478 if (s_set_user_properties_field(
479 env,
480 native_disconnect_data->user_property_count,
481 native_disconnect_data->user_properties,
482 disconnect_packet_data,
483 mqtt5_disconnect_packet_properties.disconnect_user_properties_field_id) != AWS_OP_SUCCESS) {
484 AWS_LOGF_ERROR(
485 AWS_LS_MQTT5_CLIENT, "Error when creating DisconnectPacket from native: could not add user property!");
486 return NULL;
487 }
488
489 return disconnect_packet_data;
490 }
491
s_aws_mqtt5_client_create_jni_negotiated_settings_from_native(JNIEnv * env,const struct aws_mqtt5_negotiated_settings * native_negotiated_settings_data)492 jobject s_aws_mqtt5_client_create_jni_negotiated_settings_from_native(
493 JNIEnv *env,
494 const struct aws_mqtt5_negotiated_settings *native_negotiated_settings_data) {
495
496 jobject negotiated_settings_data = (*env)->NewObject(
497 env,
498 mqtt5_negotiated_settings_properties.negotiated_settings_class,
499 mqtt5_negotiated_settings_properties.negotiated_settings_constructor_id);
500
501 (*env)->CallVoidMethod(
502 env,
503 negotiated_settings_data,
504 mqtt5_negotiated_settings_properties.negotiated_settings_native_set_qos_id,
505 (jint)native_negotiated_settings_data->maximum_qos);
506 aws_jni_check_and_clear_exception(env); /* To hide JNI warning */
507
508 (*env)->SetLongField(
509 env,
510 negotiated_settings_data,
511 mqtt5_negotiated_settings_properties.negotiated_settings_session_expiry_interval_field_id,
512 (jlong)native_negotiated_settings_data->session_expiry_interval);
513 (*env)->SetIntField(
514 env,
515 negotiated_settings_data,
516 mqtt5_negotiated_settings_properties.negotiated_settings_receive_maximum_from_server_field_id,
517 (jint)native_negotiated_settings_data->receive_maximum_from_server);
518 (*env)->SetLongField(
519 env,
520 negotiated_settings_data,
521 mqtt5_negotiated_settings_properties.negotiated_settings_maximum_packet_size_to_server_field_id,
522 (jlong)native_negotiated_settings_data->maximum_packet_size_to_server);
523 (*env)->SetIntField(
524 env,
525 negotiated_settings_data,
526 mqtt5_negotiated_settings_properties.negotiated_settings_topic_alias_maximum_to_server_field_id,
527 (jint)native_negotiated_settings_data->topic_alias_maximum_to_server);
528 (*env)->SetIntField(
529 env,
530 negotiated_settings_data,
531 mqtt5_negotiated_settings_properties.negotiated_settings_topic_alias_maximum_to_client_field_id,
532 (jint)native_negotiated_settings_data->topic_alias_maximum_to_client);
533 (*env)->SetIntField(
534 env,
535 negotiated_settings_data,
536 mqtt5_negotiated_settings_properties.negotiated_settings_server_keep_alive_field_id,
537 (jint)native_negotiated_settings_data->server_keep_alive);
538 (*env)->SetBooleanField(
539 env,
540 negotiated_settings_data,
541 mqtt5_negotiated_settings_properties.negotiated_settings_retain_available_field_id,
542 (jboolean)native_negotiated_settings_data->retain_available);
543 (*env)->SetBooleanField(
544 env,
545 negotiated_settings_data,
546 mqtt5_negotiated_settings_properties.negotiated_settings_wildcard_subscriptions_available_field_id,
547 (jboolean)native_negotiated_settings_data->wildcard_subscriptions_available);
548 (*env)->SetBooleanField(
549 env,
550 negotiated_settings_data,
551 mqtt5_negotiated_settings_properties.negotiated_settings_subscription_identifiers_available_field_id,
552 (jboolean)native_negotiated_settings_data->subscription_identifiers_available);
553 (*env)->SetBooleanField(
554 env,
555 negotiated_settings_data,
556 mqtt5_negotiated_settings_properties.negotiated_settings_shared_subscriptions_available_field_id,
557 (jboolean)native_negotiated_settings_data->shared_subscriptions_available);
558 (*env)->SetBooleanField(
559 env,
560 negotiated_settings_data,
561 mqtt5_negotiated_settings_properties.negotiated_settings_rejoined_session_field_id,
562 (jboolean)native_negotiated_settings_data->rejoined_session);
563
564 struct aws_byte_cursor client_id_storage_cursor =
565 aws_byte_cursor_from_buf(&native_negotiated_settings_data->client_id_storage);
566 jstring jni_assigned_client_id = aws_jni_string_from_cursor(env, &client_id_storage_cursor);
567 (*env)->SetObjectField(
568 env,
569 negotiated_settings_data,
570 mqtt5_negotiated_settings_properties.negotiated_settings_assigned_client_id_field_id,
571 jni_assigned_client_id);
572
573 return negotiated_settings_data;
574 }
575
s_aws_mqtt5_client_create_jni_publish_packet_from_native(JNIEnv * env,const struct aws_mqtt5_packet_publish_view * publish)576 jobject s_aws_mqtt5_client_create_jni_publish_packet_from_native(
577 JNIEnv *env,
578 const struct aws_mqtt5_packet_publish_view *publish) {
579 jobject publish_packet_data = (*env)->NewObject(
580 env,
581 mqtt5_publish_packet_properties.publish_packet_class,
582 mqtt5_publish_packet_properties.publish_constructor_id);
583
584 jbyteArray jni_payload = aws_jni_byte_array_from_cursor(env, &publish->payload);
585 (*env)->SetObjectField(
586 env, publish_packet_data, mqtt5_publish_packet_properties.publish_payload_field_id, jni_payload);
587
588 int publish_qos_int = (int)publish->qos;
589 if (s_set_int_enum_in_packet(
590 env,
591 &publish_qos_int,
592 publish_packet_data,
593 mqtt5_publish_packet_properties.publish_native_set_qos_id,
594 false) != AWS_OP_SUCCESS) {
595 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error when creating PublishPacket from native: Could not set QOS");
596 return NULL;
597 }
598
599 if (s_set_jni_bool_field_in_packet(
600 env,
601 &publish->retain,
602 publish_packet_data,
603 mqtt5_publish_packet_properties.publish_retain_field_id,
604 "retain",
605 false) != AWS_OP_SUCCESS) {
606 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error when creating PublishPacket from native: Could not set retain");
607 return NULL;
608 }
609
610 jstring jni_topic = aws_jni_string_from_cursor(env, &publish->topic);
611 (*env)->SetObjectField(env, publish_packet_data, mqtt5_publish_packet_properties.publish_topic_field_id, jni_topic);
612
613 if (publish->payload_format) {
614 if (s_set_int_enum_in_packet(
615 env,
616 (int *)publish->payload_format,
617 publish_packet_data,
618 mqtt5_publish_packet_properties.publish_native_set_payload_format_indicator_id,
619 true) != AWS_OP_SUCCESS) {
620 AWS_LOGF_ERROR(
621 AWS_LS_MQTT5_CLIENT, "Error when creating PublishPacket from native: Could not set payload format");
622 return NULL;
623 }
624 }
625
626 if (s_set_jni_uint32_t_field_in_packet(
627 env,
628 publish->message_expiry_interval_seconds,
629 publish_packet_data,
630 mqtt5_publish_packet_properties.publish_message_expiry_interval_seconds_field_id,
631 "message expiry interval seconds",
632 true) != AWS_OP_SUCCESS) {
633 return NULL;
634 }
635
636 if (s_set_jni_uint16_t_field_in_packet(
637 env,
638 publish->topic_alias,
639 publish_packet_data,
640 mqtt5_publish_packet_properties.publish_topic_alias_field_id,
641 "topic alias",
642 true) != AWS_OP_SUCCESS) {
643 return NULL;
644 }
645
646 if (s_set_jni_string_field_in_packet(
647 env,
648 publish->response_topic,
649 publish_packet_data,
650 mqtt5_publish_packet_properties.publish_response_topic_field_id,
651 "response topic",
652 true) != AWS_OP_SUCCESS) {
653 return NULL;
654 }
655
656 if (s_set_jni_byte_array_field_in_packet(
657 env,
658 publish->correlation_data,
659 publish_packet_data,
660 mqtt5_publish_packet_properties.publish_correlation_data_field_id,
661 "correlation data",
662 true) != AWS_OP_SUCCESS) {
663 return NULL;
664 }
665
666 if (s_set_jni_string_field_in_packet(
667 env,
668 publish->content_type,
669 publish_packet_data,
670 mqtt5_publish_packet_properties.publish_content_type_field_id,
671 "content type",
672 true) != AWS_OP_SUCCESS) {
673 return NULL;
674 }
675
676 if (publish->subscription_identifier_count && publish->subscription_identifiers) {
677 jobject jni_subscription_identifiers = (*env)->NewObject(
678 env, boxed_array_list_properties.list_class, boxed_array_list_properties.list_constructor_id);
679 (*env)->SetObjectField(
680 env,
681 publish_packet_data,
682 mqtt5_publish_packet_properties.publish_subscription_identifiers_field_id,
683 jni_subscription_identifiers);
684
685 for (size_t i = 0; i < publish->subscription_identifier_count; ++i) {
686 const uint32_t *identifier = &publish->subscription_identifiers[i];
687 jobject jni_identifier_obj = (*env)->NewObject(
688 env, boxed_long_properties.long_class, boxed_long_properties.constructor, (jlong)*identifier);
689 jboolean jni_add_result = (*env)->CallBooleanMethod(
690 env, jni_subscription_identifiers, boxed_list_properties.list_add_id, jni_identifier_obj);
691 if (aws_jni_check_and_clear_exception(env)) {
692 AWS_LOGF_ERROR(
693 AWS_LS_MQTT5_CLIENT,
694 "When creating PublishPacket from native could not add subscription identifier!");
695 return NULL;
696 }
697 if ((bool)jni_add_result == false) {
698 AWS_LOGF_ERROR(
699 AWS_LS_MQTT5_CLIENT,
700 "When creating PublishPacket from native could not add subscription identifier!");
701 return NULL;
702 }
703 }
704 }
705
706 if (s_set_user_properties_field(
707 env,
708 publish->user_property_count,
709 publish->user_properties,
710 publish_packet_data,
711 mqtt5_publish_packet_properties.publish_user_properties_field_id) == AWS_OP_ERR) {
712 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "When creating PublishPacket from native could not add user properties!");
713 return NULL;
714 }
715
716 return publish_packet_data;
717 }
718
s_aws_mqtt5_client_create_jni_puback_packet_from_native(JNIEnv * env,struct aws_mqtt5_packet_puback_view * puback_packet)719 jobject s_aws_mqtt5_client_create_jni_puback_packet_from_native(
720 JNIEnv *env,
721 struct aws_mqtt5_packet_puback_view *puback_packet) {
722 /* Make the PubAck packet */
723 jobject puback_packet_data = (*env)->NewObject(
724 env, mqtt5_puback_packet_properties.puback_packet_class, mqtt5_puback_packet_properties.puback_constructor_id);
725
726 int reason_code_int = (int)puback_packet->reason_code;
727 if (s_set_int_enum_in_packet(
728 env,
729 &reason_code_int,
730 puback_packet_data,
731 mqtt5_puback_packet_properties.puback_native_add_reason_code_id,
732 false) != AWS_OP_SUCCESS) {
733 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "Error when creating PubAck result from native: Could not set reason code");
734 return NULL;
735 }
736 if (s_set_jni_string_field_in_packet(
737 env,
738 puback_packet->reason_string,
739 puback_packet_data,
740 mqtt5_puback_packet_properties.puback_reason_string_field_id,
741 "reason string",
742 true) != AWS_OP_SUCCESS) {
743 return NULL;
744 }
745 if (s_set_user_properties_field(
746 env,
747 puback_packet->user_property_count,
748 puback_packet->user_properties,
749 puback_packet_data,
750 mqtt5_puback_packet_properties.puback_user_properties_field_id) == AWS_OP_ERR) {
751 AWS_LOGF_ERROR(AWS_LS_MQTT5_CLIENT, "When creating PubAckPacket from native could not add user property!");
752 return NULL;
753 }
754 return puback_packet_data;
755 }
756