Android/NET/sntpclient
/*
* Copyright (c) 2008 the android open source project
*
* Licensed under the Apache license, version 2.0 (the "License ");
* You may not use this file before t in compliance with the license.
* You may obtain a copy of the license
*
* Http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* Distributed under the license is distributed on an "as is" basis,
* Without warranties or conditions of any kind, either express or implied.
* See the license for the specific language governing permissions and
* Limitations under the license.
*/
Package com. NEC. Android. ntptime;
Import Android. OS. systemclock;
Import Android. util. config;
Import Android. util. log;
Import java.net. datagrampacket;
Import java.net. datagramsocket;
Import java.net. inetaddress;
/**
* {@ Hide}
*
* Simple SNTP client class for retrieving network time.
*
* Sample usage:
* <PRE> sntpclient client = new sntpclient ();
* If (client. requesttime ("time.foo.com ")){
* Long Now = client. getntptime () + systemclock. elapsedrealtime ()-client. getntptimereference ();
*}
* </PRE>
*/
Public class sntpclient
{
Private Static final string tag = "sntpclient ";
Private Static final int reference_time_offset = 16;
Private Static final int originate_time_offset = 24;
Private Static final int receive_time_offset = 32;
Private Static final int transmit_time_offset = 40;
Private Static final int ntp_packet_size = 48;
Private Static final int ntp_port = 123;
Private Static final int ntp_mode_client = 3;
Private Static final int ntp_version = 3;
// Number of seconds between Jan 1, 1900 and Jan 1, 1970
// 70 years plus 17 leap days
Private Static final long offset_1900_to_1970 = (365l * 70l) + 17l) * 24l * 60l * 60l;
// System time computed from NTP server response
Private long mntptime;
// Value of systemclock. elapsedrealtime () corresponding to mntptime
Private long mntptimereference;
// Round trip time in milliseconds
Private long mroundtriptime;
/**
* Sends an SNTP request to the given host and processes the response.
*
* @ Param host Host Name of the server.
* @ Param timeout network timeout in milliseconds.
* @ Return true if the transaction was successful.
*/
Public Boolean requesttime (string host, int timeout ){
Try {
Datagramsocket socket = new datagramsocket ();
Socket. setsotimeout (timeout );
Inetaddress address = inetaddress. getbyname (host );
Byte [] buffer = new byte [ntp_packet_size];
Datagrampacket request = new datagrampacket (buffer, buffer. length, address, ntp_port );
// Set mode = 3 (client) and version = 3
// Mode is in low 3 bits of first byte
// Version is in bits 3-5 of first byte
Buffer [0] = ntp_mode_client | (ntp_version <3 );
// Get current time and write it to the Request Packet
Long requesttime = system. currenttimemillis ();
Long requestticks = systemclock. elapsedrealtime ();
Writetimestamp (buffer, transmit_time_offset, requesttime );
Socket. Send (request );
// Read the response
Datagrampacket response = new datagrampacket (buffer, buffer. Length );
Socket. Receive (response );
Long responseticks = systemclock. elapsedrealtime ();
Long responsetime = requesttime + (responseticks-requestticks );
Socket. Close ();
// Extract the results
Long originatetime = readtimestamp (buffer, originate_time_offset );
Long receivetime = readtimestamp (buffer, receive_time_offset );
Long transmittime = readtimestamp (buffer, transmit_time_offset );
Long roundtriptime = responseticks-requestticks-(transmittime-receivetime );
Long clockoffset = (receivetime-originatetime) + (transmittime-responsetime );
If (config. logd) log. D (TAG, "round trip:" + roundtriptime + "Ms ");
If (config. logd) log. D (TAG, "clock offset:" + clockoffset + "Ms ");
// Save Our results
Mntptime = requesttime + clockoffset;
Mntptimereference = requestticks;
Mroundtriptime = roundtriptime;
} Catch (exception e ){
If (config. logd) log. D (TAG, "request time failed:" + E );
Return false;
}
Return true;
}
/**
* Returns the time computed from the NTP transaction.
*
* @ Return time value computed from NTP server response.
*/
Public long getntptime (){
Return mntptime;
}
/**
* Returns the reference clock value (value of systemclock. elapsedrealtime ())
* Corresponding to the NTP time.
*
* @ Return reference clock corresponding to the NTP time.
*/
Public long getntptimereference (){
Return mntptimereference;
}
/**
* Returns the round trip time of the NTP transaction
*
* @ Return round trip time in milliseconds.
*/
Public long getroundtriptime (){
Return mroundtriptime;
}
/**
* Reads an unsigned 32 bit big endian number from the given offset in the buffer.
*/
Private long read32 (byte [] buffer, int offset ){
Byte b0 = buffer [offset];
Byte b1 = buffer [Offset + 1];
Byte b2 = buffer [Offset + 2];
Byte B3 = buffer [Offset + 3];
// Convert signed bytes to unsigned values
Int I0 = (B0 & 0x80) = 0x80? (B0 & 0x7f) + 0x80: B0 );
Int I1 = (B1 & 0x80) = 0x80? (B1 & 0x7f) + 0x80: B1 );
Int I2 = (B2 & 0x80) = 0x80? (B2 & 0x7f) + 0x80: B2 );
Int I3 = (B3 & 0x80) = 0x80? (B3 & 0x7f) + 0x80: B3 );
Return (long) I0 <24) + (long) i1 <16) + (long) I2 <8) + (long) I3;
}
/**
* Reads the NTP time stamp at the given offset in the buffer and returns
* It as a system time (milliseconds since January 1, 1970 ).
*/
Private long readtimestamp (byte [] buffer, int offset ){
Long seconds = read32 (buffer, offset );
Long fraction = read32 (buffer, offset + 4 );
Return (seconds-offset_1900_to_1970) * 1000) + (fraction * 1000l)/0x00000000l );
}
/**
* Writes system time (milliseconds since January 1, 1970) as an NTP time stamp
* At the given offset in the buffer.
*/
Private void writetimestamp (byte [] buffer, int offset, long time ){
Long seconds = Time/1000l;
Long milliseconds = Time-seconds * 1000l;
Seconds + = offset_1900_to_1970;
// Write seconds in big endian format
Buffer [offset ++] = (byte) (seconds> 24 );
Buffer [offset ++] = (byte) (seconds> 16 );
Buffer [offset ++] = (byte) (seconds> 8 );
Buffer [offset ++] = (byte) (seconds> 0 );
Long fraction = milliseconds * 0x00000000l/1000l;
// Write fraction in big endian format
Buffer [offset ++] = (byte) (fraction> 24 );
Buffer [offset ++] = (byte) (fraction> 16 );
Buffer [offset ++] = (byte) (fraction> 8 );
// Low order bits shocould be random data
Buffer [offset ++] = (byte) (math. Random () * 255.0 );
}
}