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_api.h"
12 #ifndef SAMPLE_DHCP_DISABLE
13 #include "nxd_dhcp_client.h"
14 #endif /* SAMPLE_DHCP_DISABLE */
15 #include "nxd_dns.h"
16 #include "nxd_sntp_client.h"
17 #include "nx_secure_tls_api.h"
18 
19 /* Defined, HTTP proxy is enabled.  */
20 /*
21 #define SAMPLE_HTTP_PROXY_ENABLE
22 */
23 
24 #ifdef SAMPLE_HTTP_PROXY_ENABLE
25 #ifndef NX_ENABLE_HTTP_PROXY
26 #error "SYMBOL NX_ENABLE_HTTP_PROXY must be defined. "
27 #endif /* NX_ENABLE_HTTP_PROXY */
28 #endif /* SAMPLE_HTTP_PROXY_ENABLE */
29 
30 #if defined(SAMPLE_HTTP_PROXY_ENABLE)
31 #include "nx_http_proxy_client.h"
32 #endif /* SAMPLE_HTTP_PROXY_ENABLE */
33 
34 /* Include the sample.  */
35 extern VOID sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time));
36 
37 /* Define the helper thread for running Azure SDK on ThreadX (THREADX IoT Platform).  */
38 #ifndef SAMPLE_HELPER_STACK_SIZE
39 #define SAMPLE_HELPER_STACK_SIZE        (4096)
40 #endif /* SAMPLE_HELPER_STACK_SIZE  */
41 
42 #ifndef SAMPLE_HELPER_THREAD_PRIORITY
43 #define SAMPLE_HELPER_THREAD_PRIORITY   (4)
44 #endif /* SAMPLE_HELPER_THREAD_PRIORITY  */
45 
46 /* Define user configurable symbols. */
47 #ifndef SAMPLE_IP_STACK_SIZE
48 #define SAMPLE_IP_STACK_SIZE            (2048)
49 #endif /* SAMPLE_IP_STACK_SIZE  */
50 
51 #ifndef SAMPLE_PACKET_COUNT
52 #define SAMPLE_PACKET_COUNT             (32)
53 #endif /* SAMPLE_PACKET_COUNT  */
54 
55 #ifndef SAMPLE_PACKET_SIZE
56 #define SAMPLE_PACKET_SIZE              (1536)
57 #endif /* SAMPLE_PACKET_SIZE  */
58 
59 #define SAMPLE_POOL_SIZE                ((SAMPLE_PACKET_SIZE + sizeof(NX_PACKET)) * SAMPLE_PACKET_COUNT)
60 
61 #ifndef SAMPLE_ARP_CACHE_SIZE
62 #define SAMPLE_ARP_CACHE_SIZE           (512)
63 #endif /* SAMPLE_ARP_CACHE_SIZE  */
64 
65 #ifndef SAMPLE_IP_THREAD_PRIORITY
66 #define SAMPLE_IP_THREAD_PRIORITY       (1)
67 #endif /* SAMPLE_IP_THREAD_PRIORITY */
68 
69 #if defined(SAMPLE_DHCP_DISABLE) && !defined(SAMPLE_NETWORK_CONFIGURE)
70 #ifndef SAMPLE_IPV4_ADDRESS
71 /*#define SAMPLE_IPV4_ADDRESS           IP_ADDRESS(192, 168, 100, 33)*/
72 #error "SYMBOL SAMPLE_IPV4_ADDRESS must be defined. This symbol specifies the IP address of device. "
73 #endif /* SAMPLE_IPV4_ADDRESS */
74 
75 #ifndef SAMPLE_IPV4_MASK
76 /*#define SAMPLE_IPV4_MASK              0xFFFFFF00UL*/
77 #error "SYMBOL SAMPLE_IPV4_MASK must be defined. This symbol specifies the IP address mask of device. "
78 #endif /* SAMPLE_IPV4_MASK */
79 
80 #ifndef SAMPLE_GATEWAY_ADDRESS
81 /*#define SAMPLE_GATEWAY_ADDRESS        IP_ADDRESS(192, 168, 100, 1)*/
82 #error "SYMBOL SAMPLE_GATEWAY_ADDRESS must be defined. This symbol specifies the gateway address for routing. "
83 #endif /* SAMPLE_GATEWAY_ADDRESS */
84 
85 #ifndef SAMPLE_DNS_SERVER_ADDRESS
86 /*#define SAMPLE_DNS_SERVER_ADDRESS     IP_ADDRESS(192, 168, 100, 1)*/
87 #error "SYMBOL SAMPLE_DNS_SERVER_ADDRESS must be defined. This symbol specifies the dns server address for routing. "
88 #endif /* SAMPLE_DNS_SERVER_ADDRESS */
89 #else
90 #define SAMPLE_IPV4_ADDRESS             IP_ADDRESS(0, 0, 0, 0)
91 #define SAMPLE_IPV4_MASK                IP_ADDRESS(0, 0, 0, 0)
92 
93 #ifndef SAMPLE_DHCP_WAIT_OPTION
94 #define SAMPLE_DHCP_WAIT_OPTION         (20 * NX_IP_PERIODIC_RATE)
95 #endif /* SAMPLE_DHCP_WAIT_OPTION */
96 
97 #endif /* SAMPLE_DHCP_DISABLE */
98 
99 #ifndef SAMPLE_SNTP_SYNC_MAX
100 #define SAMPLE_SNTP_SYNC_MAX            30
101 #endif /* SAMPLE_SNTP_SYNC_MAX */
102 
103 #ifndef SAMPLE_SNTP_UPDATE_MAX
104 #define SAMPLE_SNTP_UPDATE_MAX          10
105 #endif /* SAMPLE_SNTP_UPDATE_MAX */
106 
107 #ifndef SAMPLE_SNTP_UPDATE_INTERVAL
108 #define SAMPLE_SNTP_UPDATE_INTERVAL     (NX_IP_PERIODIC_RATE / 2)
109 #endif /* SAMPLE_SNTP_UPDATE_INTERVAL */
110 
111 /* Default time. GMT: Friday, Jan 1, 2022 12:00:00 AM. Epoch timestamp: 1640995200.  */
112 #ifndef SAMPLE_SYSTEM_TIME
113 #define SAMPLE_SYSTEM_TIME              1640995200
114 #endif /* SAMPLE_SYSTEM_TIME  */
115 
116 /* Seconds between Unix Epoch (1/1/1970) and NTP Epoch (1/1/1999) */
117 #define SAMPLE_UNIX_TO_NTP_EPOCH_SECOND 0x83AA7E80
118 
119 #if defined(SAMPLE_HTTP_PROXY_ENABLE)
120 #ifndef SAMPLE_HTTP_PROXY_SERVER
121 #define SAMPLE_HTTP_PROXY_SERVER        IP_ADDRESS(192, 168, 100, 6)
122 #endif /* SAMPLE_HTTP_PROXY_SERVER  */
123 
124 #ifndef SAMPLE_HTTP_PROXY_SERVER_PORT
125 #define SAMPLE_HTTP_PROXY_SERVER_PORT   8888
126 #endif /* SAMPLE_HTTP_PROXY_SERVER_PORT  */
127 
128 #ifndef SAMPLE_HTTP_PROXY_USER_NAME
129 #define SAMPLE_HTTP_PROXY_USER_NAME     ""
130 #endif /* SAMPLE_HTTP_PROXY_USER_NAME  */
131 
132 #ifndef SAMPLE_HTTP_PROXY_PASSWORD
133 #define SAMPLE_HTTP_PROXY_PASSWORD      ""
134 #endif /* SAMPLE_HTTP_PROXY_PASSWORD  */
135 #endif /* SAMPLE_HTTP_PROXY_ENABLE  */
136 
137 static TX_THREAD        sample_helper_thread;
138 static NX_PACKET_POOL   pool_0;
139 static NX_IP            ip_0;
140 static NX_DNS           dns_0;
141 #ifndef SAMPLE_DHCP_DISABLE
142 static NX_DHCP          dhcp_0;
143 #endif /* SAMPLE_DHCP_DISABLE  */
144 static NX_SNTP_CLIENT   sntp_client;
145 
146 /* System clock time for UTC.  */
147 static ULONG            unix_time_base;
148 
149 /* Define the stack/cache for ThreadX.  */
150 static ULONG sample_ip_stack[SAMPLE_IP_STACK_SIZE / sizeof(ULONG)];
151 #ifndef SAMPLE_POOL_STACK_USER
152 static ULONG sample_pool_stack[SAMPLE_POOL_SIZE / sizeof(ULONG)];
153 static ULONG sample_pool_stack_size = sizeof(sample_pool_stack);
154 #else
155 extern ULONG sample_pool_stack[];
156 extern ULONG sample_pool_stack_size;
157 #endif
158 #ifndef SAMPLE_NETWORK_CONFIGURE
159 static ULONG sample_arp_cache_area[SAMPLE_ARP_CACHE_SIZE / sizeof(ULONG)];
160 #endif
161 static ULONG sample_helper_thread_stack[SAMPLE_HELPER_STACK_SIZE / sizeof(ULONG)];
162 
163 static const CHAR *sntp_servers[] =
164 {
165     "0.pool.ntp.org",
166     "1.pool.ntp.org",
167     "2.pool.ntp.org",
168     "3.pool.ntp.org",
169 };
170 static UINT sntp_server_index;
171 
172 /* Define the prototypes for sample thread.  */
173 static void sample_helper_thread_entry(ULONG parameter);
174 
175 #ifndef SAMPLE_DHCP_DISABLE
176 static UINT dhcp_wait();
177 #endif /* SAMPLE_DHCP_DISABLE */
178 
179 static UINT dns_create(ULONG dns_server_address);
180 
181 static UINT sntp_time_sync();
182 static UINT unix_time_get(ULONG *unix_time);
183 
184 #ifndef SAMPLE_NETWORK_DRIVER
185 #define SAMPLE_NETWORK_DRIVER           _nx_ram_network_driver
186 #endif /* SAMPLE_NETWORK_DRIVER */
187 
188 /* Include the platform IP driver. */
189 void SAMPLE_NETWORK_DRIVER(struct NX_IP_DRIVER_STRUCT *driver_req);
190 
191 #ifdef SAMPLE_BOARD_SETUP
192 void SAMPLE_BOARD_SETUP();
193 #endif /* SAMPLE_BOARD_SETUP */
194 
195 #ifdef SAMPLE_NETWORK_CONFIGURE
196 void SAMPLE_NETWORK_CONFIGURE(NX_IP *ip_ptr, ULONG *dns_address);
197 #endif
198 
199 /* Define main entry point.  */
main(void)200 int main(void)
201 {
202 
203 #ifdef SAMPLE_BOARD_SETUP
204     SAMPLE_BOARD_SETUP();
205 #endif /* SAMPLE_BOARD_SETUP */
206 
207     /* Enter the ThreadX kernel.  */
208     tx_kernel_enter();
209 }
210 
211 /* Define what the initial system looks like.  */
tx_application_define(void * first_unused_memory)212 void    tx_application_define(void *first_unused_memory)
213 {
214 
215 UINT  status;
216 
217     NX_PARAMETER_NOT_USED(first_unused_memory);
218 
219     /* Initialize the NetX system.  */
220     nx_system_initialize();
221 
222     /* Create a packet pool.  */
223     status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", SAMPLE_PACKET_SIZE,
224                                    (UCHAR *)sample_pool_stack , sample_pool_stack_size);
225 
226     /* Check for pool creation error.  */
227     if (status)
228     {
229         printf("nx_packet_pool_create fail: %u\r\n", status);
230         return;
231     }
232 
233     /* Create an IP instance.  */
234     status = nx_ip_create(&ip_0, "NetX IP Instance 0",
235                           SAMPLE_IPV4_ADDRESS, SAMPLE_IPV4_MASK,
236                           &pool_0, SAMPLE_NETWORK_DRIVER,
237                           (UCHAR*)sample_ip_stack, sizeof(sample_ip_stack),
238                           SAMPLE_IP_THREAD_PRIORITY);
239 
240     /* Check for IP create errors.  */
241     if (status)
242     {
243         printf("nx_ip_create fail: %u\r\n", status);
244         return;
245     }
246 
247 #ifndef SAMPLE_NETWORK_CONFIGURE
248     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
249     status = nx_arp_enable(&ip_0, (VOID *)sample_arp_cache_area, sizeof(sample_arp_cache_area));
250 
251     /* Check for ARP enable errors.  */
252     if (status)
253     {
254         printf("nx_arp_enable fail: %u\r\n", status);
255         return;
256     }
257 
258     /* Enable ICMP traffic.  */
259     status = nx_icmp_enable(&ip_0);
260 
261     /* Check for ICMP enable errors.  */
262     if (status)
263     {
264         printf("nx_icmp_enable fail: %u\r\n", status);
265         return;
266     }
267 #endif
268 
269     /* Enable TCP traffic.  */
270     status = nx_tcp_enable(&ip_0);
271 
272     /* Check for TCP enable errors.  */
273     if (status)
274     {
275         printf("nx_tcp_enable fail: %u\r\n", status);
276         return;
277     }
278 
279     /* Enable UDP traffic.  */
280     status = nx_udp_enable(&ip_0);
281 
282     /* Check for UDP enable errors.  */
283     if (status)
284     {
285         printf("nx_udp_enable fail: %u\r\n", status);
286         return;
287     }
288 
289     /* Initialize TLS.  */
290     nx_secure_tls_initialize();
291 
292     /* Create sample helper thread.  */
293     status = tx_thread_create(&sample_helper_thread, "Demo Thread",
294                               sample_helper_thread_entry, 0,
295                               sample_helper_thread_stack, SAMPLE_HELPER_STACK_SIZE,
296                               SAMPLE_HELPER_THREAD_PRIORITY, SAMPLE_HELPER_THREAD_PRIORITY,
297                               TX_NO_TIME_SLICE, TX_AUTO_START);
298 
299     /* Check status.  */
300     if (status)
301     {
302         printf("Demo helper thread creation fail: %u\r\n", status);
303         return;
304     }
305 }
306 
307 /* Define sample helper thread entry.  */
sample_helper_thread_entry(ULONG parameter)308 void sample_helper_thread_entry(ULONG parameter)
309 {
310 
311 UINT    status;
312 ULONG   ip_address = 0;
313 ULONG   network_mask = 0;
314 ULONG   gateway_address = 0;
315 UINT    unix_time;
316 ULONG   dns_server_address[3];
317 #ifndef SAMPLE_DHCP_DISABLE
318 UINT    dns_server_address_size = sizeof(dns_server_address);
319 #endif
320 #if defined(SAMPLE_HTTP_PROXY_ENABLE)
321 NXD_ADDRESS proxy_server_address;
322 #endif /* SAMPLE_HTTP_PROXY_ENABLE */
323 
324     NX_PARAMETER_NOT_USED(parameter);
325 
326 #if defined(SAMPLE_HTTP_PROXY_ENABLE)
327 
328     /* Enabled HTTP proxy.  */
329     proxy_server_address.nxd_ip_version = NX_IP_VERSION_V4;
330     proxy_server_address.nxd_ip_address.v4 = SAMPLE_HTTP_PROXY_SERVER;
331     status = nx_http_proxy_client_enable(&ip_0, &proxy_server_address, SAMPLE_HTTP_PROXY_SERVER_PORT,
332                                          SAMPLE_HTTP_PROXY_USER_NAME, sizeof(SAMPLE_HTTP_PROXY_USER_NAME) - 1,
333                                          SAMPLE_HTTP_PROXY_PASSWORD, sizeof(SAMPLE_HTTP_PROXY_PASSWORD) - 1);
334     if (status)
335     {
336         printf("Failed to enable HTTP proxy!\r\n");
337         return;
338     }
339 #endif /* SAMPLE_HTTP_PROXY_ENABLE  */
340 
341 #ifndef SAMPLE_DHCP_DISABLE
342     if (dhcp_wait())
343     {
344         printf("Failed to get the IP address!\r\n");
345         return;
346     }
347 #elif defined(SAMPLE_NETWORK_CONFIGURE)
348     SAMPLE_NETWORK_CONFIGURE(&ip_0, &dns_server_address[0]);
349 #else
350     nx_ip_gateway_address_set(&ip_0, SAMPLE_GATEWAY_ADDRESS);
351 #endif /* SAMPLE_DHCP_DISABLE  */
352 
353     /* Get IP address and gateway address.  */
354     nx_ip_address_get(&ip_0, &ip_address, &network_mask);
355     nx_ip_gateway_address_get(&ip_0, &gateway_address);
356 
357     /* Output IP address and gateway address.  */
358     printf("IP address: %lu.%lu.%lu.%lu\r\n",
359            (ip_address >> 24),
360            (ip_address >> 16 & 0xFF),
361            (ip_address >> 8 & 0xFF),
362            (ip_address & 0xFF));
363     printf("Mask: %lu.%lu.%lu.%lu\r\n",
364            (network_mask >> 24),
365            (network_mask >> 16 & 0xFF),
366            (network_mask >> 8 & 0xFF),
367            (network_mask & 0xFF));
368     printf("Gateway: %lu.%lu.%lu.%lu\r\n",
369            (gateway_address >> 24),
370            (gateway_address >> 16 & 0xFF),
371            (gateway_address >> 8 & 0xFF),
372            (gateway_address & 0xFF));
373 
374 #ifndef SAMPLE_DHCP_DISABLE
375     /* Retrieve DNS server address.  */
376     nx_dhcp_interface_user_option_retrieve(&dhcp_0, 0, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)(dns_server_address),
377                                            &dns_server_address_size);
378 #elif !defined(SAMPLE_NETWORK_CONFIGURE)
379     dns_server_address[0] = SAMPLE_DNS_SERVER_ADDRESS;
380 #endif /* SAMPLE_DHCP_DISABLE */
381 
382     /* Create DNS.  */
383     status = dns_create(dns_server_address[0]);
384 
385     /* Check for DNS create errors.  */
386     if (status)
387     {
388         printf("dns_create fail: %u\r\n", status);
389         return;
390     }
391 
392     /* Sync up time by SNTP at start up.  */
393     status = sntp_time_sync();
394 
395     /* Check status.  */
396     if (status)
397     {
398         printf("SNTP Time Sync failed.\r\n");
399         printf("Set Time to default value: SAMPLE_SYSTEM_TIME.");
400         unix_time_base = SAMPLE_SYSTEM_TIME;
401     }
402     else
403     {
404         printf("SNTP Time Sync successfully.\r\n");
405     }
406 
407     unix_time_get((ULONG *)&unix_time);
408     srand(unix_time);
409 
410     /* Start sample.  */
411     sample_entry(&ip_0, &pool_0, (VOID *)&dns_0, unix_time_get);
412 }
413 
414 #ifndef SAMPLE_DHCP_DISABLE
dhcp_wait()415 static UINT dhcp_wait()
416 {
417 UINT    status;
418 ULONG   actual_status;
419 
420     printf("DHCP In Progress...\r\n");
421 
422     /* Create the DHCP instance.  */
423     status = nx_dhcp_create(&dhcp_0, &ip_0, "DHCP Client");
424 
425     /* Check status.  */
426     if (status)
427     {
428         return(status);
429     }
430 
431     /* Request NTP server.  */
432     status = nx_dhcp_user_option_request(&dhcp_0, NX_DHCP_OPTION_NTP_SVR);
433 
434     /* Check status.  */
435     if (status)
436     {
437         nx_dhcp_delete(&dhcp_0);
438         return(status);
439     }
440 
441     /* Start the DHCP Client.  */
442     status = nx_dhcp_start(&dhcp_0);
443 
444     /* Check status.  */
445     if (status)
446     {
447         nx_dhcp_delete(&dhcp_0);
448         return(status);
449     }
450 
451     /* Wait util address is solved.  */
452     status = nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, SAMPLE_DHCP_WAIT_OPTION);
453 
454     /* Check status.  */
455     if (status)
456     {
457         nx_dhcp_delete(&dhcp_0);
458         return(status);
459     }
460 
461     return(NX_SUCCESS);
462 }
463 #endif /* SAMPLE_DHCP_DISABLE  */
464 
dns_create(ULONG dns_server_address)465 static UINT dns_create(ULONG dns_server_address)
466 {
467 UINT    status;
468 
469     /* Create a DNS instance for the Client.  Note this function will create
470        the DNS Client packet pool for creating DNS message packets intended
471        for querying its DNS server.  */
472     status = nx_dns_create(&dns_0, &ip_0, (UCHAR *)"DNS Client");
473     if (status)
474     {
475         return(status);
476     }
477 
478     /* Is the DNS client configured for the host application to create the packet pool?  */
479 #ifdef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL
480 
481     /* Yes, use the packet pool created above which has appropriate payload size
482        for DNS messages.  */
483     status = nx_dns_packet_pool_set(&dns_0, ip_0.nx_ip_default_packet_pool);
484     if (status)
485     {
486         nx_dns_delete(&dns_0);
487         return(status);
488     }
489 #endif /* NX_DNS_CLIENT_USER_CREATE_PACKET_POOL */
490 
491     /* Add an IPv4 server address to the Client list.  */
492     status = nx_dns_server_add(&dns_0, dns_server_address);
493     if (status)
494     {
495         nx_dns_delete(&dns_0);
496         return(status);
497     }
498 
499     /* Output DNS Server address.  */
500     printf("DNS Server address: %lu.%lu.%lu.%lu\r\n",
501            (dns_server_address >> 24),
502            (dns_server_address >> 16 & 0xFF),
503            (dns_server_address >> 8 & 0xFF),
504            (dns_server_address & 0xFF));
505 
506     return(NX_SUCCESS);
507 }
508 
509 /* Sync up the local time.  */
sntp_time_sync_internal(ULONG sntp_server_address)510 static UINT sntp_time_sync_internal(ULONG sntp_server_address)
511 {
512 UINT    status;
513 UINT    server_status;
514 UINT    i;
515 
516     /* Create the SNTP Client to run in broadcast mode.. */
517     status =  nx_sntp_client_create(&sntp_client, &ip_0, 0, &pool_0,
518                                     NX_NULL,
519                                     NX_NULL,
520                                     NX_NULL /* no random_number_generator callback */);
521 
522     /* Check status.  */
523     if (status)
524     {
525         return(status);
526     }
527 
528     /* Use the IPv4 service to initialize the Client and set the IPv4 SNTP server. */
529     status = nx_sntp_client_initialize_unicast(&sntp_client, sntp_server_address);
530 
531     /* Check status.  */
532     if (status)
533     {
534         nx_sntp_client_delete(&sntp_client);
535         return(status);
536     }
537 
538     /* Set local time to 0 */
539     status = nx_sntp_client_set_local_time(&sntp_client, 0, 0);
540 
541     /* Check status.  */
542     if (status)
543     {
544         nx_sntp_client_delete(&sntp_client);
545         return(status);
546     }
547 
548     /* Run Unicast client */
549     status = nx_sntp_client_run_unicast(&sntp_client);
550 
551     /* Check status.  */
552     if (status)
553     {
554         nx_sntp_client_stop(&sntp_client);
555         nx_sntp_client_delete(&sntp_client);
556         return(status);
557     }
558 
559     /* Wait till updates are received */
560     for (i = 0; i < SAMPLE_SNTP_UPDATE_MAX; i++)
561     {
562 
563         /* First verify we have a valid SNTP service running. */
564         status = nx_sntp_client_receiving_updates(&sntp_client, &server_status);
565 
566         /* Check status.  */
567         if ((status == NX_SUCCESS) && (server_status == NX_TRUE))
568         {
569 
570             /* Server status is good. Now get the Client local time. */
571             ULONG sntp_seconds, sntp_fraction;
572             ULONG system_time_in_second;
573 
574             /* Get the local time.  */
575             status = nx_sntp_client_get_local_time(&sntp_client, &sntp_seconds, &sntp_fraction, NX_NULL);
576 
577             /* Check status.  */
578             if (status != NX_SUCCESS)
579             {
580                 continue;
581             }
582 
583             /* Get the system time in second.  */
584             system_time_in_second = tx_time_get() / TX_TIMER_TICKS_PER_SECOND;
585 
586             /* Convert to Unix epoch and minus the current system time.  */
587             unix_time_base = (sntp_seconds - (system_time_in_second + SAMPLE_UNIX_TO_NTP_EPOCH_SECOND));
588 
589             /* Time sync successfully.  */
590 
591             /* Stop and delete SNTP.  */
592             nx_sntp_client_stop(&sntp_client);
593             nx_sntp_client_delete(&sntp_client);
594 
595             return(NX_SUCCESS);
596         }
597 
598         /* Sleep.  */
599         tx_thread_sleep(SAMPLE_SNTP_UPDATE_INTERVAL);
600     }
601 
602     /* Time sync failed.  */
603 
604     /* Stop and delete SNTP.  */
605     nx_sntp_client_stop(&sntp_client);
606     nx_sntp_client_delete(&sntp_client);
607 
608     /* Return success.  */
609     return(NX_NOT_SUCCESSFUL);
610 }
611 
sntp_time_sync()612 static UINT sntp_time_sync()
613 {
614 UINT status;
615 ULONG gateway_address;
616 ULONG sntp_server_address[3];
617 #ifndef SAMPLE_DHCP_DISABLE
618 UINT  sntp_server_address_size = sizeof(sntp_server_address);
619 #endif
620 
621 #ifndef SAMPLE_DHCP_DISABLE
622     /* Retrieve NTP server address.  */
623     status = nx_dhcp_interface_user_option_retrieve(&dhcp_0, 0, NX_DHCP_OPTION_NTP_SVR, (UCHAR *)(sntp_server_address),
624                                                     &sntp_server_address_size);
625 
626     /* Check status.  */
627     if (status == NX_SUCCESS)
628     {
629         for (UINT i = 0; (i * 4) < sntp_server_address_size; i++)
630         {
631             printf("SNTP Time Sync...%lu.%lu.%lu.%lu (DHCP)\r\n",
632                    (sntp_server_address[i] >> 24),
633                    (sntp_server_address[i] >> 16 & 0xFF),
634                    (sntp_server_address[i] >> 8 & 0xFF),
635                    (sntp_server_address[i] & 0xFF));
636 
637             /* Start SNTP to sync the local time.  */
638             status = sntp_time_sync_internal(sntp_server_address[i]);
639 
640             /* Check status.  */
641             if(status == NX_SUCCESS)
642             {
643                 return(NX_SUCCESS);
644             }
645         }
646     }
647 #endif /* SAMPLE_DHCP_DISABLE */
648 
649     /* Sync time by NTP server array.  */
650     for (UINT i = 0; i < SAMPLE_SNTP_SYNC_MAX; i++)
651     {
652         printf("SNTP Time Sync...%s\r\n", sntp_servers[sntp_server_index]);
653 
654         /* Make sure the network is still valid.  */
655         while (nx_ip_gateway_address_get(&ip_0, &gateway_address))
656         {
657             tx_thread_sleep(NX_IP_PERIODIC_RATE);
658         }
659 
660         /* Look up SNTP Server address. */
661         status = nx_dns_host_by_name_get(&dns_0, (UCHAR *)sntp_servers[sntp_server_index], &sntp_server_address[0], 5 * NX_IP_PERIODIC_RATE);
662 
663         /* Check status.  */
664         if (status == NX_SUCCESS)
665         {
666 
667             /* Start SNTP to sync the local time.  */
668             status = sntp_time_sync_internal(sntp_server_address[0]);
669 
670             /* Check status.  */
671             if(status == NX_SUCCESS)
672             {
673                 return(NX_SUCCESS);
674             }
675         }
676 
677         /* Switch SNTP server every time.  */
678         sntp_server_index = (sntp_server_index + 1) % (sizeof(sntp_servers) / sizeof(sntp_servers[0]));
679     }
680 
681     return(NX_NOT_SUCCESSFUL);
682 }
683 
unix_time_get(ULONG * unix_time)684 static UINT unix_time_get(ULONG *unix_time)
685 {
686 
687     /* Return number of seconds since Unix Epoch (1/1/1970 00:00:00).  */
688     *unix_time =  unix_time_base + (tx_time_get() / TX_TIMER_TICKS_PER_SECOND);
689 
690     return(NX_SUCCESS);
691 }
692