00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00074 #include <cfg/sntp.h>
00075
00076 #include <pro/sntp.h>
00077 #include <sys/socket.h>
00078 #include <sys/heap.h>
00079 #include <string.h>
00080 #include "../crt/ctime.h"
00081 #include <stdio.h>
00082 #include <sys/thread.h>
00083 #include <sys/timer.h>
00084 #include <sys/types.h>
00085 #include <netinet/in.h>
00086
00091
00092 #ifndef NUT_THREAD_SNTPSTACK
00093 #define NUT_THREAD_SNTPSTACK 256
00094 #endif
00095
00096 typedef struct _sntpframe sntpframe;
00097 struct _sntpframe {
00098 uint8_t mode;
00099 uint8_t stratum;
00100 uint8_t poll;
00101 uint8_t precision;
00102 uint32_t root_delay;
00103 uint32_t root_dispersion;
00104 uint32_t reference_identifier;
00105 uint32_t reference_ts_sec;
00106 uint32_t reference_ts_frac;
00107 uint32_t originate_ts_sec;
00108 uint32_t originate_ts_frac;
00109 uint32_t receive_ts_sec;
00110 uint32_t receive_ts_frac;
00111 uint32_t transmit_ts_sec;
00112 uint32_t transmit_ts_frac;
00113 };
00114
00115
00116 #define NTP_PORT 123
00117 #define SNTP_PORT NTP_PORT
00118
00119 struct SNTP_resync_args {
00120 uint32_t server_addr;
00121 uint32_t interval;
00122 };
00123
00124 THREAD(SNTP_resync, arg)
00125 {
00126 uint32_t server_addr = ((struct SNTP_resync_args *) arg)->server_addr;
00127 uint32_t interval = ((struct SNTP_resync_args *) arg)->interval;
00128 uint32_t cur_server_addr = server_addr;
00129 int retry = 0;
00130 time_t t;
00131
00132 NutHeapFree(arg);
00133
00134 NutThreadSetPriority(63);
00135 for (;;) {
00136 if (NutSNTPGetTime(&cur_server_addr, &t)) {
00137 if (cur_server_addr != server_addr && server_addr == 0xFFFFFFFF) {
00138 cur_server_addr = server_addr;
00139 continue;
00140 }
00141
00142 if (retry++ >= 3) {
00143 retry = 0;
00144 NutSleep(30000);
00145 } else
00146 NutSleep(5000);
00147 } else {
00148 stime(&t);
00149 retry = 0;
00150 NutSleep(interval);
00151 }
00152 }
00153 }
00154
00155 int NutSNTPGetTime(uint32_t * server_adr, time_t * t)
00156 {
00157
00158 uint32_t rec_addr;
00159 UDPSOCKET *sock = NULL;
00160 sntpframe *data;
00161 uint16_t port;
00162 int len;
00163 int result = -1;
00164
00165 uint16_t bufsize = 256;
00166
00167
00168 if (t == NULL)
00169 return -1;
00170 if (server_adr == NULL)
00171 return -1;
00172
00173 if ((data = NutHeapAllocClear(sizeof(*data))) == NULL)
00174 goto error;
00175
00176 sock = NutUdpCreateSocket(0);
00177 if (sock == NULL)
00178 goto error;
00179
00180 NutUdpSetSockOpt(sock, SO_RCVBUF, &bufsize, sizeof(bufsize));
00181
00182 data->mode = 0x1B;
00183 if (NutUdpSendTo(sock, *server_adr, SNTP_PORT, data, sizeof(*data)))
00184 goto error;
00185 retry:
00186 rec_addr = 0;
00187 len = NutUdpReceiveFrom(sock, &rec_addr, &port, data, sizeof(*data), 5000);
00188 if (len <= 0) {
00189 goto error;
00190 }
00191
00192 if (port != SNTP_PORT || (data->mode & 0xc0) == 0xc0)
00193 {
00194 if (*server_adr == 0xFFFFFFFF)
00195 goto retry;
00196 else
00197 goto error;
00198 }
00199
00200 *t = ntohl(data->transmit_ts_sec) - (70 * 365 + _LEAP_YEAR_ADJUST) * _DAY_SEC;
00201 *server_adr = rec_addr;
00202 result = 0;
00203 error:
00204 if (sock)
00205 NutUdpDestroySocket(sock);
00206 if (data)
00207 NutHeapFree(data);
00208 return result;
00209 }
00210
00211 int NutSNTPStartThread(uint32_t server_addr, uint32_t interval)
00212 {
00213 struct SNTP_resync_args *arg = NutHeapAlloc(sizeof(struct SNTP_resync_args));
00214 if (!arg)
00215 return -1;
00216 arg->server_addr = server_addr;
00217 arg->interval = interval;
00218 if (NutThreadCreate("sntpc", SNTP_resync, arg, NUT_THREAD_SNTPSTACK))
00219 return 0;
00220 else {
00221 NutHeapFree(arg);
00222 return -1;
00223 }
00224 }
00225