1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 #include "nx_azure_iot_provisioning_client.h"
12 
13 #include "azure/core/az_span.h"
14 
15 /* Define AZ IoT Provisioning Client state.  */
16 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_NONE                  0
17 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT                  1
18 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_CONNECT               2
19 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_SUBSCRIBE             3
20 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_REQUEST               4
21 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_WAITING_FOR_RESPONSE  5
22 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE                  6
23 #define NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_ERROR                 7
24 
25 /* Define AZ IoT Provisioning Client topic format.  */
26 #define NX_AZURE_IOT_PROVISIONING_CLIENT_REG_SUB_TOPIC                "$dps/registrations/res/#"
27 #define NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_START                "{\"registrationId\" : \""
28 #define NX_AZURE_IOT_PROVISIONING_CLIENT_QUOTE                        "\""
29 #define NX_AZURE_IOT_PROVISIONING_CLIENT_CUSTOM_PAYLOAD                ", \"payload\" : "
30 #define NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_END                  "}"
31 #define NX_AZURE_IOT_PROVISIONING_CLIENT_POLICY_NAME                  "registration"
32 
33 #define NX_AZURE_IOT_PROVISIONING_CLIENT_WEB_SOCKET_PATH              "/$iothub/websocket"
34 
35 /* Set the default retry to Provisioning service.  */
36 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_DEFAULT_RETRY
37 #define NX_AZURE_IOT_PROVISIONING_CLIENT_DEFAULT_RETRY                (3)
38 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_DEFAULT_RETRY */
39 
40 /* Set default PROVISIONING CLIENT wait option.  */
41 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_WAIT_OPTION
42 #define NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_WAIT_OPTION          (NX_NO_WAIT)
43 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_WAIT_OPTION */
44 
45 static UINT nx_azure_iot_provisioning_client_connect_internal(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
46                                                               UINT wait_option);
47 static VOID nx_azure_iot_provisioning_client_mqtt_receive_callback(NXD_MQTT_CLIENT *client_ptr,
48                                                                    UINT number_of_messages);
49 static VOID nx_azure_iot_provisioning_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr);
50 static UINT nx_azure_iot_provisioning_client_send_req(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
51                                                       az_iot_provisioning_client_register_response const *register_response,
52                                                       UINT wait_option);
53 static VOID nx_azure_iot_provisioning_client_event_process(NX_AZURE_IOT *nx_azure_iot_ptr,
54                                                            ULONG common_events, ULONG module_own_events);
55 static VOID nx_azure_iot_provisioning_client_update_state(NX_AZURE_IOT_PROVISIONING_CLIENT *context, UINT action_result);
56 
57 extern UINT _nxd_mqtt_process_publish_packet(NX_PACKET *packet_ptr, ULONG *topic_offset_ptr, USHORT *topic_length_ptr,
58                                              ULONG *message_offset_ptr, ULONG *message_length_ptr);
59 
nx_azure_iot_provisioning_client_process_message(NX_AZURE_IOT_PROVISIONING_CLIENT * context,NX_PACKET * packet_ptr,NX_AZURE_IOT_PROVISIONING_RESPONSE * response)60 static UINT nx_azure_iot_provisioning_client_process_message(NX_AZURE_IOT_PROVISIONING_CLIENT *context, NX_PACKET *packet_ptr,
61                                                              NX_AZURE_IOT_PROVISIONING_RESPONSE *response)
62 {
63 ULONG topic_offset;
64 USHORT topic_length;
65 ULONG message_offset;
66 ULONG message_length;
67 az_span received_topic;
68 az_span received_payload;
69 az_result core_result;
70 UINT status;
71 
72     status = _nxd_mqtt_process_publish_packet(packet_ptr, &topic_offset, &topic_length,
73                                               &message_offset, &message_length);
74     if (status)
75     {
76         return(status);
77     }
78 
79     if ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) <
80         (message_offset + message_length))
81     {
82         LogError(LogLiteralArgs("IoTProvisioning client failed to parse chained packet"));
83         return(NX_AZURE_IOT_MESSAGE_TOO_LONG);
84     }
85 
86     received_topic = az_span_create(packet_ptr -> nx_packet_prepend_ptr + topic_offset, (INT)topic_length);
87     received_payload = az_span_create(packet_ptr -> nx_packet_prepend_ptr + message_offset, (INT)message_length);
88     core_result =
89       az_iot_provisioning_client_parse_received_topic_and_payload(&(context -> nx_azure_iot_provisioning_client_core),
90                                                                   received_topic, received_payload,
91                                                                   &response -> register_response);
92     if (az_result_failed(core_result))
93     {
94         LogError(LogLiteralArgs("IoTProvisioning client failed to parse packet, error status: %d"), core_result);
95         return(NX_AZURE_IOT_SDK_CORE_ERROR);
96     }
97 
98     response -> packet_ptr = packet_ptr;
99 
100     return(NX_AZURE_IOT_SUCCESS);
101 }
102 
nx_azure_iot_provisioning_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT * client_ptr)103 static VOID nx_azure_iot_provisioning_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr)
104 {
105 UINT status;
106 NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr);
107 NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr = NX_NULL;
108 
109     /* This function is protected by MQTT mutex.  */
110 
111     if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING))
112     {
113         prov_client_ptr = (NX_AZURE_IOT_PROVISIONING_CLIENT *)resource -> resource_data_ptr;
114     }
115 
116     /* Set disconnect event.  */
117     if (prov_client_ptr)
118     {
119         status = nx_cloud_module_event_set(&(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
120                                            NX_AZURE_IOT_PROVISIONING_CLIENT_DISCONNECT_EVENT);
121         if (status)
122         {
123             nx_azure_iot_provisioning_client_update_state(prov_client_ptr, status);
124         }
125     }
126 }
127 
nx_azure_iot_provisioning_client_connect_internal(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,UINT wait_option)128 static UINT nx_azure_iot_provisioning_client_connect_internal(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
129                                                               UINT wait_option)
130 {
131 
132 UINT status;
133 NXD_ADDRESS server_address;
134 NXD_MQTT_CLIENT *mqtt_client_ptr;
135 NX_AZURE_IOT_RESOURCE *resource_ptr;
136 UINT server_port;
137 
138     /* Resolve the host name.  */
139     status = nxd_dns_host_by_name_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_dns_ptr,
140                                       (UCHAR *)prov_client_ptr -> nx_azure_iot_provisioning_client_endpoint,
141                                       &server_address, NX_AZURE_IOT_PROVISIONING_CLIENT_DNS_TIMEOUT,
142                                       NX_IP_VERSION_V4);
143     if (status)
144     {
145         LogError(LogLiteralArgs("IoTProvisioning client connect fail: DNS RESOLVE FAIL status: %d"), status);
146         return(status);
147     }
148 
149     /* Set MQTT Client.  */
150     resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource);
151     mqtt_client_ptr = &(resource_ptr -> resource_mqtt);
152 
153     /* Set login info.  */
154     if (resource_ptr -> resource_mqtt_sas_token_length == 0)
155     {
156 
157         /* X509 authentication. Set NULL for password.  */
158         status = nxd_mqtt_client_login_set(mqtt_client_ptr, (CHAR *)resource_ptr -> resource_mqtt_user_name,
159                                         resource_ptr -> resource_mqtt_user_name_length,
160                                         NX_NULL, 0);
161     }
162     else
163     {
164         status = nxd_mqtt_client_login_set(mqtt_client_ptr, (CHAR *)resource_ptr -> resource_mqtt_user_name,
165                                         resource_ptr -> resource_mqtt_user_name_length,
166                                         (CHAR *)resource_ptr -> resource_mqtt_sas_token,
167                                         resource_ptr -> resource_mqtt_sas_token_length);
168     }
169 
170     if (status)
171     {
172         LogError(LogLiteralArgs("IoTProvisioning client connect fail: MQTT CLIENT LOGIN SET FAIL status: %d"), status);
173         return(status);
174     }
175 
176 #ifdef NXD_MQTT_OVER_WEBSOCKET
177     if (mqtt_client_ptr -> nxd_mqtt_client_use_websocket == NX_TRUE)
178     {
179         server_port = NXD_MQTT_OVER_WEBSOCKET_TLS_PORT;
180     }
181     else
182     {
183         server_port = NXD_MQTT_TLS_PORT;
184     }
185 #else
186     server_port = NXD_MQTT_TLS_PORT;
187 #endif /* NXD_MQTT_OVER_WEBSOCKET */
188 
189     /* Start MQTT connection.  */
190     status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, server_port,
191                                             nx_azure_iot_mqtt_tls_setup, NX_AZURE_IOT_MQTT_KEEP_ALIVE,
192                                             NX_FALSE, wait_option);
193 
194     if ((wait_option == NX_NO_WAIT) && (status == NX_IN_PROGRESS))
195     {
196         LogInfo(LogLiteralArgs("IoTProvisioning client connect pending"));
197         return(NX_AZURE_IOT_SUCCESS);
198     }
199 
200     /* Check status.  */
201     if (status != NX_AZURE_IOT_SUCCESS)
202     {
203         LogError(LogLiteralArgs("IoTProvisioning client connect fail: MQTT CONNECT FAIL status: %d"), status);
204         return(status);
205     }
206 
207     return(NX_AZURE_IOT_SUCCESS);
208 }
209 
nx_azure_iot_provisioning_client_mqtt_receive_callback(NXD_MQTT_CLIENT * client_ptr,UINT number_of_messages)210 static VOID nx_azure_iot_provisioning_client_mqtt_receive_callback(NXD_MQTT_CLIENT *client_ptr,
211                                                                    UINT number_of_messages)
212 {
213 NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr);
214 NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr = NX_NULL;
215 NX_PACKET *packet_ptr;
216 NX_PACKET *packet_next_ptr;
217 UINT status;
218 
219     /* This function is protected by MQTT mutex.  */
220 
221     NX_PARAMETER_NOT_USED(number_of_messages);
222 
223     if (resource && (resource -> resource_type == NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING))
224     {
225         prov_client_ptr = (NX_AZURE_IOT_PROVISIONING_CLIENT *)resource -> resource_data_ptr;
226     }
227 
228     if (prov_client_ptr)
229     {
230         for (packet_ptr = client_ptr -> message_receive_queue_head;
231             packet_ptr;
232             packet_ptr = packet_next_ptr)
233         {
234 
235             /* Store next packet in case current packet is consumed.  */
236             packet_next_ptr = packet_ptr -> nx_packet_queue_next;
237 
238             /* Adjust packet to simply process logic.  */
239             nx_azure_iot_mqtt_packet_adjust(packet_ptr);
240 
241             /* Last response was not yet consumed, probably duplicate from service.  */
242             if (prov_client_ptr -> nx_azure_iot_provisioning_client_last_response)
243             {
244                 nx_packet_release(packet_ptr);
245                 continue;
246             }
247 
248             prov_client_ptr -> nx_azure_iot_provisioning_client_last_response = packet_ptr;
249             status = nx_cloud_module_event_set(&(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
250                                                NX_AZURE_IOT_PROVISIONING_CLIENT_RESPONSE_EVENT);
251             if (status)
252             {
253                 nx_azure_iot_provisioning_client_update_state(prov_client_ptr, status);
254             }
255         }
256 
257         /* Clear all message from MQTT receive queue.  */
258         client_ptr -> message_receive_queue_head = NX_NULL;
259         client_ptr -> message_receive_queue_tail = NX_NULL;
260         client_ptr -> message_receive_queue_depth = 0;
261     }
262 }
263 
264 /**
265  *  State transitions :
266  *      INIT -> {CONNECT|ERROR} -> {REQUEST|ERROR} -> {WAITING_FOR_REPONSE|ERROR} -> {DONE|REQUEST|ERROR}
267  **/
nx_azure_iot_provisioning_client_update_state(NX_AZURE_IOT_PROVISIONING_CLIENT * context,UINT action_result)268 static VOID nx_azure_iot_provisioning_client_update_state(NX_AZURE_IOT_PROVISIONING_CLIENT *context,
269                                                           UINT action_result)
270 {
271 UINT state = context -> nx_azure_iot_provisioning_client_state;
272 NX_AZURE_IOT_PROVISIONING_THREAD *thread_list_ptr;
273 
274     LogDebug(LogLiteralArgs("Action result in state %d"), state);
275     LogDebug(LogLiteralArgs("status : %d"), action_result);
276 
277     context -> nx_azure_iot_provisioning_client_result = action_result;
278 
279     if (action_result == NX_AZURE_IOT_PENDING)
280     {
281         switch (state)
282         {
283             case NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT :
284             {
285                 context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_CONNECT;
286             }
287             break;
288 
289             case NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_CONNECT :
290             {
291                 context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_SUBSCRIBE;
292             }
293             break;
294 
295             case NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_SUBSCRIBE :
296             {
297                 context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_REQUEST;
298             }
299             break;
300 
301             case NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_REQUEST :
302             {
303                 context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_WAITING_FOR_RESPONSE;
304             }
305             break;
306 
307             case NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_WAITING_FOR_RESPONSE :
308             {
309                 context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_REQUEST;
310             }
311             break;
312 
313             default :
314             {
315                 LogError(LogLiteralArgs("Unknown state: %d"), state);
316             }
317             break;
318         }
319     }
320     else
321     {
322         if (action_result == NX_AZURE_IOT_SUCCESS)
323         {
324             context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE;
325         }
326         else
327         {
328             context -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_ERROR;
329         }
330 
331         /* Wake up all threads.  */
332         for (thread_list_ptr = context -> nx_azure_iot_provisioning_client_thread_suspended;
333              thread_list_ptr;
334              thread_list_ptr = thread_list_ptr -> thread_next)
335         {
336             tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
337         }
338 
339         /* Delete the list.  */
340         context -> nx_azure_iot_provisioning_client_thread_suspended = NULL;
341 
342         /* Notify completion if required.  */
343         if (context -> nx_azure_iot_provisioning_client_on_complete_callback)
344         {
345             context -> nx_azure_iot_provisioning_client_on_complete_callback(context, context -> nx_azure_iot_provisioning_client_result);
346         }
347     }
348 }
349 
nx_azure_iot_provisioning_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT * client_ptr,UINT status,VOID * context)350 static VOID nx_azure_iot_provisioning_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr,
351                                                                  UINT status, VOID *context)
352 {
353 
354 NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr = (NX_AZURE_IOT_PROVISIONING_CLIENT*)context;
355 
356     NX_PARAMETER_NOT_USED(client_ptr);
357 
358     /* Mutex might got deleted by deinitialization.  */
359     if (tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER))
360     {
361         return;
362     }
363 
364     /* Update hub client status.  */
365     if (status == NXD_MQTT_SUCCESS)
366     {
367         if (prov_client_ptr -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_CONNECT)
368         {
369             nx_azure_iot_provisioning_client_update_state(prov_client_ptr, NX_AZURE_IOT_PENDING);
370             status = nx_cloud_module_event_set(&(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
371                                                NX_AZURE_IOT_PROVISIONING_CLIENT_SUBSCRIBE_EVENT);
372             if (status)
373             {
374                 nx_azure_iot_provisioning_client_update_state(prov_client_ptr, status);
375             }
376         }
377     }
378     else
379     {
380         status = nx_cloud_module_event_set(&(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
381                                            NX_AZURE_IOT_PROVISIONING_CLIENT_DISCONNECT_EVENT);
382         if (status)
383         {
384             nx_azure_iot_provisioning_client_update_state(prov_client_ptr, status);
385         }
386     }
387     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
388 }
389 
nx_azure_iot_provisioning_client_process_connect(NX_AZURE_IOT_PROVISIONING_CLIENT * context)390 static VOID nx_azure_iot_provisioning_client_process_connect(NX_AZURE_IOT_PROVISIONING_CLIENT *context)
391 {
392 UINT status;
393 
394     /* Check the state.  */
395     if (context -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_CONNECT)
396     {
397         context -> nx_azure_iot_provisioning_client_resource.resource_mqtt.nxd_mqtt_connect_notify =
398             nx_azure_iot_provisioning_client_mqtt_connect_notify;
399         context -> nx_azure_iot_provisioning_client_resource.resource_mqtt.nxd_mqtt_connect_context = context;
400 
401         /* Start connect.  */
402         status = nx_azure_iot_provisioning_client_connect_internal(context, NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_WAIT_OPTION);
403 
404         if (status)
405         {
406             nx_azure_iot_provisioning_client_update_state(context, status);
407         }
408     }
409 }
410 
nx_azure_iot_provisioning_client_process_timer(NX_AZURE_IOT_PROVISIONING_CLIENT * context)411 static VOID nx_azure_iot_provisioning_client_process_timer(NX_AZURE_IOT_PROVISIONING_CLIENT *context)
412 {
413 UINT status;
414 
415     if (context -> nx_azure_iot_provisioning_client_req_timeout == 0)
416     {
417         return;
418     }
419 
420     /* Trigger Request.  */
421     if (context -> nx_azure_iot_provisioning_client_req_timeout == 1)
422     {
423 
424         /* Set request event.  */
425         status = nx_cloud_module_event_set(&(context -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
426                                            NX_AZURE_IOT_PROVISIONING_CLIENT_REQUEST_EVENT);
427         if (status)
428         {
429             nx_azure_iot_provisioning_client_update_state(context, status);
430         }
431     }
432 
433     context -> nx_azure_iot_provisioning_client_req_timeout--;
434 }
435 
nx_azure_iot_provisioning_client_subscribe(NX_AZURE_IOT_PROVISIONING_CLIENT * context)436 static VOID nx_azure_iot_provisioning_client_subscribe(NX_AZURE_IOT_PROVISIONING_CLIENT *context)
437 {
438 UINT status;
439 
440     /* Check the state.  */
441     if (context -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_SUBSCRIBE)
442     {
443 
444         /* Subscribe topic.  */
445         status = nxd_mqtt_client_subscribe(&(context -> nx_azure_iot_provisioning_client_resource.resource_mqtt),
446                                            NX_AZURE_IOT_PROVISIONING_CLIENT_REG_SUB_TOPIC,
447                                            sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_REG_SUB_TOPIC) - 1, 0);
448 
449         if (status)
450         {
451             nx_azure_iot_provisioning_client_update_state(context, status);
452         }
453         else
454         {
455             nx_azure_iot_provisioning_client_update_state(context, NX_AZURE_IOT_PENDING);
456             status = nx_cloud_module_event_set(&(context -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
457                                                NX_AZURE_IOT_PROVISIONING_CLIENT_REQUEST_EVENT);
458             if (status)
459             {
460                 nx_azure_iot_provisioning_client_update_state(context, status);
461             }
462         }
463     }
464 }
465 
nx_azure_iot_provisioning_client_generate_service_request(NX_AZURE_IOT_PROVISIONING_CLIENT * context)466 static VOID nx_azure_iot_provisioning_client_generate_service_request(NX_AZURE_IOT_PROVISIONING_CLIENT *context)
467 {
468 UINT status;
469 
470     /* Check the state.  */
471     if (context -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_REQUEST)
472     {
473         if (context -> nx_azure_iot_provisioning_client_response.packet_ptr)
474         {
475 
476             /* Request status of existing operationId.  */
477             status = nx_azure_iot_provisioning_client_send_req(context,
478                                                                &(context -> nx_azure_iot_provisioning_client_response.register_response),
479                                                                NX_NO_WAIT);
480             nx_packet_release(context -> nx_azure_iot_provisioning_client_response.packet_ptr);
481 
482             context -> nx_azure_iot_provisioning_client_response.packet_ptr = NULL;
483         }
484         else
485         {
486 
487             /* Start new operation.  */
488             status = nx_azure_iot_provisioning_client_send_req(context, NULL, NX_NO_WAIT);
489         }
490 
491         if (status)
492         {
493             nx_azure_iot_provisioning_client_update_state(context, status);
494         }
495         else
496         {
497             nx_azure_iot_provisioning_client_update_state(context, NX_AZURE_IOT_PENDING);
498         }
499     }
500 }
501 
nx_azure_iot_provisioning_client_process_service_response(NX_AZURE_IOT_PROVISIONING_CLIENT * context)502 static VOID nx_azure_iot_provisioning_client_process_service_response(NX_AZURE_IOT_PROVISIONING_CLIENT *context)
503 {
504 NX_PACKET *packet_ptr;
505 az_iot_provisioning_client_register_response *response;
506 
507     /* Check the state.  */
508     if (context -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_WAITING_FOR_RESPONSE)
509     {
510 
511         packet_ptr = context -> nx_azure_iot_provisioning_client_last_response;
512         context -> nx_azure_iot_provisioning_client_last_response = NULL;
513 
514         context -> nx_azure_iot_provisioning_client_result =
515             nx_azure_iot_provisioning_client_process_message(context, packet_ptr,
516                                                              &context -> nx_azure_iot_provisioning_client_response);
517         if (context -> nx_azure_iot_provisioning_client_result)
518         {
519             nx_packet_release(packet_ptr);
520             nx_azure_iot_provisioning_client_update_state(context, context -> nx_azure_iot_provisioning_client_result);
521             return;
522         }
523 
524         response = &(context -> nx_azure_iot_provisioning_client_response.register_response);
525         if (response -> operation_status == AZ_IOT_PROVISIONING_STATUS_ASSIGNED)
526         {
527             nx_azure_iot_provisioning_client_update_state(context, NX_AZURE_IOT_SUCCESS);
528         }
529         else if (response -> retry_after_seconds == 0)
530         {
531             LogError(LogLiteralArgs("Registration failed with dPS response: operation status = %d"),
532                      response -> operation_status);
533             LogError(LogLiteralArgs("Registration error track id = %s"),
534                      az_span_ptr(response -> registration_state.error_tracking_id),
535                      (UINT)az_span_size(response -> registration_state.error_tracking_id));
536 
537             /* Server responded with error with no retry.  */
538             nx_azure_iot_provisioning_client_update_state(context, NX_AZURE_IOT_SERVER_RESPONSE_ERROR);
539         }
540         else
541         {
542             nx_azure_iot_provisioning_client_update_state(context, NX_AZURE_IOT_PENDING);
543             context -> nx_azure_iot_provisioning_client_req_timeout = response -> retry_after_seconds;
544         }
545     }
546 }
547 
nx_azure_iot_provisioning_client_process_disconnect(NX_AZURE_IOT_PROVISIONING_CLIENT * context)548 static VOID nx_azure_iot_provisioning_client_process_disconnect(NX_AZURE_IOT_PROVISIONING_CLIENT *context)
549 {
550 
551     /* Check the state and only allow disconnect event to be processed in non-complete state.  */
552     if (context -> nx_azure_iot_provisioning_client_state > NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT &&
553         context -> nx_azure_iot_provisioning_client_state < NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE)
554     {
555         nx_azure_iot_provisioning_client_update_state(context, NX_AZURE_IOT_DISCONNECTED);
556     }
557 }
558 
nx_azure_iot_provisioning_client_append_device_reg_payload(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,NX_PACKET * packet_ptr,UINT wait_option)559 static UINT nx_azure_iot_provisioning_client_append_device_reg_payload(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
560                                                                        NX_PACKET *packet_ptr, UINT wait_option)
561 {
562 UINT status;
563 
564     if ((status = nx_packet_data_append(packet_ptr, NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_START,
565                                         sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_START) - 1,
566                                         packet_ptr -> nx_packet_pool_owner,
567                                         wait_option)))
568     {
569         LogError(LogLiteralArgs("failed to append data registration payload"));
570         return(status);
571     }
572 
573     if ((status = nx_packet_data_append(packet_ptr, (VOID *)prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id,
574                                         prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id_length,
575                                         packet_ptr -> nx_packet_pool_owner,
576                                         wait_option)))
577     {
578         LogError(LogLiteralArgs("failed to append data registration payload"));
579         return(status);
580     }
581 
582    if ((status = nx_packet_data_append(packet_ptr, NX_AZURE_IOT_PROVISIONING_CLIENT_QUOTE,
583                                        sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_QUOTE) - 1,
584                                        packet_ptr -> nx_packet_pool_owner,
585                                        wait_option)))
586     {
587         LogError(LogLiteralArgs("failed to append data"));
588         return(status);
589     }
590 
591     if (prov_client_ptr -> nx_azure_iot_provisioning_client_registration_payload != NX_NULL)
592     {
593         if ((status = nx_packet_data_append(packet_ptr, NX_AZURE_IOT_PROVISIONING_CLIENT_CUSTOM_PAYLOAD,
594                                             sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_CUSTOM_PAYLOAD) - 1,
595                                             packet_ptr -> nx_packet_pool_owner,
596                                             wait_option)))
597         {
598             LogError(LogLiteralArgs("failed to append data registration custom payload"));
599             return(status);
600         }
601 
602         if ((status = nx_packet_data_append(packet_ptr,
603                                             (VOID *)prov_client_ptr -> nx_azure_iot_provisioning_client_registration_payload,
604                                             prov_client_ptr -> nx_azure_iot_provisioning_client_registration_payload_length,
605                                             packet_ptr -> nx_packet_pool_owner,
606                                             wait_option)))
607         {
608             LogError(LogLiteralArgs("failed to append data registration custom payload"));
609             return(status);
610         }
611     }
612 
613     if ((status = nx_packet_data_append(packet_ptr, NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_END,
614                                         sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_END) - 1,
615                                         packet_ptr -> nx_packet_pool_owner,
616                                         wait_option)))
617     {
618         LogError(LogLiteralArgs("failed to append data registration end"));
619     }
620 
621     return(status);
622 }
623 
nx_azure_iot_provisioning_client_send_req(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,az_iot_provisioning_client_register_response const * register_response,UINT wait_option)624 static UINT nx_azure_iot_provisioning_client_send_req(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
625                                                       az_iot_provisioning_client_register_response const *register_response,
626                                                       UINT wait_option)
627 {
628 NX_PACKET *packet_ptr;
629 UCHAR *buffer_ptr;
630 UINT buffer_size;
631 UCHAR packet_id[2];
632 UINT status;
633 UINT mqtt_topic_length;
634 az_result core_result;
635 
636     status = nx_azure_iot_publish_packet_get(prov_client_ptr -> nx_azure_iot_ptr,
637                                              &prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt,
638                                              &packet_ptr, wait_option);
639 
640     if (status)
641     {
642         LogError(LogLiteralArgs("IoTProvisioning request buffer creation failed"));
643         return(status);
644     }
645 
646     buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
647     buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr);
648 
649     status = nx_azure_iot_mqtt_packet_id_get(&(prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt),
650                                              packet_id);
651     if (status)
652     {
653         LogError(LogLiteralArgs("failed to get packetId "));
654         nx_packet_release(packet_ptr);
655         return(status);
656     }
657 
658     /* if no registration response or operation Id is missing, send new registration request. */
659     if ((register_response == NULL) ||
660         (az_span_size(register_response -> operation_id) == 0))
661     {
662         core_result = az_iot_provisioning_client_register_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
663                                                                             (CHAR *)buffer_ptr, buffer_size,
664                                                                             (size_t *)&mqtt_topic_length);
665     }
666     else
667     {
668         core_result = az_iot_provisioning_client_query_status_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
669                                                                                 register_response -> operation_id, (CHAR *)buffer_ptr,
670                                                                                 buffer_size,
671                                                                                 (size_t *)&mqtt_topic_length);
672     }
673 
674     if (az_result_failed(core_result))
675     {
676         LogError(LogLiteralArgs("failed to get topic, error status: %d"), core_result);
677         nx_packet_release(packet_ptr);
678         return(NX_AZURE_IOT_SDK_CORE_ERROR);
679     }
680 
681     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + mqtt_topic_length;
682     packet_ptr -> nx_packet_length += mqtt_topic_length;
683 
684     status = nx_packet_data_append(packet_ptr, packet_id, sizeof(packet_id),
685                                    packet_ptr -> nx_packet_pool_owner,
686                                    wait_option);
687     if (status)
688     {
689         LogError(LogLiteralArgs("failed to append data packet id"));
690         nx_packet_release(packet_ptr);
691         return(status);
692     }
693 
694     status = nx_azure_iot_provisioning_client_append_device_reg_payload(prov_client_ptr,
695                                                                         packet_ptr, wait_option);
696     if (status)
697     {
698         LogError(LogLiteralArgs("failed to add device registration data"));
699         nx_packet_release(packet_ptr);
700         return(status);
701     }
702 
703     status = nx_azure_iot_publish_mqtt_packet(&(prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt),
704                                               packet_ptr, mqtt_topic_length, packet_id, NX_AZURE_IOT_MQTT_QOS_1,
705                                               wait_option);
706 
707     if (status)
708     {
709         LogError(LogLiteralArgs("failed to publish packet"));
710         nx_packet_release(packet_ptr);
711         return(status);
712     }
713 
714     return(NX_AZURE_IOT_SUCCESS);
715 }
716 
nx_azure_iot_provisioning_client_thread_dequeue(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,NX_AZURE_IOT_PROVISIONING_THREAD * node)717 static VOID nx_azure_iot_provisioning_client_thread_dequeue(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
718                                                             NX_AZURE_IOT_PROVISIONING_THREAD *node)
719 {
720 NX_AZURE_IOT_PROVISIONING_THREAD *thread_list_ptr;
721 NX_AZURE_IOT_PROVISIONING_THREAD *thread_list_prev = NX_NULL;
722 
723     for (thread_list_ptr = prov_client_ptr -> nx_azure_iot_provisioning_client_thread_suspended;
724          thread_list_ptr;
725          thread_list_prev = thread_list_ptr, thread_list_ptr = thread_list_ptr -> thread_next)
726     {
727         if (thread_list_ptr == node)
728         {
729             if (thread_list_prev == NX_NULL)
730             {
731                 prov_client_ptr -> nx_azure_iot_provisioning_client_thread_suspended =
732                     thread_list_ptr -> thread_next;
733             }
734             else
735             {
736                 thread_list_prev -> thread_next = thread_list_ptr -> thread_next;
737             }
738 
739             break;
740         }
741     }
742 }
743 
nx_azure_iot_provisioning_client_sas_token_get(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,ULONG expiry_time_secs)744 static UINT nx_azure_iot_provisioning_client_sas_token_get(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
745                                                            ULONG expiry_time_secs)
746 {
747 UCHAR *buffer_ptr;
748 UINT buffer_size;
749 VOID *buffer_context;
750 UINT status;
751 NX_AZURE_IOT_RESOURCE *resource_ptr;
752 UCHAR *output_ptr;
753 UINT output_len;
754 az_span span;
755 az_result core_result;
756 az_span buffer_span;
757 az_span policy_name = AZ_SPAN_LITERAL_FROM_STR(NX_AZURE_IOT_PROVISIONING_CLIENT_POLICY_NAME);
758 
759     resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource);
760     span = az_span_create(resource_ptr -> resource_mqtt_sas_token,
761                           (INT)prov_client_ptr -> nx_azure_iot_provisioning_client_sas_token_buff_size);
762 
763     status = nx_azure_iot_buffer_allocate(prov_client_ptr -> nx_azure_iot_ptr,
764                                           &buffer_ptr, &buffer_size,
765                                           &buffer_context);
766     if (status)
767     {
768         LogError(LogLiteralArgs("IoTProvisioning client sas token fail: BUFFER ALLOCATE FAIL"));
769         return(status);
770     }
771 
772     core_result = az_iot_provisioning_client_sas_get_signature(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
773                                                                expiry_time_secs, span, &span);
774 
775     if (az_result_failed(core_result))
776     {
777         LogError(LogLiteralArgs("IoTProvisioning failed failed to get signature with error status: %d"), core_result);
778         nx_azure_iot_buffer_free(buffer_context);
779         return(NX_AZURE_IOT_SDK_CORE_ERROR);
780     }
781 
782     status = nx_azure_iot_base64_hmac_sha256_calculate(resource_ptr,
783                                                        prov_client_ptr -> nx_azure_iot_provisioning_client_symmetric_key,
784                                                        prov_client_ptr -> nx_azure_iot_provisioning_client_symmetric_key_length,
785                                                        az_span_ptr(span), (UINT)az_span_size(span), buffer_ptr, buffer_size,
786                                                        &output_ptr, &output_len);
787     if (status)
788     {
789         LogError(LogLiteralArgs("IoTProvisioning failed to encoded hash"));
790         nx_azure_iot_buffer_free(buffer_context);
791         return(status);
792     }
793 
794     buffer_span = az_span_create(output_ptr, (INT)output_len);
795     core_result = az_iot_provisioning_client_sas_get_password(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
796                                                               buffer_span, expiry_time_secs, policy_name,
797                                                               (CHAR *)resource_ptr -> resource_mqtt_sas_token,
798                                                               prov_client_ptr -> nx_azure_iot_provisioning_client_sas_token_buff_size,
799                                                               (size_t *)&(resource_ptr -> resource_mqtt_sas_token_length));
800     if (az_result_failed(core_result))
801     {
802         LogError(LogLiteralArgs("IoTProvisioning failed to generate token with error : %d"), core_result);
803         nx_azure_iot_buffer_free(buffer_context);
804         return(NX_AZURE_IOT_SDK_CORE_ERROR);
805     }
806 
807     nx_azure_iot_buffer_free(buffer_context);
808 
809     return(NX_AZURE_IOT_SUCCESS);
810 }
811 
812 /* Define the prototypes for Azure RTOS IoT.  */
nx_azure_iot_provisioning_client_initialize(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,NX_AZURE_IOT * nx_azure_iot_ptr,const UCHAR * endpoint,UINT endpoint_length,const UCHAR * id_scope,UINT id_scope_length,const UCHAR * registration_id,UINT registration_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)813 UINT nx_azure_iot_provisioning_client_initialize(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
814                                                  NX_AZURE_IOT *nx_azure_iot_ptr,
815                                                  const UCHAR *endpoint, UINT endpoint_length,
816                                                  const UCHAR *id_scope, UINT id_scope_length,
817                                                  const UCHAR *registration_id, UINT registration_id_length,
818                                                  const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size,
819                                                  const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size,
820                                                  UCHAR *metadata_memory, UINT memory_size,
821                                                  NX_SECURE_X509_CERT *trusted_certificate)
822 {
823 UINT status;
824 UINT mqtt_user_name_length;
825 NXD_MQTT_CLIENT *mqtt_client_ptr;
826 NX_AZURE_IOT_RESOURCE *resource_ptr;
827 UCHAR *buffer_ptr;
828 UINT buffer_size;
829 VOID *buffer_context;
830 az_span endpoint_span = az_span_create((UCHAR *)endpoint, (INT)endpoint_length);
831 az_span id_scope_span = az_span_create((UCHAR *)id_scope, (INT)id_scope_length);
832 az_span registration_id_span = az_span_create((UCHAR *)registration_id, (INT)registration_id_length);
833 
834     if ((nx_azure_iot_ptr == NX_NULL) || (prov_client_ptr == NX_NULL) || (endpoint == NX_NULL) ||
835         (id_scope == NX_NULL) || (registration_id == NX_NULL) || (endpoint_length == 0) ||
836         (id_scope_length == 0) || (registration_id_length == 0))
837     {
838         LogError(LogLiteralArgs("IoTProvisioning client initialize fail: INVALID POINTER"));
839         return(NX_AZURE_IOT_INVALID_PARAMETER);
840     }
841 
842     /* Obtain the mutex.   */
843     tx_mutex_get(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
844 
845     memset(prov_client_ptr, 0, sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT));
846 
847     /* Set resource pointer.  */
848     resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource);
849     mqtt_client_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt);
850 
851     prov_client_ptr -> nx_azure_iot_ptr = nx_azure_iot_ptr;
852     prov_client_ptr -> nx_azure_iot_provisioning_client_endpoint = endpoint;
853     prov_client_ptr -> nx_azure_iot_provisioning_client_endpoint_length = endpoint_length;
854     prov_client_ptr -> nx_azure_iot_provisioning_client_id_scope = id_scope;
855     prov_client_ptr -> nx_azure_iot_provisioning_client_id_scope_length = id_scope_length;
856     prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id = registration_id;
857     prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id_length = registration_id_length;
858     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_crypto_array = crypto_array;
859     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_crypto_array_size = crypto_array_size;
860     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_cipher_map = cipher_map;
861     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_cipher_map_size = cipher_map_size;
862     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_metadata_ptr = metadata_memory;
863     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_metadata_size = memory_size;
864     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_trusted_certificates[0] = trusted_certificate;
865     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_hostname = endpoint;
866     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_hostname_length = endpoint_length;
867     resource_ptr -> resource_mqtt_client_id_length = prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id_length;
868     resource_ptr -> resource_mqtt_client_id = (UCHAR *)prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id;
869 
870     if (az_result_failed(az_iot_provisioning_client_init(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
871                                                          endpoint_span, id_scope_span,
872                                                          registration_id_span, NULL)))
873     {
874          LogError(LogLiteralArgs("IoTProvisioning client initialize fail: failed to initialize core client"));
875         return(NX_AZURE_IOT_SDK_CORE_ERROR);
876     }
877 
878     status = _nxd_mqtt_client_cloud_create(mqtt_client_ptr, (CHAR *)nx_azure_iot_ptr -> nx_azure_iot_name,
879                                            (CHAR *)resource_ptr -> resource_mqtt_client_id,
880                                            resource_ptr -> resource_mqtt_client_id_length,
881                                            nx_azure_iot_ptr -> nx_azure_iot_ip_ptr,
882                                            nx_azure_iot_ptr -> nx_azure_iot_pool_ptr,
883                                            &nx_azure_iot_ptr -> nx_azure_iot_cloud);
884     if (status)
885     {
886 
887         /* Release the mutex.  */
888         tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
889         LogError(LogLiteralArgs("IoTProvisioning initialize create fail: MQTT CLIENT CREATE FAIL status: %d"), status);
890         return(status);
891     }
892 
893     status = nxd_mqtt_client_receive_notify_set(mqtt_client_ptr,
894                                                 nx_azure_iot_provisioning_client_mqtt_receive_callback);
895     if (status)
896     {
897 
898         /* Release the mutex.  */
899         tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
900         LogError(LogLiteralArgs("IoTProvisioning client set message callback status: %d"), status);
901         nxd_mqtt_client_delete(mqtt_client_ptr);
902         return(status);
903     }
904 
905     status = nx_azure_iot_buffer_allocate(prov_client_ptr -> nx_azure_iot_ptr,
906                                           &buffer_ptr, &buffer_size, &buffer_context);
907     if (status)
908     {
909 
910         /* Release the mutex.  */
911         tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
912         LogError(LogLiteralArgs("IoTProvisioning client failed initialization: BUFFER ALLOCATE FAIL"));
913         nxd_mqtt_client_delete(mqtt_client_ptr);
914         return(status);
915     }
916 
917     /* Build user name.  */
918     if (az_result_failed(az_iot_provisioning_client_get_user_name(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core),
919                                                                   (CHAR *)buffer_ptr, buffer_size,
920                                                                   (size_t *)&mqtt_user_name_length)))
921     {
922         LogError(LogLiteralArgs("IoTProvisioning client connect fail: NX_AZURE_IOT_Provisioning_CLIENT_USERNAME_SIZE is too small."));
923         nx_azure_iot_buffer_free(buffer_context);
924         nxd_mqtt_client_delete(mqtt_client_ptr);
925         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
926     }
927 
928     /* Save the resource buffer.  */
929     resource_ptr -> resource_mqtt_buffer_context = buffer_context;
930     resource_ptr -> resource_mqtt_buffer_size = buffer_size;
931     resource_ptr -> resource_mqtt_user_name_length = mqtt_user_name_length;
932     resource_ptr -> resource_mqtt_user_name = buffer_ptr;
933     resource_ptr -> resource_mqtt_sas_token = buffer_ptr + mqtt_user_name_length;
934     prov_client_ptr -> nx_azure_iot_provisioning_client_sas_token_buff_size = buffer_size - mqtt_user_name_length;
935 
936     /* Link the resource.  */
937     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_data_ptr = (VOID *)prov_client_ptr;
938     prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_type = NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING;
939     nx_azure_iot_resource_add(nx_azure_iot_ptr, &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource));
940 
941     /* Set event processing routine.  */
942     nx_azure_iot_ptr -> nx_azure_iot_provisioning_client_event_process = nx_azure_iot_provisioning_client_event_process;
943 
944     /* Update state.  */
945     prov_client_ptr -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT;
946 
947     /* Release the mutex.  */
948     tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
949 
950     return(NX_AZURE_IOT_SUCCESS);
951 }
952 
nx_azure_iot_provisioning_client_deinitialize(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr)953 UINT nx_azure_iot_provisioning_client_deinitialize(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr)
954 {
955 NX_AZURE_IOT_PROVISIONING_THREAD *thread_list_ptr;
956 UINT status;
957 
958     /* Check for invalid input pointers.  */
959     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL))
960     {
961         LogError(LogLiteralArgs("IoTProvisioning client deinitialize fail: INVALID POINTER"));
962         return(NX_AZURE_IOT_INVALID_PARAMETER);
963     }
964 
965     /* Obtain the mutex.  */
966     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
967 
968     if ((prov_client_ptr -> nx_azure_iot_provisioning_client_state > NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT &&
969          prov_client_ptr -> nx_azure_iot_provisioning_client_state < NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE))
970     {
971 
972         /* Wake up all the threads.  */
973         for (thread_list_ptr = prov_client_ptr -> nx_azure_iot_provisioning_client_thread_suspended;
974              thread_list_ptr;
975              thread_list_ptr = thread_list_ptr -> thread_next)
976         {
977             tx_thread_wait_abort(thread_list_ptr -> thread_ptr);
978         }
979 
980         /* Delete the list.  */
981         prov_client_ptr -> nx_azure_iot_provisioning_client_thread_suspended = NULL;
982     }
983 
984     /* Force to error state.  */
985     prov_client_ptr -> nx_azure_iot_provisioning_client_state = NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_ERROR;
986     prov_client_ptr -> nx_azure_iot_provisioning_client_on_complete_callback = NULL;
987 
988     if (prov_client_ptr -> nx_azure_iot_provisioning_client_last_response)
989     {
990         nx_packet_release(prov_client_ptr -> nx_azure_iot_provisioning_client_last_response);
991         prov_client_ptr -> nx_azure_iot_provisioning_client_last_response = NULL;
992     }
993 
994     if (prov_client_ptr -> nx_azure_iot_provisioning_client_response.packet_ptr)
995     {
996         nx_packet_release(prov_client_ptr -> nx_azure_iot_provisioning_client_response.packet_ptr);
997         prov_client_ptr -> nx_azure_iot_provisioning_client_response.packet_ptr = NULL;
998     }
999 
1000     /* Release the mqtt connection resource.  */
1001     if (prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt_buffer_context)
1002     {
1003         nx_azure_iot_buffer_free(prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt_buffer_context);
1004         prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt_buffer_context = NX_NULL;
1005     }
1006 
1007     /* Release the mutex.  */
1008     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1009 
1010     /* Disconnect.  */
1011     nxd_mqtt_client_disconnect(&prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt);
1012 
1013     /* Delete the client.  */
1014     nxd_mqtt_client_delete(&prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt);
1015 
1016     /* Obtain the mutex.  */
1017     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1018 
1019     /* Remove resource from list.  */
1020     status = nx_azure_iot_resource_remove(prov_client_ptr -> nx_azure_iot_ptr, &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource));
1021 
1022     if (status)
1023     {
1024 
1025         /* Release the mutex.  */
1026         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1027         LogError(LogLiteralArgs("IoTProvisioning client handle not found"));
1028         return(status);
1029     }
1030 
1031     /* Release the mutex.  */
1032     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1033 
1034     return(NX_AZURE_IOT_SUCCESS);
1035 }
1036 
nx_azure_iot_provisioning_client_trusted_cert_add(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,NX_SECURE_X509_CERT * trusted_certificate)1037 UINT nx_azure_iot_provisioning_client_trusted_cert_add(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
1038                                                        NX_SECURE_X509_CERT *trusted_certificate)
1039 {
1040 UINT i;
1041 NX_AZURE_IOT_RESOURCE *resource_ptr;
1042 
1043     if ((prov_client_ptr == NX_NULL) ||
1044         (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
1045         (trusted_certificate == NX_NULL))
1046     {
1047         LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER"));
1048         return(NX_AZURE_IOT_INVALID_PARAMETER);
1049     }
1050 
1051     /* Obtain the mutex.  */
1052     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER);
1053 
1054     resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource);
1055     for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates); i++)
1056     {
1057         if (resource_ptr -> resource_trusted_certificates[i] == NX_NULL)
1058         {
1059             resource_ptr -> resource_trusted_certificates[i] = trusted_certificate;
1060             break;
1061         }
1062     }
1063 
1064     /* Release the mutex.  */
1065     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1066 
1067     if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates))
1068     {
1069         return(NX_AZURE_IOT_SUCCESS);
1070     }
1071     else
1072     {
1073 
1074         /* No more space to store trusted certificate.  */
1075         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
1076     }
1077 }
1078 
nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,NX_SECURE_X509_CERT * x509_cert)1079 UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
1080                                                       NX_SECURE_X509_CERT *x509_cert)
1081 {
1082 UINT i;
1083 NX_AZURE_IOT_RESOURCE *resource_ptr;
1084 
1085     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL) || (x509_cert == NX_NULL))
1086     {
1087         LogError(LogLiteralArgs("IoTProvisioning device cert set fail: INVALID POINTER"));
1088         return(NX_AZURE_IOT_INVALID_PARAMETER);
1089     }
1090 
1091     /* Obtain the mutex.  */
1092     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1093 
1094     resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource);
1095     for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates); i++)
1096     {
1097         if (resource_ptr -> resource_device_certificates[i] == NX_NULL)
1098         {
1099             resource_ptr -> resource_device_certificates[i] = x509_cert;
1100             break;
1101         }
1102     }
1103 
1104     /* Release the mutex.  */
1105     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1106 
1107     if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates))
1108     {
1109         return(NX_AZURE_IOT_SUCCESS);
1110     }
1111     else
1112     {
1113 
1114         /* No more space to store device certificate.  */
1115         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
1116     }
1117 }
1118 
1119 #ifdef NXD_MQTT_OVER_WEBSOCKET
nx_azure_iot_provisioning_client_websocket_enable(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr)1120 UINT nx_azure_iot_provisioning_client_websocket_enable(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr)
1121 {
1122 NX_AZURE_IOT_RESOURCE *resource_ptr;
1123 
1124     if (prov_client_ptr == NX_NULL)
1125     {
1126         LogError(LogLiteralArgs("IoTProvisioning client WebSocket enable fail: INVALID POINTER"));
1127         return(NX_AZURE_IOT_INVALID_PARAMETER);
1128     }
1129 
1130     /* Set resource pointer.  */
1131     resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource);
1132 
1133     return(nxd_mqtt_client_websocket_set(&(resource_ptr -> resource_mqtt), (UCHAR *)resource_ptr -> resource_hostname, resource_ptr -> resource_hostname_length,
1134                                          (UCHAR *)NX_AZURE_IOT_PROVISIONING_CLIENT_WEB_SOCKET_PATH, sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_WEB_SOCKET_PATH) - 1));
1135 }
1136 #endif /* NXD_MQTT_OVER_WEBSOCKET */
1137 
nx_azure_iot_provisioning_client_event_process(NX_AZURE_IOT * nx_azure_iot_ptr,ULONG common_events,ULONG module_own_events)1138 static VOID nx_azure_iot_provisioning_client_event_process(NX_AZURE_IOT *nx_azure_iot_ptr,
1139                                                            ULONG common_events, ULONG module_own_events)
1140 {
1141 NX_AZURE_IOT_RESOURCE *resource;
1142 NX_AZURE_IOT_PROVISIONING_CLIENT *provisioning_client;
1143 
1144     /* Process module own events.  */
1145     LogDebug(LogLiteralArgs("Event generated common event: %d"), common_events);
1146     LogDebug(LogLiteralArgs("module event: %d"), module_own_events);
1147 
1148     /* Obtain the mutex.  */
1149     tx_mutex_get(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1150 
1151     /* Loop to check IoT Provisioning Client.  */
1152     for (resource = nx_azure_iot_ptr -> nx_azure_iot_resource_list_header; resource;
1153          resource = resource -> resource_next)
1154     {
1155         if (resource -> resource_type != NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING)
1156         {
1157             continue;
1158         }
1159 
1160         /* Set provisioning client pointer.  */
1161         provisioning_client = (NX_AZURE_IOT_PROVISIONING_CLIENT *)resource -> resource_data_ptr;
1162 
1163         NX_ASSERT(provisioning_client != NX_NULL);
1164 
1165         if (common_events & NX_CLOUD_COMMON_PERIODIC_EVENT)
1166         {
1167             nx_azure_iot_provisioning_client_process_timer(provisioning_client);
1168         }
1169 
1170         if (module_own_events & NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_EVENT)
1171         {
1172             nx_azure_iot_provisioning_client_process_connect(provisioning_client);
1173         }
1174 
1175         if (module_own_events & NX_AZURE_IOT_PROVISIONING_CLIENT_SUBSCRIBE_EVENT)
1176         {
1177             nx_azure_iot_provisioning_client_subscribe(provisioning_client);
1178         }
1179 
1180         if (module_own_events & NX_AZURE_IOT_PROVISIONING_CLIENT_RESPONSE_EVENT)
1181         {
1182             nx_azure_iot_provisioning_client_process_service_response(provisioning_client);
1183         }
1184 
1185         if (module_own_events & NX_AZURE_IOT_PROVISIONING_CLIENT_REQUEST_EVENT)
1186         {
1187             nx_azure_iot_provisioning_client_generate_service_request(provisioning_client);
1188         }
1189 
1190         if (module_own_events & NX_AZURE_IOT_PROVISIONING_CLIENT_DISCONNECT_EVENT)
1191         {
1192             nx_azure_iot_provisioning_client_process_disconnect(provisioning_client);
1193         }
1194     }
1195 
1196     /* Release the mutex.  */
1197     tx_mutex_put(nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1198 }
1199 
nx_azure_iot_provisioning_client_register(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,UINT wait_option)1200 UINT nx_azure_iot_provisioning_client_register(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, UINT wait_option)
1201 {
1202 NX_AZURE_IOT_PROVISIONING_THREAD thread_list;
1203 UINT old_threshold;
1204 UINT status;
1205 
1206     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL))
1207     {
1208         LogError(LogLiteralArgs("IoTProvisioning register fail: INVALID POINTER"));
1209         return(NX_AZURE_IOT_INVALID_PARAMETER);
1210     }
1211 
1212     if (prov_client_ptr -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_NONE)
1213     {
1214         LogError(LogLiteralArgs("IoTProvisioning register fail: not intialized"));
1215         return(NX_AZURE_IOT_NOT_INITIALIZED);
1216     }
1217 
1218     /* Set callback function for disconnection.  */
1219     nxd_mqtt_client_disconnect_notify_set(&(prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt),
1220                                           nx_azure_iot_provisioning_client_mqtt_disconnect_notify);
1221 
1222     /* Obtain the mutex.  */
1223     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1224 
1225     if (prov_client_ptr -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT)
1226     {
1227 
1228         /* Update state in user thread under mutex.  */
1229         nx_azure_iot_provisioning_client_update_state(prov_client_ptr, NX_AZURE_IOT_PENDING);
1230 
1231         /* Trigger workflow.  */
1232         status = nx_cloud_module_event_set(&(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
1233                                            NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_EVENT);
1234         if (status)
1235         {
1236             nx_azure_iot_provisioning_client_update_state(prov_client_ptr, status);
1237         }
1238     }
1239 
1240     if (wait_option)
1241     {
1242         if (prov_client_ptr -> nx_azure_iot_provisioning_client_state > NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT &&
1243              prov_client_ptr -> nx_azure_iot_provisioning_client_state < NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE)
1244         {
1245             thread_list.thread_next = prov_client_ptr -> nx_azure_iot_provisioning_client_thread_suspended;
1246             thread_list.thread_ptr = tx_thread_identify();
1247             prov_client_ptr -> nx_azure_iot_provisioning_client_thread_suspended = &thread_list;
1248 
1249             /* Disable preemption.  */
1250             tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
1251 
1252             /* Release the mutex.  */
1253             tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1254 
1255             tx_thread_sleep(wait_option);
1256 
1257             /* Obtain the mutex.  */
1258             tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1259 
1260             /* Restore preemption.  */
1261             tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
1262 
1263             nx_azure_iot_provisioning_client_thread_dequeue(prov_client_ptr, &thread_list);
1264         }
1265     }
1266 
1267     if (prov_client_ptr -> nx_azure_iot_provisioning_client_state > NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_INIT &&
1268          prov_client_ptr -> nx_azure_iot_provisioning_client_state < NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE)
1269     {
1270 
1271         /* Release the mutex.  */
1272         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1273         return(NX_AZURE_IOT_PENDING);
1274     }
1275     else if (prov_client_ptr -> nx_azure_iot_provisioning_client_state == NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_ERROR)
1276     {
1277 
1278         /* Release the mutex.  */
1279         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1280         LogError(LogLiteralArgs("IoTProvisioning register fail: Error out"));
1281         return(prov_client_ptr -> nx_azure_iot_provisioning_client_result);
1282     }
1283 
1284     /* Release the mutex.  */
1285     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1286 
1287     return(NX_AZURE_IOT_SUCCESS);
1288 }
1289 
nx_azure_iot_provisioning_client_completion_callback_set(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,VOID (* on_complete_callback)(struct NX_AZURE_IOT_PROVISIONING_CLIENT_STRUCT * client_ptr,UINT status))1290 UINT nx_azure_iot_provisioning_client_completion_callback_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
1291                                                               VOID (*on_complete_callback)(
1292                                                                     struct NX_AZURE_IOT_PROVISIONING_CLIENT_STRUCT *client_ptr,
1293                                                                     UINT status))
1294 {
1295     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL))
1296     {
1297         LogError(LogLiteralArgs("IoTProvisioning set callback fail: INVALID POINTER"));
1298         return(NX_AZURE_IOT_INVALID_PARAMETER);
1299     }
1300 
1301     /* Obtain the mutex.  */
1302     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1303 
1304     prov_client_ptr -> nx_azure_iot_provisioning_client_on_complete_callback = on_complete_callback;
1305 
1306     /* Release the mutex.  */
1307     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1308 
1309     return(NX_AZURE_IOT_SUCCESS);
1310 }
1311 
nx_azure_iot_provisioning_client_symmetric_key_set(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,const UCHAR * symmetric_key,UINT symmetric_key_length)1312 UINT nx_azure_iot_provisioning_client_symmetric_key_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
1313                                                         const UCHAR *symmetric_key, UINT symmetric_key_length)
1314 {
1315 ULONG expiry_time_secs;
1316 UINT status;
1317 
1318     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
1319         (symmetric_key == NX_NULL) || (symmetric_key_length == 0))
1320     {
1321         LogError(LogLiteralArgs("IoTProvisioning client symmetric key fail: Invalid argument"));
1322         return(NX_AZURE_IOT_INVALID_PARAMETER);
1323     }
1324 
1325     /* Obtain the mutex.  */
1326     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1327 
1328     prov_client_ptr -> nx_azure_iot_provisioning_client_symmetric_key = symmetric_key;
1329     prov_client_ptr -> nx_azure_iot_provisioning_client_symmetric_key_length = symmetric_key_length;
1330 
1331     status = nx_azure_iot_unix_time_get(prov_client_ptr -> nx_azure_iot_ptr, &expiry_time_secs);
1332     if (status)
1333     {
1334 
1335         /* Release the mutex.  */
1336         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1337         LogError(LogLiteralArgs("IoTProvisioning client symmetric key fail status: %d"), status);
1338         return(status);
1339     }
1340 
1341     expiry_time_secs += NX_AZURE_IOT_PROVISIONING_CLIENT_TOKEN_EXPIRY;
1342 
1343     status = nx_azure_iot_provisioning_client_sas_token_get(prov_client_ptr, expiry_time_secs);
1344     if (status)
1345     {
1346 
1347         /* Release the mutex.  */
1348         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1349         LogError(LogLiteralArgs("IoTProvisioning client symmetric key fail: sas token generation failed"));
1350         return(status);
1351     }
1352 
1353     /* Release the mutex.  */
1354     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1355 
1356     return(NX_AZURE_IOT_SUCCESS);
1357 }
1358 
nx_azure_iot_provisioning_client_iothub_device_info_get(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,UCHAR * iothub_hostname,UINT * iothub_hostname_len,UCHAR * device_id,UINT * device_id_len)1359 UINT nx_azure_iot_provisioning_client_iothub_device_info_get(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
1360                                                              UCHAR *iothub_hostname, UINT *iothub_hostname_len,
1361                                                              UCHAR *device_id, UINT *device_id_len)
1362 {
1363 UINT status;
1364 az_span *device_id_span_ptr;
1365 az_span *assigned_hub_span_ptr;
1366 
1367     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL) ||
1368         (iothub_hostname == NX_NULL) || (iothub_hostname_len == NX_NULL) ||
1369         (device_id == NX_NULL) || (device_id_len == NX_NULL))
1370     {
1371         LogError(LogLiteralArgs("IoTProvisioning client iothub device info get fail: Invalid argument"));
1372         return(NX_AZURE_IOT_INVALID_PARAMETER);
1373     }
1374 
1375     /* Obtain the mutex.  */
1376     status = tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1377     if (status)
1378     {
1379         LogError(LogLiteralArgs("IoTProvisioning client iothub get fail: get mutex"));
1380         return(status);
1381     }
1382 
1383     if (prov_client_ptr -> nx_azure_iot_provisioning_client_state != NX_AZURE_IOT_PROVISIONING_CLIENT_STATUS_DONE)
1384     {
1385         LogError(LogLiteralArgs("IoTProvisioning client iothub device info get fail: wrong state"));
1386         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1387         return(NX_AZURE_IOT_WRONG_STATE);
1388     }
1389 
1390     device_id_span_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_response.register_response.registration_state.device_id);
1391     assigned_hub_span_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_response.register_response.registration_state.assigned_hub_hostname);
1392     if ((UINT)az_span_size(*assigned_hub_span_ptr) >= *iothub_hostname_len || (UINT)az_span_size(*device_id_span_ptr) > *device_id_len)
1393     {
1394         LogError(LogLiteralArgs("IoTProvisioning client iothub device info get fail: insufficient memory"));
1395         tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1396         return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
1397     }
1398 
1399     /* Iothub hostname should be null terminated.  */
1400     memcpy((VOID *)iothub_hostname,
1401            (VOID *)az_span_ptr(*assigned_hub_span_ptr),
1402            (UINT)az_span_size(*assigned_hub_span_ptr)); /* Use case of memcpy is verified.  */
1403     iothub_hostname[az_span_size(*assigned_hub_span_ptr)] = 0;
1404     *iothub_hostname_len = (UINT)az_span_size(*assigned_hub_span_ptr);
1405 
1406     memcpy((VOID *)device_id,
1407            (VOID *)az_span_ptr(*device_id_span_ptr),
1408            (UINT)az_span_size(*device_id_span_ptr)); /* Use case of memcpy is verified.  */
1409     *device_id_len = (UINT)az_span_size(*device_id_span_ptr);
1410 
1411     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1412 
1413     return(NX_AZURE_IOT_SUCCESS);
1414 }
1415 
nx_azure_iot_provisioning_client_registration_payload_set(NX_AZURE_IOT_PROVISIONING_CLIENT * prov_client_ptr,const UCHAR * payload_ptr,UINT payload_length)1416 UINT nx_azure_iot_provisioning_client_registration_payload_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
1417                                                                const UCHAR *payload_ptr, UINT payload_length)
1418 {
1419     if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL))
1420     {
1421         LogError(LogLiteralArgs("IoTProvisioning client set custom payload set: Invalid argument"));
1422         return(NX_AZURE_IOT_INVALID_PARAMETER);
1423     }
1424 
1425     /* Obtain the mutex.  */
1426     tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
1427 
1428     prov_client_ptr -> nx_azure_iot_provisioning_client_registration_payload = payload_ptr;
1429     prov_client_ptr -> nx_azure_iot_provisioning_client_registration_payload_length = payload_length;
1430 
1431     tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr);
1432 
1433     return(NX_AZURE_IOT_SUCCESS);
1434 }