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