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