Tiny SNTP(NTP) Client

Dependencies:   EthernetNetIf mbed

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Thu Jul 28 17:23:43 2011 +0000
Parent:
0:41e7cfdbd23a
Commit message:

Changed in this revision

TinySNTP.cpp Show annotated file Show diff for this revision Revisions of this file
TinySNTP.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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;
+}
--- 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
--- 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);