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 }