1 /*
2 * FreeRTOS V202212.00
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
24 *
25 */
26
27 /*
28 * NTPDemo.c
29 *
30 * An example of how to lookup a domain using DNS
31 * And also how to send and receive UDP messages to get the NTP time
32 *
33 */
34
35 /* Standard includes. */
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <time.h>
40
41 /* FreeRTOS includes. */
42 #include "FreeRTOS.h"
43 #include "task.h"
44 #include "semphr.h"
45
46 /* FreeRTOS+TCP includes. */
47 #include "FreeRTOS_IP.h"
48 #include "FreeRTOS_Sockets.h"
49 #include "FreeRTOS_DNS.h"
50 #include "FreeRTOS_Stream_Buffer.h"
51
52 /* Use the date & time functions from +FAT. */
53 #if ( USE_PLUS_FAT != 0 )
54 #include "ff_time.h"
55 #endif /* ( USE_PLUS_FAT != 0 ) */
56
57 #include "NTPDemo.h"
58 #include "ntpClient.h"
59
60 #include "date_and_time.h"
61
62 #if ( ipconfigDNS_USE_CALLBACKS == 0 )
63 #error ipconfigDNS_USE_CALLBACKS must be 1
64 #endif
65
66 #if ( ipconfigMULTI_INTERFACE == 0 )
67 #ifndef ipSIZE_OF_IPv4_ADDRESS
68 #define ipSIZE_OF_IPv4_ADDRESS 4
69 #endif
70 #define FREERTOS_AF_INET4 FREERTOS_AF_INET
71 #endif
72
73 /* Set time: sets the current time in seconds-after-1/1/1970
74 * This function must be provided by the application. */
75
76 time_t get_time( time_t * puxTime );
77 int set_time( const time_t * t );
78
79 enum EStatus
80 {
81 EStatusLookup,
82 EStatusAsking,
83 EStatusPause,
84 EStatusFailed,
85 };
86
87 static struct SNtpPacket xNTPPacket;
88
89 BaseType_t xNTPHasTime;
90 uint32_t ulNTPTime;
91
92 #if ( ipconfigUSE_CALLBACKS == 0 )
93 static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ];
94 #endif
95
96 static enum EStatus xStatus = EStatusLookup;
97
98 static const char * pcTimeServers[] =
99 {
100 "0.asia.pool.ntp.org",
101 "0.europe.pool.ntp.org",
102 "0.id.pool.ntp.org",
103 "0.south-america.pool.ntp.org",
104 "0.oceania.pool.ntp.org",
105 "0.north-america.pool.ntp.org"
106 };
107
108 static SemaphoreHandle_t xNTPWakeupSem = NULL;
109 static uint32_t ulIPAddressFound;
110
111 #if ( ipconfigUSE_IPv6 != 0 )
112 static struct freertos_sockaddr xIPAddressFound;
113 #endif
114 static BaseType_t xHasIPAddress = pdFALSE;
115
116 static Socket_t xUDPSocket = NULL;
117 static TaskHandle_t xNTPTaskhandle = NULL;
118 static TickType_t uxSendTime;
119 static BaseType_t xPreferredHostType = FREERTOS_AF_INET4;
120 static BaseType_t xDNSAsynchronous = pdTRUE;
121 static BaseType_t xDNSLogging = pdFALSE;
122
123 static void prvNTPTask( void * pvParameters );
124
vSignalTask(void)125 static void vSignalTask( void )
126 {
127 #if ( ipconfigUSE_CALLBACKS == 0 )
128 if( xUDPSocket != NULL )
129 {
130 /* Send a signal to the socket so that the
131 * FreeRTOS_recvfrom will get interrupted. */
132 FreeRTOS_SignalSocket( xUDPSocket );
133 }
134 else
135 #endif
136
137 if( xNTPWakeupSem != NULL )
138 {
139 xSemaphoreGive( xNTPWakeupSem );
140 }
141 }
142
vNTPClearCache(void)143 void vNTPClearCache( void )
144 {
145 ulIPAddressFound = 0U;
146 #if ( ipconfigUSE_IPv6 != 0 )
147 {
148 memset( &( xIPAddressFound ), 0, sizeof xIPAddressFound );
149 }
150 #endif
151 xHasIPAddress = pdFALSE;
152 }
153
vNTPSetNTPType(BaseType_t aIPType,BaseType_t xAsynchronous,BaseType_t xLogging)154 void vNTPSetNTPType( BaseType_t aIPType,
155 BaseType_t xAsynchronous,
156 BaseType_t xLogging )
157 {
158 switch( aIPType )
159 {
160 case 4:
161 xPreferredHostType = FREERTOS_AF_INET4;
162 break;
163
164 #if ( ipconfigUSE_IPv6 != 0 )
165 case 6:
166 xPreferredHostType = FREERTOS_AF_INET6;
167 break;
168 #endif
169 default:
170 break;
171 }
172
173 xDNSAsynchronous = xAsynchronous;
174 xDNSLogging = xLogging;
175 }
176
vStartNTPTask(uint16_t usTaskStackSize,UBaseType_t uxTaskPriority)177 void vStartNTPTask( uint16_t usTaskStackSize,
178 UBaseType_t uxTaskPriority )
179 {
180 /* The only public function in this module: start a task to contact
181 * some NTP server. */
182
183 if( xNTPTaskhandle != NULL )
184 {
185 switch( xStatus )
186 {
187 case EStatusPause:
188 xStatus = EStatusAsking;
189 vSignalTask();
190 break;
191
192 case EStatusLookup:
193 FreeRTOS_printf( ( "NTP looking up server\n" ) );
194 break;
195
196 case EStatusAsking:
197 FreeRTOS_printf( ( "NTP still asking\n" ) );
198 break;
199
200 case EStatusFailed:
201 FreeRTOS_printf( ( "NTP failed somehow\n" ) );
202 ulIPAddressFound = 0ul;
203 xStatus = EStatusLookup;
204 vSignalTask();
205 break;
206 }
207 }
208 else
209 {
210 xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
211
212 if( xUDPSocket != NULL )
213 {
214 struct freertos_sockaddr xAddress;
215 #if ( ipconfigUSE_CALLBACKS != 0 )
216 BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
217 #else
218 BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
219 #endif
220
221 xAddress.sin_address.ulIP_IPv4 = 0ul;
222 xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
223 xAddress.sin_family = FREERTOS_AF_INET;
224
225 FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );
226 FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
227 xTaskCreate( prvNTPTask, /* The function that implements the task. */
228 ( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */
229 usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
230 NULL, /* The task parameter, not used in this case. */
231 uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
232 &xNTPTaskhandle ); /* The task handle. */
233 }
234 else
235 {
236 FreeRTOS_printf( ( "Creating socket failed\n" ) );
237 }
238 }
239 }
240 /*-----------------------------------------------------------*/
241
242 #if ( ipconfigUSE_IPv6 != 0 )
vDNS_callback(const char * pcName,void * pvSearchID,struct freertos_addrinfo * pxAddress)243 static void vDNS_callback( const char * pcName,
244 void * pvSearchID,
245 struct freertos_addrinfo * pxAddress )
246 {
247 xStatus = EStatusAsking;
248
249 ( void ) pvSearchID;
250 ( void ) pcName;
251
252 if( pxAddress == NULL )
253 {
254 FreeRTOS_printf( ( "DNS lookup timed out\n" ) );
255 }
256 else
257 {
258 if( pxAddress->ai_family == FREERTOS_AF_INET4 )
259 {
260 char pcBuf[ 16 ];
261 uint32_t ulIPAddress;
262
263 /* The DNS lookup has a result, or it has reached the time-out. */
264 ulIPAddress = pxAddress->ai_addr->sin_address.ulIP_IPv4;
265 FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );
266 FreeRTOS_printf( ( "vDNS_callback: IP address of %s found: %s\n", pcName, pcBuf ) );
267
268 /* if( ulIPAddressFound == 0U ) */
269 /* { */
270 /* ulIPAddressFound = FreeRTOS_inet_addr_quick( 162, 159, 200, 1 ); */
271 /* } */
272 if( ulIPAddressFound != 0U )
273 {
274 memset( xIPAddressFound.sin_address.xIP_IPv6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS );
275 xHasIPAddress = pdTRUE;
276 }
277 }
278 else if( pxAddress->ai_family == FREERTOS_AF_INET6 )
279 {
280 /* struct freertos_sockaddr * ai_addr */
281 struct freertos_sockaddr * sockaddr6 = ( struct freertos_sockaddr * ) pxAddress->ai_addr;
282
283 xIPAddressFound.sin_len = sizeof( xIPAddressFound ); /* Ignored, still present for backward compatibility. */
284 xIPAddressFound.sin_family = FREERTOS_AF_INET6; /* Set to FREERTOS_AF_INET6. */
285 xIPAddressFound.sin_port = FreeRTOS_htons( NTP_PORT );
286 xIPAddressFound.sin_flowinfo = 0; /* IPv6 flow information. */
287 memcpy( xIPAddressFound.sin_address.xIP_IPv6.ucBytes, sockaddr6->sin_address.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
288
289 FreeRTOS_printf( ( "vDNS_callback: using address %pip\n", xIPAddressFound.sin_address.xIP_IPv6.ucBytes ) );
290 ulIPAddressFound = 0U;
291 xHasIPAddress = pdTRUE;
292 }
293 }
294
295 vSignalTask();
296 }
297 #else /* if ( ipconfigUSE_IPv6 != 0 ) */
vDNS_callback(const char * pcName,void * pvSearchID,uint32_t ulIPAddress)298 static void vDNS_callback( const char * pcName,
299 void * pvSearchID,
300 uint32_t ulIPAddress )
301 {
302 char pcBuf[ 16 ];
303
304 /* The DNS lookup has a result, or it has reached the time-out. */
305 FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );
306 FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) );
307
308 if( ulIPAddressFound == 0U )
309 {
310 ulIPAddressFound = ulIPAddress;
311 }
312
313 /* For testing: in case DNS doesn't respond, still try some NTP server
314 * with a known IP-address. */
315 /* if( ulIPAddressFound == 0U ) */
316 /* { */
317 /* ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 ); */
318 /* / * ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); * / */
319 /* } */
320 if( ulIPAddressFound != 0U )
321 {
322 xHasIPAddress = pdTRUE;
323 xStatus = EStatusAsking;
324 }
325
326 vSignalTask();
327 }
328 #endif /* if ( ipconfigUSE_IPv6 != 0 ) */
329 /*-----------------------------------------------------------*/
330
prvSwapFields(struct SNtpPacket * pxPacket)331 static void prvSwapFields( struct SNtpPacket * pxPacket )
332 {
333 /* NTP messages are big-endian */
334 pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay );
335 pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion );
336
337 pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds );
338 pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction );
339
340 pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds );
341 pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction );
342
343 pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds );
344 pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction );
345
346 pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds );
347 pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction );
348 }
349 /*-----------------------------------------------------------*/
350
prvNTPPacketInit()351 static void prvNTPPacketInit()
352 {
353 memset( &xNTPPacket, '\0', sizeof( xNTPPacket ) );
354
355 xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */
356 xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */
357 xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */
358 xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */
359 xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */
360
361 /* use the recorded NTP time */
362 time_t uxSecs = get_time( NULL ); /* apTime may be NULL, returns seconds */
363
364 xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */
365 xNTPPacket.transmitTimestamp.seconds = uxSecs + 3;
366
367 /* Transform the contents of the fields from native to big endian. */
368 prvSwapFields( &xNTPPacket );
369 }
370 /*-----------------------------------------------------------*/
371
prvReadTime(struct SNtpPacket * pxPacket)372 static void prvReadTime( struct SNtpPacket * pxPacket )
373 {
374 #if ( USE_PLUS_FAT != 0 )
375 FF_TimeStruct_t xTimeStruct;
376 #else
377 struct tm xTimeStruct;
378 #endif
379
380 time_t uxPreviousSeconds;
381 time_t uxPreviousMS;
382
383 time_t uxCurrentSeconds;
384 time_t uxCurrentMS;
385
386 const char * pcTimeUnit;
387 int32_t ilDiff;
388 TickType_t uxTravelTime;
389
390 uxTravelTime = xTaskGetTickCount() - uxSendTime;
391
392 /* Transform the contents of the fields from big to native endian. */
393 prvSwapFields( pxPacket );
394
395 uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970;
396 uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967;
397 uxCurrentSeconds += uxCurrentMS / 1000;
398 uxCurrentMS = uxCurrentMS % 1000;
399
400 /* Get the last time recorded */
401 uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS );
402
403 /* Set the new time with precision in msec. * / */
404 FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS );
405
406 if( uxCurrentSeconds >= uxPreviousSeconds )
407 {
408 ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds );
409 }
410 else
411 {
412 ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds );
413 }
414
415 if( ( ilDiff < -5 ) || ( ilDiff > 5 ) )
416 {
417 /* More than 5 seconds difference. */
418 pcTimeUnit = "sec";
419 }
420 else
421 {
422 /* Less than or equal to 5 second difference. */
423 pcTimeUnit = "ms";
424 uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds;
425 int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS;
426 int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS;
427 ilDiff = iCurMS - iPrevMS;
428 }
429
430 /*uxCurrentSeconds -= iTimeZone; */
431
432 #if ( USE_PLUS_FAT != 0 )
433 FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct );
434 #else
435 extern struct tm * gmtime_r( const time_t * pxTime,
436 struct tm * tmStruct );
437 gmtime_r( &uxCurrentSeconds, &xTimeStruct );
438 #endif /* ( USE_PLUS_FAT != 0 ) */
439
440 /*
441 * 378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)
442 * 379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)
443 */
444 /* NTP time: -858993460/-858993459/-858991560 -858993460:-858993460:-858993460.158 Diff 1607503255 sec (60 ms) */
445 FreeRTOS_printf( ( "NTP time: %u/%u/%02u %2u:%02u:%02u.%03u Diff %d %s (%lu ms)\n",
446 ( unsigned ) xTimeStruct.tm_mday,
447 ( unsigned ) xTimeStruct.tm_mon + 1,
448 ( unsigned ) xTimeStruct.tm_year + 1900,
449 ( unsigned ) xTimeStruct.tm_hour,
450 ( unsigned ) xTimeStruct.tm_min,
451 ( unsigned ) xTimeStruct.tm_sec,
452 ( unsigned ) uxCurrentMS,
453 ( signed ) ilDiff,
454 pcTimeUnit,
455 uxTravelTime ) );
456
457 xNTPHasTime = pdTRUE;
458 ulNTPTime = uxCurrentSeconds;
459 set_time( &uxCurrentSeconds );
460
461 /* Remove compiler warnings in case FreeRTOS_printf() is not used. */
462 ( void ) pcTimeUnit;
463 ( void ) uxTravelTime;
464 }
465 /*-----------------------------------------------------------*/
466
467 #if ( ipconfigUSE_CALLBACKS != 0 )
468
xOnUDPReceive(Socket_t xSocket,void * pvData,size_t xLength,const struct freertos_sockaddr * pxFrom,const struct freertos_sockaddr * pxDest)469 static BaseType_t xOnUDPReceive( Socket_t xSocket,
470 void * pvData,
471 size_t xLength,
472 const struct freertos_sockaddr * pxFrom,
473 const struct freertos_sockaddr * pxDest )
474 {
475 ( void ) xSocket;
476 ( void ) pxFrom;
477 ( void ) pxDest;
478
479 if( xLength >= sizeof( xNTPPacket ) )
480 {
481 prvReadTime( ( struct SNtpPacket * ) pvData );
482
483 if( xStatus != EStatusPause )
484 {
485 xStatus = EStatusPause;
486 }
487 }
488
489 vSignalTask();
490 /* Tell the driver not to store the RX data */
491 return 1;
492 }
493 /*-----------------------------------------------------------*/
494
495 #endif /* ipconfigUSE_CALLBACKS != 0 */
496
prvNTPTask(void * pvParameters)497 static void prvNTPTask( void * pvParameters )
498 {
499 BaseType_t xServerIndex = 3;
500 struct freertos_sockaddr xAddress;
501
502 #if ( ipconfigUSE_CALLBACKS != 0 )
503 F_TCP_UDP_Handler_t xHandler;
504 #endif /* ipconfigUSE_CALLBACKS != 0 */
505
506 ( void ) pvParameters;
507
508 xStatus = EStatusLookup;
509 #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 )
510 {
511 xNTPWakeupSem = xSemaphoreCreateBinary();
512 }
513 #endif
514
515 #if ( ipconfigUSE_CALLBACKS != 0 )
516 {
517 memset( &xHandler, '\0', sizeof( xHandler ) );
518 xHandler.pxOnUDPReceive = xOnUDPReceive;
519 FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
520 }
521 #endif
522 #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
523 {
524 FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
525 }
526 #endif
527
528 for( ; ; )
529 {
530 switch( xStatus )
531 {
532 case EStatusLookup:
533
534 if( xHasIPAddress == 0 )
535 {
536 char pcServerName[ 64 ];
537
538 if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )
539 {
540 xServerIndex = 0;
541 }
542
543 snprintf( pcServerName, sizeof pcServerName, "%s", pcTimeServers[ xServerIndex ] );
544
545 if( ( pcServerName[ 0 ] == '0' ) && ( xPreferredHostType == FREERTOS_AF_INET6 ) )
546 {
547 pcServerName[ 0 ] = '2';
548 }
549
550 FreeRTOS_printf( ( "Looking up server '%s' IPv%c\n",
551 pcServerName,
552 ( xPreferredHostType == FREERTOS_AF_INET4 ) ? '4' : '6' ) );
553 #if ( ipconfigMULTI_INTERFACE != 0 )
554 struct freertos_addrinfo xHints;
555 struct freertos_addrinfo * pxResults = NULL;
556
557 memset( &( xHints ), 0, sizeof xHints );
558 xHints.ai_family = xPreferredHostType;
559
560 if( xDNSAsynchronous != 0 )
561 {
562 FreeRTOS_getaddrinfo_a( pcServerName, /* The name of the node or device */
563 NULL, /* Ignored for now. */
564 &( xHints ), /* If not NULL: preferences. */
565 &( pxResults ), /* An allocated struct, containing the results. */
566 vDNS_callback,
567 ( void * ) NULL, /* An object or a reference. */
568 pdMS_TO_TICKS( 2500U ) );
569 }
570 else
571 {
572 FreeRTOS_getaddrinfo( pcServerName, /* The name of the node or device */
573 NULL, /* Ignored for now. */
574 &( xHints ), /* If not NULL: preferences. */
575 &( pxResults ) ); /* An allocated struct, containing the results. */
576
577 if( pxResults != NULL )
578 {
579 vDNS_callback( pcServerName, NULL, pxResults );
580 }
581 }
582 #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */
583 FreeRTOS_gethostbyname_a( pcServerName, vDNS_callback, ( void * ) NULL, 1200 );
584 #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */
585 }
586 else
587 {
588 xStatus = EStatusAsking;
589 }
590
591 break;
592
593 case EStatusAsking:
594 prvNTPPacketInit();
595 uxSendTime = xTaskGetTickCount();
596 #if ( ipconfigUSE_IPv6 != 0 )
597 if( memcmp( xIPAddressFound.sin_address.xIP_IPv6.ucBytes, FreeRTOS_in6addr_any.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 )
598 {
599 FreeRTOS_printf( ( "Sending UDP message to %pip:%u\n",
600 xIPAddressFound.sin_address.xIP_IPv6.ucBytes,
601 FreeRTOS_ntohs( xIPAddressFound.sin_port ) ) );
602
603 FreeRTOS_sendto( xUDPSocket,
604 ( void * ) &xNTPPacket, sizeof( xNTPPacket ),
605 0,
606 ( const struct freertos_sockaddr * ) &( xIPAddressFound ),
607 sizeof( xIPAddressFound ) );
608 }
609 else
610 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
611 {
612 xAddress.sin_address.ulIP_IPv4 = ulIPAddressFound;
613 xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
614 xAddress.sin_family = FREERTOS_AF_INET;
615
616 FreeRTOS_printf( ( "Sending UDP message to %lxip:%u\n",
617 FreeRTOS_ntohl( ulIPAddressFound ),
618 FreeRTOS_ntohs( xAddress.sin_port ) ) );
619
620 FreeRTOS_sendto( xUDPSocket,
621 ( void * ) &xNTPPacket,
622 sizeof( xNTPPacket ),
623 0, &( xAddress ),
624 sizeof( xAddress ) );
625 }
626
627 break;
628
629 case EStatusPause:
630 break;
631
632 case EStatusFailed:
633 break;
634 }
635
636 #if ( ipconfigUSE_CALLBACKS != 0 )
637 {
638 xSemaphoreTake( xNTPWakeupSem, 5000 );
639 }
640 #else
641 {
642 uint32_t xAddressSize;
643 BaseType_t xReturned;
644
645 xAddressSize = sizeof( xAddress );
646 xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );
647
648 switch( xReturned )
649 {
650 case 0:
651 case -pdFREERTOS_ERRNO_EAGAIN:
652 case -pdFREERTOS_ERRNO_EINTR:
653 break;
654
655 default:
656
657 if( xReturned < sizeof( xNTPPacket ) )
658 {
659 FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) );
660 }
661 else
662 {
663 prvReadTime( ( struct SNtpPacket * ) cRecvBuffer );
664
665 if( xStatus != EStatusPause )
666 {
667 xStatus = EStatusPause;
668 }
669 }
670
671 break;
672 }
673 }
674 #endif /* if ( ipconfigUSE_CALLBACKS != 0 ) */
675 }
676 }
677 /*-----------------------------------------------------------*/
678