test code for our MBED board

Dependencies:   mbed lwip

Committer:
lolpcc
Date:
Wed May 04 08:30:52 2011 +0000
Revision:
1:6877bb99aa17

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lolpcc 1:6877bb99aa17 1 /*
lolpcc 1:6877bb99aa17 2 * @file
lolpcc 1:6877bb99aa17 3 *SNTP client module
lolpcc 1:6877bb99aa17 4 *
lolpcc 1:6877bb99aa17 5 */
lolpcc 1:6877bb99aa17 6
lolpcc 1:6877bb99aa17 7
lolpcc 1:6877bb99aa17 8 /*
lolpcc 1:6877bb99aa17 9 * Redistribution and use in source and binary forms, with or without modification,
lolpcc 1:6877bb99aa17 10 * are permitted provided that the following conditions are met:
lolpcc 1:6877bb99aa17 11 *
lolpcc 1:6877bb99aa17 12 * 1. Redistributions of source code must retain the above copyright notice,
lolpcc 1:6877bb99aa17 13 * this list of conditions and the following disclaimer.
lolpcc 1:6877bb99aa17 14 * 2. Redistributions in binary form must reproduce the above copyright notice,
lolpcc 1:6877bb99aa17 15 * this list of conditions and the following disclaimer in the documentation
lolpcc 1:6877bb99aa17 16 * and/or other materials provided with the distribution.
lolpcc 1:6877bb99aa17 17 * 3. The name of the author may not be used to endorse or promote products
lolpcc 1:6877bb99aa17 18 * derived from this software without specific prior written permission.
lolpcc 1:6877bb99aa17 19 *
lolpcc 1:6877bb99aa17 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
lolpcc 1:6877bb99aa17 21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
lolpcc 1:6877bb99aa17 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
lolpcc 1:6877bb99aa17 23 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
lolpcc 1:6877bb99aa17 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
lolpcc 1:6877bb99aa17 25 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
lolpcc 1:6877bb99aa17 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
lolpcc 1:6877bb99aa17 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
lolpcc 1:6877bb99aa17 28 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
lolpcc 1:6877bb99aa17 29 * OF SUCH DAMAGE.
lolpcc 1:6877bb99aa17 30 *
lolpcc 1:6877bb99aa17 31 * This file is part of the lwIP TCP/IP stack.
lolpcc 1:6877bb99aa17 32 *
lolpcc 1:6877bb99aa17 33 * Author: Simon Goldschmidt (lwIP raw API part)
lolpcc 1:6877bb99aa17 34 */
lolpcc 1:6877bb99aa17 35
lolpcc 1:6877bb99aa17 36 #include "lwip/opt.h"
lolpcc 1:6877bb99aa17 37
lolpcc 1:6877bb99aa17 38 //#include "sntp.h"
lolpcc 1:6877bb99aa17 39
lolpcc 1:6877bb99aa17 40 #include "lwip/sys.h"
lolpcc 1:6877bb99aa17 41 #include "lwip/sockets.h"
lolpcc 1:6877bb99aa17 42 #include "lwip/udp.h"
lolpcc 1:6877bb99aa17 43 #include "lwip/dns.h"
lolpcc 1:6877bb99aa17 44
lolpcc 1:6877bb99aa17 45 #include "sntp.h" // [iva2k] moving below for re-defines
lolpcc 1:6877bb99aa17 46 #include "useful.h"
lolpcc 1:6877bb99aa17 47 #include <string.h>
lolpcc 1:6877bb99aa17 48 #include <time.h>
lolpcc 1:6877bb99aa17 49 #define static
lolpcc 1:6877bb99aa17 50
lolpcc 1:6877bb99aa17 51 /** This is simple "SNTP" client for socket or raw API.
lolpcc 1:6877bb99aa17 52 * It is a minimal implementation of SNTPv4 as specified in RFC 4330.
lolpcc 1:6877bb99aa17 53 *
lolpcc 1:6877bb99aa17 54 * For a list of some public NTP servers, see this link :
lolpcc 1:6877bb99aa17 55 * http://support.ntp.org/bin/view/Servers/NTPPoolServers
lolpcc 1:6877bb99aa17 56 *
lolpcc 1:6877bb99aa17 57 * @todo:
lolpcc 1:6877bb99aa17 58 * - set/change servers at runtime
lolpcc 1:6877bb99aa17 59 * - complete SNTP_CHECK_RESPONSE checks 3 and 4
lolpcc 1:6877bb99aa17 60 * - support broadcast/multicast mo
lolpcc 1:6877bb99aa17 61 */
lolpcc 1:6877bb99aa17 62
lolpcc 1:6877bb99aa17 63
lolpcc 1:6877bb99aa17 64
lolpcc 1:6877bb99aa17 65 /** Decide whether to build SNTP for socket or raw API
lolpcc 1:6877bb99aa17 66 * The socket API SNTP client is a very minimal implementation that does no
lolpcc 1:6877bb99aa17 67 * fully confor to the SNTPv4 RFC, especially regarding server load and error
lolpcc 1:6877bb99aa17 68 * procesing. */
lolpcc 1:6877bb99aa17 69 #ifndef SNTP_SOCKET
lolpcc 1:6877bb99aa17 70 #define SNTP_SOCKET 0
lolpcc 1:6877bb99aa17 71 #endif
lolpcc 1:6877bb99aa17 72
lolpcc 1:6877bb99aa17 73 /**
lolpcc 1:6877bb99aa17 74 * SNTP_DEBUG: Enable debugging for SNTP.
lolpcc 1:6877bb99aa17 75 */
lolpcc 1:6877bb99aa17 76 #ifndef SNTP_DEBUG
lolpcc 1:6877bb99aa17 77 #define SNTP_DEBUG LWIP_DBG_OFF
lolpcc 1:6877bb99aa17 78 #endif
lolpcc 1:6877bb99aa17 79
lolpcc 1:6877bb99aa17 80 /** SNTP server port */
lolpcc 1:6877bb99aa17 81 #ifndef SNTP_PORT
lolpcc 1:6877bb99aa17 82 #define SNTP_PORT 123
lolpcc 1:6877bb99aa17 83 #endif
lolpcc 1:6877bb99aa17 84
lolpcc 1:6877bb99aa17 85
lolpcc 1:6877bb99aa17 86
lolpcc 1:6877bb99aa17 87 /** Set this to 1 to allow SNTP_SERVER_ADDRESS to be a DNS name */
lolpcc 1:6877bb99aa17 88
lolpcc 1:6877bb99aa17 89 #ifndef SNTP_SERVER_DNS
lolpcc 1:6877bb99aa17 90 #define SNTP_SERVER_DNS 0
lolpcc 1:6877bb99aa17 91 #endif
lolpcc 1:6877bb99aa17 92
lolpcc 1:6877bb99aa17 93 /** Set this to 1 to support more than one server */
lolpcc 1:6877bb99aa17 94 #ifndef SNTP_SUPPORT_MULTIPLE_SERVERS
lolpcc 1:6877bb99aa17 95 #define SNTP_SUPPORT_MULTIPLE_SERVERS 1
lolpcc 1:6877bb99aa17 96 #endif
lolpcc 1:6877bb99aa17 97
lolpcc 1:6877bb99aa17 98 /** SNTP server address:
lolpcc 1:6877bb99aa17 99 * - as IPv4 address in "u32_t" format
lolpcc 1:6877bb99aa17 100 * - as a DNS name if SNTP_SERVER_DNS is set to 1
lolpcc 1:6877bb99aa17 101 * May contain multiple server names (e.g. "pool.ntp.org","second.time.server")
lolpcc 1:6877bb99aa17 102 */
lolpcc 1:6877bb99aa17 103 #ifndef SNTP_SERVER_ADDRESS
lolpcc 1:6877bb99aa17 104 #if SNTP_SERVER_DNS
lolpcc 1:6877bb99aa17 105 #define SNTP_SERVER_ADDRESS "pool.ntp.org"
lolpcc 1:6877bb99aa17 106 #else
lolpcc 1:6877bb99aa17 107 #define SNTP_SERVER_ADDRESS "213.161.194.93" /* pool.ntp.org */
lolpcc 1:6877bb99aa17 108 #endif
lolpcc 1:6877bb99aa17 109 #endif
lolpcc 1:6877bb99aa17 110
lolpcc 1:6877bb99aa17 111 /** Sanity check:
lolpcc 1:6877bb99aa17 112 * Define this to
lolpcc 1:6877bb99aa17 113 * - 0 to turn off sanity checks (default; smaller code)
lolpcc 1:6877bb99aa17 114 * - >= 1 to check address and port of the response packet to ensure the
lolpcc 1:6877bb99aa17 115 * response comes from the server we sent the request to.
lolpcc 1:6877bb99aa17 116 * - >= 2 to check returned Originate Timestamp against Transmit Timestamp
lolpcc 1:6877bb99aa17 117 * sent to the server (to ensure response to older request).
lolpcc 1:6877bb99aa17 118 * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp
lolpcc 1:6877bb99aa17 119 * fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast).
lolpcc 1:6877bb99aa17 120 * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each
lolpcc 1:6877bb99aa17 121 * greater than or equal to 0 and less than infinity, where infinity is
lolpcc 1:6877bb99aa17 122 * currently a cozy number like one second. This check avoids using a
lolpcc 1:6877bb99aa17 123 * server whose synchronization source has expired for a very long time.
lolpcc 1:6877bb99aa17 124 */
lolpcc 1:6877bb99aa17 125 #ifndef SNTP_CHECK_RESPONSE
lolpcc 1:6877bb99aa17 126 #define SNTP_CHECK_RESPONSE 0
lolpcc 1:6877bb99aa17 127 #endif
lolpcc 1:6877bb99aa17 128
lolpcc 1:6877bb99aa17 129 /** According to the RFC, this shall be a random delay
lolpcc 1:6877bb99aa17 130 * between 1 and 5 minutes (in milliseconds) to prevent load peaks.
lolpcc 1:6877bb99aa17 131 * This can be defined to a random generation function,
lolpcc 1:6877bb99aa17 132 * which must return the delay in milliseconds as u32_t.
lolpcc 1:6877bb99aa17 133 * Turned off by default.
lolpcc 1:6877bb99aa17 134 */
lolpcc 1:6877bb99aa17 135 #ifndef SNTP_STARTUP_DELAY
lolpcc 1:6877bb99aa17 136 #define SNTP_STARTUP_DELAY 0
lolpcc 1:6877bb99aa17 137 #endif
lolpcc 1:6877bb99aa17 138
lolpcc 1:6877bb99aa17 139 /** SNTP receive timeout - in milliseconds
lolpcc 1:6877bb99aa17 140 * Also used as retry timeout - this shouldn't be too low.
lolpcc 1:6877bb99aa17 141 * Default is 3 seconds.
lolpcc 1:6877bb99aa17 142 */
lolpcc 1:6877bb99aa17 143 #ifndef SNTP_RECV_TIMEOUT
lolpcc 1:6877bb99aa17 144 #define SNTP_RECV_TIMEOUT 3000
lolpcc 1:6877bb99aa17 145 #endif
lolpcc 1:6877bb99aa17 146
lolpcc 1:6877bb99aa17 147 /** SNTP update delay - in milliseconds
lolpcc 1:6877bb99aa17 148 * Default is 1 hour.
lolpcc 1:6877bb99aa17 149 */
lolpcc 1:6877bb99aa17 150 #ifndef SNTP_UPDATE_DELAY
lolpcc 1:6877bb99aa17 151 #define SNTP_UPDATE_DELAY 3600000
lolpcc 1:6877bb99aa17 152 #endif
lolpcc 1:6877bb99aa17 153 #if (SNTP_UPDATE_DELAY < 15000) && !SNTP_SUPPRESS_DELAY_CHECK
lolpcc 1:6877bb99aa17 154 #error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds!"
lolpcc 1:6877bb99aa17 155 #endif
lolpcc 1:6877bb99aa17 156
lolpcc 1:6877bb99aa17 157 /** SNTP macro to change system time and/or the update the RTC clock */
lolpcc 1:6877bb99aa17 158 #ifndef SNTP_SET_SYSTEM_TIME
lolpcc 1:6877bb99aa17 159 #define SNTP_SET_SYSTEM_TIME(sec)
lolpcc 1:6877bb99aa17 160 #endif
lolpcc 1:6877bb99aa17 161
lolpcc 1:6877bb99aa17 162 /** SNTP macro to change system time including microseconds */
lolpcc 1:6877bb99aa17 163 #ifdef SNTP_SET_SYSTEM_TIME_US
lolpcc 1:6877bb99aa17 164 #define SNTP_CALC_TIME_US 1
lolpcc 1:6877bb99aa17 165 #define SNTP_RECEIVE_TIME_SIZE 2
lolpcc 1:6877bb99aa17 166 #else
lolpcc 1:6877bb99aa17 167 #define SNTP_SET_SYSTEM_TIME_US(sec, us)
lolpcc 1:6877bb99aa17 168 #define SNTP_CALC_TIME_US 0
lolpcc 1:6877bb99aa17 169 #define SNTP_RECEIVE_TIME_SIZE 1
lolpcc 1:6877bb99aa17 170 #endif
lolpcc 1:6877bb99aa17 171
lolpcc 1:6877bb99aa17 172 /** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2
lolpcc 1:6877bb99aa17 173 * to send in request and compare in response.
lolpcc 1:6877bb99aa17 174 */
lolpcc 1:6877bb99aa17 175 #ifndef SNTP_GET_SYSTEM_TIME
lolpcc 1:6877bb99aa17 176 #define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0)
lolpcc 1:6877bb99aa17 177 #endif
lolpcc 1:6877bb99aa17 178
lolpcc 1:6877bb99aa17 179 /** Default retry timeout (in milliseconds) if the response
lolpcc 1:6877bb99aa17 180 * received is invalid.
lolpcc 1:6877bb99aa17 181 * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached.
lolpcc 1:6877bb99aa17 182 */
lolpcc 1:6877bb99aa17 183 #ifndef SNTP_RETRY_TIMEOUT
lolpcc 1:6877bb99aa17 184 #define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT
lolpcc 1:6877bb99aa17 185 #endif
lolpcc 1:6877bb99aa17 186
lolpcc 1:6877bb99aa17 187 /** Maximum retry timeout (in milliseconds). */
lolpcc 1:6877bb99aa17 188 #ifndef SNTP_RETRY_TIMEOUT_MAX
lolpcc 1:6877bb99aa17 189 #define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10)
lolpcc 1:6877bb99aa17 190 #endif
lolpcc 1:6877bb99aa17 191
lolpcc 1:6877bb99aa17 192 /** Increase retry timeout with every retry sent
lolpcc 1:6877bb99aa17 193 * Default is on to conform to RFC.
lolpcc 1:6877bb99aa17 194 */
lolpcc 1:6877bb99aa17 195 #ifndef SNTP_RETRY_TIMEOUT_EXP
lolpcc 1:6877bb99aa17 196 #define SNTP_RETRY_TIMEOUT_EXP 1
lolpcc 1:6877bb99aa17 197 #endif
lolpcc 1:6877bb99aa17 198
lolpcc 1:6877bb99aa17 199 /* the various debug levels for this file */
lolpcc 1:6877bb99aa17 200 #define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE)
lolpcc 1:6877bb99aa17 201 #define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE)
lolpcc 1:6877bb99aa17 202 #define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
lolpcc 1:6877bb99aa17 203 #define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
lolpcc 1:6877bb99aa17 204 #define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
lolpcc 1:6877bb99aa17 205
lolpcc 1:6877bb99aa17 206 #define SNTP_ERR_KOD 1
lolpcc 1:6877bb99aa17 207
lolpcc 1:6877bb99aa17 208 /* SNTP protocol defines */
lolpcc 1:6877bb99aa17 209 #define SNTP_MSG_LEN 48
lolpcc 1:6877bb99aa17 210
lolpcc 1:6877bb99aa17 211 #define SNTP_OFFSET_LI_VN_MODE 0
lolpcc 1:6877bb99aa17 212 #define SNTP_LI_MASK 0xC0
lolpcc 1:6877bb99aa17 213 #define SNTP_LI_NO_WARNING 0x00
lolpcc 1:6877bb99aa17 214 #define SNTP_LI_LAST_MINUTE_61_SEC 0x01
lolpcc 1:6877bb99aa17 215 #define SNTP_LI_LAST_MINUTE_59_SEC 0x02
lolpcc 1:6877bb99aa17 216 #define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */
lolpcc 1:6877bb99aa17 217
lolpcc 1:6877bb99aa17 218 #define SNTP_VERSION_MASK 0x38
lolpcc 1:6877bb99aa17 219 #define SNTP_VERSION (4/* NTP Version 4*/<<3)
lolpcc 1:6877bb99aa17 220
lolpcc 1:6877bb99aa17 221 #define SNTP_MODE_MASK 0x07
lolpcc 1:6877bb99aa17 222 #define SNTP_MODE_CLIENT 0x03
lolpcc 1:6877bb99aa17 223 #define SNTP_MODE_SERVER 0x04
lolpcc 1:6877bb99aa17 224 #define SNTP_MODE_BROADCAST 0x05
lolpcc 1:6877bb99aa17 225
lolpcc 1:6877bb99aa17 226 #define SNTP_OFFSET_STRATUM 1
lolpcc 1:6877bb99aa17 227 #define SNTP_STRATUM_KOD 0x00
lolpcc 1:6877bb99aa17 228
lolpcc 1:6877bb99aa17 229 #define SNTP_OFFSET_ORIGINATE_TIME 24
lolpcc 1:6877bb99aa17 230 #define SNTP_OFFSET_RECEIVE_TIME 32
lolpcc 1:6877bb99aa17 231 #define SNTP_OFFSET_TRANSMIT_TIME 40
lolpcc 1:6877bb99aa17 232
lolpcc 1:6877bb99aa17 233 /* number of seconds between 1900 and 1970 */
lolpcc 1:6877bb99aa17 234 #define DIFF_SEC_1900_1970 (2208988800)
lolpcc 1:6877bb99aa17 235
lolpcc 1:6877bb99aa17 236
lolpcc 1:6877bb99aa17 237 /**
lolpcc 1:6877bb99aa17 238 * SNTP packet format (without optional fields)
lolpcc 1:6877bb99aa17 239 * Timestamps are coded as 64 bits:
lolpcc 1:6877bb99aa17 240 * - 32 bits seconds since Jan 01, 1970, 00:00
lolpcc 1:6877bb99aa17 241 * - 32 bits seconds fraction (0-padded)
lolpcc 1:6877bb99aa17 242 * For future use, if the MSB in the seconds part is set, seconds are based
lolpcc 1:6877bb99aa17 243 * on Feb 07, 2036, 06:28:16.
lolpcc 1:6877bb99aa17 244 */
lolpcc 1:6877bb99aa17 245 #ifdef PACK_STRUCT_USE_INCLUDES
lolpcc 1:6877bb99aa17 246 # include "arch/bpstruct.h"
lolpcc 1:6877bb99aa17 247 #endif
lolpcc 1:6877bb99aa17 248 PACK_STRUCT_BEGIN
lolpcc 1:6877bb99aa17 249 struct sntp_msg {
lolpcc 1:6877bb99aa17 250 PACK_STRUCT_FIELD(u8_t li_vn_mode);
lolpcc 1:6877bb99aa17 251 PACK_STRUCT_FIELD(u8_t stratum);
lolpcc 1:6877bb99aa17 252 PACK_STRUCT_FIELD(u8_t poll);
lolpcc 1:6877bb99aa17 253 PACK_STRUCT_FIELD(u8_t precision);
lolpcc 1:6877bb99aa17 254 PACK_STRUCT_FIELD(u32_t root_delay);
lolpcc 1:6877bb99aa17 255 PACK_STRUCT_FIELD(u32_t root_dispersion);
lolpcc 1:6877bb99aa17 256 PACK_STRUCT_FIELD(u32_t reference_identifier);
lolpcc 1:6877bb99aa17 257 PACK_STRUCT_FIELD(u32_t reference_timestamp[2]);
lolpcc 1:6877bb99aa17 258 PACK_STRUCT_FIELD(u32_t originate_timestamp[2]);
lolpcc 1:6877bb99aa17 259 PACK_STRUCT_FIELD(u32_t receive_timestamp[2]);
lolpcc 1:6877bb99aa17 260 PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]);
lolpcc 1:6877bb99aa17 261 } PACK_STRUCT_STRUCT;
lolpcc 1:6877bb99aa17 262 PACK_STRUCT_END
lolpcc 1:6877bb99aa17 263 #ifdef PACK_STRUCT_USE_INCLUDES
lolpcc 1:6877bb99aa17 264 # include "arch/epstruct.h"
lolpcc 1:6877bb99aa17 265 #endif
lolpcc 1:6877bb99aa17 266
lolpcc 1:6877bb99aa17 267 /* function prototypes */
lolpcc 1:6877bb99aa17 268 static void sntp_request(void *arg);
lolpcc 1:6877bb99aa17 269
lolpcc 1:6877bb99aa17 270 /** The UDP pcb used by the SNTP client */
lolpcc 1:6877bb99aa17 271 static struct udp_pcb* sntp_pcb;
lolpcc 1:6877bb99aa17 272 /** Addresses of servers */
lolpcc 1:6877bb99aa17 273 static char* sntp_server_addresses[] = {SNTP_SERVER_ADDRESS};
lolpcc 1:6877bb99aa17 274 #if SNTP_SUPPORT_MULTIPLE_SERVERS
lolpcc 1:6877bb99aa17 275 /** The currently used server (initialized to 0) */
lolpcc 1:6877bb99aa17 276 static u8_t sntp_current_server;
lolpcc 1:6877bb99aa17 277 static u8_t sntp_num_servers = sizeof(sntp_server_addresses)/sizeof(char*);
lolpcc 1:6877bb99aa17 278 #else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
lolpcc 1:6877bb99aa17 279 #define sntp_current_server 0
lolpcc 1:6877bb99aa17 280 #endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
lolpcc 1:6877bb99aa17 281
lolpcc 1:6877bb99aa17 282 #if SNTP_RETRY_TIMEOUT_EXP
lolpcc 1:6877bb99aa17 283 #define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT
lolpcc 1:6877bb99aa17 284 /** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */
lolpcc 1:6877bb99aa17 285 static u32_t sntp_retry_timeout;
lolpcc 1:6877bb99aa17 286 #else /* SNTP_RETRY_TIMEOUT_EXP */
lolpcc 1:6877bb99aa17 287 #define SNTP_RESET_RETRY_TIMEOUT()
lolpcc 1:6877bb99aa17 288 #define sntp_retry_timeout SNTP_RETRY_TIMEOUT
lolpcc 1:6877bb99aa17 289 #endif /* SNTP_RETRY_TIMEOUT_EXP */
lolpcc 1:6877bb99aa17 290
lolpcc 1:6877bb99aa17 291 #if SNTP_CHECK_RESPONSE >= 1
lolpcc 1:6877bb99aa17 292 /** Saves the last server address to compare with response */
lolpcc 1:6877bb99aa17 293 static struct ip_addr sntp_last_server_address;
lolpcc 1:6877bb99aa17 294 #endif /* SNTP_CHECK_RESPONSE >= 1 */
lolpcc 1:6877bb99aa17 295
lolpcc 1:6877bb99aa17 296 #if SNTP_CHECK_RESPONSE >= 2
lolpcc 1:6877bb99aa17 297 /** Saves the last timestamp sent (which is sent back by the server)
lolpcc 1:6877bb99aa17 298 * to compare against in response */
lolpcc 1:6877bb99aa17 299 static u32_t sntp_last_timestamp_sent[2];
lolpcc 1:6877bb99aa17 300 #endif /* SNTP_CHECK_RESPONSE >= 2 */
lolpcc 1:6877bb99aa17 301
lolpcc 1:6877bb99aa17 302 /**
lolpcc 1:6877bb99aa17 303 * SNTP processing of received timestamp
lolpcc 1:6877bb99aa17 304 */
lolpcc 1:6877bb99aa17 305 static void
lolpcc 1:6877bb99aa17 306 sntp_process(u32_t *receive_timestamp)
lolpcc 1:6877bb99aa17 307 {
lolpcc 1:6877bb99aa17 308 /* convert SNTP time (1900-based) to unix GMT time (1970-based)
lolpcc 1:6877bb99aa17 309 * @todo: if MSB is 1, SNTP time is 2036-based!
lolpcc 1:6877bb99aa17 310 */
lolpcc 1:6877bb99aa17 311 time_t t = (ntohl(receive_timestamp[0]) - DIFF_SEC_1900_1970);
lolpcc 1:6877bb99aa17 312
lolpcc 1:6877bb99aa17 313 #if SNTP_CALC_TIME_US
lolpcc 1:6877bb99aa17 314 u32_t us = ntohl(receive_timestamp[1]) / 4295;
lolpcc 1:6877bb99aa17 315 SNTP_SET_SYSTEM_TIME_US(t, us);
lolpcc 1:6877bb99aa17 316 /* display local time from GMT time */
lolpcc 1:6877bb99aa17 317 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&t), us));
lolpcc 1:6877bb99aa17 318
lolpcc 1:6877bb99aa17 319 #else /* SNTP_CALC_TIME_US */
lolpcc 1:6877bb99aa17 320
lolpcc 1:6877bb99aa17 321 /* change system time and/or the update the RTC clock */
lolpcc 1:6877bb99aa17 322 SNTP_SET_SYSTEM_TIME(t);
lolpcc 1:6877bb99aa17 323 /* display local time from GMT time */
lolpcc 1:6877bb99aa17 324 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&t)));
lolpcc 1:6877bb99aa17 325 #endif /* SNTP_CALC_TIME_US */
lolpcc 1:6877bb99aa17 326 }
lolpcc 1:6877bb99aa17 327
lolpcc 1:6877bb99aa17 328 /**
lolpcc 1:6877bb99aa17 329 * Initialize request struct to be sent to server.
lolpcc 1:6877bb99aa17 330 */
lolpcc 1:6877bb99aa17 331 static void
lolpcc 1:6877bb99aa17 332 sntp_initialize_request(struct sntp_msg *req)
lolpcc 1:6877bb99aa17 333 {
lolpcc 1:6877bb99aa17 334 memset(req, 0, SNTP_MSG_LEN);
lolpcc 1:6877bb99aa17 335 req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
lolpcc 1:6877bb99aa17 336
lolpcc 1:6877bb99aa17 337 #if SNTP_CHECK_RESPONSE >= 2
lolpcc 1:6877bb99aa17 338 {
lolpcc 1:6877bb99aa17 339 u32_t sntp_time_sec, sntp_time_us;
lolpcc 1:6877bb99aa17 340 /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */
lolpcc 1:6877bb99aa17 341 SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us);
lolpcc 1:6877bb99aa17 342 sntp_last_timestamp_sent[0] = htonl(sntp_time_sec + DIFF_SEC_1900_1970);
lolpcc 1:6877bb99aa17 343 req->transmit_timestamp[0] = sntp_last_timestamp_sent[0];
lolpcc 1:6877bb99aa17 344 /* we send/save us instead of fraction to be faster... */
lolpcc 1:6877bb99aa17 345 sntp_last_timestamp_sent[1] = htonl(sntp_time_us);
lolpcc 1:6877bb99aa17 346 req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
lolpcc 1:6877bb99aa17 347 }
lolpcc 1:6877bb99aa17 348 #endif /* SNTP_CHECK_RESPONSE >= 2 */
lolpcc 1:6877bb99aa17 349 }
lolpcc 1:6877bb99aa17 350 #if SNTP_SOCKET
lolpcc 1:6877bb99aa17 351
lolpcc 1:6877bb99aa17 352 /**
lolpcc 1:6877bb99aa17 353 * Send an SNTP request via sockets.
lolpcc 1:6877bb99aa17 354 * This is a very minimal implementation that does not fully conform
lolpcc 1:6877bb99aa17 355 * to the SNTPv4 RFC, especially regarding server load and error procesing.
lolpcc 1:6877bb99aa17 356 */
lolpcc 1:6877bb99aa17 357 static void
lolpcc 1:6877bb99aa17 358 sntp_request(void *arg)
lolpcc 1:6877bb99aa17 359 {
lolpcc 1:6877bb99aa17 360 int sock;
lolpcc 1:6877bb99aa17 361 struct sockaddr_in local;
lolpcc 1:6877bb99aa17 362 struct sockaddr_in to;
lolpcc 1:6877bb99aa17 363 int tolen;
lolpcc 1:6877bb99aa17 364 int size;
lolpcc 1:6877bb99aa17 365 int timeout;
lolpcc 1:6877bb99aa17 366 struct sntp_msg sntpmsg;
lolpcc 1:6877bb99aa17 367 u32_t sntp_server_address;
lolpcc 1:6877bb99aa17 368
lolpcc 1:6877bb99aa17 369 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 370
lolpcc 1:6877bb99aa17 371 /* if we got a valid SNTP server address... */
lolpcc 1:6877bb99aa17 372 if (inet_aton(SNTP_SERVER_ADDRESS, (struct in_addr*)&sntp_server_address)) {
lolpcc 1:6877bb99aa17 373 /* create new socket */
lolpcc 1:6877bb99aa17 374 sock = lwip_socket(AF_INET, SOCK_DGRAM, 0);
lolpcc 1:6877bb99aa17 375 if (sock >= 0) {
lolpcc 1:6877bb99aa17 376 /* prepare local address */
lolpcc 1:6877bb99aa17 377 memset(&local, 0, sizeof(local));
lolpcc 1:6877bb99aa17 378 local.sin_family = AF_INET;
lolpcc 1:6877bb99aa17 379 local.sin_port = htons(INADDR_ANY);
lolpcc 1:6877bb99aa17 380 local.sin_addr.s_addr = htonl(INADDR_ANY);
lolpcc 1:6877bb99aa17 381
lolpcc 1:6877bb99aa17 382 /* bind to local address */
lolpcc 1:6877bb99aa17 383 if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) {
lolpcc 1:6877bb99aa17 384 /* set recv timeout */
lolpcc 1:6877bb99aa17 385 timeout = SNTP_RECV_TIMEOUT;
lolpcc 1:6877bb99aa17 386 lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
lolpcc 1:6877bb99aa17 387
lolpcc 1:6877bb99aa17 388 /* prepare SNTP request */
lolpcc 1:6877bb99aa17 389 sntp_initialize_request(&sntpmsg);
lolpcc 1:6877bb99aa17 390
lolpcc 1:6877bb99aa17 391 /* prepare SNTP server address */
lolpcc 1:6877bb99aa17 392 memset(&to, 0, sizeof(to));
lolpcc 1:6877bb99aa17 393 to.sin_family = AF_INET;
lolpcc 1:6877bb99aa17 394 to.sin_port = htons(SNTP_PORT);
lolpcc 1:6877bb99aa17 395 to.sin_addr.s_addr = sntp_server_address;
lolpcc 1:6877bb99aa17 396
lolpcc 1:6877bb99aa17 397 /* send SNTP request to server */
lolpcc 1:6877bb99aa17 398 if (lwip_sendto(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, sizeof(to)) >= 0) {
lolpcc 1:6877bb99aa17 399 /* receive SNTP server response */
lolpcc 1:6877bb99aa17 400 tolen = sizeof(to);
lolpcc 1:6877bb99aa17 401 size = lwip_recvfrom(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, (socklen_t *)&tolen);
lolpcc 1:6877bb99aa17 402 /* if the response size is good */
lolpcc 1:6877bb99aa17 403 if (size == SNTP_MSG_LEN) {
lolpcc 1:6877bb99aa17 404 /* if this is a SNTP response... */
lolpcc 1:6877bb99aa17 405 if (((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_SERVER) ||
lolpcc 1:6877bb99aa17 406 ((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST)) {
lolpcc 1:6877bb99aa17 407 /* do time processing */
lolpcc 1:6877bb99aa17 408 sntp_process(sntpmsg.receive_timestamp);
lolpcc 1:6877bb99aa17 409 } else {
lolpcc 1:6877bb99aa17 410 LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not response frame code\n"));
lolpcc 1:6877bb99aa17 411 }
lolpcc 1:6877bb99aa17 412 }
lolpcc 1:6877bb99aa17 413 } else {
lolpcc 1:6877bb99aa17 414 LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not sendto==%i\n", errno));
lolpcc 1:6877bb99aa17 415 }
lolpcc 1:6877bb99aa17 416 }
lolpcc 1:6877bb99aa17 417 /* close the socket */
lolpcc 1:6877bb99aa17 418 closesocket(sock);
lolpcc 1:6877bb99aa17 419 }
lolpcc 1:6877bb99aa17 420 }
lolpcc 1:6877bb99aa17 421 }
lolpcc 1:6877bb99aa17 422
lolpcc 1:6877bb99aa17 423 /**
lolpcc 1:6877bb99aa17 424 * SNTP thread
lolpcc 1:6877bb99aa17 425 */
lolpcc 1:6877bb99aa17 426 static void
lolpcc 1:6877bb99aa17 427 sntp_thread(void *arg)
lolpcc 1:6877bb99aa17 428 {
lolpcc 1:6877bb99aa17 429 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 430 while(1) {
lolpcc 1:6877bb99aa17 431 sntp_request(NULL);
lolpcc 1:6877bb99aa17 432 sys_msleep(SNTP_UPDATE_DELAY);
lolpcc 1:6877bb99aa17 433 }
lolpcc 1:6877bb99aa17 434 }
lolpcc 1:6877bb99aa17 435
lolpcc 1:6877bb99aa17 436 /**
lolpcc 1:6877bb99aa17 437 * Initialize this module when using sockets
lolpcc 1:6877bb99aa17 438 */
lolpcc 1:6877bb99aa17 439 void
lolpcc 1:6877bb99aa17 440 sntp_init(void)
lolpcc 1:6877bb99aa17 441 {
lolpcc 1:6877bb99aa17 442 sys_thread_new("sntp_thread", sntp_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
lolpcc 1:6877bb99aa17 443 }
lolpcc 1:6877bb99aa17 444
lolpcc 1:6877bb99aa17 445 #else /* SNTP_SOCKET */
lolpcc 1:6877bb99aa17 446
lolpcc 1:6877bb99aa17 447 /**
lolpcc 1:6877bb99aa17 448 * Retry: send a new request (and increase retry timeout).
lolpcc 1:6877bb99aa17 449 *
lolpcc 1:6877bb99aa17 450 * @param arg is unused (only necessary to conform to sys_timeout)
lolpcc 1:6877bb99aa17 451 */
lolpcc 1:6877bb99aa17 452 static void
lolpcc 1:6877bb99aa17 453 sntp_retry(void* arg)
lolpcc 1:6877bb99aa17 454 {
lolpcc 1:6877bb99aa17 455 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 456
lolpcc 1:6877bb99aa17 457 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n",
lolpcc 1:6877bb99aa17 458 sntp_retry_timeout));
lolpcc 1:6877bb99aa17 459
lolpcc 1:6877bb99aa17 460 /* set up a timer to send a retry and increase the retry delay */
lolpcc 1:6877bb99aa17 461 sys_timeout(sntp_retry_timeout, sntp_request, NULL);
lolpcc 1:6877bb99aa17 462
lolpcc 1:6877bb99aa17 463 #if SNTP_RETRY_TIMEOUT_EXP
lolpcc 1:6877bb99aa17 464 {
lolpcc 1:6877bb99aa17 465 u32_t new_retry_timeout;
lolpcc 1:6877bb99aa17 466 /* increase the timeout for next retry */
lolpcc 1:6877bb99aa17 467 new_retry_timeout = sntp_retry_timeout << 1;
lolpcc 1:6877bb99aa17 468 /* limit to maximum timeout and prevent overflow */
lolpcc 1:6877bb99aa17 469 if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
lolpcc 1:6877bb99aa17 470 (new_retry_timeout > sntp_retry_timeout)) {
lolpcc 1:6877bb99aa17 471 sntp_retry_timeout = new_retry_timeout;
lolpcc 1:6877bb99aa17 472 }
lolpcc 1:6877bb99aa17 473 }
lolpcc 1:6877bb99aa17 474 #endif /* SNTP_RETRY_TIMEOUT_EXP */
lolpcc 1:6877bb99aa17 475 }
lolpcc 1:6877bb99aa17 476
lolpcc 1:6877bb99aa17 477 #if SNTP_SUPPORT_MULTIPLE_SERVERS
lolpcc 1:6877bb99aa17 478 /**
lolpcc 1:6877bb99aa17 479 * If Kiss-of-Death is received (or another packet parsing error),
lolpcc 1:6877bb99aa17 480 * try the next server or retry the current server and increase the retry
lolpcc 1:6877bb99aa17 481 * timeout if only one server is available.
lolpcc 1:6877bb99aa17 482 *
lolpcc 1:6877bb99aa17 483 * @param arg is unused (only necessary to conform to sys_timeout)
lolpcc 1:6877bb99aa17 484 */
lolpcc 1:6877bb99aa17 485 static void
lolpcc 1:6877bb99aa17 486 sntp_try_next_server(void* arg)
lolpcc 1:6877bb99aa17 487 {
lolpcc 1:6877bb99aa17 488 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 489
lolpcc 1:6877bb99aa17 490 if (sntp_num_servers > 1) {
lolpcc 1:6877bb99aa17 491 /* new server: reset retry timeout */
lolpcc 1:6877bb99aa17 492 SNTP_RESET_RETRY_TIMEOUT();
lolpcc 1:6877bb99aa17 493 sntp_current_server++;
lolpcc 1:6877bb99aa17 494 if (sntp_current_server >= sntp_num_servers) {
lolpcc 1:6877bb99aa17 495 sntp_current_server = 0;
lolpcc 1:6877bb99aa17 496 }
lolpcc 1:6877bb99aa17 497 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n",
lolpcc 1:6877bb99aa17 498 (u16_t)sntp_current_server));
lolpcc 1:6877bb99aa17 499 /* instantly send a request to the next server */
lolpcc 1:6877bb99aa17 500 sntp_request(NULL);
lolpcc 1:6877bb99aa17 501 } else {
lolpcc 1:6877bb99aa17 502 sntp_retry(NULL);
lolpcc 1:6877bb99aa17 503 }
lolpcc 1:6877bb99aa17 504 }
lolpcc 1:6877bb99aa17 505 #else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
lolpcc 1:6877bb99aa17 506 /* Always retry on error if only one server is supported */
lolpcc 1:6877bb99aa17 507 #define sntp_try_next_server sntp_retry
lolpcc 1:6877bb99aa17 508 #endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
lolpcc 1:6877bb99aa17 509
lolpcc 1:6877bb99aa17 510 /** UDP recv callback for the sntp pcb */
lolpcc 1:6877bb99aa17 511 static void
lolpcc 1:6877bb99aa17 512 sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
lolpcc 1:6877bb99aa17 513 {
lolpcc 1:6877bb99aa17 514 u8_t mode;
lolpcc 1:6877bb99aa17 515 u8_t stratum;
lolpcc 1:6877bb99aa17 516 u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE];
lolpcc 1:6877bb99aa17 517 err_t err;
lolpcc 1:6877bb99aa17 518
lolpcc 1:6877bb99aa17 519 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 520 LWIP_UNUSED_ARG(pcb);
lolpcc 1:6877bb99aa17 521 /* packet received: stop retry timeout */
lolpcc 1:6877bb99aa17 522 sys_untimeout(sntp_try_next_server, NULL);
lolpcc 1:6877bb99aa17 523 sys_untimeout(sntp_request, NULL);
lolpcc 1:6877bb99aa17 524
lolpcc 1:6877bb99aa17 525 err = ERR_ARG;
lolpcc 1:6877bb99aa17 526 #if SNTP_CHECK_RESPONSE >= 1
lolpcc 1:6877bb99aa17 527 /* check server address and port */
lolpcc 1:6877bb99aa17 528 if ((addr->addr == sntp_last_server_address.addr) &&
lolpcc 1:6877bb99aa17 529 (port == SNTP_PORT))
lolpcc 1:6877bb99aa17 530 #else /* SNTP_CHECK_RESPONSE >= 1 */
lolpcc 1:6877bb99aa17 531 LWIP_UNUSED_ARG(addr);
lolpcc 1:6877bb99aa17 532 LWIP_UNUSED_ARG(port);
lolpcc 1:6877bb99aa17 533 #endif /* SNTP_CHECK_RESPONSE >= 1 */
lolpcc 1:6877bb99aa17 534 {
lolpcc 1:6877bb99aa17 535 /* process the response */
lolpcc 1:6877bb99aa17 536 if (p->tot_len == SNTP_MSG_LEN) {
lolpcc 1:6877bb99aa17 537 pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE);
lolpcc 1:6877bb99aa17 538 mode &= SNTP_MODE_MASK;
lolpcc 1:6877bb99aa17 539 /* if this is a SNTP response... */
lolpcc 1:6877bb99aa17 540 if ((mode == SNTP_MODE_SERVER) ||
lolpcc 1:6877bb99aa17 541 (mode == SNTP_MODE_BROADCAST)) {
lolpcc 1:6877bb99aa17 542 pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM);
lolpcc 1:6877bb99aa17 543 if (stratum == SNTP_STRATUM_KOD) {
lolpcc 1:6877bb99aa17 544 /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
lolpcc 1:6877bb99aa17 545 err = SNTP_ERR_KOD;
lolpcc 1:6877bb99aa17 546 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
lolpcc 1:6877bb99aa17 547 } else {
lolpcc 1:6877bb99aa17 548 #if SNTP_CHECK_RESPONSE >= 2
lolpcc 1:6877bb99aa17 549 /* check originate_timetamp against sntp_last_timestamp_sent */
lolpcc 1:6877bb99aa17 550 u32_t originate_timestamp[2];
lolpcc 1:6877bb99aa17 551 pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME);
lolpcc 1:6877bb99aa17 552 if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) ||
lolpcc 1:6877bb99aa17 553 (originate_timestamp[1] != sntp_last_timestamp_sent[1]))
lolpcc 1:6877bb99aa17 554 {
lolpcc 1:6877bb99aa17 555 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n"));
lolpcc 1:6877bb99aa17 556 } else
lolpcc 1:6877bb99aa17 557 #endif /* SNTP_CHECK_RESPONSE >= 2 */
lolpcc 1:6877bb99aa17 558 /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
lolpcc 1:6877bb99aa17 559 {
lolpcc 1:6877bb99aa17 560 /* correct answer */
lolpcc 1:6877bb99aa17 561 err = ERR_OK;
lolpcc 1:6877bb99aa17 562 pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_RECEIVE_TIME);
lolpcc 1:6877bb99aa17 563 }
lolpcc 1:6877bb99aa17 564 }
lolpcc 1:6877bb99aa17 565 } else {
lolpcc 1:6877bb99aa17 566 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
lolpcc 1:6877bb99aa17 567 }
lolpcc 1:6877bb99aa17 568 } else {
lolpcc 1:6877bb99aa17 569 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
lolpcc 1:6877bb99aa17 570 }
lolpcc 1:6877bb99aa17 571 }
lolpcc 1:6877bb99aa17 572 pbuf_free(p);
lolpcc 1:6877bb99aa17 573
lolpcc 1:6877bb99aa17 574 if (err == ERR_OK) {
lolpcc 1:6877bb99aa17 575 /* Correct response, reset retry timeout */
lolpcc 1:6877bb99aa17 576 SNTP_RESET_RETRY_TIMEOUT();
lolpcc 1:6877bb99aa17 577 sntp_process(receive_timestamp);
lolpcc 1:6877bb99aa17 578
lolpcc 1:6877bb99aa17 579 /* Set up timeout for next request */
lolpcc 1:6877bb99aa17 580 sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
lolpcc 1:6877bb99aa17 581 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
lolpcc 1:6877bb99aa17 582 (u32_t)SNTP_UPDATE_DELAY));
lolpcc 1:6877bb99aa17 583 } else if (err == SNTP_ERR_KOD) {
lolpcc 1:6877bb99aa17 584 /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
lolpcc 1:6877bb99aa17 585 sntp_try_next_server(NULL);
lolpcc 1:6877bb99aa17 586 } else {
lolpcc 1:6877bb99aa17 587 /* another error, try the same server again */
lolpcc 1:6877bb99aa17 588 sntp_retry(NULL);
lolpcc 1:6877bb99aa17 589 }
lolpcc 1:6877bb99aa17 590 }
lolpcc 1:6877bb99aa17 591
lolpcc 1:6877bb99aa17 592 /** Actually send an sntp request to a server.
lolpcc 1:6877bb99aa17 593 *
lolpcc 1:6877bb99aa17 594 * @param server_addr resolved IP address of the SNTP server
lolpcc 1:6877bb99aa17 595 */
lolpcc 1:6877bb99aa17 596 static void
lolpcc 1:6877bb99aa17 597 sntp_send_request(struct ip_addr *server_addr)
lolpcc 1:6877bb99aa17 598 {
lolpcc 1:6877bb99aa17 599 struct pbuf* p;
lolpcc 1:6877bb99aa17 600 p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
lolpcc 1:6877bb99aa17 601 if (p != NULL) {
lolpcc 1:6877bb99aa17 602 struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload;
lolpcc 1:6877bb99aa17 603 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n"));
lolpcc 1:6877bb99aa17 604 /* initialize request message */
lolpcc 1:6877bb99aa17 605 sntp_initialize_request(sntpmsg);
lolpcc 1:6877bb99aa17 606 /* send request */
lolpcc 1:6877bb99aa17 607 udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT);
lolpcc 1:6877bb99aa17 608 pbuf_free(p); // [iva2k] fixing memory leak
lolpcc 1:6877bb99aa17 609 /* set up receive timeout: try next server or retry on timeout */
lolpcc 1:6877bb99aa17 610 sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
lolpcc 1:6877bb99aa17 611 #if SNTP_CHECK_RESPONSE >= 1
lolpcc 1:6877bb99aa17 612 /* save server address to verify it in sntp_recv */
lolpcc 1:6877bb99aa17 613 sntp_last_server_address.addr = server_addr->addr;
lolpcc 1:6877bb99aa17 614 #endif /* SNTP_CHECK_RESPONSE >= 1 */
lolpcc 1:6877bb99aa17 615 } else {
lolpcc 1:6877bb99aa17 616 LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
lolpcc 1:6877bb99aa17 617 (u32_t)SNTP_RETRY_TIMEOUT));
lolpcc 1:6877bb99aa17 618 /* out of memory: set up a timer to send a retry */
lolpcc 1:6877bb99aa17 619 sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
lolpcc 1:6877bb99aa17 620 }
lolpcc 1:6877bb99aa17 621 }
lolpcc 1:6877bb99aa17 622
lolpcc 1:6877bb99aa17 623 /**
lolpcc 1:6877bb99aa17 624 * DNS found callback when using DNS names as server address.
lolpcc 1:6877bb99aa17 625 */
lolpcc 1:6877bb99aa17 626 static void
lolpcc 1:6877bb99aa17 627 sntp_dns_found(const char* hostname, struct ip_addr *ipaddr, void *arg)
lolpcc 1:6877bb99aa17 628 {
lolpcc 1:6877bb99aa17 629 LWIP_UNUSED_ARG(hostname);
lolpcc 1:6877bb99aa17 630 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 631
lolpcc 1:6877bb99aa17 632 if (ipaddr != NULL) {
lolpcc 1:6877bb99aa17 633 /* Address resolved, send request */
lolpcc 1:6877bb99aa17 634 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n"));
lolpcc 1:6877bb99aa17 635 sntp_send_request(ipaddr);
lolpcc 1:6877bb99aa17 636 } else {
lolpcc 1:6877bb99aa17 637 /* DNS resolving failed -> try another server */
lolpcc 1:6877bb99aa17 638 LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n"));
lolpcc 1:6877bb99aa17 639 // sntp_try_next_server(NULL);
lolpcc 1:6877bb99aa17 640 // [iva2k] changing to delayed - having no DNS may mean that there is something wrong. don't hang in here.
lolpcc 1:6877bb99aa17 641 sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
lolpcc 1:6877bb99aa17 642 }
lolpcc 1:6877bb99aa17 643 }
lolpcc 1:6877bb99aa17 644 /**
lolpcc 1:6877bb99aa17 645 * Send out an sntp request via raw API.
lolpcc 1:6877bb99aa17 646 *
lolpcc 1:6877bb99aa17 647 * @param arg is unused (only necessary to conform to sys_timeout)
lolpcc 1:6877bb99aa17 648 */
lolpcc 1:6877bb99aa17 649 static void
lolpcc 1:6877bb99aa17 650 sntp_request(void *arg)
lolpcc 1:6877bb99aa17 651 {
lolpcc 1:6877bb99aa17 652 struct ip_addr sntp_server_address;
lolpcc 1:6877bb99aa17 653 err_t err;
lolpcc 1:6877bb99aa17 654
lolpcc 1:6877bb99aa17 655 LWIP_UNUSED_ARG(arg);
lolpcc 1:6877bb99aa17 656 /* initialize SNTP server address */
lolpcc 1:6877bb99aa17 657 #if SNTP_SERVER_DNS
lolpcc 1:6877bb99aa17 658 err = dns_gethostbyname(sntp_server_addresses[sntp_current_server], &sntp_server_address,
lolpcc 1:6877bb99aa17 659 sntp_dns_found, NULL);
lolpcc 1:6877bb99aa17 660 if (err == ERR_INPROGRESS) {
lolpcc 1:6877bb99aa17 661 /* DNS request sent, wait for sntp_dns_found being called */
lolpcc 1:6877bb99aa17 662 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n"));
lolpcc 1:6877bb99aa17 663 return;
lolpcc 1:6877bb99aa17 664 }
lolpcc 1:6877bb99aa17 665 #else /* SNTP_SERVER_DNS */
lolpcc 1:6877bb99aa17 666 err = inet_aton(sntp_server_addresses[sntp_current_server], (struct in_addr*)&sntp_server_address)
lolpcc 1:6877bb99aa17 667 ? ERR_OK : ERR_ARG;
lolpcc 1:6877bb99aa17 668 #endif /* SNTP_SERVER_DNS */
lolpcc 1:6877bb99aa17 669 if (err == ERR_OK) {
lolpcc 1:6877bb99aa17 670 sntp_send_request(&sntp_server_address);
lolpcc 1:6877bb99aa17 671 } else {
lolpcc 1:6877bb99aa17 672 /* address conversion failed, try another server */
lolpcc 1:6877bb99aa17 673 LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
lolpcc 1:6877bb99aa17 674 sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
lolpcc 1:6877bb99aa17 675 }
lolpcc 1:6877bb99aa17 676 }
lolpcc 1:6877bb99aa17 677 /**
lolpcc 1:6877bb99aa17 678 * Initialize this module when using raw API.
lolpcc 1:6877bb99aa17 679 * Send out request instantly or after SNTP_STARTUP_DELAY.
lolpcc 1:6877bb99aa17 680 */
lolpcc 1:6877bb99aa17 681 void
lolpcc 1:6877bb99aa17 682 sntp_init(void)
lolpcc 1:6877bb99aa17 683 {
lolpcc 1:6877bb99aa17 684 SNTP_RESET_RETRY_TIMEOUT();
lolpcc 1:6877bb99aa17 685 sntp_pcb = udp_new();
lolpcc 1:6877bb99aa17 686 LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
lolpcc 1:6877bb99aa17 687 if (sntp_pcb != NULL) {
lolpcc 1:6877bb99aa17 688 udp_recv(sntp_pcb, sntp_recv, NULL);
lolpcc 1:6877bb99aa17 689 #if SNTP_STARTUP_DELAY
lolpcc 1:6877bb99aa17 690 sys_timeout((u32_t)SNTP_STARTUP_DELAY, sntp_request, NULL);
lolpcc 1:6877bb99aa17 691 #else
lolpcc 1:6877bb99aa17 692 sntp_request(NULL);
lolpcc 1:6877bb99aa17 693 #endif
lolpcc 1:6877bb99aa17 694 }
lolpcc 1:6877bb99aa17 695 }
lolpcc 1:6877bb99aa17 696 #endif /* SNTP_SOCKET */