Tiny SNTP(NTP) Client

Dependencies:   EthernetNetIf mbed

Committer:
okini3939
Date:
Thu Jul 21 17:53:11 2011 +0000
Revision:
0:41e7cfdbd23a
Child:
1:d3c1871be1e9

        

Who changed what in which revision?

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