package anywheresoftware.b4a.specci48.spsntp;
import android.os.SystemClock;
import android.util.Log;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
@BA.ActivityObject
@BA.ShortName("SPSntp")
@BA.Version(1.03F)
public class SPSntp
{
private static String mNtpServerName = "0.us.pool.ntp.org";
private static int mTimeOut = 30000;
private static long mNtpTime;
private static long mNtpTimeReference;
private static long mRoundTripTime;
private static class SntpClient
{
private static final String TAG = "SntpClient";
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;
private static final long OFFSET_1900_TO_1970 = 2208988800L;
public boolean requestTime(String host, int timeout)
{
try
{
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(timeout);
InetAddress address = InetAddress.getByName(host);
byte[] buffer = new byte[48];
DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, 123);
buffer[0] = 27;
long requestTime = System.currentTimeMillis();
long requestTicks = SystemClock.elapsedRealtime();
writeTimeStamp(buffer, 40, requestTime);
socket.send(request);
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
socket.receive(response);
long responseTicks = SystemClock.elapsedRealtime();
long responseTime = requestTime + responseTicks - requestTicks;
socket.close();
long originateTime = readTimeStamp(buffer, 24);
long receiveTime = readTimeStamp(buffer, 32);
long transmitTime = readTimeStamp(buffer, 40);
long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime);
long clockOffset = (receiveTime - originateTime + transmitTime - responseTime) / 2L;
SPSntp.mNtpTime = responseTime + clockOffset;
SPSntp.mNtpTimeReference = responseTicks;
SPSntp.mRoundTripTime = roundTripTime;
}
catch (Exception e) {
Log.d("SntpClient", "request time failed: " + e);
return false;
}
return true;
}
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)];
int i0 = (b0 & 0x80) == 128 ? (b0 & 0x7F) + 128 : b0;
int i1 = (b1 & 0x80) == 128 ? (b1 & 0x7F) + 128 : b1;
int i2 = (b2 & 0x80) == 128 ? (b2 & 0x7F) + 128 : b2;
int i3 = (b3 & 0x80) == 128 ? (b3 & 0x7F) + 128 : b3;
return (i0 << 24) + (i1 << 16) + (i2 << 8) + i3;
}
public long readTimeStamp(byte[] buffer, int offset)
{
long seconds = read32(buffer, offset);
long fraction = read32(buffer, offset + 4);
return (seconds - 2208988800L) * 1000L + fraction * 1000L / 4294967296L;
}
private void writeTimeStamp(byte[] buffer, int offset, long time)
{
long seconds = time / 1000L;
long milliseconds = time - seconds * 1000L;
seconds += 2208988800L;
buffer[(offset++)] = (byte)(int)(seconds >> 24);
buffer[(offset++)] = (byte)(int)(seconds >> 16);
buffer[(offset++)] = (byte)(int)(seconds >> 8);
buffer[(offset++)] = (byte)(int)(seconds >> 0);
long fraction = milliseconds * 4294967296L / 1000L;
buffer[(offset++)] = (byte)(int)(fraction >> 24);
buffer[(offset++)] = (byte)(int)(fraction >> 16);
buffer[(offset++)] = (byte)(int)(fraction >> 8);
buffer[(offset++)] = (byte)(int)(Math.random() * 255.0D);
}
}
@BA.ActivityObject
@BA.ShortName("SntpTime")
public static class SntpTime
{
public long getGmtNtpTime(BA ba)
{
SPSntp.SntpClient client = new SPSntp.SntpClient(null);
SPSntp.mNtpTime = Long.valueOf(-1L).longValue();
SPSntp.mNtpTimeReference = Long.valueOf(-1L).longValue();
SPSntp.mRoundTripTime = Long.valueOf(-1L).longValue();
try {
client.requestTime(SPSntp.mNtpServerName, SPSntp.mTimeOut);
}
catch (Exception localException)
{
}
return SPSntp.mNtpTime;
}
public long getNtpTimeReference()
{
return SPSntp.mNtpTimeReference;
}
public long getRoundTripTime()
{
return SPSntp.mRoundTripTime;
}
public void setNtpServerName(String ntpServerName)
{
SPSntp.mNtpServerName = ntpServerName;
}
public void setTimeOut(int timeOut)
{
SPSntp.mTimeOut = timeOut;
}
}
}