Tiny SNTP(NTP) Client

Dependencies:   EthernetNetIf mbed

Committer:
okini3939
Date:
Thu Jul 28 17:23:43 2011 +0000
Revision:
1:d3c1871be1e9
Parent:
0:41e7cfdbd23a

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 1:d3c1871be1e9 1 /*
okini3939 1:d3c1871be1e9 2 * mbed Tiny SNTP(NTP) Client
okini3939 1:d3c1871be1e9 3 * Copyright (c) 2011 Hiroshi Suga
okini3939 1:d3c1871be1e9 4 * Released under the MIT License: http://mbed.org/license/mit
okini3939 1:d3c1871be1e9 5 */
okini3939 1:d3c1871be1e9 6
okini3939 1:d3c1871be1e9 7 /** @file
okini3939 1:d3c1871be1e9 8 * @brief Tiny DNS Resolver
okini3939 1:d3c1871be1e9 9 */
okini3939 1:d3c1871be1e9 10
okini3939 1:d3c1871be1e9 11 #include "mbed.h"
okini3939 1:d3c1871be1e9 12 #include "EthernetNetIf.h"
okini3939 1:d3c1871be1e9 13 #include "UDPSocket.h"
okini3939 1:d3c1871be1e9 14 #include "DNSRequest.h"
okini3939 1:d3c1871be1e9 15 #include "TinySNTP.h"
okini3939 1:d3c1871be1e9 16
okini3939 1:d3c1871be1e9 17 // host to network short
okini3939 1:d3c1871be1e9 18 #define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) )
okini3939 1:d3c1871be1e9 19 #define ntohs( x ) htons(x)
okini3939 1:d3c1871be1e9 20 // host to network long
okini3939 1:d3c1871be1e9 21 #define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \
okini3939 1:d3c1871be1e9 22 | (( (x) << 8 ) & 0x00FF0000) \
okini3939 1:d3c1871be1e9 23 | (( (x) >> 8 ) & 0x0000FF00) \
okini3939 1:d3c1871be1e9 24 | (( (x) >> 24 ) & 0x000000FF) )
okini3939 1:d3c1871be1e9 25 #define ntohl( x ) htonl(x)
okini3939 1:d3c1871be1e9 26
okini3939 1:d3c1871be1e9 27 static UDPSocket *sntp;
okini3939 1:d3c1871be1e9 28 static volatile unsigned long sntptime;
okini3939 1:d3c1871be1e9 29 static volatile int dns_status;
okini3939 1:d3c1871be1e9 30 extern EthernetNetIf eth;
okini3939 1:d3c1871be1e9 31
okini3939 1:d3c1871be1e9 32 int createSntpRequest (char *buf) {
okini3939 1:d3c1871be1e9 33 struct SNTPPacket *sntp;
okini3939 1:d3c1871be1e9 34
okini3939 1:d3c1871be1e9 35 sntp = (struct SNTPPacket *)buf;
okini3939 1:d3c1871be1e9 36 memset(sntp, 0, sizeof(struct SNTPPacket));
okini3939 1:d3c1871be1e9 37 sntp->info = 0x1b; // Ver.3, client
okini3939 1:d3c1871be1e9 38 sntp->txTm_s = htonl(NTP_TIMESTAMP_DELTA + time(NULL));
okini3939 1:d3c1871be1e9 39
okini3939 1:d3c1871be1e9 40 return sizeof(struct SNTPPacket);
okini3939 1:d3c1871be1e9 41 }
okini3939 1:d3c1871be1e9 42
okini3939 1:d3c1871be1e9 43 int getSntpResponse (const char *buf, uint32_t *tim) {
okini3939 1:d3c1871be1e9 44 struct SNTPPacket *sntp;
okini3939 1:d3c1871be1e9 45 uint32_t now;
okini3939 1:d3c1871be1e9 46 // long int delay, offset;
okini3939 1:d3c1871be1e9 47
okini3939 1:d3c1871be1e9 48 sntp = (struct SNTPPacket *)buf;
okini3939 1:d3c1871be1e9 49 if ((sntp->info & 0x3f) == 0x1c || (sntp->info & 0x3f) == 0x24) {
okini3939 1:d3c1871be1e9 50 // Ver.3or4, Server
okini3939 1:d3c1871be1e9 51
okini3939 1:d3c1871be1e9 52 now = htonl(NTP_TIMESTAMP_DELTA + time(NULL));
okini3939 1:d3c1871be1e9 53 /*
okini3939 1:d3c1871be1e9 54 delay = (now - sntp->origTm_s) - (sntp->rxTm_s - sntp->txTm_s);
okini3939 1:d3c1871be1e9 55 offset = ((sntp->rxTm_s - sntp->origTm_s) + (sntp->txTm_s - now));
okini3939 1:d3c1871be1e9 56
okini3939 1:d3c1871be1e9 57 *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA + (delay / 2);
okini3939 1:d3c1871be1e9 58 */
okini3939 1:d3c1871be1e9 59 *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA;
okini3939 1:d3c1871be1e9 60 #ifdef DEBUG
okini3939 1:d3c1871be1e9 61 printf("now %08x\r\n", ntohl(now));
okini3939 1:d3c1871be1e9 62 printf("ref %08x\r\n", ntohl(sntp->refTm_s));
okini3939 1:d3c1871be1e9 63 printf("orig %08x\r\n", ntohl(sntp->origTm_s));
okini3939 1:d3c1871be1e9 64 printf("rx %08x\r\n", ntohl(sntp->rxTm_s));
okini3939 1:d3c1871be1e9 65 printf("tx %08x\r\n", ntohl(sntp->txTm_s));
okini3939 1:d3c1871be1e9 66 // printf("delay %d / offset %d\r\n", delay, offset);
okini3939 1:d3c1871be1e9 67 #endif
okini3939 1:d3c1871be1e9 68 return 0;
okini3939 1:d3c1871be1e9 69 }
okini3939 1:d3c1871be1e9 70
okini3939 1:d3c1871be1e9 71 return -1;
okini3939 1:d3c1871be1e9 72 }
okini3939 1:d3c1871be1e9 73
okini3939 1:d3c1871be1e9 74 void isr_dns (DNSReply r) {
okini3939 1:d3c1871be1e9 75
okini3939 1:d3c1871be1e9 76 #ifdef DEBUG
okini3939 1:d3c1871be1e9 77 printf("dns(%d)\r\n", r);
okini3939 1:d3c1871be1e9 78 #endif
okini3939 1:d3c1871be1e9 79 if (DNS_FOUND) {
okini3939 1:d3c1871be1e9 80 dns_status = 1;
okini3939 1:d3c1871be1e9 81 } else {
okini3939 1:d3c1871be1e9 82 dns_status = -1;
okini3939 1:d3c1871be1e9 83 }
okini3939 1:d3c1871be1e9 84 }
okini3939 1:d3c1871be1e9 85
okini3939 1:d3c1871be1e9 86 void isr_sntp (UDPSocketEvent e) {
okini3939 1:d3c1871be1e9 87 char buf[100];
okini3939 1:d3c1871be1e9 88 Host dsthost;
okini3939 1:d3c1871be1e9 89 int len;
okini3939 1:d3c1871be1e9 90
okini3939 1:d3c1871be1e9 91 if (e == UDPSOCKET_READABLE) {
okini3939 1:d3c1871be1e9 92 // recv responce;
okini3939 1:d3c1871be1e9 93 len = sntp->recvfrom(buf, sizeof(buf), &dsthost);
okini3939 1:d3c1871be1e9 94 #ifdef DEBUG
okini3939 1:d3c1871be1e9 95 for (int i = 0; i < len; i ++) {
okini3939 1:d3c1871be1e9 96 printf(" %02x", (unsigned char)buf[i]);
okini3939 1:d3c1871be1e9 97 }
okini3939 1:d3c1871be1e9 98 puts("\r");
okini3939 1:d3c1871be1e9 99 #endif
okini3939 1:d3c1871be1e9 100 if (len >= sizeof(struct SNTPPacket)) {
okini3939 1:d3c1871be1e9 101 getSntpResponse(buf, (uint32_t*)&sntptime);
okini3939 1:d3c1871be1e9 102 }
okini3939 1:d3c1871be1e9 103 }
okini3939 1:d3c1871be1e9 104 }
okini3939 1:d3c1871be1e9 105
okini3939 1:d3c1871be1e9 106 int ntpdate (const char* name, uint32_t *tim) {
okini3939 1:d3c1871be1e9 107 UDPSocketErr err;
okini3939 1:d3c1871be1e9 108 Host sntphost;
okini3939 1:d3c1871be1e9 109 Timer timeout;
okini3939 1:d3c1871be1e9 110 char buf[100];
okini3939 1:d3c1871be1e9 111 int i, len;
okini3939 1:d3c1871be1e9 112
okini3939 1:d3c1871be1e9 113 sntptime = 0;
okini3939 1:d3c1871be1e9 114 sntp = new UDPSocket;
okini3939 1:d3c1871be1e9 115 sntp->setOnEvent(isr_sntp);
okini3939 1:d3c1871be1e9 116
okini3939 1:d3c1871be1e9 117 sntphost.setName(name);
okini3939 1:d3c1871be1e9 118 {
okini3939 1:d3c1871be1e9 119 // resolv
okini3939 1:d3c1871be1e9 120 DNSRequest dns;
okini3939 1:d3c1871be1e9 121 dns_status = 0;
okini3939 1:d3c1871be1e9 122 dns.setOnReply(isr_dns);
okini3939 1:d3c1871be1e9 123 if (dns.resolve(&sntphost) != DNS_OK) goto exit;
okini3939 1:d3c1871be1e9 124 timeout.reset();
okini3939 1:d3c1871be1e9 125 timeout.start();
okini3939 1:d3c1871be1e9 126 while (timeout.read_ms() < NTP_TIMEOUT) {
okini3939 1:d3c1871be1e9 127 if (dns_status) break;
okini3939 1:d3c1871be1e9 128 Net::poll();
okini3939 1:d3c1871be1e9 129 }
okini3939 1:d3c1871be1e9 130 timeout.stop();
okini3939 1:d3c1871be1e9 131 if (dns_status <= 0) goto exit;
okini3939 1:d3c1871be1e9 132 #ifdef DEBUG
okini3939 1:d3c1871be1e9 133 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]);
okini3939 1:d3c1871be1e9 134 #endif
okini3939 1:d3c1871be1e9 135 }
okini3939 1:d3c1871be1e9 136 sntphost.setPort(NTP_PORT);
okini3939 1:d3c1871be1e9 137
okini3939 1:d3c1871be1e9 138 // send request
okini3939 1:d3c1871be1e9 139 len = createSntpRequest(buf);
okini3939 1:d3c1871be1e9 140 #ifdef DEBUG
okini3939 1:d3c1871be1e9 141 for (int i = 0; i < len; i ++) {
okini3939 1:d3c1871be1e9 142 printf(" %02x", (unsigned char)buf[i]);
okini3939 1:d3c1871be1e9 143 }
okini3939 1:d3c1871be1e9 144 puts("\r");
okini3939 1:d3c1871be1e9 145 #endif
okini3939 1:d3c1871be1e9 146 sntp->sendto(buf, len, &sntphost);
okini3939 1:d3c1871be1e9 147
okini3939 1:d3c1871be1e9 148 // wait responce
okini3939 1:d3c1871be1e9 149 i = 0;
okini3939 1:d3c1871be1e9 150 timeout.reset();
okini3939 1:d3c1871be1e9 151 timeout.start();
okini3939 1:d3c1871be1e9 152 while (timeout.read_ms() < NTP_TIMEOUT) {
okini3939 1:d3c1871be1e9 153 if (sntptime) {
okini3939 1:d3c1871be1e9 154 *tim = sntptime;
okini3939 1:d3c1871be1e9 155 break;
okini3939 1:d3c1871be1e9 156 }
okini3939 1:d3c1871be1e9 157 if (timeout.read_ms() / 5000 < i) {
okini3939 1:d3c1871be1e9 158 sntp->sendto(buf, len, &sntphost);
okini3939 1:d3c1871be1e9 159 i ++;
okini3939 1:d3c1871be1e9 160 }
okini3939 1:d3c1871be1e9 161 Net::poll();
okini3939 1:d3c1871be1e9 162 }
okini3939 1:d3c1871be1e9 163 timeout.stop();
okini3939 1:d3c1871be1e9 164
okini3939 1:d3c1871be1e9 165 exit:
okini3939 1:d3c1871be1e9 166 sntp->resetOnEvent();
okini3939 1:d3c1871be1e9 167 delete sntp;
okini3939 1:d3c1871be1e9 168
okini3939 1:d3c1871be1e9 169 return sntptime ? 0 : -1;
okini3939 1:d3c1871be1e9 170 }