/***************************************************************************/ /* 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 a ntp-datagram as described in rfc2030. * Such a datagram consists of a header and four timestamps. * The four timestamps are respectively: * <UL> * <LI> * The reference timestamp. This indicates when the local clock was * last set. * Can be set to zero for datagrams originating on the client. * <LI> * The originate timestamp. Indicates when the datagram originated * on the client. Copied by the server from the transmit timestamp. * Can be set to zero for datagrams originating on the client. * <LI> * The receive timestamp. Indicates when the reply left the server. * Can be set to zero for datagrams originating on the client. * <LI> * The transmit timestamp. Indicates when the datagram departed. * </UL> * We have added a fifth timestamp. Namely a 'reception timestamp' * which is normally set by NtpConnection.receive(NtpDatagramPacket). * When transmitted a ntp-datagram is wrapped in a UDP datagram. * @see java.net.Datagram * @see TimeStamp * @see NtpHeader * @see NtpConnection */ public class NtpDatagramPacket { private static final int headerOffset = 0; private static final int referenceTimeStampOffset = 16; private static final int originateTimeStampOffset = 24; private static final int receiveTimeStampOffset = 32; private static final int transmitTimeStampOffset = 40; private static final int ntpDatagramLength = 48; private DatagramPacket dp; private TimeStamp receptionTimeStamp; /** * Construct a NtpDatagram from a header, four timestamps, an * Inetaddress and a portnumber. * @see InetAddress */ public NtpDatagramPacket(NtpHeader header, TimeStamp referenceTimeStamp, TimeStamp originateTimeStamp, TimeStamp receiveTimeStamp, TimeStamp transmitTimeStamp, InetAddress iaddr, int iport) { byte[] temp; byte[] buffer = new byte[ntpDatagramLength]; for (int i = headerOffset; i < referenceTimeStampOffset; i++) { buffer[i] = (header.getData())[i - headerOffset]; } for (int i = referenceTimeStampOffset; i < originateTimeStampOffset; i++) { temp = referenceTimeStamp.getData(); buffer[i] = temp[i - referenceTimeStampOffset]; } for (int i = originateTimeStampOffset; i < receiveTimeStampOffset; i++) { temp = originateTimeStamp.getData(); buffer[i] = temp[i - originateTimeStampOffset]; } for (int i = receiveTimeStampOffset; i < transmitTimeStampOffset; i++) { temp = receiveTimeStamp.getData(); buffer[i] = temp[i - receiveTimeStampOffset]; } for (int i = transmitTimeStampOffset; i < ntpDatagramLength; i++) { temp = transmitTimeStamp.getData(); buffer[i] = temp[i - transmitTimeStampOffset]; } dp = new DatagramPacket(buffer, ntpDatagramLength, iaddr, iport); } /** * Construct a NtpDatagram with only the transmit timestamp * filled in (set to the current time). The header is set to a * NtpHeader.defaultHeader. * @see NtpHeader */ public NtpDatagramPacket(InetAddress iaddr, int iport) { this(NtpHeader.defaultHeader, TimeStamp.zero, TimeStamp.zero, TimeStamp.zero, new TimeStamp(), iaddr, iport); } /** * Constructs an uninitialized NtpDatagram. */ public NtpDatagramPacket() { byte[] buffer = new byte[ntpDatagramLength]; dp = new DatagramPacket(buffer, ntpDatagramLength); } /** * Constructs an uninitialized NtpDatagram from a UDP datagram. */ public NtpDatagramPacket(DatagramPacket dp) { this.dp = dp; } /** * Returns the UDP datagram associated to an NtpDatagram. */ DatagramPacket getDatagramPacket() { return dp; } /** * Returns the header associated to a NtpDatagram. * @see NtpHeader */ public NtpHeader getHeader() { byte[] buffer = dp.getData(); byte[] temp = new byte[16]; for (int i = headerOffset; i < referenceTimeStampOffset; i++) { temp[i - headerOffset] = buffer[i]; } return new NtpHeader(temp); } /** * Returns the reference timestamp. */ public TimeStamp getReferenceTimeStamp() { byte[] buffer = dp.getData(); byte[] temp = new byte[8]; for (int i = referenceTimeStampOffset; i < originateTimeStampOffset; i++) { temp[i - referenceTimeStampOffset] = buffer[i]; } return new TimeStamp(temp); } /** * Returns the originate timestamp */ public TimeStamp getOriginateTimeStamp() { byte[] buffer = dp.getData(); byte[] temp = new byte[8]; for (int i = originateTimeStampOffset; i < receiveTimeStampOffset; i++) { temp[i - originateTimeStampOffset] = buffer[i]; } return new TimeStamp(temp); } /** * Returns the receive timestamp */ public TimeStamp getReceiveTimeStamp() { byte[] buffer = dp.getData(); byte[] temp = new byte[8]; for (int i = receiveTimeStampOffset; i < transmitTimeStampOffset; i++) { temp[i - receiveTimeStampOffset] = buffer[i]; } return new TimeStamp(temp); } /** * Returns the transmit timestamp */ public TimeStamp getTransmitTimeStamp() { byte[] buffer = dp.getData(); byte[] temp = new byte[8]; for (int i = transmitTimeStampOffset; i < ntpDatagramLength; i++) { temp[i - transmitTimeStampOffset] = buffer[i]; } return new TimeStamp(temp); } /** * Returns the reception timestamp */ public TimeStamp getReceptionTimeStamp() { return receptionTimeStamp; } void setReceptionTimeStamp(TimeStamp receptionTimeStamp) { this.receptionTimeStamp = receptionTimeStamp; } /** * A convenience method which returns the useful information * contained in a NtpDatagram. * @see NtpInfo */ public NtpInfo getInfo() { NtpInfo info = new NtpInfo(); NtpHeader h = getHeader(); info.serverAddress = dp.getAddress(); info.leapYearIndicator = h.getLeapYearIndicator(); info.versionNumber = h.getVersionNumber(); info.stratum = h.getStratum(); info.mode = h.getMode(); info.pollInterval = h.getPollInterval(); info.precision = h.getPrecision(); info.rootDelay = h.getRootDelay(); info.rootDispersion = h.getRootDispersion(); info.referenceIdentifier = h.getReferenceIdentifier(); info.referenceTimeStamp = getReferenceTimeStamp(); long originate = getOriginateTimeStamp().getTime().getTime(); long receive = getReceiveTimeStamp().getTime().getTime(); long transmit = getTransmitTimeStamp().getTime().getTime(); long reception = getReceptionTimeStamp().getTime().getTime(); info.roundTripDelay = receive - originate + reception - transmit; info.offset = (receive - originate - reception + transmit) / 2; return info; } public String toString() { String s; s = "Header : "; s = s + getHeader(); s = s + "\n"; s = s + "ReferenceTimeStamp : "; s = s + getReferenceTimeStamp(); s = s + "\n"; s = s + "OriginateTimeStamp : "; s = s + getOriginateTimeStamp(); s = s + "\n"; s = s + "ReceiveTimeStamp : "; s = s + getReceiveTimeStamp(); s = s + "\n"; s = s + "TransmitTimeStamp : "; s = s + getTransmitTimeStamp(); return s; } }