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