Dépôt officiel du code source de l'ERP OpenConcerto
Rev 156 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.utils.ntp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public final class Message {
/** Maximum message length (in bytes), without authentication */
public static final int MAXIMUM_LENGTH = 384;
/** Leap Indicator. */
private byte byLeapIndicator;
/** Version Number. */
private byte byVersionNumber = 0x04;
/** Client mode. */
private byte byMode = 0x03;
/** Stratum. */
private byte byStratum;
/** Poll Interval. */
private byte byPollInterval;
/** Precision. */
private byte byPrecision;
/** Rood Delay. */
private double dRootDelay;
/** Root Dispersion. */
private double dRootDispersion;
/** Reference Identifier. */
private byte[] sReferenceIdentifier = "LOCL".getBytes();
/** Reference Timestamp. */
private Timestamp tReferenceTimestamp = Timestamp.ZERO;
/** Originate Timestamp. */
private Timestamp tOriginateTimestamp = Timestamp.ZERO;
/** Receive Timestamp. */
private Timestamp tReceiveTimestamp = Timestamp.ZERO;
/** Transmit Timestamp. */
private Timestamp tTransmitTimestamp = Timestamp.ZERO;
/**
* Returns the Leap Indicator.
*
* @return the Leap Indicator.
*/
public byte getLeapIndicator() {
return byLeapIndicator;
}
/**
* Sets the Leap Indicator.
*
* @param byLeapIndicator the Leap Indicator.
*/
public void setLeapIndicator(final byte byLeapIndicator) {
this.byLeapIndicator = byLeapIndicator;
}
/**
* Returns the Version Number.
*
* @return the Version Number.
*/
public byte getVersionNumber() {
return byVersionNumber;
}
/**
* Sets the Version Number.
*
* @param byVersionNumber the Version Number.
*/
public void setVersionNumber(final byte byVersionNumber) {
this.byVersionNumber = byVersionNumber;
}
/**
* Returns the Mode.
*
* @return the Mode.
*/
public byte getMode() {
return byMode;
}
/**
* Sets the Mode.
*
* @param byMode the Mode.
*/
public void setMode(final byte byMode) {
this.byMode = byMode;
}
/**
* Returns the Stratum.
*
* @return the Stratum.
*/
public byte getStratum() {
return byStratum;
}
/**
* Sets the Stratum.
*
* @param byStratum the Stratum.
*/
public void setStratum(final byte byStratum) {
this.byStratum = byStratum;
}
/**
* Returns the Poll Interval.
*
* @return the Poll Interval.
*/
public byte getPollInterval() {
return byPollInterval;
}
/**
* Sets the Poll Interval.
*
* @param byPollInterval the Poll Interval.
*/
public void setPollInterval(final byte byPollInterval) {
this.byPollInterval = byPollInterval;
}
/**
* Returns the Precision.
*
* @return the Precision.
*/
public byte getPrecision() {
return byPrecision;
}
/**
* Sets the Precision.
*
* @param byPrecision the Precision.
*/
public void setPrecision(final byte byPrecision) {
this.byPrecision = byPrecision;
}
/**
* Returns the Root Delay.
*
* @return the Root Delay.
*/
public double getRootDelay() {
return dRootDelay;
}
/**
* Sets the Root Delay.
*
* @param dRootDelay the Root Delay.
*/
public void setRootDelay(final double dRootDelay) {
this.dRootDelay = dRootDelay;
}
/**
* Returns the Root Dispersion.
*
* @return the Root Dispersion.
*/
public double getRootDispersion() {
return dRootDispersion;
}
/**
* Sets the Root Dispersion.
*
* @param dRootDispersion the Root Dispersion.
*/
public void setRootDispersion(final double dRootDispersion) {
this.dRootDispersion = dRootDispersion;
}
/**
* Returns the Reference Identifier.
*
* @return the Reference Identifier.
*/
public byte[] getReferenceIdentifier() {
return sReferenceIdentifier;
}
/**
* Sets the Reference Identifier.
*
* @param sReferenceIdentifier the Reference Identifier.
*/
public void setReferenceIdentifier(final byte[] sReferenceIdentifier) {
this.sReferenceIdentifier = sReferenceIdentifier;
}
/**
* Returns the Reference Timestamp.
*
* @return the Reference Timestamp.
*/
public Timestamp getReferenceTimestamp() {
return tReferenceTimestamp;
}
/**
* Sets the Reference Timestamp.
*
* @param tReferenceTimestamp the Reference Timestamp.
*/
public void setReferenceTimestamp(final Timestamp tReferenceTimestamp) {
this.tReferenceTimestamp = tReferenceTimestamp;
}
/**
* Returns the Originate Timestamp.
*
* @return the Originate Timestamp.
*/
public Timestamp getOriginateTimestamp() {
return tOriginateTimestamp;
}
/**
* Sets the Originate Timestamp.
*
* @param tOriginateTimestamp the Originate Timestamp.
*/
public void setOriginateTimestamp(final Timestamp tOriginateTimestamp) {
this.tOriginateTimestamp = tOriginateTimestamp;
}
/**
* Returns the Receive Timestamp.
*
* @return the Receive Timestamp.
*/
public Timestamp getReceiveTimestamp() {
return tReceiveTimestamp;
}
/**
* Sets the Receive Timestamp.
*
* @param tReceiveTimestamp the Receive Timestamp.
*/
public void setReceiveTimestamp(final Timestamp tReceiveTimestamp) {
this.tReceiveTimestamp = tReceiveTimestamp;
}
/**
* Returns the Transmit Timestamp.
*
* @return the Transmit Timestamp.
*/
public Timestamp getTransmitTimestamp() {
return tTransmitTimestamp;
}
/**
* Sets the Transmit Timestamp.
*
* @param tTransmitTimestamp the Transmit Timestamp.
*/
public void setTransmitTimestamp(final Timestamp tTransmitTimestamp) {
this.tTransmitTimestamp = tTransmitTimestamp;
}
/**
* Encodes an SNTP message to a byte stream.
*
* @param output the byte stream.
*/
public void encodeMessage(final OutputStream output) throws IOException {
byte flags = (byte) (this.getLeapIndicator() << 6);
flags += (byte) (this.getVersionNumber() << 3);
flags += this.getMode();
output.write(flags);
output.write(this.getStratum());
output.write(this.getPollInterval());
output.write(this.getPrecision());
encodeFixedPoint(this.getRootDelay(), output);
encodeFixedPoint(this.getRootDispersion(), output);
encodeBitstring(this.getReferenceIdentifier(), output);
encodeTimestamp(this.getReferenceTimestamp(), output);
encodeTimestamp(this.getOriginateTimestamp(), output);
encodeTimestamp(this.getReceiveTimestamp(), output);
encodeTimestamp(this.getTransmitTimestamp(), output);
}
/**
* Decodes an SNTP message from a byte stream.
*
* @param input the byte stream.
* @return the message.
*/
public static Message decodeMessage(final InputStream input) throws IOException {
final Message message = new Message();
final byte flags = (byte) input.read();
message.setLeapIndicator((byte) (flags >> 6));
message.setVersionNumber((byte) ((flags >> 3) & 0x07));
message.setMode((byte) (flags & 0x07));
message.setStratum((byte) input.read());
message.setPollInterval((byte) input.read());
message.setPrecision((byte) input.read());
message.setRootDelay(decodeFixedPoint(input));
message.setRootDispersion(decodeFixedPoint(input));
message.setReferenceIdentifier(decodeBitstring(input));
message.setReferenceTimestamp(decodeTimestamp(input));
message.setOriginateTimestamp(decodeTimestamp(input));
message.setReceiveTimestamp(decodeTimestamp(input));
message.setTransmitTimestamp(decodeTimestamp(input));
return message;
}
/**
* Encodes a 32 bit number to a byte stream.
*
* @param number the number to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encode32(final long number, final OutputStream output) throws IOException {
for (int i = 3; i >= 0; i--) {
output.write((int) ((number >> (8 * i)) & 0xFF));
}
}
/**
* Decodes a 32 bit number from a byte stream.
*
* @param input the byte stream.
* @return the decoded number.
* @throws IOException if an error occurs while reading from the stream.
*/
private static long decode32(final InputStream input) throws IOException {
long number = 0;
for (int i = 0; i < 4; i++) {
number = (number << 8) + input.read();
}
return number;
}
/**
* Encodes a 32-bit bitstring to a byte stream.
*
* @param bitstring the bitstring to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encodeBitstring(final byte[] bitstring, final OutputStream output) throws IOException {
final byte[] temp = { 0, 0, 0, 0 };
System.arraycopy(bitstring, 0, temp, 0, bitstring.length);
output.write(temp);
}
/**
* Decodes a 32-bit bitstring from a byte stream.
*
* @param input the byte stream.
* @return the decoded string.
* @throws IOException if an error occurs while reading from the stream.
*/
private static byte[] decodeBitstring(final InputStream input) throws IOException {
final byte[] bitstring = new byte[4];
input.read(bitstring, 0, 4);
return bitstring;
}
/**
* Encodes a 32 bit fixed-point number to a byte stream.
*
* @param number the fixed-point number to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encodeFixedPoint(final double number, final OutputStream output) throws IOException {
encode32((long) (number * 0x10000L), output);
}
/**
* Decodes a 32 bit fixed-point number from a byte stream. The binary point is between bits 15
* and 16.
*
* @param input the byte stream.
* @return the decoded fixed-point number.
* @throws IOException if an error occurs while reading from the stream.
*/
private static double decodeFixedPoint(final InputStream input) throws IOException {
return ((double) decode32(input)) / 0x10000L;
}
/**
* Encodes a timestamp to a byte stream.
*
* @param timestamp the timestamp to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encodeTimestamp(final Timestamp timestamp, final OutputStream output) throws IOException {
encode32(timestamp.getInteger(), output);
encode32(timestamp.getFraction(), output);
}
/**
* Decodes a timestamp from a byte stream.
*
* @param input the byte stream.
* @return the decoded timestamp.
* @throws IOException if an error occurs while reading from the stream.
*/
private static Timestamp decodeTimestamp(final InputStream input) throws IOException {
final long integer = decode32(input);
final long fraction = decode32(input);
return new Timestamp(integer, fraction);
}
}