Tiny SNTP(NTP) Client
Dependencies: EthernetNetIf mbed
TinySNTP.cpp
- Committer:
- okini3939
- Date:
- 2011-07-28
- Revision:
- 1:d3c1871be1e9
- Parent:
- 0:41e7cfdbd23a
File content as of revision 1:d3c1871be1e9:
/* * 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; }