Go to the documentation of this file.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
00082 #include <cfg/sntp.h>
00083
00084 #include <pro/sntp.h>
00085 #include <sys/socket.h>
00086 #include <sys/heap.h>
00087 #include <stdlib.h>
00088 #include <string.h>
00089 #include "../crt/ctime.h"
00090 #include <stdio.h>
00091 #include <memdebug.h>
00092 #include <sys/thread.h>
00093 #include <sys/timer.h>
00094 #include <sys/types.h>
00095 #include <netinet/in.h>
00096
00101
00102 #ifndef NUT_THREAD_SNTPSTACK
00103 #define NUT_THREAD_SNTPSTACK 256
00104 #endif
00105
00106 typedef struct _sntpframe sntpframe;
00107 struct _sntpframe {
00108 uint8_t mode;
00109 uint8_t stratum;
00110 uint8_t poll;
00111 uint8_t precision;
00112 uint32_t root_delay;
00113 uint32_t root_dispersion;
00114 uint32_t reference_identifier;
00115 uint32_t reference_ts_sec;
00116 uint32_t reference_ts_frac;
00117 uint32_t originate_ts_sec;
00118 uint32_t originate_ts_frac;
00119 uint32_t receive_ts_sec;
00120 uint32_t receive_ts_frac;
00121 uint32_t transmit_ts_sec;
00122 uint32_t transmit_ts_frac;
00123 };
00124
00125
00126 #define NTP_PORT 123
00127 #define SNTP_PORT NTP_PORT
00128
00129 struct SNTP_resync_args {
00130 uint32_t server_addr;
00131 uint32_t interval;
00132 };
00133
00134 THREAD(SNTP_resync, arg)
00135 {
00136 uint32_t server_addr = ((struct SNTP_resync_args *) arg)->server_addr;
00137 uint32_t interval = ((struct SNTP_resync_args *) arg)->interval;
00138 uint32_t cur_server_addr = server_addr;
00139 int retry = 0;
00140 time_t t;
00141
00142 free(arg);
00143
00144 NutThreadSetPriority(63);
00145 for (;;) {
00146 if (NutSNTPGetTime(&cur_server_addr, &t)) {
00147 if (cur_server_addr != server_addr && server_addr == 0xFFFFFFFF) {
00148 cur_server_addr = server_addr;
00149 continue;
00150 }
00151
00152 if (retry++ >= 3) {
00153 retry = 0;
00154 NutSleep(30000);
00155 } else
00156 NutSleep(5000);
00157 } else {
00158 stime(&t);
00159 retry = 0;
00160 NutSleep(interval);
00161 }
00162 }
00163 }
00164
00165 int NutSNTPGetTime(uint32_t * server_adr, time_t * t)
00166 {
00167
00168 uint32_t rec_addr;
00169 UDPSOCKET *sock = NULL;
00170 sntpframe *data;
00171 uint16_t port;
00172 int len;
00173 int result = -1;
00174
00175 uint16_t bufsize = 256;
00176
00177
00178 if (t == NULL)
00179 return -1;
00180 if (server_adr == NULL)
00181 return -1;
00182
00183 if ((data = calloc(1, sizeof(*data))) == NULL)
00184 goto error;
00185
00186 sock = NutUdpCreateSocket(0);
00187 if (sock == NULL)
00188 goto error;
00189
00190 NutUdpSetSockOpt(sock, SO_RCVBUF, &bufsize, sizeof(bufsize));
00191
00192 data->mode = 0x1B;
00193 if (NutUdpSendTo(sock, *server_adr, SNTP_PORT, data, sizeof(*data)))
00194 goto error;
00195 retry:
00196 rec_addr = 0;
00197 len = NutUdpReceiveFrom(sock, &rec_addr, &port, data, sizeof(*data), 5000);
00198 if (len <= 0) {
00199 goto error;
00200 }
00201
00202 if (port != SNTP_PORT || (data->mode & 0xc0) == 0xc0)
00203 {
00204 if (*server_adr == 0xFFFFFFFF)
00205 goto retry;
00206 else
00207 goto error;
00208 }
00209
00210 *t = ntohl(data->transmit_ts_sec) - (70 * 365 + _LEAP_YEAR_ADJUST) * _DAY_SEC;
00211 *server_adr = rec_addr;
00212 result = 0;
00213 error:
00214 if (sock)
00215 NutUdpDestroySocket(sock);
00216 if (data)
00217 free(data);
00218 return result;
00219 }
00220
00221 int NutSNTPStartThread(uint32_t server_addr, uint32_t interval)
00222 {
00223 struct SNTP_resync_args *arg = malloc(sizeof(struct SNTP_resync_args));
00224 if (!arg)
00225 return -1;
00226 arg->server_addr = server_addr;
00227 arg->interval = interval;
00228 if (NutThreadCreate("sntpc", SNTP_resync, arg,
00229 (NUT_THREAD_SNTPSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD))
00230 return 0;
00231 else {
00232 free(arg);
00233 return -1;
00234 }
00235 }
00236