|
@@ -0,0 +1,213 @@
|
|
|
|
+/**
|
|
|
|
+ * @file
|
|
|
|
+ * SNTP client module
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
+ * are permitted provided that the following conditions are met:
|
|
|
|
+ *
|
|
|
|
+ * 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
+ * this list of conditions and the following disclaimer.
|
|
|
|
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
+ * this list of conditions and the following disclaimer in the documentation
|
|
|
|
+ * and/or other materials provided with the distribution.
|
|
|
|
+ * 3. The name of the author may not be used to endorse or promote products
|
|
|
|
+ * derived from this software without specific prior written permission.
|
|
|
|
+ *
|
|
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
|
|
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
|
|
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
|
|
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
|
|
+ * OF SUCH DAMAGE.
|
|
|
|
+ *
|
|
|
|
+ * This file is part of the lwIP TCP/IP stack.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include "lwip/sys.h"
|
|
|
|
+#include "lwip/sockets.h"
|
|
|
|
+
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <time.h>
|
|
|
|
+
|
|
|
|
+/** This is an example of a "SNTP" client (with socket API).
|
|
|
|
+ *
|
|
|
|
+ * For a list of some public NTP servers, see this link :
|
|
|
|
+ * http://support.ntp.org/bin/view/Servers/NTPPoolServers
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * SNTP_DEBUG: Enable debugging for SNTP.
|
|
|
|
+ */
|
|
|
|
+#ifndef SNTP_DEBUG
|
|
|
|
+#define SNTP_DEBUG LWIP_DBG_ON
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/** SNTP server port */
|
|
|
|
+#ifndef SNTP_PORT
|
|
|
|
+#define SNTP_PORT 123
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/** SNTP server address as IPv4 address in "u32_t" format */
|
|
|
|
+#ifndef SNTP_SERVER_ADDRESS
|
|
|
|
+#define SNTP_SERVER_ADDRESS inet_addr("213.161.194.93") /* pool.ntp.org */
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/** SNTP receive timeout - in milliseconds */
|
|
|
|
+#ifndef SNTP_RECV_TIMEOUT
|
|
|
|
+#define SNTP_RECV_TIMEOUT 3000
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/** SNTP update delay - in milliseconds */
|
|
|
|
+#ifndef SNTP_UPDATE_DELAY
|
|
|
|
+#define SNTP_UPDATE_DELAY 60000
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/** SNTP macro to change system time and/or the update the RTC clock */
|
|
|
|
+#ifndef SNTP_SYSTEM_TIME
|
|
|
|
+#define SNTP_SYSTEM_TIME(t)
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/* SNTP protocol defines */
|
|
|
|
+#define SNTP_MAX_DATA_LEN 48
|
|
|
|
+#define SNTP_RCV_TIME_OFS 32
|
|
|
|
+#define SNTP_LI_NO_WARNING 0x00
|
|
|
|
+#define SNTP_VERSION (4/* NTP Version 4*/<<3)
|
|
|
|
+#define SNTP_MODE_CLIENT 0x03
|
|
|
|
+#define SNTP_MODE_SERVER 0x04
|
|
|
|
+#define SNTP_MODE_BROADCAST 0x05
|
|
|
|
+#define SNTP_MODE_MASK 0x07
|
|
|
|
+
|
|
|
|
+/* number of seconds between 1900 and 1970 */
|
|
|
|
+#define DIFF_SEC_1900_1970 (2208988800)
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * SNTP processing
|
|
|
|
+ */
|
|
|
|
+static void sntp_process( time_t t)
|
|
|
|
+{
|
|
|
|
+ /* change system time and/or the update the RTC clock */
|
|
|
|
+ SNTP_SYSTEM_TIME(t);
|
|
|
|
+
|
|
|
|
+ /* display local time from GMT time */
|
|
|
|
+ LWIP_DEBUGF( SNTP_DEBUG, ("sntp_process: %s", ctime(&t)));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * SNTP request
|
|
|
|
+ */
|
|
|
|
+static void sntp_request()
|
|
|
|
+{
|
|
|
|
+ int sock;
|
|
|
|
+ struct sockaddr_in local;
|
|
|
|
+ struct sockaddr_in to;
|
|
|
|
+ int tolen;
|
|
|
|
+ int size;
|
|
|
|
+ int timeout;
|
|
|
|
+ u8_t sntp_request [SNTP_MAX_DATA_LEN];
|
|
|
|
+ u8_t sntp_response[SNTP_MAX_DATA_LEN];
|
|
|
|
+ u32_t sntp_server_address;
|
|
|
|
+ u32_t timestamp;
|
|
|
|
+ time_t t;
|
|
|
|
+
|
|
|
|
+ /* initialize SNTP server address */
|
|
|
|
+ sntp_server_address = SNTP_SERVER_ADDRESS;
|
|
|
|
+
|
|
|
|
+ /* if we got a valid SNTP server address... */
|
|
|
|
+ if (sntp_server_address!=0)
|
|
|
|
+ {
|
|
|
|
+ /* create new socket */
|
|
|
|
+ sock = socket( AF_INET, SOCK_DGRAM, 0);
|
|
|
|
+ if (sock>=0)
|
|
|
|
+ {
|
|
|
|
+ /* prepare local address */
|
|
|
|
+ memset(&local, 0, sizeof(local));
|
|
|
|
+ local.sin_family = AF_INET;
|
|
|
|
+ local.sin_port = htons(INADDR_ANY);
|
|
|
|
+ local.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
+
|
|
|
|
+ /* bind to local address */
|
|
|
|
+ if (bind( sock, (struct sockaddr *)&local, sizeof(local))==0)
|
|
|
|
+ {
|
|
|
|
+ /* set recv timeout */
|
|
|
|
+ timeout = SNTP_RECV_TIMEOUT;
|
|
|
|
+ setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
|
|
|
+
|
|
|
|
+ /* prepare SNTP request */
|
|
|
|
+ memset( sntp_request, 0, sizeof(sntp_request));
|
|
|
|
+ sntp_request[0] = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
|
|
|
|
+
|
|
|
|
+ /* prepare SNTP server address */
|
|
|
|
+ memset(&to, 0, sizeof(to));
|
|
|
|
+ to.sin_family = AF_INET;
|
|
|
|
+ to.sin_port = htons(SNTP_PORT);
|
|
|
|
+ to.sin_addr.s_addr = sntp_server_address;
|
|
|
|
+
|
|
|
|
+ /* send SNTP request to server */
|
|
|
|
+ if (sendto( sock, sntp_request, sizeof(sntp_request), 0, (struct sockaddr *)&to, sizeof(to))>=0)
|
|
|
|
+ {
|
|
|
|
+ /* receive SNTP server response */
|
|
|
|
+ tolen = sizeof(to);
|
|
|
|
+ size = recvfrom( sock, sntp_response, sizeof(sntp_response), 0, (struct sockaddr *)&to, (socklen_t *)&tolen);
|
|
|
|
+
|
|
|
|
+ /* if the response size is good */
|
|
|
|
+ if (size == SNTP_MAX_DATA_LEN)
|
|
|
|
+ {
|
|
|
|
+ /* if this is a SNTP response... */
|
|
|
|
+ if (((sntp_response[0] & SNTP_MODE_MASK) == SNTP_MODE_SERVER) || ((sntp_response[0] & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST))
|
|
|
|
+ {
|
|
|
|
+ /* extract GMT time from response */
|
|
|
|
+ SMEMCPY( ×tamp, (sntp_response+SNTP_RCV_TIME_OFS), sizeof(timestamp));
|
|
|
|
+ t = (ntohl(timestamp) - DIFF_SEC_1900_1970);
|
|
|
|
+
|
|
|
|
+ /* do time processing */
|
|
|
|
+ sntp_process(t);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not response frame code\n"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not recvfrom==%i\n", errno));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not sendto==%i\n", errno));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /* close the socket */
|
|
|
|
+ closesocket(sock);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * SNTP thread
|
|
|
|
+ */
|
|
|
|
+static void
|
|
|
|
+sntp_thread(void *arg)
|
|
|
|
+{
|
|
|
|
+ LWIP_UNUSED_ARG(arg);
|
|
|
|
+ while(1)
|
|
|
|
+ {
|
|
|
|
+ sntp_request();
|
|
|
|
+ sys_msleep(SNTP_UPDATE_DELAY);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void sntp_init(void)
|
|
|
|
+{
|
|
|
|
+ sys_thread_new("sntp_thread", sntp_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
|
|
|
|
+}
|