/***************************************************************************/
/* COACH: Component Based Open Source Architecture for */
/* Distributed Telecom Applications */
/* See: http://www.objectweb.org/ */
/* */
/* Copyright (C) 2003 Lucent Technologies Nederland BV */
/* Bell Labs Advanced Technologies - EMEA */
/* */
/* Initial developer(s): Harold Batteram */
/* */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */
/* */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
/* Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/***************************************************************************/
package org.coach.tracing.service.ntp;
import java.net.*;
/**
* This class encapsulates the header of a NtpDatagram. See rfc2030 for more
* details.
*/
public class NtpHeader {
/**
* The default header data for a client datagram. Version=3, Mode=client.
*/
public static final byte[] defaultHeaderData = { (byte)0x1B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/**
* The default header for a client datagram. This is a wrapper around
* 'defaultHeaderData'
*/
public static final NtpHeader defaultHeader = new NtpHeader(defaultHeaderData);
private byte[] data;
/**
* Reference identifier is InetAddress.
*/
private static final byte RI_IP_ADDRESS = 0;
/**
* Reference identifier is String.
*/
private static final byte RI_CODE = 1;
/**
* Reference identifier is 4 byte array.
*/
private static final byte RI_OTHER = 2;
private int mp(byte b) {
int bb = b;
return (bb < 0) ? 256 + bb : bb;
}
/**
* Construct a NtpHeader from a 16 byte array.
*/
public NtpHeader(byte[] data) {
this.data = data;
}
/**
* Gets the 16 byte array constituting the header.
*/
public byte[] getData() {
return data;
}
public int getLeapYearIndicator() {
return (int)((data[0] & 0xc0) >>> 6);
}
public int getVersionNumber() {
return (int)((data[0] & 0x38) >>> 3);
}
public int getMode() {
return (int)(data[0] & 0x07);
}
public int getStratum() {
return (int)data[1];
}
public int getPollInterval() {
return (int)Math.round(Math.pow(2, data[2]));
}
/**
* Get precision in milliseconds.
*/
public double getPrecision() {
return 1000 * Math.pow(2, data[3]);
}
/**
* Get root delay in milliseconds.
*/
public double getRootDelay() {
int temp = 0;
temp = 256 * (256 * (256 * data[4] + data[5]) + data[6]) + data[7];
return 1000 * (((double)temp) / 0x10000);
}
/**
* Get root dispersion in milliseconds.
*/
public double getRootDispersion() {
long temp = 0;
temp = 256 * (256 * (256 * data[8] + data[9]) + data[10]) + data[11];
return 1000 * (((double)temp) / 0x10000);
}
/**
* Gets the type of the reference identifier.
*/
private int getReferenceIdentifierType() {
if (getMode() == NtpInfo.MODE_CLIENT) {
return RI_OTHER;
} else if (getStratum() < 2) {
return RI_CODE;
} else if (getVersionNumber() <= 3) {
return RI_IP_ADDRESS;
} else {
return RI_OTHER;
}
}
private InetAddress getReferenceAddress() throws IllegalArgumentException, UnknownHostException {
if (getReferenceIdentifierType() != RI_IP_ADDRESS) {
throw new IllegalArgumentException();
}
String temp = "" + mp(data[12]) + "." + mp(data[13]) + "." + mp(data[14]) + "." + mp(data[15]);
return InetAddress.getByName(temp);
}
private String getReferenceCode() throws IllegalArgumentException {
if (getReferenceIdentifierType() != RI_CODE) {
throw new IllegalArgumentException();
}
int codeLength = 0;
int index = 12;
boolean zeroFound = false;
while ((!zeroFound) && (index <= 15)) {
if (data[index] == 0) {
zeroFound = true;
} else {
index++;
codeLength++;
}
}
return new String(data, 12, codeLength);
}
private byte[] getReferenceData() {
byte[] temp = new byte[4];
temp[0] = data[12];
temp[1] = data[13];
temp[2] = data[14];
temp[3] = data[15];
return temp;
}
/**
* Gets the reference identifier as an object. It can be either a
* String, a InetAddress or a 4 byte array. Use 'instanceof' to find out what
* the true class is.
*/
public Object getReferenceIdentifier() {
if (getReferenceIdentifierType() == RI_IP_ADDRESS) {
try {
return getReferenceAddress();
} catch (Exception e) {
return getReferenceData();
}
} else if (getReferenceIdentifierType() == RI_CODE) {
return getReferenceCode();
} else {
return getReferenceData();
}
}
public String toString() {
String s = "Leap year indicator : " + getLeapYearIndicator() + "\n" + "Version number : " + getVersionNumber() + "\n" + "Mode : " + getMode() + "\n" + "Stratum : " + getStratum() + "\n" + "Poll interval : " + getPollInterval() + " s\n" + "Precision : " + getPrecision() + " ms\n" + "Root delay : " + getRootDelay() + " ms\n" + "Root dispersion : " + getRootDispersion() + " ms\n";
Object o = getReferenceIdentifier();
if (o instanceof InetAddress) {
s = s + "Reference address : " + (InetAddress)o;
} else if (o instanceof String) {
s = s + "Reference code : " + (String)o;
} else {
byte[] temp = (byte[])o;
s = s + "Reference data : " + temp[0] + " " + temp[1] + " " + temp[2] + " " + temp[3];
}
return s;
}
}