Tiny SNTP(NTP) Client
Dependencies: EthernetNetIf mbed
Revision 1:d3c1871be1e9, committed 2011-07-28
- Comitter:
- okini3939
- Date:
- Thu Jul 28 17:23:43 2011 +0000
- Parent:
- 0:41e7cfdbd23a
- Commit message:
Changed in this revision
diff -r 41e7cfdbd23a -r d3c1871be1e9 TinySNTP.cpp --- a/TinySNTP.cpp Thu Jul 21 17:53:11 2011 +0000 +++ b/TinySNTP.cpp Thu Jul 28 17:23:43 2011 +0000 @@ -1,143 +1,170 @@ -/* - * mbed Tiny SNTP(NTP) Client - * Copyright (c) 2011 Hiroshi Suga - * Released under the MIT License: http://mbed.org/license/mit - */ - -/** @file - * @brief Tiny DNS Resolver - */ - -#include "mbed.h" -#include "EthernetNetIf.h" -#include "UDPSocket.h" -#include "DNSRequest.h" -#include "TinySNTP.h" - -// host to network short -#define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) ) -#define ntohs( x ) htons(x) -// host to network long -#define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \ - | (( (x) << 8 ) & 0x00FF0000) \ - | (( (x) >> 8 ) & 0x0000FF00) \ - | (( (x) >> 24 ) & 0x000000FF) ) -#define ntohl( x ) htonl(x) - -static UDPSocket *sntp; -static volatile unsigned long sntptime; -extern EthernetNetIf eth; - -int createSntpRequest (char *buf) { - struct SNTPPacket *sntp; - - sntp = (struct SNTPPacket *)buf; - memset(sntp, 0, sizeof(struct SNTPPacket)); - sntp->info = 0x1b; // Ver.3, client - sntp->txTm_s = htonl(NTP_TIMESTAMP_DELTA + time(NULL)); - - return sizeof(struct SNTPPacket); -} - -int getSntpResponse (const char *buf, uint32_t *tim) { - struct SNTPPacket *sntp; - uint32_t now; -// long int delay, offset; - - sntp = (struct SNTPPacket *)buf; - if ((sntp->info & 0x3f) == 0x1c || (sntp->info & 0x3f) == 0x24) { - // Ver.3or4, Server - - now = htonl(NTP_TIMESTAMP_DELTA + time(NULL)); -/* - delay = (now - sntp->origTm_s) - (sntp->rxTm_s - sntp->txTm_s); - offset = ((sntp->rxTm_s - sntp->origTm_s) + (sntp->txTm_s - now)); - - *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA + (delay / 2); -*/ - *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA; -#ifdef DEBUG - printf("now %08x\r\n", ntohl(now)); - printf("ref %08x\r\n", ntohl(sntp->refTm_s)); - printf("orig %08x\r\n", ntohl(sntp->origTm_s)); - printf("rx %08x\r\n", ntohl(sntp->rxTm_s)); - printf("tx %08x\r\n", ntohl(sntp->txTm_s)); -// printf("delay %d / offset %d\r\n", delay, offset); -#endif - return 0; - } - - return -1; -} - -void isr_sntp (UDPSocketEvent e) { - char buf[100]; - Host dsthost; - int len; - - if (e == UDPSOCKET_READABLE) { - // recv responce; - len = sntp->recvfrom(buf, sizeof(buf), &dsthost); -#ifdef DEBUG - for (int i = 0; i < len; i ++) { - printf(" %02x", (unsigned char)buf[i]); - } - puts("\r"); -#endif - if (len >= sizeof(struct SNTPPacket)) { - getSntpResponse(buf, (uint32_t*)&sntptime); - } - } -} - -int ntpdate (const char* name, uint32_t *tim) { - UDPSocketErr err; - Host myhost, sntphost; - char buf[100]; - int i, len; - DNSRequest dns; - DNSRequestErr dnsErr; - - sntptime = 0; - sntp = new UDPSocket; - sntp->setOnEvent(isr_sntp); - - // bind - myhost.setIp(eth.getIp()); - myhost.setPort(NTP_SRC_PORT); - err = sntp->bind(myhost); - if (err != UDPSOCKET_OK) goto exit; - - // send request - sntphost.setName(name); - sntphost.setPort(NTP_PORT); - dnsErr = dns.resolve(&sntphost); - if (dnsErr != DNS_OK) goto exit; - len = createSntpRequest(buf); -#ifdef DEBUG - for (int i = 0; i < len; i ++) { - printf(" %02x", (unsigned char)buf[i]); - } - puts("\r"); -#endif - sntp->sendto(buf, len, &sntphost); - - // wait responce - for (i = 0; i < NTP_TIMEOUT / 10; i ++) { - if (sntptime) { - *tim = sntptime; - break; - } - if (i % 500 == 499) { - sntp->sendto(buf, len, &sntphost); - } - Net::poll(); - wait_ms(10); - } - -exit: - sntp->resetOnEvent(); - delete sntp; - - return sntptime ? 0 : -1; -} +/* + * mbed Tiny SNTP(NTP) Client + * Copyright (c) 2011 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief Tiny DNS Resolver + */ + +#include "mbed.h" +#include "EthernetNetIf.h" +#include "UDPSocket.h" +#include "DNSRequest.h" +#include "TinySNTP.h" + +// host to network short +#define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) ) +#define ntohs( x ) htons(x) +// host to network long +#define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \ + | (( (x) << 8 ) & 0x00FF0000) \ + | (( (x) >> 8 ) & 0x0000FF00) \ + | (( (x) >> 24 ) & 0x000000FF) ) +#define ntohl( x ) htonl(x) + +static UDPSocket *sntp; +static volatile unsigned long sntptime; +static volatile int dns_status; +extern EthernetNetIf eth; + +int createSntpRequest (char *buf) { + struct SNTPPacket *sntp; + + sntp = (struct SNTPPacket *)buf; + memset(sntp, 0, sizeof(struct SNTPPacket)); + sntp->info = 0x1b; // Ver.3, client + sntp->txTm_s = htonl(NTP_TIMESTAMP_DELTA + time(NULL)); + + return sizeof(struct SNTPPacket); +} + +int getSntpResponse (const char *buf, uint32_t *tim) { + struct SNTPPacket *sntp; + uint32_t now; +// long int delay, offset; + + sntp = (struct SNTPPacket *)buf; + if ((sntp->info & 0x3f) == 0x1c || (sntp->info & 0x3f) == 0x24) { + // Ver.3or4, Server + + now = htonl(NTP_TIMESTAMP_DELTA + time(NULL)); +/* + delay = (now - sntp->origTm_s) - (sntp->rxTm_s - sntp->txTm_s); + offset = ((sntp->rxTm_s - sntp->origTm_s) + (sntp->txTm_s - now)); + + *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA + (delay / 2); +*/ + *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA; +#ifdef DEBUG + printf("now %08x\r\n", ntohl(now)); + printf("ref %08x\r\n", ntohl(sntp->refTm_s)); + printf("orig %08x\r\n", ntohl(sntp->origTm_s)); + printf("rx %08x\r\n", ntohl(sntp->rxTm_s)); + printf("tx %08x\r\n", ntohl(sntp->txTm_s)); +// printf("delay %d / offset %d\r\n", delay, offset); +#endif + return 0; + } + + return -1; +} + +void isr_dns (DNSReply r) { + +#ifdef DEBUG + printf("dns(%d)\r\n", r); +#endif + if (DNS_FOUND) { + dns_status = 1; + } else { + dns_status = -1; + } +} + +void isr_sntp (UDPSocketEvent e) { + char buf[100]; + Host dsthost; + int len; + + if (e == UDPSOCKET_READABLE) { + // recv responce; + len = sntp->recvfrom(buf, sizeof(buf), &dsthost); +#ifdef DEBUG + for (int i = 0; i < len; i ++) { + printf(" %02x", (unsigned char)buf[i]); + } + puts("\r"); +#endif + if (len >= sizeof(struct SNTPPacket)) { + getSntpResponse(buf, (uint32_t*)&sntptime); + } + } +} + +int ntpdate (const char* name, uint32_t *tim) { + UDPSocketErr err; + Host sntphost; + Timer timeout; + char buf[100]; + int i, len; + + sntptime = 0; + sntp = new UDPSocket; + sntp->setOnEvent(isr_sntp); + + sntphost.setName(name); + { + // resolv + DNSRequest dns; + dns_status = 0; + dns.setOnReply(isr_dns); + if (dns.resolve(&sntphost) != DNS_OK) goto exit; + timeout.reset(); + timeout.start(); + while (timeout.read_ms() < NTP_TIMEOUT) { + if (dns_status) break; + Net::poll(); + } + timeout.stop(); + if (dns_status <= 0) goto exit; +#ifdef DEBUG + printf("%s [%d.%d.%d.%d]\r\n", sntphost.getName(), (unsigned char)sntphost.getIp()[0], (unsigned char)sntphost.getIp()[1], (unsigned char)sntphost.getIp()[2], (unsigned char)sntphost.getIp()[3]); +#endif + } + sntphost.setPort(NTP_PORT); + + // send request + len = createSntpRequest(buf); +#ifdef DEBUG + for (int i = 0; i < len; i ++) { + printf(" %02x", (unsigned char)buf[i]); + } + puts("\r"); +#endif + sntp->sendto(buf, len, &sntphost); + + // wait responce + i = 0; + timeout.reset(); + timeout.start(); + while (timeout.read_ms() < NTP_TIMEOUT) { + if (sntptime) { + *tim = sntptime; + break; + } + if (timeout.read_ms() / 5000 < i) { + sntp->sendto(buf, len, &sntphost); + i ++; + } + Net::poll(); + } + timeout.stop(); + +exit: + sntp->resetOnEvent(); + delete sntp; + + return sntptime ? 0 : -1; +}
diff -r 41e7cfdbd23a -r d3c1871be1e9 TinySNTP.h --- a/TinySNTP.h Thu Jul 21 17:53:11 2011 +0000 +++ b/TinySNTP.h Thu Jul 28 17:23:43 2011 +0000 @@ -1,53 +1,53 @@ -/* - * mbed Tiny SNTP(NTP) Client - * Copyright (c) 2011 Hiroshi Suga - * Released under the MIT License: http://mbed.org/license/mit - */ - -/** @file - * @brief Tiny DNS Resolver - */ - -#ifndef TinySNTP_h -#define TinySNTP_h - -#include <inttypes.h> - -#define DEBUG - -#define NTP_PORT 123 -#define NTP_SRC_PORT 50420 -#define NTP_TIMESTAMP_DELTA 2208988800ull -#define NTP_TIMEOUT 15000 // ms - -struct SNTPPacket { - uint8_t info; - uint8_t stratum; - uint8_t poll; - uint8_t precision; - - uint32_t rootDelay; - uint32_t rootDispersion; - uint32_t refId; - - uint32_t refTm_s; - uint32_t refTm_f; - uint32_t origTm_s; - uint32_t origTm_f; - uint32_t rxTm_s; - uint32_t rxTm_f; - uint32_t txTm_s; - uint32_t txTm_f; -} __attribute__((packed)); - -int createSntpRequest (char*); -int getSntpResponse (const char*, uint32_t *time); - -/** resolv host by name - * @param name NTP server - * @param tim time (return) - * @return 0:success, -1:failue - */ -int ntpdate (const char* name, uint32_t *tim); - -#endif +/* + * mbed Tiny SNTP(NTP) Client + * Copyright (c) 2011 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief Tiny DNS Resolver + */ + +#ifndef TinySNTP_h +#define TinySNTP_h + +#include <inttypes.h> + +#define DEBUG + +#define NTP_PORT 123 +#define NTP_SRC_PORT 50420 +#define NTP_TIMESTAMP_DELTA 2208988800ull +#define NTP_TIMEOUT 15000 // ms + +struct SNTPPacket { + uint8_t info; + uint8_t stratum; + uint8_t poll; + uint8_t precision; + + uint32_t rootDelay; + uint32_t rootDispersion; + uint32_t refId; + + uint32_t refTm_s; + uint32_t refTm_f; + uint32_t origTm_s; + uint32_t origTm_f; + uint32_t rxTm_s; + uint32_t rxTm_f; + uint32_t txTm_s; + uint32_t txTm_f; +} __attribute__((packed)); + +int createSntpRequest (char*); +int getSntpResponse (const char*, uint32_t *time); + +/** resolv host by name + * @param name NTP server + * @param tim time (return) + * @return 0:success, -1:failue + */ +int ntpdate (const char* name, uint32_t *tim); + +#endif
diff -r 41e7cfdbd23a -r d3c1871be1e9 main.cpp --- a/main.cpp Thu Jul 21 17:53:11 2011 +0000 +++ b/main.cpp Thu Jul 28 17:23:43 2011 +0000 @@ -22,7 +22,7 @@ ntpdate("ntp1.sakura.ad.jp", &t); - t += 60 * 60 * 9; // JST + t = t + 60 * 60 * 9; // JST tm_buf = localtime((time_t*)&t); printf("now: %04d/%02d/%02d %02d:%02d:%02d\n", 1900 + tm_buf->tm_year, tm_buf->tm_mon + 1, tm_buf->tm_mday, tm_buf->tm_hour, tm_buf->tm_min, tm_buf->tm_sec);