main.c 20 KB

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