The extracted NTP client from Segundos NetServices library, for use with the [[http://mbed.org/users/hlipka/libraries/NetServicesMin|NetServicesMin]] library. The only fixed bug is the memory leak / OOM problem. Needs the [[http://mbed.org/users/hlipka/libraries/DNSResolver|DNSResolver]] library as well.

Dependents:   SPIVFDclock LPC1768_AppBoard_Internet_LCD_Clock

Committer:
hlipka
Date:
Mon Jan 10 22:38:49 2011 +0000
Revision:
0:ebea15f18f84
Child:
1:63ded11b8fa2
initial version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hlipka 0:ebea15f18f84 1 #pragma diag_remark 1293
hlipka 0:ebea15f18f84 2 /*
hlipka 0:ebea15f18f84 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
hlipka 0:ebea15f18f84 4
hlipka 0:ebea15f18f84 5 Permission is hereby granted, free of charge, to any person obtaining a copy
hlipka 0:ebea15f18f84 6 of this software and associated documentation files (the "Software"), to deal
hlipka 0:ebea15f18f84 7 in the Software without restriction, including without limitation the rights
hlipka 0:ebea15f18f84 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
hlipka 0:ebea15f18f84 9 copies of the Software, and to permit persons to whom the Software is
hlipka 0:ebea15f18f84 10 furnished to do so, subject to the following conditions:
hlipka 0:ebea15f18f84 11
hlipka 0:ebea15f18f84 12 The above copyright notice and this permission notice shall be included in
hlipka 0:ebea15f18f84 13 all copies or substantial portions of the Software.
hlipka 0:ebea15f18f84 14
hlipka 0:ebea15f18f84 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
hlipka 0:ebea15f18f84 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
hlipka 0:ebea15f18f84 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
hlipka 0:ebea15f18f84 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
hlipka 0:ebea15f18f84 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
hlipka 0:ebea15f18f84 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
hlipka 0:ebea15f18f84 21 THE SOFTWARE.
hlipka 0:ebea15f18f84 22 */
hlipka 0:ebea15f18f84 23
hlipka 0:ebea15f18f84 24 #include "NTPClient.h"
hlipka 0:ebea15f18f84 25
hlipka 0:ebea15f18f84 26 #include <stdio.h>
hlipka 0:ebea15f18f84 27
hlipka 0:ebea15f18f84 28 //#define __DEBUG
hlipka 0:ebea15f18f84 29 #include "dbg/dbg.h"
hlipka 0:ebea15f18f84 30
hlipka 0:ebea15f18f84 31 #define NTP_PORT 123
hlipka 0:ebea15f18f84 32 #define NTP_CLIENT_PORT 0//50420 //Random port
hlipka 0:ebea15f18f84 33 #define NTP_REQUEST_TIMEOUT 15000
hlipka 0:ebea15f18f84 34 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
hlipka 0:ebea15f18f84 35
hlipka 0:ebea15f18f84 36 #define htons( x ) ( (( x << 8 ) & 0xFF00) | (( x >> 8 ) & 0x00FF) )
hlipka 0:ebea15f18f84 37 #define ntohs( x ) (htons(x))
hlipka 0:ebea15f18f84 38
hlipka 0:ebea15f18f84 39 #define htonl( x ) ( (( x << 24 ) & 0xFF000000) \
hlipka 0:ebea15f18f84 40 | (( x << 8 ) & 0x00FF0000) \
hlipka 0:ebea15f18f84 41 | (( x >> 8 ) & 0x0000FF00) \
hlipka 0:ebea15f18f84 42 | (( x >> 24 ) & 0x000000FF) )
hlipka 0:ebea15f18f84 43 #define ntohl( x ) (htonl(x))
hlipka 0:ebea15f18f84 44
hlipka 0:ebea15f18f84 45 NTPClient::NTPClient() :
hlipka 0:ebea15f18f84 46 m_state(NTP_PING),
hlipka 0:ebea15f18f84 47 // m_watchdog(),
hlipka 0:ebea15f18f84 48 m_timeout(NTP_REQUEST_TIMEOUT),
hlipka 0:ebea15f18f84 49 m_closed(true),
hlipka 0:ebea15f18f84 50 m_host(),
hlipka 0:ebea15f18f84 51 m_pDnsReq(NULL),
hlipka 0:ebea15f18f84 52 m_blockingResult(NTP_PROCESSING)
hlipka 0:ebea15f18f84 53 {
hlipka 0:ebea15f18f84 54 m_watchdog=new Timer();
hlipka 0:ebea15f18f84 55 DBG("\r\nNew NTPClient %p\r\n",this);
hlipka 0:ebea15f18f84 56 }
hlipka 0:ebea15f18f84 57
hlipka 0:ebea15f18f84 58 NTPClient::~NTPClient()
hlipka 0:ebea15f18f84 59 {
hlipka 0:ebea15f18f84 60 close();
hlipka 0:ebea15f18f84 61 delete m_watchdog;
hlipka 0:ebea15f18f84 62 }
hlipka 0:ebea15f18f84 63
hlipka 0:ebea15f18f84 64 //High level setup functions
hlipka 0:ebea15f18f84 65 NTPResult NTPClient::setTime(const Host& host) //Blocking
hlipka 0:ebea15f18f84 66 {
hlipka 0:ebea15f18f84 67 doSetTime(host);
hlipka 0:ebea15f18f84 68 return blockingProcess();
hlipka 0:ebea15f18f84 69 }
hlipka 0:ebea15f18f84 70
hlipka 0:ebea15f18f84 71 void NTPClient::doSetTime(const Host& host)
hlipka 0:ebea15f18f84 72 {
hlipka 0:ebea15f18f84 73 init();
hlipka 0:ebea15f18f84 74 resetTimeout();
hlipka 0:ebea15f18f84 75 m_host = host;
hlipka 0:ebea15f18f84 76 if(!m_host.getPort())
hlipka 0:ebea15f18f84 77 {
hlipka 0:ebea15f18f84 78 m_host.setPort(NTP_PORT);
hlipka 0:ebea15f18f84 79 }
hlipka 0:ebea15f18f84 80 if(m_host.getIp().isNull())
hlipka 0:ebea15f18f84 81 {
hlipka 0:ebea15f18f84 82 //DNS query required
hlipka 0:ebea15f18f84 83 m_pDnsReq = new DNSRequest();
hlipka 0:ebea15f18f84 84 DBG("\r\nNTPClient : DNSRequest %p\r\n", m_pDnsReq);
hlipka 0:ebea15f18f84 85 m_pDnsReq->setOnReply(this, &NTPClient::onDNSReply);
hlipka 0:ebea15f18f84 86 m_pDnsReq->resolve(&m_host);
hlipka 0:ebea15f18f84 87 return;
hlipka 0:ebea15f18f84 88 }
hlipka 0:ebea15f18f84 89 open();
hlipka 0:ebea15f18f84 90 }
hlipka 0:ebea15f18f84 91
hlipka 0:ebea15f18f84 92 void NTPClient::close()
hlipka 0:ebea15f18f84 93 {
hlipka 0:ebea15f18f84 94 if(m_closed)
hlipka 0:ebea15f18f84 95 return;
hlipka 0:ebea15f18f84 96 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
hlipka 0:ebea15f18f84 97 m_watchdog->stop();
hlipka 0:ebea15f18f84 98 m_pUDPSocket->resetOnEvent();
hlipka 0:ebea15f18f84 99 m_pUDPSocket->close();
hlipka 0:ebea15f18f84 100 delete m_pUDPSocket;
hlipka 0:ebea15f18f84 101 if( m_pDnsReq )
hlipka 0:ebea15f18f84 102 {
hlipka 0:ebea15f18f84 103 m_pDnsReq->close();
hlipka 0:ebea15f18f84 104 delete m_pDnsReq;
hlipka 0:ebea15f18f84 105 m_pDnsReq = NULL;
hlipka 0:ebea15f18f84 106 }
hlipka 0:ebea15f18f84 107 }
hlipka 0:ebea15f18f84 108
hlipka 0:ebea15f18f84 109 /*
hlipka 0:ebea15f18f84 110 void NTPClient::poll() //Called by NetServices
hlipka 0:ebea15f18f84 111 {
hlipka 0:ebea15f18f84 112 if( (!m_closed) && (m_watchdog->read_ms() >= m_timeout) )
hlipka 0:ebea15f18f84 113 {
hlipka 0:ebea15f18f84 114 onTimeout();
hlipka 0:ebea15f18f84 115 }
hlipka 0:ebea15f18f84 116 }
hlipka 0:ebea15f18f84 117 */
hlipka 0:ebea15f18f84 118 void NTPClient::init() //Create and setup socket if needed
hlipka 0:ebea15f18f84 119 {
hlipka 0:ebea15f18f84 120 if(!m_closed) //Already opened
hlipka 0:ebea15f18f84 121 return;
hlipka 0:ebea15f18f84 122 m_state = NTP_PING;
hlipka 0:ebea15f18f84 123 m_pUDPSocket = new UDPSocket;
hlipka 0:ebea15f18f84 124 m_pUDPSocket->setOnEvent(this, &NTPClient::onUDPSocketEvent);
hlipka 0:ebea15f18f84 125 m_closed = false;
hlipka 0:ebea15f18f84 126 DBG("NTPClient: Init OK\n");
hlipka 0:ebea15f18f84 127 }
hlipka 0:ebea15f18f84 128
hlipka 0:ebea15f18f84 129 void NTPClient::open()
hlipka 0:ebea15f18f84 130 {
hlipka 0:ebea15f18f84 131 resetTimeout();
hlipka 0:ebea15f18f84 132 DBG("Opening connection\n");
hlipka 0:ebea15f18f84 133 m_state = NTP_PING;
hlipka 0:ebea15f18f84 134 Host localhost(IpAddr(), NTP_CLIENT_PORT, "localhost"); //Any local address
hlipka 0:ebea15f18f84 135 m_pUDPSocket->bind(localhost);
hlipka 0:ebea15f18f84 136 if ((int)time(NULL) < 1280000000) set_time( 1280000000 ); //End of July 2010... just there to limit offset range
hlipka 0:ebea15f18f84 137
hlipka 0:ebea15f18f84 138 process();
hlipka 0:ebea15f18f84 139
hlipka 0:ebea15f18f84 140 }
hlipka 0:ebea15f18f84 141
hlipka 0:ebea15f18f84 142 #define MIN(a,b) ((a)<(b))?(a):(b)
hlipka 0:ebea15f18f84 143 void NTPClient::process() //Main state-machine
hlipka 0:ebea15f18f84 144 {
hlipka 0:ebea15f18f84 145 int len;
hlipka 0:ebea15f18f84 146 Host host;
hlipka 0:ebea15f18f84 147
hlipka 0:ebea15f18f84 148 switch(m_state)
hlipka 0:ebea15f18f84 149 {
hlipka 0:ebea15f18f84 150 case NTP_PING:
hlipka 0:ebea15f18f84 151 DBG("Ping\r\n");
hlipka 0:ebea15f18f84 152 //Prepare NTP Packet:
hlipka 0:ebea15f18f84 153 m_pkt.li = 0; //Leap Indicator : No warning
hlipka 0:ebea15f18f84 154 m_pkt.vn = 4; //Version Number : 4
hlipka 0:ebea15f18f84 155 m_pkt.mode = 3; //Client mode
hlipka 0:ebea15f18f84 156 m_pkt.stratum = 0; //Not relevant here
hlipka 0:ebea15f18f84 157 m_pkt.poll = 0; //Not significant as well
hlipka 0:ebea15f18f84 158 m_pkt.precision = 0; //Neither this one is
hlipka 0:ebea15f18f84 159
hlipka 0:ebea15f18f84 160 m_pkt.rootDelay = 0; //Or this one
hlipka 0:ebea15f18f84 161 m_pkt.rootDispersion = 0; //Or that one
hlipka 0:ebea15f18f84 162 m_pkt.refId = 0; //...
hlipka 0:ebea15f18f84 163
hlipka 0:ebea15f18f84 164 m_pkt.refTm_s = 0;
hlipka 0:ebea15f18f84 165 m_pkt.origTm_s = 0;
hlipka 0:ebea15f18f84 166 m_pkt.rxTm_s = 0;
hlipka 0:ebea15f18f84 167 m_pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
hlipka 0:ebea15f18f84 168
hlipka 0:ebea15f18f84 169 m_pkt.refTm_f = m_pkt.origTm_f = m_pkt.rxTm_f = m_pkt.txTm_f = 0;
hlipka 0:ebea15f18f84 170
hlipka 0:ebea15f18f84 171 #ifdef __DEBUG
hlipka 0:ebea15f18f84 172 //Hex Dump:
hlipka 0:ebea15f18f84 173 DBG("Dump Tx:\r\n");
hlipka 0:ebea15f18f84 174 for(int i = 0; i< sizeof(NTPPacket); i++)
hlipka 0:ebea15f18f84 175 {
hlipka 0:ebea15f18f84 176 DBGL("%02x ", *((char*)&m_pkt + i));
hlipka 0:ebea15f18f84 177 }
hlipka 0:ebea15f18f84 178 DBGL("\r\n");
hlipka 0:ebea15f18f84 179 #endif
hlipka 0:ebea15f18f84 180
hlipka 0:ebea15f18f84 181 len = m_pUDPSocket->sendto( (char*)&m_pkt, sizeof(NTPPacket), &m_host );
hlipka 0:ebea15f18f84 182 if(len < sizeof(NTPPacket))
hlipka 0:ebea15f18f84 183 { onResult(NTP_PRTCL); close(); return; }
hlipka 0:ebea15f18f84 184
hlipka 0:ebea15f18f84 185 m_state = NTP_PONG;
hlipka 0:ebea15f18f84 186
hlipka 0:ebea15f18f84 187 break;
hlipka 0:ebea15f18f84 188
hlipka 0:ebea15f18f84 189 case NTP_PONG:
hlipka 0:ebea15f18f84 190 DBG("Pong\r\n");
hlipka 0:ebea15f18f84 191 while( len = m_pUDPSocket->recvfrom( (char*)&m_pkt, sizeof(NTPPacket), &host ) )
hlipka 0:ebea15f18f84 192 {
hlipka 0:ebea15f18f84 193 if( len <= 0 )
hlipka 0:ebea15f18f84 194 break;
hlipka 0:ebea15f18f84 195 if( !host.getIp().isEq(m_host.getIp()) )
hlipka 0:ebea15f18f84 196 continue; //Not our packet
hlipka 0:ebea15f18f84 197 if( len > 0 )
hlipka 0:ebea15f18f84 198 break;
hlipka 0:ebea15f18f84 199 }
hlipka 0:ebea15f18f84 200
hlipka 0:ebea15f18f84 201 if(len == 0)
hlipka 0:ebea15f18f84 202 return; //Wait for the next packet
hlipka 0:ebea15f18f84 203
hlipka 0:ebea15f18f84 204 if(len < 0)
hlipka 0:ebea15f18f84 205 { onResult(NTP_PRTCL); close(); return; }
hlipka 0:ebea15f18f84 206
hlipka 0:ebea15f18f84 207 if(len < sizeof(NTPPacket)) //TODO: Accept chunks
hlipka 0:ebea15f18f84 208 { onResult(NTP_PRTCL); close(); return; }
hlipka 0:ebea15f18f84 209
hlipka 0:ebea15f18f84 210 #ifdef __DEBUG
hlipka 0:ebea15f18f84 211 //Hex Dump:
hlipka 0:ebea15f18f84 212 DBG("Dump Rx:\r\n");
hlipka 0:ebea15f18f84 213 for(int i = 0; i< sizeof(NTPPacket); i++)
hlipka 0:ebea15f18f84 214 {
hlipka 0:ebea15f18f84 215 DBGL("%02x ", *((char*)&m_pkt + i));
hlipka 0:ebea15f18f84 216 }
hlipka 0:ebea15f18f84 217 DBGL("\r\n");
hlipka 0:ebea15f18f84 218 #endif
hlipka 0:ebea15f18f84 219
hlipka 0:ebea15f18f84 220 if( m_pkt.stratum == 0) //Kiss of death message : Not good !
hlipka 0:ebea15f18f84 221 {
hlipka 0:ebea15f18f84 222 onResult(NTP_PRTCL); close(); return;
hlipka 0:ebea15f18f84 223 }
hlipka 0:ebea15f18f84 224
hlipka 0:ebea15f18f84 225 //Correct Endianness
hlipka 0:ebea15f18f84 226 m_pkt.refTm_s = ntohl( m_pkt.refTm_s );
hlipka 0:ebea15f18f84 227 m_pkt.refTm_f = ntohl( m_pkt.refTm_f );
hlipka 0:ebea15f18f84 228 m_pkt.origTm_s = ntohl( m_pkt.origTm_s );
hlipka 0:ebea15f18f84 229 m_pkt.origTm_f = ntohl( m_pkt.origTm_f );
hlipka 0:ebea15f18f84 230 m_pkt.rxTm_s = ntohl( m_pkt.rxTm_s );
hlipka 0:ebea15f18f84 231 m_pkt.rxTm_f = ntohl( m_pkt.rxTm_f );
hlipka 0:ebea15f18f84 232 m_pkt.txTm_s = ntohl( m_pkt.txTm_s );
hlipka 0:ebea15f18f84 233 m_pkt.txTm_f = ntohl( m_pkt.txTm_f );
hlipka 0:ebea15f18f84 234
hlipka 0:ebea15f18f84 235 //Compute offset, see RFC 4330 p.13
hlipka 0:ebea15f18f84 236 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
hlipka 0:ebea15f18f84 237 //int32_t origTm = (int32_t) ((uint64_t) m_pkt.origTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
hlipka 0:ebea15f18f84 238 //int32_t rxTm = (int32_t) ((uint64_t) m_pkt.rxTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
hlipka 0:ebea15f18f84 239 //int32_t txTm = (int32_t) ((uint64_t) m_pkt.txTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
hlipka 0:ebea15f18f84 240 // int64_t offset = ( ( ( m_pkt.rxTm_s - m_pkt.origTm_s ) + ( m_pkt.txTm_s - destTm_s ) ) << 32 + ( ( m_pkt.rxTm_f - m_pkt.origTm_f ) + ( m_pkt.txTm_f - 0 ) ) ) / 2;
hlipka 0:ebea15f18f84 241 int64_t offset = ( (int64_t)( m_pkt.rxTm_s - m_pkt.origTm_s ) + (int64_t) ( m_pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
hlipka 0:ebea15f18f84 242 DBG("Sent @%d\r\n", m_pkt.txTm_s);
hlipka 0:ebea15f18f84 243 DBG("Offset: %d\r\n", offset);
hlipka 0:ebea15f18f84 244
hlipka 0:ebea15f18f84 245 //Set time accordingly
hlipka 0:ebea15f18f84 246 set_time( time(NULL) + (offset /*>> 32*/) );
hlipka 0:ebea15f18f84 247
hlipka 0:ebea15f18f84 248 onResult(NTP_OK);
hlipka 0:ebea15f18f84 249 close();
hlipka 0:ebea15f18f84 250 break;
hlipka 0:ebea15f18f84 251 }
hlipka 0:ebea15f18f84 252 }
hlipka 0:ebea15f18f84 253
hlipka 0:ebea15f18f84 254 void NTPClient::setTimeout(int ms)
hlipka 0:ebea15f18f84 255 {
hlipka 0:ebea15f18f84 256 m_timeout = ms;
hlipka 0:ebea15f18f84 257 }
hlipka 0:ebea15f18f84 258
hlipka 0:ebea15f18f84 259 void NTPClient::resetTimeout()
hlipka 0:ebea15f18f84 260 {
hlipka 0:ebea15f18f84 261 m_watchdog->reset();
hlipka 0:ebea15f18f84 262 m_watchdog->start();
hlipka 0:ebea15f18f84 263 }
hlipka 0:ebea15f18f84 264
hlipka 0:ebea15f18f84 265 void NTPClient::onTimeout() //Connection has timed out
hlipka 0:ebea15f18f84 266 {
hlipka 0:ebea15f18f84 267 close();
hlipka 0:ebea15f18f84 268 onResult(NTP_TIMEOUT);
hlipka 0:ebea15f18f84 269 }
hlipka 0:ebea15f18f84 270
hlipka 0:ebea15f18f84 271 void NTPClient::onDNSReply(DNSReply r)
hlipka 0:ebea15f18f84 272 {
hlipka 0:ebea15f18f84 273 if(m_closed)
hlipka 0:ebea15f18f84 274 {
hlipka 0:ebea15f18f84 275 DBG("\r\nWARN: Discarded\r\n");
hlipka 0:ebea15f18f84 276 return;
hlipka 0:ebea15f18f84 277 }
hlipka 0:ebea15f18f84 278
hlipka 0:ebea15f18f84 279 if( r != DNS_FOUND )
hlipka 0:ebea15f18f84 280 {
hlipka 0:ebea15f18f84 281 DBG("\r\nCould not resolve hostname.\r\n");
hlipka 0:ebea15f18f84 282 onResult(NTP_DNS);
hlipka 0:ebea15f18f84 283 close();
hlipka 0:ebea15f18f84 284 return;
hlipka 0:ebea15f18f84 285 }
hlipka 0:ebea15f18f84 286 DBG("\r\nDNS resolved.\r\n");
hlipka 0:ebea15f18f84 287 m_pDnsReq->close();
hlipka 0:ebea15f18f84 288 delete m_pDnsReq;
hlipka 0:ebea15f18f84 289 m_pDnsReq=NULL;
hlipka 0:ebea15f18f84 290
hlipka 0:ebea15f18f84 291 open();
hlipka 0:ebea15f18f84 292 }
hlipka 0:ebea15f18f84 293
hlipka 0:ebea15f18f84 294 void NTPClient::onUDPSocketEvent(UDPSocketEvent e)
hlipka 0:ebea15f18f84 295 {
hlipka 0:ebea15f18f84 296 resetTimeout();
hlipka 0:ebea15f18f84 297 switch(e)
hlipka 0:ebea15f18f84 298 {
hlipka 0:ebea15f18f84 299 case UDPSOCKET_READABLE: //The only event for now
hlipka 0:ebea15f18f84 300 resetTimeout();
hlipka 0:ebea15f18f84 301 process();
hlipka 0:ebea15f18f84 302 break;
hlipka 0:ebea15f18f84 303 }
hlipka 0:ebea15f18f84 304 }
hlipka 0:ebea15f18f84 305
hlipka 0:ebea15f18f84 306 void NTPClient::onResult(NTPResult r) //Must be called by impl when the request completes
hlipka 0:ebea15f18f84 307 {
hlipka 0:ebea15f18f84 308 m_blockingResult = r; //Blocking mode
hlipka 0:ebea15f18f84 309 }
hlipka 0:ebea15f18f84 310
hlipka 0:ebea15f18f84 311 NTPResult NTPClient::blockingProcess() //Called in blocking mode, calls Net::poll() until return code is available
hlipka 0:ebea15f18f84 312 {
hlipka 0:ebea15f18f84 313 m_blockingResult = NTP_PROCESSING;
hlipka 0:ebea15f18f84 314 do
hlipka 0:ebea15f18f84 315 {
hlipka 0:ebea15f18f84 316 Net::poll();
hlipka 0:ebea15f18f84 317 } while(m_blockingResult == NTP_PROCESSING);
hlipka 0:ebea15f18f84 318
hlipka 0:ebea15f18f84 319 Net::poll(); //Necessary for cleanup
hlipka 0:ebea15f18f84 320
hlipka 0:ebea15f18f84 321 return m_blockingResult;
hlipka 0:ebea15f18f84 322 }