1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 #include "nx_azure_iot_hub_client.h"
13 
14 #include "azure/core/az_version.h"
15 
16 
17 #define NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE     10
18 #define NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON              "{}"
19 #define NX_AZURE_IOT_HUB_CLIENT_THROTTLE_STATUS_CODE    429
20 
21 #ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT
22 #ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE
23 #define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE NX_INTERFACE_TYPE_UNKNOWN
24 #define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE
25 #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE */
26 
27 #ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR
28 #define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR 0
29 #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR */
30 
31 #ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE
32 #define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE "U"
33 #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE */
34 
35 /* Useragent e.g: azsdk-c%2F1.3.0%20%28azrtos%206.1.2%3B0%3B0%3BU%29 */
36 #define NX_AZURE_IOT_HUB_CLIENT_STR(C)          #C
37 #define NX_AZURE_IOT_HUB_CLIENT_TO_STR(x)       NX_AZURE_IOT_HUB_CLIENT_STR(x)
38 #define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT      "azsdk-c%2F" AZ_SDK_VERSION_STRING "%20%28azrtos%20" \
39                                                 NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_MAJOR_VERSION) "." \
40                                                 NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_MINOR_VERSION) "." \
41                                                 NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_PATCH_VERSION) "%3B"\
42                                                 NX_AZURE_IOT_HUB_CLIENT_TO_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE) "%3B"\
43                                                 NX_AZURE_IOT_HUB_CLIENT_TO_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR) "%3B"\
44                                                 NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE "%29"
45 static UCHAR _nx_azure_iot_hub_client_user_agent[] = NX_AZURE_IOT_HUB_CLIENT_USER_AGENT;
46 
47 #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT */
48 
49 #define NX_AZURE_IOT_HUB_CLIENT_COMPONENT_STRING        "$.sub"
50 
51 #define NX_AZURE_IOT_HUB_CLIENT_WEB_SOCKET_PATH         "/$iothub/websocket"
52 
53 static VOID nx_azure_iot_hub_client_received_message_cleanup(NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *message);
54 static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
55                                                             UINT is_subscribe);
56 static UINT nx_azure_iot_hub_client_process_publish_packet(UCHAR *start_ptr,
57                                                            ULONG *topic_offset_ptr,
58                                                            USHORT *topic_length_ptr);
59 static VOID nx_azure_iot_hub_client_mqtt_receive_callback(NXD_MQTT_CLIENT* client_ptr,
60                                                           UINT number_of_messages);
61 static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
62                                                 NX_PACKET *packet_ptr,
63                                                 ULONG topic_offset,
64                                                 USHORT topic_length);
65 static UINT nx_azure_iot_hub_client_properties_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
66                                                        NX_PACKET *packet_ptr,
67                                                        ULONG topic_offset,
68                                                        USHORT topic_length);
69 static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
70                                                       NX_PACKET *packet_ptr, ULONG topic_offset,
71                                                       USHORT topic_length, UINT *request_id_ptr,
72                                                       ULONG *version_ptr, UINT *message_type_ptr,
73                                                       UINT *status_ptr);
74 extern UINT _nxd_mqtt_process_publish_packet(NX_PACKET *packet_ptr, ULONG *topic_offset_ptr,
75                                              USHORT *topic_length_ptr, ULONG *message_offset_ptr,
76                                              ULONG *message_length_ptr);
77 static VOID nx_azure_iot_hub_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr,
78                                                         UINT status, VOID *context);
79 static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr);
80 static VOID nx_azure_iot_hub_client_mqtt_ack_receive_notify(NXD_MQTT_CLIENT *client_ptr, UINT type,
81                                                             USHORT packet_id, NX_PACKET *transmit_packet_ptr,
82                                                             VOID *context);
83 static VOID nx_azure_iot_hub_client_thread_dequeue(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
84                                                    NX_AZURE_IOT_THREAD *thread_list_ptr);
85 static UINT nx_azure_iot_hub_client_sas_token_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
86                                                   ULONG expiry_time_secs, const UCHAR *key, UINT key_len,
87                                                   UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length);
88 static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr);
89 UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr);
90 UINT nx_azure_iot_hub_client_component_add_internal(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
91                                                     const UCHAR *component_name_ptr,
92                                                     USHORT component_name_length,
93                                                     UINT (*callback_ptr)(VOID *json_reader_ptr,
94                                                                         ULONG version,
95                                                                         VOID *args),
96                                                     VOID *callback_args);
97 
nx_azure_iot_hub_client_throttle_with_jitter(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)98 static UINT nx_azure_iot_hub_client_throttle_with_jitter(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
99 {
100 UINT jitter;
101 UINT base_delay = NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC;
102 UINT retry_count = hub_client_ptr -> nx_azure_iot_hub_client_throttle_count;
103 uint64_t delay;
104 
105     if (retry_count < (sizeof(UINT) * 8 - 1))
106     {
107         retry_count++;
108         delay = (uint64_t)((1 << retry_count) * NX_AZURE_IOT_HUB_CLIENT_INITIAL_BACKOFF_IN_SEC);
109 
110         if (delay <= (UINT)(-1))
111         {
112             base_delay = (UINT)delay;
113         }
114     }
115 
116     if (base_delay > NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC)
117     {
118         base_delay = NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC;
119     }
120     else
121     {
122        hub_client_ptr -> nx_azure_iot_hub_client_throttle_count = retry_count;
123     }
124 
125     jitter = base_delay * NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_JITTER_PERCENT * (NX_RAND() & 0xFF) / 25600;
126     return((UINT)(base_delay + jitter));
127 }
128 
nx_azure_iot_hub_client_throttled_check(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)129 static UINT nx_azure_iot_hub_client_throttled_check(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
130 {
131 ULONG current_time;
132 UINT status = NX_AZURE_IOT_SUCCESS;
133 
134     if (hub_client_ptr -> nx_azure_iot_hub_client_throttle_count != 0)
135     {
136         if ((status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, &current_time)))
137         {
138             LogError(LogLiteralArgs("IoTHub client fail to get unix time: %d"), status);
139             return(status);
140         }
141 
142         if (current_time < hub_client_ptr -> nx_azure_iot_hub_client_throttle_end_time)
143         {
144             return(NX_AZURE_IOT_THROTTLED);
145         }
146     }
147 
148     return(status);
149 }
150 
nx_azure_iot_hub_client_initialize(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT * nx_azure_iot_ptr,const UCHAR * host_name,UINT host_name_length,const UCHAR * device_id,UINT device_id_length,const UCHAR * module_id,UINT module_id_length,const NX_CRYPTO_METHOD ** crypto_array,UINT crypto_array_size,const NX_CRYPTO_CIPHERSUITE ** cipher_map,UINT cipher_map_size,UCHAR * metadata_memory,UINT memory_size,NX_SECURE_X509_CERT * trusted_certificate)151 UINT nx_azure_iot_hub_client_initialize(NX_AZURE_IOT_HUB_CLIENT* hub_client_ptr,
152                                         NX_AZURE_IOT *nx_azure_iot_ptr,
153                                         const UCHAR *host_name, UINT host_name_length,
154                                         const UCHAR *device_id, UINT device_id_length,
155                                         const UCHAR *module_id, UINT module_id_length,
156                                         const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size,
157                                         const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size,
158                                         UCHAR * metadata_memory, UINT memory_size,
159                                         NX_SECURE_X509_CERT *trusted_certificate)
160 {
161 
162 UINT status;
163 NX_AZURE_IOT_RESOURCE *resource_ptr;
164 az_span hostname_span = az_span_create((UCHAR *)host_name, (INT)host_name_length);
165 az_span device_id_span = az_span_create((UCHAR *)device_id, (INT)device_id_length);
166 az_iot_hub_client_options options = az_iot_hub_client_options_default();
167 az_result core_result;
168 
169     if ((nx_azure_iot_ptr == NX_NULL) || (hub_client_ptr == NX_NULL) || (host_name == NX_NULL) ||
170         (device_id == NX_NULL) || (host_name_length == 0) || (device_id_length == 0))
171     {
172         LogError(LogLiteralArgs("IoTHub client initialization fail: INVALID POINTER"));
173         return(NX_AZURE_IOT_INVALID_PARAMETER);
174     }
175 
176     memset(hub_client_ptr, 0, sizeof(NX_AZURE_IOT_HUB_CLIENT));
177 
178     hub_client_ptr -> nx_azure_iot_ptr = nx_azure_iot_ptr;
179     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_crypto_array = crypto_array;
180     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_crypto_array_size = crypto_array_size;
181     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_cipher_map = cipher_map;
182     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_cipher_map_size = cipher_map_size;
183     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_metadata_ptr = metadata_memory;
184     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_metadata_size = memory_size;
185     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_trusted_certificates[0] = trusted_certificate;
186     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname = host_name;
187     hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname_length = host_name_length;
188     options.module_id = az_span_create((UCHAR *)module_id, (INT)module_id_length);
189     options.user_agent = AZ_SPAN_FROM_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT);
190     options.component_names = hub_client_ptr -> nx_azure_iot_hub_client_component_list;
191     options.component_names_length = 0;
192 
193     core_result = az_iot_hub_client_init(&hub_client_ptr -> iot_hub_client_core,
194                                          hostname_span, device_id_span, &options);
195     if (az_result_failed(core_result))
196     {
197         LogError(LogLiteralArgs("IoTHub client failed initialization with error status: %d"), core_result);
198         return(NX_AZURE_IOT_SDK_CORE_ERROR);
199     }
200 
201     /* Set resource pointer.  */
202     resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource);
203 
204     /* Create MQTT client.  */
205     status = _nxd_mqtt_client_cloud_create(&(resource_ptr -> resource_mqtt),
206                                            (CHAR *)nx_azure_iot_ptr -> nx_azure_iot_name,
207                                            "", 0,
208                                            nx_azure_iot_ptr -> nx_azure_iot_ip_ptr,
209                                            nx_azure_iot_ptr -> nx_azure_iot_pool_ptr,
210                                            &nx_azure_iot_ptr -> nx_azure_iot_cloud);
211     if (status)
212     {
213         LogError(LogLiteralArgs("IoTHub client initialization fail: MQTT CLIENT CREATE FAIL status: %d"), status);
214         return(status);
215     }
216 
217     /* Set mqtt receive notify.  */
218     status = nxd_mqtt_client_receive_notify_set(&(resource_ptr -> resource_mqtt),
219                                                 nx_azure_iot_hub_client_mqtt_receive_callback);
220     if (status)
221     {
222         LogError(LogLiteralArgs("IoTHub client set message callback status: %d"), status);
223         nxd_mqtt_client_delete(&(resource_ptr -> resource_mqtt));
224         return(status);
225     }
226 
227     /* Obtain the mutex.   */
228     tx_mutex_get(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
229 
230     /* Link the resource.  */
231     resource_ptr -> resource_data_ptr = (VOID *)hub_client_ptr;
232     resource_ptr -> resource_type = NX_AZURE_IOT_RESOURCE_IOT_HUB;
233     nx_azure_iot_resource_add(nx_azure_iot_ptr, resource_ptr);
234 
235     /* Release the mutex.  */
236     tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
237 
238     return(NX_AZURE_IOT_SUCCESS);
239 }
240 
nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,VOID (* connection_status_cb)(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT * client_ptr,UINT status))241 UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
242                                                             VOID (*connection_status_cb)(
243                                                                   struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *client_ptr,
244                                                                   UINT status))
245 {
246 
247     /* Check for invalid input pointers.  */
248     if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL))
249     {
250         LogError(LogLiteralArgs("IoTHub client connect callback fail: INVALID POINTER"));
251         return(NX_AZURE_IOT_INVALID_PARAMETER);
252     }
253 
254     /* Set callback function for disconnection.  */
255     nxd_mqtt_client_disconnect_notify_set(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
256                                           nx_azure_iot_hub_client_mqtt_disconnect_notify);
257 
258     /* Obtain the mutex.   */
259     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
260 
261     /* Set connection status callback.  */
262     hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback = connection_status_cb;
263 
264     /* Release the mutex.  */
265     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
266 
267     /* Return success.  */
268     return(NX_AZURE_IOT_SUCCESS);
269 
270 }
271 
272 #ifdef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE
nx_azure_iot_hub_client_user_agent_update(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NXD_ADDRESS * server_address)273 static VOID nx_azure_iot_hub_client_user_agent_update(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NXD_ADDRESS *server_address)
274 {
275 NX_IP        *ip_ptr = hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_ip_ptr;
276 NX_INTERFACE *outgoing_interface = NX_NULL;
277 UINT          status;
278 #ifndef NX_DISABLE_IPV4
279 ULONG         next_hop_address;
280 #endif /* NX_DISABLE_IPV4 */
281 #ifdef FEATURE_NX_IPV6
282 NXD_IPV6_ADDRESS *ipv6_addr;
283 #endif /* FEATURE_NX_IPV6 */
284 ULONG         interface_type;
285 ULONG         index;
286 
287     /* Make sure the server IP address is accesible. */
288 #ifndef NX_DISABLE_IPV4
289     if (server_address -> nxd_ip_version == NX_IP_VERSION_V4)
290     {
291         if (_nx_ip_route_find(ip_ptr, server_address -> nxd_ip_address.v4, &outgoing_interface, &next_hop_address) != NX_SUCCESS)
292         {
293             return;
294         }
295     }
296 #endif /* !NX_DISABLE_IPV4  */
297 
298 #ifdef FEATURE_NX_IPV6
299     /* For IPv6 connections, find a suitable outgoing interface, based on the TCP peer address. */
300     if (server_address -> nxd_ip_version == NX_IP_VERSION_V6)
301     {
302 
303         status = _nxd_ipv6_interface_find(ip_ptr, server_address -> nxd_ip_address.v6,
304                                           &ipv6_addr,
305                                           NX_NULL);
306 
307         if (status != NX_SUCCESS)
308         {
309             return;
310         }
311 
312         outgoing_interface = ipv6_addr -> nxd_ipv6_address_attached;
313     }
314 #endif /* FEATURE_NX_IPV6 */
315 
316     /* Check if found the outgoing interface.  */
317     if (outgoing_interface == NX_NULL)
318     {
319         return;
320     }
321 
322     /* Get the interface type.  */
323     status = nx_ip_driver_interface_direct_command(ip_ptr, NX_LINK_GET_INTERFACE_TYPE, outgoing_interface -> nx_interface_index, &interface_type);
324 
325     /* Check status.  */
326     if (status != NX_SUCCESS)
327     {
328         return;
329     }
330 
331     /* Check if the interface type is listed in nx_api.h.  */
332     if (interface_type > NX_INTERFACE_TYPE_LORAWAN)
333     {
334         interface_type = NX_INTERFACE_TYPE_OTHER;
335     }
336 
337     /* Update the interface type in user agent.  */
338     for (index = 0; index < sizeof(_nx_azure_iot_hub_client_user_agent) - 3; index++)
339     {
340 
341         /* The interface type is after the first semicolon.  */
342         if ((_nx_azure_iot_hub_client_user_agent[index] == '%') &&
343             (_nx_azure_iot_hub_client_user_agent[index + 1] == '3') &&
344             (_nx_azure_iot_hub_client_user_agent[index + 2] == 'B'))
345         {
346             _nx_azure_iot_hub_client_user_agent[index + 3] = (UCHAR)(interface_type + '0');
347             hub_client_ptr -> iot_hub_client_core._internal.options.user_agent = AZ_SPAN_FROM_BUFFER(_nx_azure_iot_hub_client_user_agent);
348             return;
349         }
350     }
351 }
352 #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE */
353 
354 #ifdef NXD_MQTT_OVER_WEBSOCKET
nx_azure_iot_hub_client_websocket_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)355 UINT nx_azure_iot_hub_client_websocket_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
356 {
357 NX_AZURE_IOT_RESOURCE *resource_ptr;
358 
359     if (hub_client_ptr == NX_NULL)
360     {
361         LogError(LogLiteralArgs("IoTHub WebSocket enable fail: INVALID POINTER"));
362         return(NX_AZURE_IOT_INVALID_PARAMETER);
363     }
364 
365     /* Set resource pointer.  */
366     resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource);
367 
368     return(nxd_mqtt_client_websocket_set(&(resource_ptr -> resource_mqtt), (UCHAR *)resource_ptr -> resource_hostname, resource_ptr -> resource_hostname_length,
369                                          (UCHAR *)NX_AZURE_IOT_HUB_CLIENT_WEB_SOCKET_PATH, sizeof(NX_AZURE_IOT_HUB_CLIENT_WEB_SOCKET_PATH) - 1));
370 }
371 #endif /* NXD_MQTT_OVER_WEBSOCKET */
372 
nx_azure_iot_hub_client_connect(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT clean_session,UINT wait_option)373 UINT nx_azure_iot_hub_client_connect(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
374                                      UINT clean_session, UINT wait_option)
375 {
376 UINT            status;
377 NXD_ADDRESS     server_address;
378 NX_AZURE_IOT_RESOURCE *resource_ptr;
379 NXD_MQTT_CLIENT *mqtt_client_ptr;
380 UCHAR           *buffer_ptr;
381 UINT            buffer_size;
382 VOID            *buffer_context;
383 UINT            buffer_length;
384 ULONG           expiry_time_secs;
385 az_result       core_result;
386 UINT            server_port;
387 
388     /* Check for invalid input pointers.  */
389     if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL))
390     {
391         LogError(LogLiteralArgs("IoTHub client connect fail: INVALID POINTER"));
392         return(NX_AZURE_IOT_INVALID_PARAMETER);
393     }
394 
395     /* Check for status.  */
396     if (hub_client_ptr -> nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
397     {
398         LogError(LogLiteralArgs("IoTHub client already connected"));
399         return(NX_AZURE_IOT_ALREADY_CONNECTED);
400     }
401     else if (hub_client_ptr -> nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING)
402     {
403         LogError(LogLiteralArgs("IoTHub client is connecting"));
404         return(NX_AZURE_IOT_CONNECTING);
405     }
406 
407     /* Resolve the host name.  */
408     /* Note: always using default dns timeout.  */
409     status = nxd_dns_host_by_name_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_dns_ptr,
410                                       (UCHAR *)hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname,
411                                       &server_address, NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT, NX_IP_VERSION_V4);
412     if (status)
413     {
414         LogError(LogLiteralArgs("IoTHub client connect fail: DNS RESOLVE FAIL status: %d"), status);
415         return(status);
416     }
417 
418     /* Allocate buffer for client id, username and sas token.  */
419     status = nx_azure_iot_buffer_allocate(hub_client_ptr -> nx_azure_iot_ptr,
420                                           &buffer_ptr, &buffer_size, &buffer_context);
421     if (status)
422     {
423         LogError(LogLiteralArgs("IoTHub client failed initialization: BUFFER ALLOCATE FAIL"));
424         return(status);
425     }
426 
427     /* Obtain the mutex.   */
428     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
429 
430 #ifdef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE
431     /* Add the real interface type into the user agent string.  */
432     nx_azure_iot_hub_client_user_agent_update(hub_client_ptr, &server_address);
433 #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE */
434 
435     /* Set resource pointer and buffer context.  */
436     resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource);
437 
438     /* Build client id.  */
439     buffer_length = buffer_size;
440     core_result = az_iot_hub_client_get_client_id(&(hub_client_ptr -> iot_hub_client_core),
441                                                   (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length);
442     if (az_result_failed(core_result))
443     {
444 
445         /* Release the mutex.  */
446         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
447         nx_azure_iot_buffer_free(buffer_context);
448         LogError(LogLiteralArgs("IoTHub client failed to get clientId with error status: "), core_result);
449         return(NX_AZURE_IOT_SDK_CORE_ERROR);
450     }
451     resource_ptr -> resource_mqtt_client_id = buffer_ptr;
452     resource_ptr -> resource_mqtt_client_id_length = buffer_length;
453 
454     /* Update buffer for user name.  */
455     buffer_ptr += resource_ptr -> resource_mqtt_client_id_length;
456     buffer_size -= resource_ptr -> resource_mqtt_client_id_length;
457 
458     /* Build user name.  */
459     buffer_length = buffer_size;
460     core_result = az_iot_hub_client_get_user_name(&hub_client_ptr -> iot_hub_client_core,
461                                                   (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length);
462     if (az_result_failed(core_result))
463     {
464 
465         /* Release the mutex.  */
466         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
467         nx_azure_iot_buffer_free(buffer_context);
468         LogError(LogLiteralArgs("IoTHub client connect fail, with error status: %d"), core_result);
469         return(NX_AZURE_IOT_SDK_CORE_ERROR);
470     }
471     resource_ptr -> resource_mqtt_user_name = buffer_ptr;
472     resource_ptr -> resource_mqtt_user_name_length = buffer_length;
473 
474     /* Build sas token.  */
475     resource_ptr -> resource_mqtt_sas_token = buffer_ptr + buffer_length;
476     resource_ptr -> resource_mqtt_sas_token_length = buffer_size - buffer_length;
477 
478     /* Check if token refersh is setup.  */
479     if (hub_client_ptr -> nx_azure_iot_hub_client_token_refresh)
480     {
481         status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, &expiry_time_secs);
482         if (status)
483         {
484 
485             /* Release the mutex.  */
486             tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
487             nx_azure_iot_buffer_free(buffer_context);
488             LogError(LogLiteralArgs("IoTHub client connect fail: unixtime get failed status: %d"), status);
489             return(status);
490         }
491 
492         expiry_time_secs += NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT;
493         status = hub_client_ptr -> nx_azure_iot_hub_client_token_refresh(hub_client_ptr,
494                                                                          expiry_time_secs,
495                                                                          hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key,
496                                                                          hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key_length,
497                                                                          resource_ptr -> resource_mqtt_sas_token,
498                                                                          resource_ptr -> resource_mqtt_sas_token_length,
499                                                                          &(resource_ptr -> resource_mqtt_sas_token_length));
500         if (status)
501         {
502 
503             /* Release the mutex.  */
504             tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
505             nx_azure_iot_buffer_free(buffer_context);
506             LogError(LogLiteralArgs("IoTHub client connect fail: Token generation failed status: %d"), status);
507             return(status);
508         }
509         hub_client_ptr -> nx_azure_iot_hub_client_sas_token_expiry_time = expiry_time_secs;
510     }
511     else
512     {
513         resource_ptr -> resource_mqtt_sas_token = NX_NULL;
514         resource_ptr ->  resource_mqtt_sas_token_length = 0;
515     }
516 
517     /* Set azure IoT and MQTT client.  */
518     mqtt_client_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt);
519 
520     /* Update client id.  */
521     mqtt_client_ptr -> nxd_mqtt_client_id = (CHAR *)resource_ptr -> resource_mqtt_client_id;
522     mqtt_client_ptr -> nxd_mqtt_client_id_length = resource_ptr -> resource_mqtt_client_id_length;
523 
524     /* Set login info.  */
525     status = nxd_mqtt_client_login_set(&(resource_ptr -> resource_mqtt),
526                                        (CHAR *)resource_ptr -> resource_mqtt_user_name,
527                                        resource_ptr -> resource_mqtt_user_name_length,
528                                        (CHAR *)resource_ptr -> resource_mqtt_sas_token,
529                                        resource_ptr -> resource_mqtt_sas_token_length);
530     if (status)
531     {
532 
533         /* Release the mutex.  */
534         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
535         nx_azure_iot_buffer_free(buffer_context);
536         LogError(LogLiteralArgs("IoTHub client connect fail: MQTT CLIENT LOGIN SET FAIL status: %d"), status);
537         return(status);
538     }
539 
540     /* Set connect notify for non-blocking mode.  */
541     if (wait_option == 0)
542     {
543         mqtt_client_ptr -> nxd_mqtt_connect_notify = nx_azure_iot_hub_client_mqtt_connect_notify;
544         mqtt_client_ptr -> nxd_mqtt_connect_context = hub_client_ptr;
545     }
546 
547     /* Save the resource buffer.  */
548     resource_ptr -> resource_mqtt_buffer_context = buffer_context;
549     resource_ptr -> resource_mqtt_buffer_size = buffer_size;
550 
551     /* Release the mutex.  */
552     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
553 
554 #ifdef NXD_MQTT_OVER_WEBSOCKET
555     if (mqtt_client_ptr -> nxd_mqtt_client_use_websocket == NX_TRUE)
556     {
557         server_port = NXD_MQTT_OVER_WEBSOCKET_TLS_PORT;
558     }
559     else
560     {
561         server_port = NXD_MQTT_TLS_PORT;
562     }
563 #else
564     server_port = NXD_MQTT_TLS_PORT;
565 #endif /* NXD_MQTT_OVER_WEBSOCKET */
566 
567     /* Start MQTT connection.  */
568     status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, server_port,
569                                             nx_azure_iot_mqtt_tls_setup, NX_AZURE_IOT_MQTT_KEEP_ALIVE,
570                                             clean_session, wait_option);
571 
572     /* Obtain the mutex.  */
573     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
574 
575     /* Check status for non-blocking mode.  */
576     if ((wait_option == 0) && (status == NX_IN_PROGRESS))
577     {
578         hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTING;
579 
580         /* Release the mutex.  */
581         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
582 
583         /* Return in-progress completion status.  */
584         return(NX_AZURE_IOT_CONNECTING);
585     }
586 
587     /* Release the mqtt connection resource.  */
588     if (resource_ptr -> resource_mqtt_buffer_context)
589     {
590         nx_azure_iot_buffer_free(resource_ptr -> resource_mqtt_buffer_context);
591         resource_ptr -> resource_mqtt_buffer_context = NX_NULL;
592     }
593 
594     /* Check status.  */
595     if (status != NX_AZURE_IOT_SUCCESS)
596     {
597         hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
598         LogError(LogLiteralArgs("IoTHub client connect fail: MQTT CONNECT FAIL status: %d"), status);
599     }
600     else
601     {
602 
603         /* Connected to IoT Hub.  */
604         hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED;
605     }
606 
607     if (status == NX_AZURE_IOT_SUCCESS)
608     {
609         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
610 
611         status = nx_azure_iot_hub_client_messages_enable(hub_client_ptr);
612 
613         tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
614 
615         if (status)
616         {
617             hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
618             LogError(LogLiteralArgs("IoTHub client connect fail: MQTT SUBSCRIBE FAIL status: %d"), status);
619         }
620     }
621 
622     /* Call connection notify if it is set.  */
623     if (hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback)
624     {
625         hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr, status);
626     }
627 
628     /* Release the mutex.  */
629     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
630 
631     return(status);
632 }
633 
nx_azure_iot_hub_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT * client_ptr,UINT status,VOID * context)634 static VOID nx_azure_iot_hub_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr,
635                                                         UINT status, VOID *context)
636 {
637 
638 NX_AZURE_IOT_HUB_CLIENT *iot_hub_client = (NX_AZURE_IOT_HUB_CLIENT*)context;
639 
640 
641     NX_PARAMETER_NOT_USED(client_ptr);
642 
643     /* Obtain the mutex.  */
644     tx_mutex_get(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
645 
646     /* Release the mqtt connection resource.  */
647     if (iot_hub_client -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context)
648     {
649         nx_azure_iot_buffer_free(iot_hub_client -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context);
650         iot_hub_client -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context = NX_NULL;
651     }
652 
653     /* Update hub client status.  */
654     if (status == NXD_MQTT_SUCCESS)
655     {
656         iot_hub_client -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED;
657     }
658     else
659     {
660         iot_hub_client -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
661     }
662 
663     if (status == NXD_MQTT_SUCCESS)
664     {
665         tx_mutex_put(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
666 
667         status = nx_azure_iot_hub_client_messages_enable(iot_hub_client);
668 
669         tx_mutex_get(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
670 
671         if (status)
672         {
673             iot_hub_client -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
674             LogError(LogLiteralArgs("IoTHub client connect fail: MQTT SUBSCRIBE FAIL status: %d"), status);
675         }
676     }
677 
678     /* Call connection notify if it is set.  */
679     if (iot_hub_client -> nx_azure_iot_hub_client_connection_status_callback)
680     {
681         iot_hub_client -> nx_azure_iot_hub_client_connection_status_callback(iot_hub_client, status);
682     }
683 
684     /* Release the mutex.  */
685     tx_mutex_put(iot_hub_client -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
686 }
687 
nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT * client_ptr)688 static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr)
689 {
690 NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr);
691 NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NX_NULL;
692 NX_AZURE_IOT_THREAD *thread_list_ptr;
693 ULONG current_time = 0;
694 
695     /* This function is protected by MQTT mutex.  */
696 
697     if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB))
698     {
699         hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource -> resource_data_ptr;
700     }
701 
702     if (hub_client_ptr == NX_NULL)
703     {
704         return;
705     }
706 
707     /* Wake up all threads.  */
708     for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
709          thread_list_ptr;
710          thread_list_ptr = thread_list_ptr -> thread_next)
711     {
712         tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
713     }
714 
715     /* Do not call callback if not connected, as at our layer connected means : mqtt connect + subscribe messages topic.  */
716     if (hub_client_ptr -> nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
717     {
718         hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
719 
720         /* Call connection notify if it is set.  */
721         if (hub_client_ptr && hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback)
722         {
723             if (hub_client_ptr -> nx_azure_iot_hub_client_token_refresh &&
724                 (nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr,
725                                             &current_time) == NX_AZURE_IOT_SUCCESS) &&
726                 (current_time > hub_client_ptr -> nx_azure_iot_hub_client_sas_token_expiry_time))
727             {
728                 hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr,
729                                                                                      NX_AZURE_IOT_SAS_TOKEN_EXPIRED);
730             }
731             else
732             {
733                 hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr,
734                                                                                      NX_AZURE_IOT_DISCONNECTED);
735             }
736 
737         }
738     }
739 }
740 
nx_azure_iot_hub_client_disconnect(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)741 UINT nx_azure_iot_hub_client_disconnect(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
742 {
743 UINT status;
744 NX_AZURE_IOT_THREAD *thread_list_ptr;
745 
746 
747     /* Check for invalid input pointers.  */
748     if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL))
749     {
750         LogError(LogLiteralArgs("IoTHub client disconnect fail: INVALID POINTER"));
751         return(NX_AZURE_IOT_INVALID_PARAMETER);
752     }
753 
754     /* Disconnect.  */
755     status = nxd_mqtt_client_disconnect(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt));
756     if (status)
757     {
758         LogError(LogLiteralArgs("IoTHub client disconnect fail status: %d"), status);
759         return(status);
760     }
761 
762     /* Obtain the mutex.  */
763     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
764 
765     /* Release the mqtt connection resource.  */
766     if (hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context)
767     {
768         nx_azure_iot_buffer_free(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context);
769         hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt_buffer_context = NX_NULL;
770     }
771 
772     /* Wakeup all suspend threads.  */
773     for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
774          thread_list_ptr;
775          thread_list_ptr = thread_list_ptr -> thread_next)
776     {
777         tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
778     }
779 
780     /* Cleanup received messages.  */
781     nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message));
782     nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_properties_message));
783     nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message));
784     nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_command_message));
785 
786     hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED;
787 
788     /* Release the mutex.  */
789     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
790 
791     return(NX_AZURE_IOT_SUCCESS);
792 }
793 
nx_azure_iot_hub_client_received_message_cleanup(NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE * message)794 static VOID nx_azure_iot_hub_client_received_message_cleanup(NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *message)
795 {
796 NX_PACKET *current_ptr;
797 NX_PACKET *next_ptr;
798 
799     for (current_ptr = message -> message_head; current_ptr; current_ptr = next_ptr)
800     {
801 
802         /* Get next packet in queue.  */
803         next_ptr = current_ptr -> nx_packet_queue_next;
804 
805         /* Release current packet.  */
806         current_ptr -> nx_packet_queue_next = NX_NULL;
807         nx_packet_release(current_ptr);
808     }
809 
810     /* Reset received messages.  */
811     message -> message_head = NX_NULL;
812     message -> message_tail = NX_NULL;
813 }
814 
nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)815 static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
816 {
817 UINT status = NX_AZURE_IOT_SUCCESS;
818 
819     if (status == NX_AZURE_IOT_SUCCESS &&
820         (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process != NX_NULL))
821     {
822         status = hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_enable(hub_client_ptr);
823     }
824 
825     if (status == NX_AZURE_IOT_SUCCESS &&
826         (hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process != NX_NULL))
827     {
828         status = hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_enable(hub_client_ptr);
829     }
830 
831     if (status == NX_AZURE_IOT_SUCCESS &&
832         (hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process != NX_NULL))
833     {
834         status = hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_enable(hub_client_ptr);
835     }
836 
837     return(status);
838 }
839 
nx_azure_iot_hub_client_deinitialize(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)840 UINT nx_azure_iot_hub_client_deinitialize(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
841 {
842 UINT status;
843 
844     /* Check for invalid input pointers.  */
845     if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL))
846     {
847         LogError(LogLiteralArgs("IoTHub client deinitialize fail: INVALID POINTER"));
848         return(NX_AZURE_IOT_INVALID_PARAMETER);
849     }
850 
851     nx_azure_iot_hub_client_disconnect(hub_client_ptr);
852 
853     status = nxd_mqtt_client_delete(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt));
854     if (status)
855     {
856         LogError(LogLiteralArgs("IoTHub client delete fail status: %d"), status);
857         return(status);
858     }
859 
860     /* Obtain the mutex.  */
861     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
862 
863     /* Remove resource from list.  */
864     status = nx_azure_iot_resource_remove(hub_client_ptr -> nx_azure_iot_ptr,
865                                           &(hub_client_ptr -> nx_azure_iot_hub_client_resource));
866     if (status)
867     {
868 
869         /* Release the mutex.  */
870         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
871         LogError(LogLiteralArgs("IoTHub client handle not found"));
872         return(status);
873     }
874 
875     /* Release the mutex.  */
876     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
877 
878     return(NX_AZURE_IOT_SUCCESS);
879 }
880 
nx_azure_iot_hub_client_trusted_cert_add(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_SECURE_X509_CERT * trusted_certificate)881 UINT nx_azure_iot_hub_client_trusted_cert_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
882                                               NX_SECURE_X509_CERT *trusted_certificate)
883 {
884 UINT i;
885 NX_AZURE_IOT_RESOURCE *resource_ptr;
886 
887     if ((hub_client_ptr == NX_NULL) ||
888         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
889         (trusted_certificate == NX_NULL))
890     {
891         LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER"));
892         return(NX_AZURE_IOT_INVALID_PARAMETER);
893     }
894 
895     /* Obtain the mutex.  */
896     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
897 
898     resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource);
899     for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates); i++)
900     {
901         if (resource_ptr -> resource_trusted_certificates[i] == NX_NULL)
902         {
903             resource_ptr -> resource_trusted_certificates[i] = trusted_certificate;
904             break;
905         }
906     }
907 
908     /* Release the mutex.  */
909     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
910 
911     if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates))
912     {
913         return(NX_AZURE_IOT_SUCCESS);
914     }
915     else
916     {
917 
918         /* No more space to store trusted certificate.  */
919         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
920     }
921 }
922 
nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_SECURE_X509_CERT * device_certificate)923 UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
924                                              NX_SECURE_X509_CERT *device_certificate)
925 {
926 UINT i;
927 NX_AZURE_IOT_RESOURCE *resource_ptr;
928 
929     if ((hub_client_ptr == NX_NULL) ||
930         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
931         (device_certificate == NX_NULL))
932     {
933         LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER"));
934         return(NX_AZURE_IOT_INVALID_PARAMETER);
935     }
936 
937     /* Obtain the mutex.  */
938     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
939 
940     resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource);
941     for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates); i++)
942     {
943         if (resource_ptr -> resource_device_certificates[i] == NX_NULL)
944         {
945             resource_ptr -> resource_device_certificates[i] = device_certificate;
946             break;
947         }
948     }
949 
950     /* Release the mutex.  */
951     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
952 
953     if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates))
954     {
955         return(NX_AZURE_IOT_SUCCESS);
956     }
957     else
958     {
959 
960         /* No more space to store device certificate.  */
961         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
962     }
963 }
964 
nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR * symmetric_key,UINT symmetric_key_length)965 UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
966                                                const UCHAR *symmetric_key, UINT symmetric_key_length)
967 {
968     if ((hub_client_ptr == NX_NULL)  || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
969         (symmetric_key == NX_NULL) || (symmetric_key_length == 0))
970     {
971         LogError(LogLiteralArgs("IoTHub client symmetric key fail: Invalid argument"));
972         return(NX_AZURE_IOT_INVALID_PARAMETER);
973     }
974 
975     /* Obtain the mutex.  */
976     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
977 
978     hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key = symmetric_key;
979     hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key_length = symmetric_key_length;
980 
981     hub_client_ptr -> nx_azure_iot_hub_client_token_refresh = nx_azure_iot_hub_client_sas_token_get;
982 
983     /* Release the mutex.  */
984     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
985 
986     return(NX_AZURE_IOT_SUCCESS);
987 }
988 
nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR * model_id_ptr,UINT model_id_length)989 UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
990                                           const UCHAR *model_id_ptr, UINT model_id_length)
991 {
992     if ((hub_client_ptr == NX_NULL)  || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
993         (model_id_ptr == NX_NULL) || (model_id_length == 0))
994     {
995         LogError(LogLiteralArgs("IoTHub client model Id fail: Invalid argument"));
996         return(NX_AZURE_IOT_INVALID_PARAMETER);
997     }
998 
999     /* Obtain the mutex.  */
1000     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1001 
1002     /* Had no way to update option, so had to access the internal fields of iot_hub_client_core.  */
1003     hub_client_ptr -> iot_hub_client_core._internal.options.model_id =
1004         az_span_create((UCHAR *)model_id_ptr, (INT)model_id_length);
1005 
1006     /* Release the mutex.  */
1007     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1008 
1009     return(NX_AZURE_IOT_SUCCESS);
1010 }
1011 
nx_azure_iot_hub_client_component_add(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR * component_name_ptr,USHORT component_name_length)1012 UINT nx_azure_iot_hub_client_component_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1013                                            const UCHAR *component_name_ptr,
1014                                            USHORT component_name_length)
1015 {
1016     return(nx_azure_iot_hub_client_component_add_internal(hub_client_ptr, component_name_ptr, component_name_length, NX_NULL, NX_NULL));
1017 }
1018 
nx_azure_iot_hub_client_component_add_internal(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR * component_name_ptr,USHORT component_name_length,UINT (* callback_ptr)(VOID * json_reader_ptr,ULONG version,VOID * args),VOID * callback_args)1019 UINT nx_azure_iot_hub_client_component_add_internal(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1020                                                     const UCHAR *component_name_ptr,
1021                                                     USHORT component_name_length,
1022                                                     UINT (*callback_ptr)(VOID *json_reader_ptr,
1023                                                                          ULONG version,
1024                                                                          VOID *args),
1025                                                     VOID *callback_args)
1026 {
1027 UINT length_of_componet_list;
1028 
1029     if ((hub_client_ptr == NX_NULL) ||
1030         (component_name_ptr == NX_NULL) ||
1031         (component_name_length == NX_NULL))
1032     {
1033         LogError(LogLiteralArgs("IoT Hub add component fail: INVALID POINTER"));
1034         return(NX_AZURE_IOT_INVALID_PARAMETER);
1035     }
1036 
1037     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1038 
1039     length_of_componet_list =
1040         (UINT)hub_client_ptr -> iot_hub_client_core._internal.options.component_names_length;
1041 
1042     if (length_of_componet_list >= NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST)
1043     {
1044         LogError(LogLiteralArgs("IoT Hub fail due to buffer insufficient"));
1045         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1046         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
1047     }
1048 
1049     /* Using internal fields for faster update */
1050     hub_client_ptr -> nx_azure_iot_hub_client_component_list[length_of_componet_list] =
1051         az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length);
1052     hub_client_ptr -> iot_hub_client_core._internal.options.component_names_length++;
1053     hub_client_ptr -> nx_azure_iot_hub_client_component_callback[length_of_componet_list] = callback_ptr;
1054     hub_client_ptr -> nx_azure_iot_hub_client_component_callback_args[length_of_componet_list] = callback_args;
1055 
1056     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1057 
1058     return(NX_AZURE_IOT_SUCCESS);
1059 }
1060 
nx_azure_iot_hub_client_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)1061 UINT nx_azure_iot_hub_client_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1062                                                       NX_PACKET **packet_pptr, UINT wait_option)
1063 {
1064 NX_PACKET *packet_ptr;
1065 UINT topic_length;
1066 UINT status;
1067 az_result core_result;
1068 
1069     if ((hub_client_ptr == NX_NULL) ||
1070         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
1071         (packet_pptr == NX_NULL))
1072     {
1073         LogError(LogLiteralArgs("IoTHub telemetry message create fail: INVALID POINTER"));
1074         return(NX_AZURE_IOT_INVALID_PARAMETER);
1075     }
1076 
1077     status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr,
1078                                              &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1079                                              &packet_ptr, wait_option);
1080     if (status)
1081     {
1082         LogError(LogLiteralArgs("Create telemetry data fail"));
1083         return(status);
1084     }
1085 
1086     topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
1087     core_result = az_iot_hub_client_telemetry_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
1088                                                                 NULL, (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
1089                                                                 topic_length, (size_t *)&topic_length);
1090     if (az_result_failed(core_result))
1091     {
1092         LogError(LogLiteralArgs("IoTHub client telemetry message create fail with error status: %d"), core_result);
1093         nx_packet_release(packet_ptr);
1094         return(NX_AZURE_IOT_SDK_CORE_ERROR);
1095     }
1096 
1097     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length;
1098     packet_ptr -> nx_packet_length = topic_length;
1099     *packet_pptr = packet_ptr;
1100     return(NX_AZURE_IOT_SUCCESS);
1101 }
1102 
nx_azure_iot_hub_client_telemetry_message_delete(NX_PACKET * packet_ptr)1103 UINT nx_azure_iot_hub_client_telemetry_message_delete(NX_PACKET *packet_ptr)
1104 {
1105     return(nx_packet_release(packet_ptr));
1106 }
1107 
nx_azure_iot_hub_client_telemetry_component_set(NX_PACKET * packet_ptr,const UCHAR * component_name_ptr,USHORT component_name_length,UINT wait_option)1108 UINT nx_azure_iot_hub_client_telemetry_component_set(NX_PACKET *packet_ptr,
1109                                                      const UCHAR *component_name_ptr,
1110                                                      USHORT component_name_length,
1111                                                      UINT wait_option)
1112 {
1113 UINT status;
1114 
1115     if ((packet_ptr == NX_NULL) ||
1116         (component_name_ptr == NX_NULL) ||
1117         (component_name_length == 0))
1118     {
1119         LogError(LogLiteralArgs("IoTHub telemetry component set fail: INVALID POINTER"));
1120         return(NX_AZURE_IOT_INVALID_PARAMETER);
1121     }
1122 
1123     status = nx_azure_iot_hub_client_telemetry_property_add(packet_ptr,
1124                                                             (const UCHAR*)NX_AZURE_IOT_HUB_CLIENT_COMPONENT_STRING,
1125                                                             sizeof(NX_AZURE_IOT_HUB_CLIENT_COMPONENT_STRING) - 1,
1126                                                             component_name_ptr, component_name_length,
1127                                                             wait_option);
1128     if (status)
1129     {
1130         LogError(LogLiteralArgs("Telemetry component append fail: error status: %d"), status);
1131         return(status);
1132     }
1133 
1134     return(NX_AZURE_IOT_SUCCESS);
1135 }
1136 
nx_azure_iot_hub_client_telemetry_property_add(NX_PACKET * packet_ptr,const UCHAR * property_name,USHORT property_name_length,const UCHAR * property_value,USHORT property_value_length,UINT wait_option)1137 UINT nx_azure_iot_hub_client_telemetry_property_add(NX_PACKET *packet_ptr,
1138                                                     const UCHAR *property_name, USHORT property_name_length,
1139                                                     const UCHAR *property_value, USHORT property_value_length,
1140                                                     UINT wait_option)
1141 {
1142 UINT status;
1143 
1144     if ((packet_ptr == NX_NULL) ||
1145         (property_name == NX_NULL) ||
1146         (property_value == NX_NULL))
1147     {
1148         LogError(LogLiteralArgs("IoTHub telemetry property add fail: INVALID POINTER"));
1149         return(NX_AZURE_IOT_INVALID_PARAMETER);
1150     }
1151 
1152     if (*(packet_ptr -> nx_packet_append_ptr - 1) != '/')
1153     {
1154         status = nx_packet_data_append(packet_ptr, "&", 1,
1155                                        packet_ptr -> nx_packet_pool_owner,
1156                                        wait_option);
1157         if (status)
1158         {
1159             LogError(LogLiteralArgs("Telemetry data append fail"));
1160             return(status);
1161         }
1162     }
1163 
1164     status = nx_packet_data_append(packet_ptr, (VOID *)property_name, (UINT)property_name_length,
1165                                    packet_ptr -> nx_packet_pool_owner, wait_option);
1166     if (status)
1167     {
1168         LogError(LogLiteralArgs("Telemetry data append fail"));
1169         return(status);
1170     }
1171 
1172     status = nx_packet_data_append(packet_ptr, "=", 1,
1173                                    packet_ptr -> nx_packet_pool_owner,
1174                                    wait_option);
1175     if (status)
1176     {
1177         LogError(LogLiteralArgs("Telemetry data append fail"));
1178         return(status);
1179     }
1180 
1181     status = nx_packet_data_append(packet_ptr, (VOID *)property_value, (UINT)property_value_length,
1182                                    packet_ptr -> nx_packet_pool_owner, wait_option);
1183     if (status)
1184     {
1185         LogError(LogLiteralArgs("Telemetry data append fail"));
1186         return(status);
1187     }
1188 
1189     return(NX_AZURE_IOT_SUCCESS);
1190 }
1191 
nx_azure_iot_hub_client_telemetry_send(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,const UCHAR * telemetry_data,UINT data_size,UINT wait_option)1192 UINT nx_azure_iot_hub_client_telemetry_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1193                                             NX_PACKET *packet_ptr, const UCHAR *telemetry_data,
1194                                             UINT data_size, UINT wait_option)
1195 {
1196 UINT status;
1197 UINT topic_len;
1198 UCHAR packet_id[2];
1199 
1200     if ((hub_client_ptr == NX_NULL) || (packet_ptr == NX_NULL))
1201     {
1202         LogError(LogLiteralArgs("IoTHub telemetry send fail: INVALID POINTER"));
1203         return(NX_AZURE_IOT_INVALID_PARAMETER);
1204     }
1205 
1206     topic_len = packet_ptr -> nx_packet_length;
1207 
1208     status = nx_azure_iot_mqtt_packet_id_get(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1209                                              packet_id);
1210     if (status)
1211     {
1212         LogError(LogLiteralArgs("Failed to get packet id"));
1213         return(status);
1214     }
1215 
1216     /* Append packet identifier.  */
1217     status = nx_packet_data_append(packet_ptr, packet_id, sizeof(packet_id),
1218                                    packet_ptr -> nx_packet_pool_owner,
1219                                    wait_option);
1220     if (status)
1221     {
1222         LogError(LogLiteralArgs("Telemetry append fail"));
1223         return(status);
1224     }
1225 
1226     if (telemetry_data && (data_size != 0))
1227     {
1228 
1229         /* Append payload.  */
1230         status = nx_packet_data_append(packet_ptr, (VOID *)telemetry_data, data_size,
1231                                        packet_ptr -> nx_packet_pool_owner,
1232                                        wait_option);
1233         if (status)
1234         {
1235             LogError(LogLiteralArgs("Telemetry data append fail"));
1236             return(status);
1237         }
1238     }
1239 
1240     status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1241                                               packet_ptr, topic_len, packet_id, NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS,
1242                                               wait_option);
1243     if (status)
1244     {
1245         LogError(LogLiteralArgs("IoTHub client send fail: PUBLISH FAIL status: %d"), status);
1246         return(status);
1247     }
1248 
1249     return(NX_AZURE_IOT_SUCCESS);
1250 }
1251 
nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT message_type,VOID (* callback_ptr)(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,VOID * args),VOID * callback_args)1252 UINT nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1253                                                   UINT message_type,
1254                                                   VOID (*callback_ptr)(
1255                                                         NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1256                                                         VOID *args),
1257                                                   VOID *callback_args)
1258 {
1259     if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL))
1260     {
1261         LogError(LogLiteralArgs("IoTHub receive callback set fail: INVALID POINTER"));
1262         return(NX_AZURE_IOT_INVALID_PARAMETER);
1263     }
1264 
1265     /* Obtain the mutex.  */
1266     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1267 
1268     if (message_type == NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE)
1269     {
1270         hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_callback = callback_ptr;
1271         hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_callback_args = callback_args;
1272     }
1273     else if (message_type == NX_AZURE_IOT_HUB_PROPERTIES)
1274     {
1275         hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_callback = callback_ptr;
1276         hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_callback_args = callback_args;
1277     }
1278     else if (message_type == NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES)
1279     {
1280         hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_callback = callback_ptr;
1281         hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_callback_args = callback_args;
1282     }
1283     else if (message_type == NX_AZURE_IOT_HUB_COMMAND)
1284     {
1285         hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_callback = callback_ptr;
1286         hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_callback_args = callback_args;
1287     }
1288     else
1289     {
1290 
1291         /* Release the mutex.  */
1292         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1293         return(NX_AZURE_IOT_NOT_SUPPORTED);
1294     }
1295 
1296     /* Release the mutex.  */
1297     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1298 
1299     return(NX_AZURE_IOT_SUCCESS);
1300 }
1301 
nx_azure_iot_hub_client_cloud_message_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)1302 UINT nx_azure_iot_hub_client_cloud_message_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
1303 {
1304 
1305     if (hub_client_ptr == NX_NULL)
1306     {
1307         LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: INVALID POINTER"));
1308         return(NX_AZURE_IOT_INVALID_PARAMETER);
1309     }
1310 
1311     return(nx_azure_iot_hub_client_cloud_message_sub_unsub(hub_client_ptr, NX_TRUE));
1312 }
1313 
nx_azure_iot_hub_client_cloud_message_disable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)1314 UINT nx_azure_iot_hub_client_cloud_message_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
1315 {
1316     if (hub_client_ptr == NX_NULL)
1317     {
1318         LogError(LogLiteralArgs("IoTHub cloud message unsubscribe fail: INVALID POINTER"));
1319         return(NX_AZURE_IOT_INVALID_PARAMETER);
1320     }
1321 
1322     return(nx_azure_iot_hub_client_cloud_message_sub_unsub(hub_client_ptr, NX_FALSE));
1323 }
1324 
nx_azure_iot_hub_client_process_publish_packet(UCHAR * start_ptr,ULONG * topic_offset_ptr,USHORT * topic_length_ptr)1325 static UINT nx_azure_iot_hub_client_process_publish_packet(UCHAR *start_ptr,
1326                                                            ULONG *topic_offset_ptr,
1327                                                            USHORT *topic_length_ptr)
1328 {
1329 UCHAR *byte = start_ptr;
1330 UINT byte_count = 0;
1331 UINT multiplier = 1;
1332 UINT remaining_length = 0;
1333 UINT topic_length;
1334 
1335     /* Validate packet start contains fixed header.  */
1336     do
1337     {
1338         if (byte_count >= 4)
1339         {
1340             LogError(LogLiteralArgs("Invalid mqtt packet start position"));
1341             return(NX_AZURE_IOT_INVALID_PACKET);
1342         }
1343 
1344         byte++;
1345         remaining_length += (((*byte) & 0x7F) * multiplier);
1346         multiplier = multiplier << 7;
1347         byte_count++;
1348     } while ((*byte) & 0x80);
1349 
1350     if (remaining_length < 2)
1351     {
1352         return(NX_AZURE_IOT_INVALID_PACKET);
1353     }
1354 
1355     /* Retrieve topic length.  */
1356     byte++;
1357     topic_length = (UINT)(*(byte) << 8) | (*(byte + 1));
1358 
1359     if (topic_length > remaining_length - 2u)
1360     {
1361         return(NX_AZURE_IOT_INVALID_PACKET);
1362     }
1363 
1364     *topic_offset_ptr = (ULONG)((byte + 2) - start_ptr);
1365     *topic_length_ptr = (USHORT)topic_length;
1366 
1367     /* Return.  */
1368     return(NX_AZURE_IOT_SUCCESS);
1369 }
1370 
nx_azure_iot_hub_client_message_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT message_type,NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE * receive_message,NX_PACKET ** packet_pptr,UINT wait_option)1371 static UINT nx_azure_iot_hub_client_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT message_type,
1372                                                     NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *receive_message,
1373                                                     NX_PACKET **packet_pptr, UINT wait_option)
1374 {
1375 NX_PACKET *packet_ptr = NX_NULL;
1376 UINT old_threshold;
1377 NX_AZURE_IOT_THREAD thread_list;
1378 
1379     if ((hub_client_ptr == NX_NULL) ||
1380         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
1381         (packet_pptr == NX_NULL))
1382     {
1383         LogError(LogLiteralArgs("IoTHub message receive fail: INVALID POINTER"));
1384         return(NX_AZURE_IOT_INVALID_PARAMETER);
1385     }
1386 
1387     if (receive_message -> message_process == NX_NULL)
1388     {
1389         LogError(LogLiteralArgs("IoTHub message receive fail: NOT ENABLED"));
1390         return(NX_AZURE_IOT_NOT_ENABLED);
1391     }
1392 
1393     /* Obtain the mutex.  */
1394     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1395 
1396     if (receive_message -> message_head)
1397     {
1398         packet_ptr = receive_message -> message_head;
1399         if (receive_message -> message_tail == packet_ptr)
1400         {
1401             receive_message -> message_tail = NX_NULL;
1402         }
1403         receive_message -> message_head = packet_ptr -> nx_packet_queue_next;
1404     }
1405     else if (wait_option)
1406     {
1407         thread_list.thread_message_type = message_type;
1408         thread_list.thread_ptr = tx_thread_identify();
1409         thread_list.thread_received_message = NX_NULL;
1410         thread_list.thread_expected_id = 0;
1411         thread_list.thread_next = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
1412         hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = &thread_list;
1413 
1414         /* Disable preemption.  */
1415         tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
1416 
1417         /* Release the mutex.  */
1418         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1419 
1420         tx_thread_sleep(wait_option);
1421 
1422         /* Obtain the mutex.  */
1423         tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1424 
1425         nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list);
1426 
1427         /* Restore preemption.  */
1428         tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
1429         packet_ptr = thread_list.thread_received_message;
1430     }
1431 
1432     /* Release the mutex.  */
1433     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1434 
1435     if (packet_ptr == NX_NULL)
1436     {
1437         if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
1438         {
1439             LogError(LogLiteralArgs("IoTHub message receive fail:  IoTHub client not connected"));
1440             return(NX_AZURE_IOT_DISCONNECTED);
1441         }
1442 
1443         return(NX_AZURE_IOT_NO_PACKET);
1444     }
1445 
1446     *packet_pptr = packet_ptr;
1447 
1448     return(NX_AZURE_IOT_SUCCESS);
1449 }
1450 
nx_azure_iot_hub_client_adjust_payload(NX_PACKET * packet_ptr)1451 UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr)
1452 {
1453 UINT status;
1454 ULONG topic_offset;
1455 USHORT topic_length;
1456 ULONG message_offset;
1457 ULONG message_length;
1458 
1459     status = _nxd_mqtt_process_publish_packet(packet_ptr, &topic_offset,
1460                                               &topic_length, &message_offset,
1461                                               &message_length);
1462     if (status)
1463     {
1464         nx_packet_release(packet_ptr);
1465         return(status);
1466     }
1467 
1468     packet_ptr -> nx_packet_length = message_length;
1469 
1470     /* Adjust packet to pointer to message payload.  */
1471     while (packet_ptr)
1472     {
1473         if ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > message_offset)
1474         {
1475 
1476             /* This packet contains message payload.  */
1477             packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + message_offset;
1478             break;
1479         }
1480 
1481         message_offset -= (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr);
1482 
1483         /* Set current packet to empty.  */
1484         packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_append_ptr;
1485 
1486         /* Move to next packet.  */
1487         packet_ptr = packet_ptr -> nx_packet_next;
1488     }
1489 
1490     return(NX_AZURE_IOT_SUCCESS);
1491 }
1492 
nx_azure_iot_hub_client_cloud_message_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)1493 UINT nx_azure_iot_hub_client_cloud_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1494                                                    NX_PACKET **packet_pptr, UINT wait_option)
1495 {
1496 UINT status;
1497 
1498     if ((hub_client_ptr == NX_NULL) ||
1499         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
1500         (packet_pptr == NX_NULL))
1501     {
1502         LogError(LogLiteralArgs("IoTHub cloud message receive fail: INVALID POINTER"));
1503         return(NX_AZURE_IOT_INVALID_PARAMETER);
1504     }
1505 
1506     status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE,
1507                                                      &(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message),
1508                                                      packet_pptr, wait_option);
1509     if (status)
1510     {
1511         return(status);
1512     }
1513 
1514     return(nx_azure_iot_hub_client_adjust_payload(*packet_pptr));
1515 }
1516 
nx_azure_iot_hub_client_cloud_message_property_get(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,const UCHAR * property_name,USHORT property_name_length,const UCHAR ** property_value,USHORT * property_value_length)1517 UINT nx_azure_iot_hub_client_cloud_message_property_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1518                                                         NX_PACKET *packet_ptr, const UCHAR *property_name,
1519                                                         USHORT property_name_length, const UCHAR **property_value,
1520                                                         USHORT *property_value_length)
1521 {
1522 USHORT topic_size;
1523 UINT status;
1524 ULONG topic_offset;
1525 UCHAR *topic_name;
1526 az_iot_hub_client_c2d_request request;
1527 az_span receive_topic;
1528 az_result core_result;
1529 az_span span;
1530 
1531     if (packet_ptr == NX_NULL ||
1532         property_name == NX_NULL ||
1533         property_value == NX_NULL ||
1534         property_value_length == NX_NULL)
1535     {
1536         LogError(LogLiteralArgs("IoTHub cloud message get property fail: INVALID POINTER"));
1537         return(NX_AZURE_IOT_INVALID_PARAMETER);
1538     }
1539 
1540     status = nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_data_start,
1541                                                             &topic_offset, &topic_size);
1542     if (status)
1543     {
1544         return(status);
1545     }
1546 
1547     topic_name = packet_ptr -> nx_packet_data_start + topic_offset;
1548 
1549     /* NOTE: Current implementation does not support topic to span multiple packets.  */
1550     if ((ULONG)(packet_ptr -> nx_packet_append_ptr - topic_name) < (ULONG)topic_size)
1551     {
1552         LogError(LogLiteralArgs("IoTHub cloud message get property fail: topic out of boundaries of single packet"));
1553         return(NX_AZURE_IOT_TOPIC_TOO_LONG);
1554     }
1555 
1556     receive_topic = az_span_create(topic_name, (INT)topic_size);
1557     core_result = az_iot_hub_client_c2d_parse_received_topic(&hub_client_ptr -> iot_hub_client_core,
1558                                                              receive_topic, &request);
1559     if (az_result_failed(core_result))
1560     {
1561         LogError(LogLiteralArgs("IoTHub cloud message get property fail: parsing error"));
1562         return(NX_AZURE_IOT_SDK_CORE_ERROR);
1563     }
1564 
1565     span = az_span_create((UCHAR *)property_name, property_name_length);
1566     core_result = az_iot_message_properties_find(&request.properties, span, &span);
1567     if (az_result_failed(core_result))
1568     {
1569         if (core_result == AZ_ERROR_ITEM_NOT_FOUND)
1570         {
1571             status = NX_AZURE_IOT_NOT_FOUND;
1572         }
1573         else
1574         {
1575             LogError(LogLiteralArgs("IoTHub cloud message get property fail: property find"));
1576             status = NX_AZURE_IOT_SDK_CORE_ERROR;
1577         }
1578 
1579         return(status);
1580     }
1581 
1582     *property_value = (UCHAR *)az_span_ptr(span);
1583     *property_value_length = (USHORT)az_span_size(span);
1584 
1585     return(NX_AZURE_IOT_SUCCESS);
1586 }
1587 
nx_azure_iot_hub_client_mqtt_ack_receive_notify(NXD_MQTT_CLIENT * client_ptr,UINT type,USHORT packet_id,NX_PACKET * transmit_packet_ptr,VOID * context)1588 static VOID nx_azure_iot_hub_client_mqtt_ack_receive_notify(NXD_MQTT_CLIENT *client_ptr, UINT type,
1589                                                             USHORT packet_id, NX_PACKET *transmit_packet_ptr,
1590     VOID *context)
1591 {
1592 
1593 NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)context;
1594 UCHAR buffer[sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1];
1595 ULONG bytes_copied;
1596 
1597 
1598     NX_PARAMETER_NOT_USED(client_ptr);
1599     NX_PARAMETER_NOT_USED(packet_id);
1600     NX_PARAMETER_NOT_USED(context);
1601 
1602     /* Monitor subscribe ack.  */
1603     if (type == MQTT_CONTROL_PACKET_TYPE_SUBACK)
1604     {
1605 
1606         /* Get the topic.  */
1607         if (nx_packet_data_extract_offset(transmit_packet_ptr,
1608                                           NX_AZURE_IOT_MQTT_SUBSCRIBE_TOPIC_OFFSET,
1609                                           buffer, sizeof(buffer), &bytes_copied))
1610         {
1611             return;
1612         }
1613 
1614         /* Compare the topic.  */
1615         if ((bytes_copied == sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1) &&
1616             (!memcmp(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC,
1617                      buffer, sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1)))
1618         {
1619             hub_client_ptr -> nx_azure_iot_hub_client_properties_subscribe_ack = NX_TRUE;
1620         }
1621     }
1622 }
1623 
nx_azure_iot_hub_client_properties_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)1624 UINT nx_azure_iot_hub_client_properties_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
1625 {
1626 UINT status;
1627 NXD_MQTT_CLIENT *client_ptr;
1628 
1629     if (hub_client_ptr == NX_NULL)
1630     {
1631         LogError(LogLiteralArgs("IoTHub client properties subscribe fail: INVALID POINTER"));
1632         return(NX_AZURE_IOT_INVALID_PARAMETER);
1633     }
1634 
1635     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1636 
1637     /* Atomically update the handler as we need to serialize the handler with incoming messages.  */
1638     hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process =
1639                       nx_azure_iot_hub_client_properties_process;
1640     hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_process =
1641                       nx_azure_iot_hub_client_properties_process;
1642     hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_enable =
1643                       nx_azure_iot_hub_client_properties_enable;
1644     hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_enable =
1645                       nx_azure_iot_hub_client_properties_enable;
1646 
1647     /* Register callbacks even if not connect and when connect complete subscribe for topics.  */
1648     if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
1649     {
1650         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1651         return(NX_AZURE_IOT_SUCCESS);
1652     }
1653 
1654     /* Initialize variables.  */
1655     hub_client_ptr -> nx_azure_iot_hub_client_properties_subscribe_ack = NX_FALSE;
1656 
1657     /* Set ack receive notify for subscribe ack.  */
1658     client_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt);
1659     client_ptr -> nxd_mqtt_ack_receive_notify = nx_azure_iot_hub_client_mqtt_ack_receive_notify;
1660     client_ptr -> nxd_mqtt_ack_receive_context = hub_client_ptr;
1661 
1662     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1663 
1664     status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1665                                        AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC,
1666                                        sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1,
1667                                        NX_AZURE_IOT_MQTT_QOS_0);
1668     if (status)
1669     {
1670 
1671         /* Clean ack receive notify.  */
1672         client_ptr -> nxd_mqtt_ack_receive_notify = NX_NULL;
1673         LogError(LogLiteralArgs("IoTHub client device twin subscribe fail status: %d"), status);
1674         return(status);
1675     }
1676 
1677     status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1678                                        AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC,
1679                                        sizeof(AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC) - 1,
1680                                        NX_AZURE_IOT_MQTT_QOS_0);
1681     if (status)
1682     {
1683 
1684         /* Clean ack receive notify.  */
1685         client_ptr -> nxd_mqtt_ack_receive_notify = NX_NULL;
1686         LogError(LogLiteralArgs("IoTHub client device twin subscribe fail status: %d"), status);
1687         return(status);
1688     }
1689 
1690     return(NX_AZURE_IOT_SUCCESS);
1691 }
1692 
nx_azure_iot_hub_client_properties_disable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)1693 UINT nx_azure_iot_hub_client_properties_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
1694 {
1695 UINT status;
1696 
1697     if (hub_client_ptr == NX_NULL)
1698     {
1699         LogError(LogLiteralArgs("IoTHub client properties unsubscribe fail: INVALID POINTER"));
1700         return(NX_AZURE_IOT_INVALID_PARAMETER);
1701     }
1702 
1703     status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1704                                          AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC,
1705                                          sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1);
1706     if (status)
1707     {
1708         LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail status: %d"), status);
1709         return(status);
1710     }
1711 
1712     status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1713                                          AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC,
1714                                          sizeof(AZ_IOT_HUB_CLIENT_TWIN_PATCH_SUBSCRIBE_TOPIC) - 1);
1715     if (status)
1716     {
1717         LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail status: %d"), status);
1718         return(status);
1719     }
1720 
1721     hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process = NX_NULL;
1722     hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_process = NX_NULL;
1723 
1724     return(NX_AZURE_IOT_SUCCESS);
1725 }
1726 
nx_azure_iot_hub_client_reported_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,VOID (* callback_ptr)(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT request_id,UINT response_status,ULONG version,VOID * args),VOID * callback_args)1727 UINT nx_azure_iot_hub_client_reported_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1728                                                                        VOID (*callback_ptr)(
1729                                                                              NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1730                                                                              UINT request_id,
1731                                                                              UINT response_status,
1732                                                                              ULONG version,
1733                                                                              VOID *args),
1734                                                                        VOID *callback_args)
1735 {
1736     if (hub_client_ptr == NX_NULL)
1737     {
1738         LogError(LogLiteralArgs("IoTHub client device twin set callback fail: INVALID POINTER"));
1739         return(NX_AZURE_IOT_INVALID_PARAMETER);
1740     }
1741 
1742     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1743 
1744     hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback = callback_ptr;
1745     hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback_args = callback_args;
1746 
1747     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1748 
1749     return(NX_AZURE_IOT_SUCCESS);
1750 }
1751 
nx_azure_iot_hub_client_properties_request_id_get(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UCHAR * buffer_ptr,UINT buffer_len,az_span * request_id_span_ptr,UINT * request_id_ptr,UINT odd_seq)1752 static UINT nx_azure_iot_hub_client_properties_request_id_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1753                                                               UCHAR *buffer_ptr, UINT buffer_len,
1754                                                               az_span *request_id_span_ptr,
1755                                                               UINT *request_id_ptr, UINT odd_seq)
1756 {
1757 az_span span;
1758 
1759     /* Obtain the mutex.  */
1760     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1761 
1762     /* Check if current request_id is even and new requested is also even or
1763        current request_id is odd and new requested is also odd.  */
1764     if ((hub_client_ptr -> nx_azure_iot_hub_client_request_id & 0x1) == odd_seq)
1765     {
1766         hub_client_ptr -> nx_azure_iot_hub_client_request_id += 2;
1767     }
1768     else
1769     {
1770         hub_client_ptr -> nx_azure_iot_hub_client_request_id += 1;
1771     }
1772 
1773     if (hub_client_ptr -> nx_azure_iot_hub_client_request_id == 0)
1774     {
1775         hub_client_ptr -> nx_azure_iot_hub_client_request_id = 2;
1776     }
1777 
1778     *request_id_ptr = hub_client_ptr -> nx_azure_iot_hub_client_request_id;
1779     span = az_span_create(buffer_ptr, (INT)buffer_len);
1780     if (az_result_failed(az_span_u32toa(span, *request_id_ptr, &span)))
1781     {
1782 
1783         /* Release the mutex.  */
1784         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1785         LogError(LogLiteralArgs("IoTHub client device failed to u32toa"));
1786         return(NX_AZURE_IOT_SDK_CORE_ERROR);
1787     }
1788 
1789     *request_id_span_ptr = az_span_create(buffer_ptr, (INT)(buffer_len - (UINT)az_span_size(span)));
1790 
1791     /* Release the mutex.  */
1792     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1793 
1794     return(NX_AZURE_IOT_SUCCESS);
1795 }
1796 
nx_azure_iot_hub_client_properties_subscribe_status_check(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT wait_option)1797 static UINT nx_azure_iot_hub_client_properties_subscribe_status_check(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT wait_option)
1798 {
1799 
1800     /* Wait for subscribe ack of topic "$iothub/twin/res/#".  */
1801     while (1)
1802     {
1803         tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1804 
1805         /* Check if it is still in connected status.  */
1806         if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
1807         {
1808 
1809             /* Clean ack receive notify.  */
1810             hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = NX_NULL;
1811             tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1812             return(NX_AZURE_IOT_DISCONNECTED);
1813         }
1814 
1815         /* Check if receive the subscribe ack.  */
1816         if (hub_client_ptr -> nx_azure_iot_hub_client_properties_subscribe_ack == NX_TRUE)
1817         {
1818 
1819             /* Clean ack receive notify.  */
1820             hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt.nxd_mqtt_ack_receive_notify = NX_NULL;
1821             tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1822             break;
1823         }
1824 
1825         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1826 
1827         /* Update wait time.  */
1828         if (wait_option != NX_WAIT_FOREVER)
1829         {
1830             if (wait_option > 0)
1831             {
1832                 wait_option--;
1833             }
1834             else
1835             {
1836                 return(NX_AZURE_IOT_NO_SUBSCRIBE_ACK);
1837             }
1838         }
1839 
1840         tx_thread_sleep(1);
1841     }
1842 
1843     return(NX_AZURE_IOT_SUCCESS);
1844 }
1845 
nx_azure_iot_hub_client_properties_request_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT request_id,NX_PACKET * packet_ptr,ULONG topic_length,const UCHAR * message_buffer,UINT message_length,UINT message_type,NX_PACKET ** response_packet_pptr,UINT wait_option)1846 static UINT nx_azure_iot_hub_client_properties_request_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1847                                                                 UINT request_id, NX_PACKET *packet_ptr, ULONG topic_length,
1848                                                                 const UCHAR *message_buffer, UINT message_length, UINT message_type,
1849                                                                 NX_PACKET **response_packet_pptr, UINT wait_option)
1850 {
1851 NX_AZURE_IOT_THREAD thread_list;
1852 UINT status;
1853 
1854     if ((message_buffer != NX_NULL) && (message_length != 0))
1855     {
1856 
1857         /* Append payload.  */
1858         status = nx_packet_data_append(packet_ptr, (VOID *)message_buffer, message_length,
1859                                        packet_ptr -> nx_packet_pool_owner,
1860                                        wait_option);
1861         if (status)
1862         {
1863             LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed"));
1864             return(status);
1865         }
1866     }
1867 
1868     /* Obtain the mutex.  */
1869     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1870 
1871     thread_list.thread_message_type = message_type;
1872     thread_list.thread_ptr = tx_thread_identify();
1873     thread_list.thread_expected_id = request_id;
1874     thread_list.thread_received_message = NX_NULL;
1875     thread_list.thread_next = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
1876     hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = &thread_list;
1877 
1878     /* Release the mutex.  */
1879     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1880 
1881     status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1882                                               packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0,
1883                                               wait_option);
1884 
1885     if (status)
1886     {
1887 
1888         /* Remove thread from waiting suspend queue.  */
1889         tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1890         nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list);
1891         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1892 
1893         LogError(LogLiteralArgs("IoTHub transport send: PUBLISH FAIL status: %d"), status);
1894         return(status);
1895     }
1896 
1897     if ((thread_list.thread_received_message) == NX_NULL && wait_option)
1898     {
1899         tx_thread_sleep(wait_option);
1900     }
1901 
1902     /* Obtain the mutex.  */
1903     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1904 
1905     nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list);
1906     *response_packet_pptr = thread_list.thread_received_message;
1907 
1908     /* Release the mutex.  */
1909     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1910 
1911     return(NX_AZURE_IOT_SUCCESS);
1912 }
1913 
nx_azure_iot_hub_client_reported_properties_create(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)1914 UINT nx_azure_iot_hub_client_reported_properties_create(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
1915                                                         NX_PACKET **packet_pptr,
1916                                                         UINT wait_option)
1917 {
1918 UINT status;
1919 NX_PACKET *packet_ptr;
1920 UINT request_id;
1921 UCHAR *buffer_ptr;
1922 ULONG buffer_size;
1923 az_span request_id_span;
1924 az_result core_result;
1925 UINT topic_length;
1926 
1927     if ((hub_client_ptr == NX_NULL) ||
1928         (packet_pptr == NX_NULL))
1929     {
1930         LogError(LogLiteralArgs("IoTHub reported properties create fail: INVALID POINTER"));
1931         return(NX_AZURE_IOT_INVALID_PARAMETER);
1932     }
1933 
1934     status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr,
1935                                              &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
1936                                              &packet_ptr, wait_option);
1937     if (status)
1938     {
1939         LogError(LogLiteralArgs("IoTHub client reported properties create fail: BUFFER ALLOCATE FAIL"));
1940         return(status);
1941     }
1942 
1943     buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
1944     if (buffer_size <= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE)
1945     {
1946         LogError(LogLiteralArgs("IoTHub client reported properties create fail: BUFFER INSUFFICENT"));
1947         nx_packet_release(packet_ptr);
1948         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
1949     }
1950 
1951     buffer_size -= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE;
1952 
1953     /* Generate odd request id for reported properties send */
1954     status = nx_azure_iot_hub_client_properties_request_id_get(hub_client_ptr,
1955                                                                (UCHAR *)(packet_ptr -> nx_packet_data_end -
1956                                                                  NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE),
1957                                                                NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE,
1958                                                                &request_id_span, &request_id, NX_TRUE);
1959 
1960     if (status)
1961     {
1962         LogError(LogLiteralArgs("IoTHub client reported properties create fail: get request id failed"));
1963         nx_packet_release(packet_ptr);
1964         return(status);
1965     }
1966 
1967     core_result = az_iot_hub_client_properties_get_reported_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
1968                                                                           request_id_span,
1969                                                                           (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
1970                                                                           buffer_size, &topic_length);
1971     if (az_result_failed(core_result))
1972     {
1973         LogError(LogLiteralArgs("IoTHub client reported properties create fail: NX_AZURE_IOT_PNP_CLIENT_TOPIC_SIZE is too small."));
1974         nx_packet_release(packet_ptr);
1975         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
1976     }
1977 
1978     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length;
1979     packet_ptr -> nx_packet_length = topic_length;
1980 
1981     /* Set the buffer pointer.  */
1982     buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET;
1983 
1984     /* encode topic length */
1985     buffer_ptr[5] = (UCHAR)(packet_ptr -> nx_packet_length >> 8);
1986     buffer_ptr[6] = (UCHAR)(packet_ptr -> nx_packet_length & 0xFF);
1987 
1988     /* encode request id */
1989     buffer_ptr[4] = (UCHAR)((request_id & 0xFF));
1990     request_id >>= 8;
1991     buffer_ptr[3] = (UCHAR)((request_id & 0xFF));
1992     request_id >>= 8;
1993     buffer_ptr[2] = (UCHAR)((request_id & 0xFF));
1994     request_id >>= 8;
1995     buffer_ptr[1] = (UCHAR)(request_id & 0xFF);
1996 
1997     *packet_pptr = packet_ptr;
1998 
1999     return(NX_AZURE_IOT_SUCCESS);
2000 }
2001 
nx_azure_iot_hub_client_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,UINT * request_id_ptr,UINT * response_status_ptr,ULONG * version_ptr,UINT wait_option)2002 UINT nx_azure_iot_hub_client_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2003                                                       NX_PACKET *packet_ptr,
2004                                                       UINT *request_id_ptr, UINT *response_status_ptr,
2005                                                       ULONG *version_ptr, UINT wait_option)
2006 {
2007 NX_PACKET *response_packet_ptr;
2008 UINT topic_length;
2009 UINT request_id = 0;
2010 ULONG topic_offset;
2011 USHORT length;
2012 UCHAR *buffer_ptr;
2013 UINT status;
2014 
2015     if ((hub_client_ptr == NX_NULL) ||
2016         (packet_ptr == NX_NULL))
2017     {
2018         LogError(LogLiteralArgs("IoTHub client reported properties send fail: INVALID POINTER"));
2019         return(NX_AZURE_IOT_INVALID_PARAMETER);
2020     }
2021 
2022     /* Check if properties is subscribed */
2023     if ((status = nx_azure_iot_hub_client_properties_subscribe_status_check(hub_client_ptr, wait_option)))
2024     {
2025         LogError(LogLiteralArgs("IoTHub client reported properties send fail with error %d"), status);
2026         return(status);
2027     }
2028 
2029     /* Check if the last request was throttled and if the next need to be throttled.  */
2030     if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr)))
2031     {
2032         LogError(LogLiteralArgs("IoTHub client reported properties send fail with error %d"), status);
2033         return(status);
2034     }
2035 
2036     /* Steps.
2037      * 1. Publish message to topic "$iothub/twin/PATCH/properties/reported/?$rid={request id}"
2038      * 2. Wait for the response if required.
2039      * 3. Return result if present.
2040      * */
2041 
2042     buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET;
2043 
2044     topic_length = (UINT)((buffer_ptr[5] << 8) | buffer_ptr[6]);
2045 
2046     request_id += (buffer_ptr[1] & 0xFF);
2047     request_id <<= 8;
2048     request_id += (buffer_ptr[2] & 0xFF);
2049     request_id <<= 8;
2050     request_id += (buffer_ptr[3] & 0xFF);
2051     request_id <<= 8;
2052     request_id += (buffer_ptr[4] & 0xFF);
2053 
2054     status = nx_azure_iot_hub_client_properties_request_response(hub_client_ptr,
2055                                                                  request_id, packet_ptr, topic_length, NX_NULL, 0,
2056                                                                  NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE,
2057                                                                  &response_packet_ptr, wait_option);
2058     if (status)
2059     {
2060         LogError(LogLiteralArgs("IoTHub client reported properties send fail: append failed"));
2061         return(status);
2062     }
2063 
2064     /* The packet of reported properties has been sent out successfully,
2065        next the return value should be NX_AZURE_IOT_SUCCESS.  */
2066 
2067     /* Continue to process response and the caller can check the response status to see if iothub accept the properties or not,
2068        the reponse status is available only when the return status is NX_AZURE_IOT_SUCCESS.    */
2069     if (request_id_ptr)
2070     {
2071         *request_id_ptr = request_id;
2072     }
2073 
2074     if (response_status_ptr)
2075     {
2076         *response_status_ptr = 0;
2077     }
2078 
2079     if (response_packet_ptr)
2080     {
2081         if(nx_azure_iot_hub_client_process_publish_packet(response_packet_ptr -> nx_packet_prepend_ptr,
2082                                                           &topic_offset, &length) == NX_AZURE_IOT_SUCCESS)
2083         {
2084             nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr,
2085                                                       response_packet_ptr, topic_offset, length,
2086                                                       NX_NULL, version_ptr, NX_NULL,
2087                                                       response_status_ptr);
2088         }
2089 
2090         nx_packet_release(response_packet_ptr);
2091     }
2092 
2093     return(NX_AZURE_IOT_SUCCESS);
2094 }
2095 
nx_azure_iot_hub_client_properties_request(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT wait_option)2096 UINT nx_azure_iot_hub_client_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2097                                                 UINT wait_option)
2098 {
2099 UINT status;
2100 UINT topic_length;
2101 UINT buffer_size;
2102 NX_PACKET *packet_ptr;
2103 az_span request_id_span;
2104 UINT request_id;
2105 az_result core_result;
2106 
2107     if (hub_client_ptr == NX_NULL)
2108     {
2109         LogError(LogLiteralArgs("IoTHub client properties request failed: INVALID POINTER"));
2110         return(NX_AZURE_IOT_INVALID_PARAMETER);
2111     }
2112 
2113     if ((status = nx_azure_iot_hub_client_properties_subscribe_status_check(hub_client_ptr, wait_option)))
2114     {
2115         LogError(LogLiteralArgs("IoTHub client properties request failed with error %d"), status);
2116         return(status);
2117     }
2118 
2119     /* Check if the last request was throttled and if the next need to be throttled.  */
2120     if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr)))
2121     {
2122         LogError(LogLiteralArgs("IoTHub client properties request failed with error %d"), status);
2123         return(status);
2124     }
2125 
2126     /* Steps.
2127      * 1. Publish message to topic "$iothub/twin/GET/?$rid={request id}"
2128      * */
2129     status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr,
2130                                              &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
2131                                              &packet_ptr, wait_option);
2132     if (status)
2133     {
2134         LogError(LogLiteralArgs("IoTHub client properties request failed: BUFFER ALLOCATE FAIL"));
2135         return(status);
2136     }
2137 
2138     buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
2139     if (buffer_size <= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE)
2140     {
2141         LogError(LogLiteralArgs("IoTHub client device twin publish fail: BUFFER ALLOCATE FAIL"));
2142         nx_packet_release(packet_ptr);
2143         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
2144     }
2145 
2146     buffer_size -= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE;
2147 
2148     /* Generate even request id for properties request.  */
2149     status = nx_azure_iot_hub_client_properties_request_id_get(hub_client_ptr,
2150                                                                (UCHAR *)(packet_ptr -> nx_packet_data_end -
2151                                                                  NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE),
2152                                                                NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE,
2153                                                                &request_id_span, &request_id, NX_FALSE);
2154     if (status)
2155     {
2156         LogError(LogLiteralArgs("IoTHub client device twin failed to get request id"));
2157         nx_packet_release(packet_ptr);
2158         return(status);
2159     }
2160 
2161     core_result = az_iot_hub_client_properties_document_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
2162                                                                           request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
2163                                                                           buffer_size, (size_t *)&topic_length);
2164     if (az_result_failed(core_result))
2165     {
2166         LogError(LogLiteralArgs("IoTHub client device twin get topic fail."));
2167         nx_packet_release(packet_ptr);
2168         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
2169     }
2170 
2171     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length;
2172     packet_ptr -> nx_packet_length = topic_length;
2173 
2174     status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
2175                                               packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0,
2176                                               wait_option);
2177     if (status)
2178     {
2179         LogError(LogLiteralArgs("IoTHub client device twin: PUBLISH FAIL status: %d"), status);
2180         nx_packet_release(packet_ptr);
2181         return(status);
2182     }
2183 
2184     return(NX_AZURE_IOT_SUCCESS);
2185 }
2186 
nx_azure_iot_hub_client_properties_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)2187 UINT nx_azure_iot_hub_client_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2188                                                 NX_PACKET **packet_pptr,
2189                                                 UINT wait_option)
2190 {
2191 UINT status;
2192 ULONG topic_offset;
2193 USHORT topic_length;
2194 az_result core_result;
2195 az_span topic_span;
2196 az_iot_hub_client_properties_message out_message;
2197 NX_PACKET *packet_ptr;
2198 
2199     if ((hub_client_ptr == NX_NULL) || (packet_pptr == NX_NULL))
2200     {
2201         LogError(LogLiteralArgs("IoTHub client properties receive failed: INVALID POINTER"));
2202         return(NX_AZURE_IOT_INVALID_PARAMETER);
2203     }
2204 
2205     /* Steps.
2206      * 1. Check if the properties document is available to receive from linklist.
2207      * 2. If present check the response.
2208      * 3. Return the payload of the response.
2209      * */
2210     status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_PROPERTIES,
2211                                                      &(hub_client_ptr -> nx_azure_iot_hub_client_properties_message),
2212                                                      &packet_ptr, wait_option);
2213     if (status)
2214     {
2215         LogError(LogLiteralArgs("IoTHub client device twin receive failed status: %d"), status);
2216         return(status);
2217     }
2218 
2219     if (nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, &topic_length))
2220     {
2221 
2222         /* Message not supported. It will be released.  */
2223         nx_packet_release(packet_ptr);
2224         return(NX_AZURE_IOT_INVALID_PACKET);
2225     }
2226 
2227     topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), (INT)topic_length);
2228     core_result = az_iot_hub_client_properties_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core),
2229                                                                     topic_span, &out_message);
2230     if (az_result_failed(core_result))
2231     {
2232 
2233         /* Topic name does not match properties format.  */
2234         nx_packet_release(packet_ptr);
2235         return(NX_AZURE_IOT_SDK_CORE_ERROR);
2236     }
2237 
2238     if ((out_message.status < 200) || (out_message.status >= 300))
2239     {
2240         nx_packet_release(packet_ptr);
2241         return(NX_AZURE_IOT_SERVER_RESPONSE_ERROR);
2242     }
2243 
2244     if ((status = nx_azure_iot_hub_client_adjust_payload(packet_ptr)))
2245     {
2246         nx_packet_release(packet_ptr);
2247         return(status);
2248     }
2249 
2250     *packet_pptr = packet_ptr;
2251 
2252     return(NX_AZURE_IOT_SUCCESS);
2253 }
2254 
nx_azure_iot_hub_client_writable_properties_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)2255 UINT nx_azure_iot_hub_client_writable_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2256                                                         NX_PACKET **packet_pptr,
2257                                                         UINT wait_option)
2258 {
2259 UINT status;
2260 NX_PACKET *packet_ptr;
2261 
2262     if ((hub_client_ptr == NX_NULL) ||
2263         (packet_pptr == NX_NULL))
2264     {
2265         LogError(LogLiteralArgs("IoTHub client receive properties failed: INVALID POINTER"));
2266         return(NX_AZURE_IOT_INVALID_PARAMETER);
2267     }
2268 
2269     /* Steps.
2270      * 1. Check if the writable properties document is available to receive from linklist.
2271      * 2. Parse result if present.
2272      * 3. Return parse result.
2273      * */
2274     status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES,
2275                                                      &(hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message),
2276                                                      &packet_ptr, wait_option);
2277     if (status)
2278     {
2279         LogError(LogLiteralArgs("IoTHub client device twin receive failed status: %d"), status);
2280         return(status);
2281     }
2282 
2283     if ((status = nx_azure_iot_hub_client_adjust_payload(packet_ptr)))
2284     {
2285         nx_packet_release(packet_ptr);
2286         return(status);
2287     }
2288 
2289     *packet_pptr = packet_ptr;
2290 
2291     return(NX_AZURE_IOT_SUCCESS);
2292 }
2293 
2294 
nx_azure_iot_hub_client_device_twin_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)2295 UINT nx_azure_iot_hub_client_device_twin_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
2296 {
2297 
2298     if (hub_client_ptr == NX_NULL)
2299     {
2300         LogError(LogLiteralArgs("IoTHub client device twin subscribe fail: INVALID POINTER"));
2301         return(NX_AZURE_IOT_INVALID_PARAMETER);
2302     }
2303 
2304     return(nx_azure_iot_hub_client_properties_enable(hub_client_ptr));
2305 }
2306 
nx_azure_iot_hub_client_device_twin_disable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)2307 UINT nx_azure_iot_hub_client_device_twin_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
2308 {
2309 
2310     if (hub_client_ptr == NX_NULL)
2311     {
2312         LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail: INVALID POINTER"));
2313         return(NX_AZURE_IOT_INVALID_PARAMETER);
2314     }
2315 
2316     return(nx_azure_iot_hub_client_properties_disable(hub_client_ptr));
2317 }
2318 
2319 
nx_azure_iot_hub_client_device_twin_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR * message_buffer,UINT message_length,UINT * request_id_ptr,UINT * response_status_ptr,ULONG * version_ptr,UINT wait_option)2320 UINT nx_azure_iot_hub_client_device_twin_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2321                                                                   const UCHAR *message_buffer, UINT message_length,
2322                                                                   UINT *request_id_ptr, UINT *response_status_ptr,
2323                                                                   ULONG *version_ptr, UINT wait_option)
2324 {
2325 UINT status;
2326 UINT buffer_size;
2327 NX_PACKET *packet_ptr;
2328 UINT topic_length;
2329 UINT request_id;
2330 az_span request_id_span;
2331 az_result core_result;
2332 ULONG topic_offset;
2333 USHORT length;
2334 NX_PACKET *response_packet_ptr;
2335 
2336     if (hub_client_ptr == NX_NULL)
2337     {
2338         LogError(LogLiteralArgs("IoTHub client reported state send fail: INVALID POINTER"));
2339         return(NX_AZURE_IOT_INVALID_PARAMETER);
2340     }
2341 
2342     if ((status = nx_azure_iot_hub_client_properties_subscribe_status_check(hub_client_ptr, wait_option)))
2343     {
2344         LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status);
2345         return(status);
2346     }
2347 
2348     /* Check if the last request was throttled and if the next need to be throttled.  */
2349     if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr)))
2350     {
2351         LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status);
2352         return(status);
2353     }
2354 
2355     /* Steps.
2356      * 1. Publish message to topic "$iothub/twin/PATCH/properties/reported/?$rid={request id}"
2357      * 2. Wait for the response if required.
2358      * 3. Return result if present.
2359      * */
2360     if (hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process == NX_NULL)
2361     {
2362         LogError(LogLiteralArgs("IoTHub client reported state send fail: NOT ENABLED"));
2363         return(NX_AZURE_IOT_NOT_ENABLED);
2364     }
2365 
2366     status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr,
2367                                              &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
2368                                              &packet_ptr, wait_option);
2369     if (status)
2370     {
2371         LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER ALLOCATE FAIL"));
2372         return(status);
2373     }
2374 
2375     buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
2376     if (buffer_size <= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE)
2377     {
2378         LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER INSUFFICENT"));
2379         nx_packet_release(packet_ptr);
2380         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
2381     }
2382 
2383     buffer_size -= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE;
2384 
2385     /* Generate odd request id for reported properties send.  */
2386     status = nx_azure_iot_hub_client_properties_request_id_get(hub_client_ptr,
2387                                                                (UCHAR *)(packet_ptr -> nx_packet_data_end -
2388                                                                  NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE),
2389                                                                NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE,
2390                                                                &request_id_span, &request_id, NX_TRUE);
2391 
2392     if (status)
2393     {
2394         LogError(LogLiteralArgs("IoTHub client reported state send failed to get request id"));
2395         nx_packet_release(packet_ptr);
2396         return(status);
2397     }
2398 
2399     core_result = az_iot_hub_client_twin_patch_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
2400                                                                  request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
2401                                                                  buffer_size, (size_t *)&topic_length);
2402     if (az_result_failed(core_result))
2403     {
2404         LogError(LogLiteralArgs("IoTHub client reported state send fail: NX_AZURE_IOT_HUB_CLIENT_TOPIC_SIZE is too small."));
2405         nx_packet_release(packet_ptr);
2406         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
2407     }
2408 
2409     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length;
2410     packet_ptr -> nx_packet_length = topic_length;
2411 
2412     status = nx_azure_iot_hub_client_properties_request_response(hub_client_ptr,
2413                                                                 request_id, packet_ptr, topic_length, message_buffer, message_length,
2414                                                                 NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE,
2415                                                                 &response_packet_ptr, wait_option);
2416     if (status)
2417     {
2418         LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed"));
2419         nx_packet_release(packet_ptr);
2420         return(status);
2421     }
2422 
2423     if (request_id_ptr)
2424     {
2425         *request_id_ptr = request_id;
2426     }
2427 
2428     if (response_packet_ptr == NX_NULL)
2429     {
2430         if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
2431         {
2432             return(NX_AZURE_IOT_DISCONNECTED);
2433         }
2434         return(NX_AZURE_IOT_NO_PACKET);
2435     }
2436 
2437     if ((status = nx_azure_iot_hub_client_process_publish_packet(response_packet_ptr -> nx_packet_prepend_ptr,
2438                                                                  &topic_offset, &length)))
2439     {
2440         nx_packet_release(response_packet_ptr);
2441         return(status);
2442     }
2443 
2444     if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr,
2445                                                             response_packet_ptr, topic_offset, length,
2446                                                             NX_NULL, version_ptr, NX_NULL,
2447                                                             response_status_ptr)))
2448     {
2449         nx_packet_release(response_packet_ptr);
2450         return(status);
2451     }
2452 
2453     /* Release message block.  */
2454     nx_packet_release(response_packet_ptr);
2455 
2456     return(NX_AZURE_IOT_SUCCESS);
2457 }
2458 
nx_azure_iot_hub_client_device_twin_properties_request(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT wait_option)2459 UINT nx_azure_iot_hub_client_device_twin_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2460                                                             UINT wait_option)
2461 {
2462 
2463     if (hub_client_ptr == NX_NULL)
2464     {
2465         LogError(LogLiteralArgs("IoTHub client device twin properties request failed: INVALID POINTER"));
2466         return(NX_AZURE_IOT_INVALID_PARAMETER);
2467     }
2468 
2469     return(nx_azure_iot_hub_client_properties_request(hub_client_ptr, wait_option));
2470 }
2471 
nx_azure_iot_hub_client_device_twin_properties_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)2472 UINT nx_azure_iot_hub_client_device_twin_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2473                                                             NX_PACKET **packet_pptr, UINT wait_option)
2474 {
2475 
2476     if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL)
2477     {
2478         LogError(LogLiteralArgs("IoTHub client device twin properties receive failed: INVALID POINTER"));
2479         return(NX_AZURE_IOT_INVALID_PARAMETER);
2480     }
2481 
2482     return(nx_azure_iot_hub_client_properties_receive(hub_client_ptr, packet_pptr, wait_option));
2483 }
2484 
nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)2485 UINT nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2486                                                                     NX_PACKET **packet_pptr, UINT wait_option)
2487 {
2488 
2489     if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL)
2490     {
2491         LogError(LogLiteralArgs("IoTHub client device twin desired properties receive failed: INVALID POINTER"));
2492         return(NX_AZURE_IOT_INVALID_PARAMETER);
2493     }
2494 
2495     return(nx_azure_iot_hub_client_writable_properties_receive(hub_client_ptr, packet_pptr, wait_option));
2496 }
2497 
nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT is_subscribe)2498 static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT is_subscribe)
2499 {
2500 UINT status;
2501 
2502     if (is_subscribe)
2503     {
2504         tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
2505 
2506         /* Atomically update the handler as we need to serialize the handler with incoming messages.  */
2507         hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process = nx_azure_iot_hub_client_c2d_process;
2508         hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_enable = nx_azure_iot_hub_client_cloud_message_enable;
2509 
2510         /* Register callbacks even if not connect and when connect complete subscribe for topics.  */
2511         if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
2512         {
2513             tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
2514             return(NX_AZURE_IOT_SUCCESS);
2515         }
2516 
2517         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
2518 
2519         status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
2520                                            AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, sizeof(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) - 1,
2521                                            NX_AZURE_IOT_MQTT_QOS_1);
2522         if (status)
2523         {
2524             LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: status: %d"), status);
2525             return(status);
2526         }
2527     }
2528     else
2529     {
2530         status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
2531                                              AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, sizeof(AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC) - 1);
2532         if (status)
2533         {
2534             LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: status: %d"), status);
2535             return(status);
2536         }
2537 
2538         hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process = NX_NULL;
2539     }
2540 
2541     return(NX_AZURE_IOT_SUCCESS);
2542 }
2543 
nx_azure_iot_hub_client_mqtt_receive_callback(NXD_MQTT_CLIENT * client_ptr,UINT number_of_messages)2544 static VOID nx_azure_iot_hub_client_mqtt_receive_callback(NXD_MQTT_CLIENT* client_ptr,
2545                                                           UINT number_of_messages)
2546 {
2547 NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr);
2548 NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NX_NULL;
2549 NX_PACKET *packet_ptr;
2550 NX_PACKET *packet_next_ptr;
2551 ULONG topic_offset;
2552 USHORT topic_length;
2553 
2554     /* This function is protected by MQTT mutex.  */
2555 
2556     NX_PARAMETER_NOT_USED(number_of_messages);
2557 
2558     if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB))
2559     {
2560         hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource -> resource_data_ptr;
2561     }
2562 
2563     if (hub_client_ptr)
2564     {
2565         for (packet_ptr = client_ptr -> message_receive_queue_head;
2566              packet_ptr;
2567              packet_ptr = packet_next_ptr)
2568         {
2569 
2570             /* Store next packet in case current packet is consumed.  */
2571             packet_next_ptr = packet_ptr -> nx_packet_queue_next;
2572 
2573             /* Adjust packet to simply process logic.  */
2574             nx_azure_iot_mqtt_packet_adjust(packet_ptr);
2575 
2576             if (nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset,
2577                                                                &topic_length))
2578             {
2579 
2580                 /* Message not supported. It will be released.  */
2581                 nx_packet_release(packet_ptr);
2582                 continue;
2583             }
2584 
2585             if ((topic_offset + topic_length) >
2586                 (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr))
2587             {
2588 
2589                 /* Only process topic in the first packet since the fixed topic is short enough to fit into one packet.  */
2590                 topic_length = (USHORT)(((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) -
2591                                          topic_offset) & 0xFFFF);
2592             }
2593 
2594             if (hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process &&
2595                 (hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process(hub_client_ptr, packet_ptr,
2596                                                                                                  topic_offset,
2597                                                                                                  topic_length) == NX_AZURE_IOT_SUCCESS))
2598             {
2599 
2600                 /* Direct method message is processed.  */
2601                 continue;
2602             }
2603 
2604             if (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process &&
2605                 (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process(hub_client_ptr, packet_ptr,
2606                                                                                        topic_offset,
2607                                                                                        topic_length) == NX_AZURE_IOT_SUCCESS))
2608             {
2609 
2610                 /* Could to Device message is processed.  */
2611                 continue;
2612             }
2613 
2614             if ((hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process) &&
2615                 (hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process(hub_client_ptr,
2616                                                                                                packet_ptr, topic_offset,
2617                                                                                                topic_length) == NX_AZURE_IOT_SUCCESS))
2618             {
2619 
2620                 /* Device Twin message is processed.  */
2621                 continue;
2622             }
2623 
2624             /* Message not supported. It will be released.  */
2625             nx_packet_release(packet_ptr);
2626         }
2627 
2628         /* Clear all message from MQTT receive queue.  */
2629         client_ptr -> message_receive_queue_head = NX_NULL;
2630         client_ptr -> message_receive_queue_tail = NX_NULL;
2631         client_ptr -> message_receive_queue_depth = 0;
2632     }
2633 }
2634 
nx_azure_iot_hub_client_message_notify(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE * receive_message,NX_PACKET * packet_ptr)2635 static VOID nx_azure_iot_hub_client_message_notify(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2636                                                    NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *receive_message,
2637                                                    NX_PACKET *packet_ptr)
2638 {
2639     if (receive_message -> message_tail)
2640     {
2641         receive_message -> message_tail -> nx_packet_queue_next = packet_ptr;
2642     }
2643     else
2644     {
2645         receive_message -> message_head = packet_ptr;
2646     }
2647     receive_message -> message_tail = packet_ptr;
2648 
2649     /* Check for user callback function.  */
2650     if (receive_message -> message_callback)
2651     {
2652         receive_message -> message_callback(hub_client_ptr, receive_message -> message_callback_args);
2653     }
2654 }
2655 
nx_azure_iot_hub_client_receive_thread_find(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,UINT message_type,UINT request_id,NX_AZURE_IOT_THREAD ** thread_list_pptr)2656 static UINT nx_azure_iot_hub_client_receive_thread_find(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2657                                                         NX_PACKET *packet_ptr, UINT message_type,
2658                                                         UINT request_id, NX_AZURE_IOT_THREAD **thread_list_pptr)
2659 {
2660 NX_AZURE_IOT_THREAD *thread_list_prev = NX_NULL;
2661 NX_AZURE_IOT_THREAD *thread_list_ptr;
2662 
2663     /* Search thread waiting for message type.  */
2664     for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
2665          thread_list_ptr;
2666          thread_list_ptr = thread_list_ptr -> thread_next)
2667     {
2668         if ((thread_list_ptr -> thread_message_type == message_type) &&
2669             (request_id == thread_list_ptr -> thread_expected_id))
2670         {
2671 
2672             /* Found a thread waiting for message type.  */
2673             if (thread_list_prev == NX_NULL)
2674             {
2675                 hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = thread_list_ptr -> thread_next;
2676             }
2677             else
2678             {
2679                 thread_list_prev -> thread_next = thread_list_ptr -> thread_next;
2680             }
2681             thread_list_ptr -> thread_received_message = packet_ptr;
2682             *thread_list_pptr =  thread_list_ptr;
2683             return(NX_AZURE_IOT_SUCCESS);
2684         }
2685 
2686         thread_list_prev = thread_list_ptr;
2687     }
2688 
2689     return(NX_AZURE_IOT_NOT_FOUND);
2690 }
2691 
nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,ULONG topic_offset,USHORT topic_length)2692 static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2693                                                 NX_PACKET *packet_ptr,
2694                                                 ULONG topic_offset,
2695                                                 USHORT topic_length)
2696 {
2697 UCHAR *topic_name;
2698 az_iot_hub_client_c2d_request request;
2699 az_span receive_topic;
2700 az_result core_result;
2701 UINT status;
2702 NX_AZURE_IOT_THREAD *thread_list_ptr;
2703 
2704     /* This function is protected by MQTT mutex.  */
2705 
2706     /* Check message type first.  */
2707     topic_name = &(packet_ptr -> nx_packet_prepend_ptr[topic_offset]);
2708 
2709     /* NOTE: Current implementation does not support topic to span multiple packets.  */
2710     if ((ULONG)(packet_ptr -> nx_packet_append_ptr - topic_name) < topic_length)
2711     {
2712         LogError(LogLiteralArgs("topic out of boundaries of single packet"));
2713         return(NX_AZURE_IOT_TOPIC_TOO_LONG);
2714     }
2715 
2716     receive_topic = az_span_create(topic_name, topic_length);
2717     core_result = az_iot_hub_client_c2d_parse_received_topic(&hub_client_ptr -> iot_hub_client_core,
2718                                                              receive_topic, &request);
2719     if (az_result_failed(core_result))
2720     {
2721 
2722         /* Topic name does not match C2D format.  */
2723         return(NX_AZURE_IOT_NOT_FOUND);
2724     }
2725 
2726     status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr,
2727                                                          packet_ptr,
2728                                                          NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE,
2729                                                          0, &thread_list_ptr);
2730     if (status == NX_AZURE_IOT_SUCCESS)
2731     {
2732         tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
2733         return(NX_AZURE_IOT_SUCCESS);
2734     }
2735 
2736     /* No thread is waiting for C2D message yet.  */
2737     nx_azure_iot_hub_client_message_notify(hub_client_ptr,
2738                                            &(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message),
2739                                            packet_ptr);
2740 
2741     return(NX_AZURE_IOT_SUCCESS);
2742 }
2743 
nx_azure_iot_hub_client_command_process(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,ULONG topic_offset,USHORT topic_length)2744 static UINT nx_azure_iot_hub_client_command_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2745                                                     NX_PACKET *packet_ptr,
2746                                                     ULONG topic_offset,
2747                                                     USHORT topic_length)
2748 {
2749 UCHAR *topic_name;
2750 az_iot_hub_client_command_request request;
2751 az_span receive_topic;
2752 az_result core_result;
2753 UINT status;
2754 NX_AZURE_IOT_THREAD *thread_list_ptr;
2755 
2756     /* This function is protected by MQTT mutex.  */
2757 
2758     /* Check message type first.  */
2759     topic_name = &(packet_ptr -> nx_packet_prepend_ptr[topic_offset]);
2760 
2761     /* NOTE: Current implementation does not support topic to span multiple packets.  */
2762     if ((ULONG)(packet_ptr -> nx_packet_append_ptr - topic_name) < topic_length)
2763     {
2764         LogError(LogLiteralArgs("topic out of boundaries of single packet"));
2765         return(NX_AZURE_IOT_TOPIC_TOO_LONG);
2766     }
2767 
2768     receive_topic = az_span_create(topic_name, topic_length);
2769     core_result = az_iot_hub_client_commands_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core),
2770                                                                   receive_topic, &request);
2771     if (az_result_failed(core_result))
2772     {
2773 
2774         /* Topic name does not match direct method format.  */
2775         return(NX_AZURE_IOT_NOT_FOUND);
2776     }
2777 
2778     status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr,
2779                                                          packet_ptr,
2780                                                          NX_AZURE_IOT_HUB_COMMAND,
2781                                                          0, &thread_list_ptr);
2782     if (status == NX_AZURE_IOT_SUCCESS)
2783     {
2784         tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
2785         return(NX_AZURE_IOT_SUCCESS);
2786     }
2787 
2788     /* No thread is waiting for direct method message yet.  */
2789     nx_azure_iot_hub_client_message_notify(hub_client_ptr,
2790                                            &(hub_client_ptr -> nx_azure_iot_hub_client_command_message),
2791                                            packet_ptr);
2792     return(NX_AZURE_IOT_SUCCESS);
2793 }
2794 
nx_azure_iot_hub_client_properties_message_type_get(UINT core_message_type,UINT request_id)2795 static UINT nx_azure_iot_hub_client_properties_message_type_get(UINT core_message_type, UINT request_id)
2796 {
2797 UINT message_type;
2798 
2799     switch (core_message_type)
2800     {
2801         case AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_GET_RESPONSE :
2802 
2803         /* Fall through.  */
2804 
2805         case AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_ACKNOWLEDGEMENT :
2806         {
2807 
2808             /* Odd requests are of reported properties and even of twin properties.  */
2809             message_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_PROPERTIES : NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE;
2810         }
2811         break;
2812 
2813         case AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_WRITABLE_UPDATED :
2814         {
2815             message_type = NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES;
2816         }
2817         break;
2818 
2819         default :
2820         {
2821             message_type = NX_AZURE_IOT_HUB_NONE;
2822         }
2823     }
2824 
2825     return message_type;
2826 }
2827 
nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,ULONG topic_offset,USHORT topic_length,UINT * request_id_ptr,ULONG * version_ptr,UINT * message_type_ptr,UINT * status_ptr)2828 static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2829                                                       NX_PACKET *packet_ptr, ULONG topic_offset,
2830                                                       USHORT topic_length, UINT *request_id_ptr,
2831                                                       ULONG *version_ptr, UINT *message_type_ptr,
2832                                                       UINT *status_ptr)
2833 {
2834 az_result core_result;
2835 az_span topic_span;
2836 az_iot_hub_client_twin_response out_twin_response;
2837 uint32_t request_id = 0;
2838 uint32_t version;
2839 
2840     topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), (INT)topic_length);
2841     core_result = az_iot_hub_client_twin_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core),
2842                                                               topic_span, &out_twin_response);
2843     if (az_result_failed(core_result))
2844     {
2845         return(NX_AZURE_IOT_SDK_CORE_ERROR);
2846     }
2847 
2848     if (version_ptr != NX_NULL && az_span_ptr(out_twin_response.version))
2849     {
2850         core_result = az_span_atou32(out_twin_response.version, &version);
2851         if (az_result_failed(core_result))
2852         {
2853             return(NX_AZURE_IOT_SDK_CORE_ERROR);
2854         }
2855 
2856         *version_ptr = (ULONG)version;
2857     }
2858 
2859     if (az_span_ptr(out_twin_response.request_id))
2860     {
2861         core_result = az_span_atou32(out_twin_response.request_id, &request_id);
2862         if (az_result_failed(core_result))
2863         {
2864             return(NX_AZURE_IOT_SDK_CORE_ERROR);
2865         }
2866     }
2867 
2868     if (request_id_ptr)
2869     {
2870         *request_id_ptr = (UINT)request_id;
2871     }
2872 
2873     if (message_type_ptr)
2874     {
2875         *message_type_ptr = nx_azure_iot_hub_client_properties_message_type_get((UINT)out_twin_response.response_type,
2876                                                                                 (UINT)request_id);
2877     }
2878 
2879     if (status_ptr)
2880     {
2881         *status_ptr = (UINT)out_twin_response.status;
2882     }
2883 
2884     return(NX_AZURE_IOT_SUCCESS);
2885 }
2886 
nx_azure_iot_hub_client_properties_process(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_PACKET * packet_ptr,ULONG topic_offset,USHORT topic_length)2887 static UINT nx_azure_iot_hub_client_properties_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
2888                                                        NX_PACKET *packet_ptr,
2889                                                        ULONG topic_offset,
2890                                                        USHORT topic_length)
2891 {
2892 NX_AZURE_IOT_THREAD *thread_list_ptr;
2893 UINT message_type;
2894 UINT response_status;
2895 UINT request_id = 0;
2896 ULONG version = 0;
2897 UINT correlation_id;
2898 UINT status;
2899 ULONG current_time;
2900 
2901     /* This function is protected by MQTT mutex. */
2902     if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, packet_ptr,
2903                                                             topic_offset, topic_length,
2904                                                             &request_id, &version,
2905                                                             &message_type, &response_status)))
2906     {
2907         return(status);
2908     }
2909 
2910     if (response_status == NX_AZURE_IOT_HUB_CLIENT_THROTTLE_STATUS_CODE)
2911     {
2912         if ((status = nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, &current_time)))
2913         {
2914             LogError(LogLiteralArgs("IoTHub client fail to get unix time: %d"), status);
2915             return(status);
2916         }
2917 
2918         hub_client_ptr -> nx_azure_iot_hub_client_throttle_end_time =
2919             current_time + nx_azure_iot_hub_client_throttle_with_jitter(hub_client_ptr);
2920     }
2921     else
2922     {
2923         hub_client_ptr -> nx_azure_iot_hub_client_throttle_count = 0;
2924         hub_client_ptr -> nx_azure_iot_hub_client_throttle_end_time = 0;
2925     }
2926 
2927     if (message_type == NX_AZURE_IOT_HUB_NONE)
2928     {
2929         LogError(LogLiteralArgs("IoTHub client fail to parse device twin: %d"), NX_AZURE_IOT_SERVER_RESPONSE_ERROR);
2930         return(NX_AZURE_IOT_SERVER_RESPONSE_ERROR);
2931     }
2932     else if (message_type == NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE)
2933     {
2934 
2935         /* Only requested thread should be woken.  */
2936         correlation_id = request_id;
2937     }
2938     else
2939     {
2940 
2941         /* Any thread can be woken.  */
2942         correlation_id = 0;
2943 
2944         /* Process system component.  */
2945         if ((hub_client_ptr -> nx_azure_iot_hub_client_component_properties_process) &&
2946             ((response_status >= 200) && (response_status < 300)))
2947         {
2948             hub_client_ptr -> nx_azure_iot_hub_client_component_properties_process(hub_client_ptr, packet_ptr, message_type);
2949         }
2950     }
2951 
2952     status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr,
2953                                                          packet_ptr,
2954                                                          message_type,
2955                                                          correlation_id, &thread_list_ptr);
2956     if (status == NX_AZURE_IOT_SUCCESS)
2957     {
2958         tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
2959         return(NX_AZURE_IOT_SUCCESS);
2960     }
2961 
2962     switch(message_type)
2963     {
2964         case NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE :
2965         {
2966             if (hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback)
2967             {
2968                 hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback(hub_client_ptr,
2969                                                                                               request_id,
2970                                                                                               response_status,
2971                                                                                               version,
2972                                                                                               hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback_args);
2973             }
2974 
2975             nx_packet_release(packet_ptr);
2976         }
2977         break;
2978 
2979         case NX_AZURE_IOT_HUB_PROPERTIES :
2980         {
2981 
2982             /* No thread is waiting for device twin message yet.  */
2983             nx_azure_iot_hub_client_message_notify(hub_client_ptr,
2984                                                    &(hub_client_ptr -> nx_azure_iot_hub_client_properties_message),
2985                                                    packet_ptr);
2986         }
2987         break;
2988 
2989         case NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES :
2990         {
2991 
2992             /* No thread is waiting for device twin message yet.  */
2993             nx_azure_iot_hub_client_message_notify(hub_client_ptr,
2994                                                    &(hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message),
2995                                                    packet_ptr);
2996         }
2997         break;
2998 
2999         default :
3000             nx_packet_release(packet_ptr);
3001     }
3002 
3003     return(NX_AZURE_IOT_SUCCESS);
3004 }
3005 
nx_azure_iot_hub_client_thread_dequeue(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,NX_AZURE_IOT_THREAD * thread_list_ptr)3006 static VOID nx_azure_iot_hub_client_thread_dequeue(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
3007                                                    NX_AZURE_IOT_THREAD *thread_list_ptr)
3008 {
3009 NX_AZURE_IOT_THREAD *thread_list_prev = NX_NULL;
3010 NX_AZURE_IOT_THREAD *thread_list_current;
3011 
3012     for (thread_list_current = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended;
3013          thread_list_current;
3014          thread_list_current = thread_list_current -> thread_next)
3015     {
3016         if (thread_list_current == thread_list_ptr)
3017         {
3018 
3019             /* Found the thread to dequeue.  */
3020             if (thread_list_prev == NX_NULL)
3021             {
3022                 hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = thread_list_current -> thread_next;
3023             }
3024             else
3025             {
3026                 thread_list_prev -> thread_next = thread_list_current -> thread_next;
3027             }
3028             break;
3029         }
3030 
3031         thread_list_prev = thread_list_current;
3032     }
3033 }
3034 
nx_azure_iot_hub_client_sas_token_get(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,ULONG expiry_time_secs,const UCHAR * key,UINT key_len,UCHAR * sas_buffer,UINT sas_buffer_len,UINT * sas_length)3035 static UINT nx_azure_iot_hub_client_sas_token_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
3036                                                   ULONG expiry_time_secs, const UCHAR *key, UINT key_len,
3037                                                   UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length)
3038 {
3039 UCHAR *buffer_ptr;
3040 UINT buffer_size;
3041 VOID *buffer_context;
3042 az_span span = az_span_create(sas_buffer, (INT)sas_buffer_len);
3043 az_span buffer_span;
3044 UINT status;
3045 UCHAR *output_ptr;
3046 UINT output_len;
3047 az_result core_result;
3048 
3049     status = nx_azure_iot_buffer_allocate(hub_client_ptr -> nx_azure_iot_ptr, &buffer_ptr, &buffer_size, &buffer_context);
3050     if (status)
3051     {
3052         LogError(LogLiteralArgs("IoTHub client sas token fail: BUFFER ALLOCATE FAIL"));
3053         return(status);
3054     }
3055 
3056     core_result = az_iot_hub_client_sas_get_signature(&(hub_client_ptr -> iot_hub_client_core),
3057                                                       expiry_time_secs, span, &span);
3058     if (az_result_failed(core_result))
3059     {
3060         LogError(LogLiteralArgs("IoTHub failed failed to get signature with error status: %d"), core_result);
3061         nx_azure_iot_buffer_free(buffer_context);
3062         return(NX_AZURE_IOT_SDK_CORE_ERROR);
3063     }
3064 
3065     status = nx_azure_iot_base64_hmac_sha256_calculate(&(hub_client_ptr -> nx_azure_iot_hub_client_resource),
3066                                                        key, key_len, az_span_ptr(span), (UINT)az_span_size(span),
3067                                                        buffer_ptr, buffer_size, &output_ptr, &output_len);
3068     if (status)
3069     {
3070         LogError(LogLiteralArgs("IoTHub failed to encoded hash"));
3071         nx_azure_iot_buffer_free(buffer_context);
3072         return(status);
3073     }
3074 
3075     buffer_span = az_span_create(output_ptr, (INT)output_len);
3076     core_result= az_iot_hub_client_sas_get_password(&(hub_client_ptr -> iot_hub_client_core),
3077                                                     expiry_time_secs, buffer_span, AZ_SPAN_EMPTY,
3078                                                     (CHAR *)sas_buffer, sas_buffer_len, (size_t *)&sas_buffer_len);
3079     if (az_result_failed(core_result))
3080     {
3081         LogError(LogLiteralArgs("IoTHub failed to generate token with error status: %d"), core_result);
3082         nx_azure_iot_buffer_free(buffer_context);
3083         return(NX_AZURE_IOT_SDK_CORE_ERROR);
3084     }
3085 
3086     *sas_length = sas_buffer_len;
3087     nx_azure_iot_buffer_free(buffer_context);
3088 
3089     return(NX_AZURE_IOT_SUCCESS);
3090 }
3091 
nx_azure_iot_hub_client_command_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)3092 UINT nx_azure_iot_hub_client_command_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
3093 {
3094 UINT status;
3095 
3096     if (hub_client_ptr == NX_NULL)
3097     {
3098         LogError(LogLiteralArgs("IoTHub client command subscribe fail: INVALID POINTER"));
3099         return(NX_AZURE_IOT_INVALID_PARAMETER);
3100     }
3101 
3102     tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
3103 
3104     /* Atomically update the handler as we need to serialize the handler with incoming messages.  */
3105     hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process = nx_azure_iot_hub_client_command_process;
3106     hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_enable = nx_azure_iot_hub_client_command_enable;
3107 
3108     /* Register callbacks even if not connect and when connect complete subscribe for topics.  */
3109     if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED)
3110     {
3111         tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
3112         return(NX_AZURE_IOT_SUCCESS);
3113     }
3114 
3115     tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
3116 
3117     status = nxd_mqtt_client_subscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
3118                                        AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC,
3119                                        sizeof(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC) - 1,
3120                                        NX_AZURE_IOT_MQTT_QOS_0);
3121     if (status)
3122     {
3123         LogError(LogLiteralArgs("IoTHub client command subscribe fail %d"), status);
3124         return(status);
3125     }
3126 
3127     return(NX_AZURE_IOT_SUCCESS);
3128 }
3129 
nx_azure_iot_hub_client_command_disable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)3130 UINT nx_azure_iot_hub_client_command_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
3131 {
3132 UINT status;
3133 
3134     if (hub_client_ptr == NX_NULL)
3135     {
3136         LogError(LogLiteralArgs("IoTHub client command unsubscribe fail: INVALID POINTER"));
3137         return(NX_AZURE_IOT_INVALID_PARAMETER);
3138     }
3139 
3140     status = nxd_mqtt_client_unsubscribe(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
3141                                          AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC,
3142                                          sizeof(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC) - 1);
3143     if (status)
3144     {
3145         LogError(LogLiteralArgs("IoTHub client command unsubscribe fail status: %d"), status);
3146         return(status);
3147     }
3148 
3149     hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process = NX_NULL;
3150 
3151     return(NX_AZURE_IOT_SUCCESS);
3152 }
3153 
nx_azure_iot_hub_client_command_message_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR ** component_name_pptr,USHORT * component_name_length_ptr,const UCHAR ** command_name_pptr,USHORT * command_name_length_ptr,VOID ** context_pptr,USHORT * context_length_ptr,NX_PACKET ** packet_pptr,UINT wait_option)3154 UINT nx_azure_iot_hub_client_command_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
3155                                                      const UCHAR **component_name_pptr, USHORT *component_name_length_ptr,
3156                                                      const UCHAR **command_name_pptr, USHORT *command_name_length_ptr,
3157                                                      VOID **context_pptr, USHORT *context_length_ptr,
3158                                                      NX_PACKET **packet_pptr, UINT wait_option)
3159 {
3160 
3161 UINT status;
3162 ULONG topic_offset = 0;
3163 USHORT topic_length = 0;
3164 az_span topic_span;
3165 NX_PACKET *packet_ptr = NX_NULL;
3166 az_result core_result;
3167 az_iot_hub_client_command_request request;
3168 
3169     if ((hub_client_ptr == NX_NULL) ||
3170         (command_name_pptr == NX_NULL) ||
3171         (command_name_length_ptr == NX_NULL) ||
3172         (context_pptr == NX_NULL) ||
3173         (context_length_ptr == NX_NULL) ||
3174         (packet_pptr == NX_NULL))
3175     {
3176         LogError(LogLiteralArgs("IoT PnP client command receive fail: INVALID POINTER"));
3177         return(NX_AZURE_IOT_INVALID_PARAMETER);
3178     }
3179 
3180     status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_COMMAND,
3181                                                      &(hub_client_ptr -> nx_azure_iot_hub_client_command_message),
3182                                                      &packet_ptr, wait_option);
3183     if (status)
3184     {
3185         return(status);
3186     }
3187 
3188     status = nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, &topic_length);
3189     if (status)
3190     {
3191         nx_packet_release(packet_ptr);
3192         return(status);
3193     }
3194 
3195     topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), topic_length);
3196     core_result = az_iot_hub_client_commands_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core),
3197                                                                   topic_span, &request);
3198     if (az_result_failed(core_result))
3199     {
3200         nx_packet_release(packet_ptr);
3201         return(NX_AZURE_IOT_SDK_CORE_ERROR);
3202     }
3203 
3204     if ((status = nx_azure_iot_hub_client_adjust_payload(packet_ptr)))
3205     {
3206         nx_packet_release(packet_ptr);
3207         return(status);
3208     }
3209 
3210     *packet_pptr = packet_ptr;
3211     if ((component_name_pptr) && (component_name_length_ptr))
3212     {
3213         *component_name_pptr = (const UCHAR *)az_span_ptr(request.component_name);
3214         *component_name_length_ptr = (USHORT)az_span_size(request.component_name);
3215     }
3216     *command_name_pptr = (const UCHAR *)az_span_ptr(request.command_name);
3217     *command_name_length_ptr = (USHORT)az_span_size(request.command_name);
3218     *context_pptr = (VOID*)az_span_ptr(request.request_id);
3219     *context_length_ptr =  (USHORT)az_span_size(request.request_id);
3220 
3221     return(NX_AZURE_IOT_SUCCESS);
3222 }
3223 
nx_azure_iot_hub_client_command_message_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT status_code,VOID * context_ptr,USHORT context_length,const UCHAR * payload,UINT payload_length,UINT wait_option)3224 UINT nx_azure_iot_hub_client_command_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
3225                                                       UINT status_code, VOID *context_ptr,
3226                                                       USHORT context_length, const UCHAR *payload,
3227                                                       UINT payload_length, UINT wait_option)
3228 {
3229 NX_PACKET *packet_ptr;
3230 UINT topic_length;
3231 az_span request_id_span;
3232 UINT status;
3233 az_result core_result;
3234 
3235     if ((hub_client_ptr == NX_NULL) ||
3236         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
3237         (context_ptr == NX_NULL) ||
3238         (context_length == 0))
3239     {
3240         LogError(LogLiteralArgs("IoTHub client command response fail: INVALID POINTER"));
3241         return(NX_AZURE_IOT_INVALID_PARAMETER);
3242     }
3243 
3244     /* Prepare response packet.  */
3245     status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr,
3246                                              &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
3247                                              &packet_ptr, wait_option);
3248     if (status)
3249     {
3250         LogError(LogLiteralArgs("Create response data fail"));
3251         return(status);
3252     }
3253 
3254     topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
3255     request_id_span = az_span_create((UCHAR*)context_ptr, (INT)context_length);
3256     core_result = az_iot_hub_client_commands_response_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core),
3257                                                                         request_id_span, (USHORT)status_code,
3258                                                                         (CHAR *)packet_ptr -> nx_packet_prepend_ptr,
3259                                                                         topic_length, (size_t *)&topic_length);
3260     if (az_result_failed(core_result))
3261     {
3262         LogError(LogLiteralArgs("Failed to create the command response topic"));
3263         nx_packet_release(packet_ptr);
3264         return(NX_AZURE_IOT_SDK_CORE_ERROR);
3265     }
3266 
3267     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length;
3268     packet_ptr -> nx_packet_length = topic_length;
3269 
3270     if (payload && (payload_length != 0))
3271     {
3272 
3273         /* Append payload.  */
3274         status = nx_packet_data_append(packet_ptr, (VOID *)payload, payload_length,
3275                                        packet_ptr -> nx_packet_pool_owner,
3276                                        wait_option);
3277         if (status)
3278         {
3279             LogError(LogLiteralArgs("Command response data append fail"));
3280             nx_packet_release(packet_ptr);
3281             return(status);
3282         }
3283     }
3284     else
3285     {
3286 
3287         /* Append payload.  */
3288         status = nx_packet_data_append(packet_ptr, NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON,
3289                                        sizeof(NX_AZURE_IOT_HUB_CLIENT_EMPTY_JSON) - 1,
3290                                        packet_ptr -> nx_packet_pool_owner,
3291                                        wait_option);
3292         if (status)
3293         {
3294             LogError(LogLiteralArgs("Adding empty json failed."));
3295             nx_packet_release(packet_ptr);
3296             return(status);
3297         }
3298     }
3299 
3300     status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt),
3301                                               packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0,
3302                                               wait_option);
3303     if (status)
3304     {
3305         LogError(LogLiteralArgs("IoTHub client command response fail: PUBLISH FAIL status: %d"), status);
3306         nx_packet_release(packet_ptr);
3307         return(status);
3308     }
3309 
3310     return(NX_AZURE_IOT_SUCCESS);
3311 }
3312 
nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)3313 UINT nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
3314 {
3315 
3316     if (hub_client_ptr == NX_NULL)
3317     {
3318         LogError(LogLiteralArgs("IoTHub client direct method subscribe fail: INVALID POINTER"));
3319         return(NX_AZURE_IOT_INVALID_PARAMETER);
3320     }
3321 
3322     return(nx_azure_iot_hub_client_command_enable(hub_client_ptr));
3323 }
3324 
nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr)3325 UINT nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)
3326 {
3327 
3328     if (hub_client_ptr == NX_NULL)
3329     {
3330         LogError(LogLiteralArgs("IoTHub client direct method unsubscribe fail: INVALID POINTER"));
3331         return(NX_AZURE_IOT_INVALID_PARAMETER);
3332     }
3333 
3334     return(nx_azure_iot_hub_client_command_disable(hub_client_ptr));
3335 }
3336 
nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,const UCHAR ** method_name_pptr,USHORT * method_name_length_ptr,VOID ** context_pptr,USHORT * context_length_ptr,NX_PACKET ** packet_pptr,UINT wait_option)3337 UINT nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
3338                                                            const UCHAR **method_name_pptr, USHORT *method_name_length_ptr,
3339                                                            VOID **context_pptr, USHORT *context_length_ptr,
3340                                                            NX_PACKET **packet_pptr, UINT wait_option)
3341 {
3342 
3343     if ((hub_client_ptr == NX_NULL) ||
3344         (method_name_pptr == NX_NULL) ||
3345         (method_name_length_ptr == NX_NULL) ||
3346         (context_pptr == NX_NULL) ||
3347         (context_length_ptr == NX_NULL) ||
3348         (packet_pptr == NX_NULL))
3349     {
3350         LogError(LogLiteralArgs("IoTHub client direct method receive fail: INVALID POINTER"));
3351         return(NX_AZURE_IOT_INVALID_PARAMETER);
3352     }
3353 
3354     return(nx_azure_iot_hub_client_command_message_receive(hub_client_ptr, NX_NULL, NX_NULL,
3355                                                            method_name_pptr, method_name_length_ptr,
3356                                                            context_pptr, context_length_ptr,
3357                                                            packet_pptr, wait_option));
3358 }
3359 
nx_azure_iot_hub_client_direct_method_message_response(NX_AZURE_IOT_HUB_CLIENT * hub_client_ptr,UINT status_code,VOID * context_ptr,USHORT context_length,const UCHAR * payload,UINT payload_length,UINT wait_option)3360 UINT nx_azure_iot_hub_client_direct_method_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr,
3361                                                             UINT status_code, VOID *context_ptr,
3362                                                             USHORT context_length, const UCHAR *payload,
3363                                                             UINT payload_length, UINT wait_option)
3364 {
3365 
3366     if ((hub_client_ptr == NX_NULL) ||
3367         (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
3368         (context_ptr == NX_NULL) ||
3369         (context_length == 0))
3370     {
3371         LogError(LogLiteralArgs("IoTHub direct method response fail: INVALID POINTER"));
3372         return(NX_AZURE_IOT_INVALID_PARAMETER);
3373     }
3374 
3375     return(nx_azure_iot_hub_client_command_message_response(hub_client_ptr, status_code,
3376                                                             context_ptr, context_length,
3377                                                             payload, payload_length,
3378                                                             wait_option));
3379 }
3380