1 #include "nx_api.h"
2 #include "nx_ip.h"
3 #include "nxd_sntp_client.h"
4 
5 extern void test_control_return(UINT status);
6 
7 #if !defined(NX_DISABLE_IPV4)
8 
9 /* Define SNTP packet size. */
10 #define NX_SNTP_CLIENT_PACKET_SIZE                 (NX_UDP_PACKET + 100)
11 
12 /* Define SNTP packet pool size. */
13 #define NX_SNTP_CLIENT_PACKET_POOL_SIZE            (4 * (NX_SNTP_CLIENT_PACKET_SIZE + sizeof(NX_PACKET)))
14 
15 /* NTP server reply. */
16 static char pkt_data[90] = {
17     0x00, 0x11, 0x22, 0x33, 0x44, 0x57, 0x00, 0x0c,
18     0x29, 0x1e, 0xaa, 0x4f, 0x08, 0x00, 0x45, 0x00,
19     0x00, 0x4c, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
20     0xbc, 0xa3, 0xc0, 0xa8, 0x7e, 0x82, 0xc0, 0xa8,
21     0x7e, 0x2a, 0x00, 0x7b, 0x00, 0x7b, 0x00, 0x38,
22     0x7f, 0xa0, 0x1c, 0x02, 0x00, 0xec, 0x00, 0x00,
23     0x07, 0xdd, 0x00, 0x00, 0x06, 0x6e, 0x89, 0xbd,
24     0x04, 0x0a, 0xd6, 0x4b, 0xd7, 0xeb, 0xb3, 0x25,
25     0xe0, 0x52, 0xd2, 0xc9, 0x6b, 0x90, 0xa1, 0x32,
26     0xdb, 0x1e, 0xd6, 0x4b, 0xd8, 0x5b, 0x20, 0x27,
27     0x62, 0xa4, 0xd6, 0x4b, 0xd8, 0x5b, 0x20, 0x2c,
28     0x4b, 0x46 };
29 
30 static UINT pkt_size = 90;
31 
32 static ULONG expected_seconds = 0xd64bd85b;
33 static ULONG expected_milliseconds = 0x88;
34 static ULONG tolerance_milliseconds = 200;
35 
36 extern void _nx_ram_network_driver_1500(NX_IP_DRIVER *driver_req_ptr);
37 
38 /* Set up client thread and network resources. */
39 
40 static NX_PACKET_POOL      client_packet_pool;
41 static NX_IP               client_ip;
42 static TX_THREAD           sntp_client_thread;
43 static NX_SNTP_CLIENT      sntp_client;
44 
45 
46 #define CLIENT_IP_ADDRESS       IP_ADDRESS(192,168,126,42)
47 #define SERVER_IP_ADDRESS       IP_ADDRESS(192,168,126,130)
48 #define SERVER_IP_ADDRESS_2     SERVER_IP_ADDRESS
49 
50 /* Set up the SNTP network and address index; */
51 static UINT     iface_index;
52 
53 static UINT     error_counter;
54 
55 /* Set up client thread entry point. */
56 static void sntp_client_thread_entry(ULONG info);
57 
58 static void inject_sntp_server_reply();
59 
60 /* Define what the initial system looks like.  */
61 #ifdef CTEST
test_application_define(void * first_unused_memory)62 VOID test_application_define(void *first_unused_memory)
63 #else
64 void netx_sntp_client_unicast_basic_test_application_define(void *first_unused_memory)
65 #endif
66 {
67 
68 UINT     status;
69 UCHAR    *free_memory_pointer;
70 
71     error_counter = 0;
72 
73     free_memory_pointer = (UCHAR *)first_unused_memory;
74 
75     /* Create client packet pool. */
76     status =  nx_packet_pool_create(&client_packet_pool, "SNTP Client Packet Pool",
77                                     NX_SNTP_CLIENT_PACKET_SIZE, free_memory_pointer,
78                                     NX_SNTP_CLIENT_PACKET_POOL_SIZE);
79     free_memory_pointer =  free_memory_pointer + NX_SNTP_CLIENT_PACKET_POOL_SIZE;
80 
81     /* Check for errors. */
82     if (status != NX_SUCCESS)
83         error_counter++;
84 
85     /* Initialize the NetX system. */
86     nx_system_initialize();
87 
88 
89     /* Create Client IP instances */
90     status = nx_ip_create(&client_ip, "SNTP IP Instance", CLIENT_IP_ADDRESS,
91                           0xFFFFFF00UL, &client_packet_pool, _nx_ram_network_driver_1500,
92                           free_memory_pointer, 2048, 1);
93     free_memory_pointer =  free_memory_pointer + 2048;
94 
95     /* Check for error. */
96     if (status != NX_SUCCESS)
97         error_counter++;
98 
99     /* Enable ARP and supply ARP cache memory. */
100     status =  nx_arp_enable(&client_ip, (void **) free_memory_pointer, 2048);
101     free_memory_pointer = free_memory_pointer + 2048;
102 
103     /* Check for error. */
104     if (status != NX_SUCCESS)
105         error_counter++;
106 
107 
108     /* Enable UDP for client. */
109     status =  nx_udp_enable(&client_ip);
110 
111     /* Check for error. */
112     if (status != NX_SUCCESS)
113         error_counter++;
114 
115     status = nx_icmp_enable(&client_ip);
116 
117     /* Check for error. */
118     if (status != NX_SUCCESS)
119         error_counter++;
120 
121     /* Create the client thread */
122     status = tx_thread_create(&sntp_client_thread, "SNTP Client Thread", sntp_client_thread_entry,
123                               (ULONG)(&sntp_client), free_memory_pointer, 2048,
124                               4, 4, TX_NO_TIME_SLICE, TX_DONT_START);
125     free_memory_pointer = free_memory_pointer + 2048;
126 
127     /* Check for errors */
128     if (status != TX_SUCCESS)
129         error_counter++;
130 
131     /* set the SNTP network interface to the primary interface. */
132     iface_index = 0;
133 
134     /* Create the SNTP Client to run in broadcast mode.. */
135     status =  nx_sntp_client_create(&sntp_client, &client_ip, iface_index, &client_packet_pool,
136                                     NX_NULL,
137                                     NX_NULL,
138                                     NX_NULL /* no random_number_generator callback */);
139 
140     /* Check for error. */
141     if (status != NX_SUCCESS)
142         error_counter++;
143 
144     tx_thread_resume(&sntp_client_thread);
145 
146     return;
147 }
148 
149 /* Define size of buffer to display client's local time. */
150 #define BUFSIZE 50
151 
152 /* Define the client thread.  */
sntp_client_thread_entry(ULONG info)153 void    sntp_client_thread_entry(ULONG info)
154 {
155 
156 UINT   status;
157 UINT   spin;
158 UINT   server_status;
159 CHAR   buffer[BUFSIZE];
160 ULONG  base_seconds;
161 ULONG  base_fraction;
162 ULONG  seconds, milliseconds, microseconds, fraction;
163 ULONG  expected_fraction;
164 
165     printf("NetX Test:   NETX SNTP Client Unicast Basic Test.......................");
166 
167     status = nx_sntp_client_delete(&sntp_client);
168 
169     /* Check for error. */
170     if (status != NX_SUCCESS)
171         error_counter++;
172 
173     /* Create the SNTP Client to run in broadcast mode.. */
174     status =  nx_sntp_client_create(&sntp_client, &client_ip, iface_index, &client_packet_pool,
175                                     NX_NULL,
176                                     NX_NULL,
177                                     NX_NULL /* no random_number_generator callback */);
178 
179     /* Check for error. */
180     if (status != NX_SUCCESS)
181         error_counter++;
182 
183     /* Give other threads (IP instance) a chance to initialize. */
184     tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);
185 
186     /* Use the IPv4 service to initialize the Client and set the IPv4 SNTP server. */
187     status = nx_sntp_client_initialize_unicast(&sntp_client, SERVER_IP_ADDRESS);
188 
189     /* Check for error. */
190     if (status != NX_SUCCESS)
191         error_counter++;
192 
193     /* Set the base time which is approximately the number of seconds since the turn of the last century. */
194     base_seconds =  0xd2c96b90;  /* Jan 24, 2012 UTC */
195     base_fraction = 0xa132db1e;
196 
197     /* Apply to the SNTP Client local time.  */
198     status = nx_sntp_client_set_local_time(&sntp_client, base_seconds, base_fraction);
199 
200     /* Check for error. */
201     if (status != NX_SUCCESS)
202         error_counter++;
203 
204     status = nx_sntp_client_run_unicast(&sntp_client);
205 
206     if (status != NX_SUCCESS)
207         error_counter++;
208 
209     inject_sntp_server_reply();
210 
211     spin = NX_TRUE;
212 
213     /* Now check periodically for time changes. */
214     while(spin)
215     {
216 
217         /* First verify we have a valid SNTP service running. */
218         status = nx_sntp_client_receiving_updates(&sntp_client, &server_status);
219 
220         if ((status == NX_SUCCESS) && (server_status == NX_TRUE))
221         {
222 
223             /* Server status is good. Now get the Client local time. */
224 
225             /* Display the local time in years, months, date format.  */
226             status = nx_sntp_client_get_local_time(&sntp_client, &seconds, &fraction, &buffer[0]);
227 
228             /* Convert fraction to microseconds. */
229             nx_sntp_client_utility_fraction_to_usecs(fraction, &microseconds);
230 
231             milliseconds = ((microseconds + 500) / 1000);
232 
233             if (status == NX_SUCCESS)
234             {
235                 if ((seconds == expected_seconds) && ((INT)milliseconds > (INT)(expected_milliseconds - tolerance_milliseconds)) &&
236                     (milliseconds < (expected_milliseconds + tolerance_milliseconds)))
237                 {
238 
239                     /* Get extended local time. */
240                     status = nx_sntp_client_get_local_time_extended(&sntp_client, &seconds, &fraction, &buffer[0], sizeof(buffer));
241                     if (status == NX_SUCCESS)
242                     {
243 
244                         /* Convert fraction to microseconds. */
245                         nx_sntp_client_utility_fraction_to_usecs(fraction, &microseconds);
246 
247                         /* Compare microseconds with milliseconds. */
248                         if (((microseconds + 500) / 1000) != milliseconds)
249                         {
250                             error_counter++;
251                         }
252 
253                         /* Convert microseconds to fraction. */
254                         nx_sntp_client_utility_usecs_to_fraction(microseconds, &expected_fraction);
255 
256                         /* Compare expected_fraction with fraction. */
257                         if (expected_fraction != fraction)
258                         {
259                             error_counter++;
260                         }
261                     }
262                     else
263                     {
264                         error_counter++;
265                     }
266                     break;
267                 }
268                 else
269                 {
270                     error_counter++;
271                     break;
272                 }
273             }
274 
275         }
276         else
277         {
278 
279             /* Wait a short bit to check again. */
280             tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);
281         }
282     }
283 
284     /* We can stop the SNTP service if for example we think the SNTP service has stopped. */
285     status = nx_sntp_client_stop(&sntp_client);
286 
287     if (status != NX_SUCCESS)
288         error_counter++;
289 
290     status = nx_sntp_client_delete(&sntp_client);
291 
292     if (status != NX_SUCCESS)
293         error_counter++;
294 
295     if(error_counter)
296     {
297         printf("ERROR!\n");
298         test_control_return(1);
299     }
300     else
301     {
302         printf("SUCCESS!\n");
303         test_control_return(0);
304     }
305 
306     return;
307 }
308 
309 
inject_sntp_server_reply()310 void inject_sntp_server_reply()
311 {
312 
313 UINT                    status;
314 NX_PACKET              *my_packet;
315 
316     /* Now, this packet is a received one, allocate the packet and let the IP stack receives it.  */
317     /* Allocate a packet.  */
318     status =  nx_packet_allocate(client_ip.nx_ip_default_packet_pool, &my_packet, 0,  5 * NX_IP_PERIODIC_RATE);
319 
320     /* Check status.  */
321     if (status != NX_SUCCESS)
322     {
323         error_counter++;
324         return;
325     }
326 
327     my_packet -> nx_packet_length = pkt_size - 14;
328     memcpy(my_packet -> nx_packet_prepend_ptr + 16, pkt_data + 14, my_packet -> nx_packet_length);
329     my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + my_packet -> nx_packet_length;
330 
331     my_packet -> nx_packet_prepend_ptr += 16;
332     my_packet -> nx_packet_append_ptr += 16;
333 
334     _nx_ip_packet_deferred_receive(&client_ip, my_packet);
335 
336 }
337 #else
338 
339 #ifdef CTEST
test_application_define(void * first_unused_memory)340 VOID test_application_define(void *first_unused_memory)
341 #else
342 void    netx_sntp_client_unicast_basic_test_application_define(void *first_unused_memory)
343 #endif
344 {
345 
346     /* Print out test information banner.  */
347     printf("NetX Test:   NETX SNTP Client Unicast Basic Test.......................N/A\n");
348 
349     test_control_return(3);
350 }
351 #endif
352