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