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