OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
156 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils.ntp;
15
 
16
import java.io.IOException;
17
import java.io.InputStream;
18
import java.io.OutputStream;
19
 
20
public final class Message {
21
 
22
    /** Maximum message length (in bytes), without authentication */
23
    public static final int MAXIMUM_LENGTH = 384;
24
 
25
    /** Leap Indicator. */
26
    private byte byLeapIndicator;
27
 
28
    /** Version Number. */
29
    private byte byVersionNumber = 0x04;
30
 
31
    /** Client mode. */
32
    private byte byMode = 0x03;
33
 
34
    /** Stratum. */
35
    private byte byStratum;
36
 
37
    /** Poll Interval. */
38
    private byte byPollInterval;
39
 
40
    /** Precision. */
41
    private byte byPrecision;
42
 
43
    /** Rood Delay. */
44
    private double dRootDelay;
45
 
46
    /** Root Dispersion. */
47
    private double dRootDispersion;
48
 
49
    /** Reference Identifier. */
50
    private byte[] sReferenceIdentifier = "LOCL".getBytes();
51
 
52
    /** Reference Timestamp. */
53
    private Timestamp tReferenceTimestamp = Timestamp.ZERO;
54
 
55
    /** Originate Timestamp. */
56
    private Timestamp tOriginateTimestamp = Timestamp.ZERO;
57
 
58
    /** Receive Timestamp. */
59
    private Timestamp tReceiveTimestamp = Timestamp.ZERO;
60
 
61
    /** Transmit Timestamp. */
62
    private Timestamp tTransmitTimestamp = Timestamp.ZERO;
63
 
64
    /**
65
     * Returns the Leap Indicator.
66
     *
67
     * @return the Leap Indicator.
68
     */
69
    public byte getLeapIndicator() {
70
        return byLeapIndicator;
71
    }
72
 
73
    /**
74
     * Sets the Leap Indicator.
75
     *
76
     * @param byLeapIndicator the Leap Indicator.
77
     */
78
    public void setLeapIndicator(final byte byLeapIndicator) {
79
        this.byLeapIndicator = byLeapIndicator;
80
    }
81
 
82
    /**
83
     * Returns the Version Number.
84
     *
85
     * @return the Version Number.
86
     */
87
    public byte getVersionNumber() {
88
        return byVersionNumber;
89
    }
90
 
91
    /**
92
     * Sets the Version Number.
93
     *
94
     * @param byVersionNumber the Version Number.
95
     */
96
    public void setVersionNumber(final byte byVersionNumber) {
97
        this.byVersionNumber = byVersionNumber;
98
    }
99
 
100
    /**
101
     * Returns the Mode.
102
     *
103
     * @return the Mode.
104
     */
105
    public byte getMode() {
106
        return byMode;
107
    }
108
 
109
    /**
110
     * Sets the Mode.
111
     *
112
     * @param byMode the Mode.
113
     */
114
    public void setMode(final byte byMode) {
115
        this.byMode = byMode;
116
    }
117
 
118
    /**
119
     * Returns the Stratum.
120
     *
121
     * @return the Stratum.
122
     */
123
    public byte getStratum() {
124
        return byStratum;
125
    }
126
 
127
    /**
128
     * Sets the Stratum.
129
     *
130
     * @param byStratum the Stratum.
131
     */
132
    public void setStratum(final byte byStratum) {
133
        this.byStratum = byStratum;
134
    }
135
 
136
    /**
137
     * Returns the Poll Interval.
138
     *
139
     * @return the Poll Interval.
140
     */
141
    public byte getPollInterval() {
142
        return byPollInterval;
143
    }
144
 
145
    /**
146
     * Sets the Poll Interval.
147
     *
148
     * @param byPollInterval the Poll Interval.
149
     */
150
    public void setPollInterval(final byte byPollInterval) {
151
        this.byPollInterval = byPollInterval;
152
    }
153
 
154
    /**
155
     * Returns the Precision.
156
     *
157
     * @return the Precision.
158
     */
159
    public byte getPrecision() {
160
        return byPrecision;
161
    }
162
 
163
    /**
164
     * Sets the Precision.
165
     *
166
     * @param byPrecision the Precision.
167
     */
168
    public void setPrecision(final byte byPrecision) {
169
        this.byPrecision = byPrecision;
170
    }
171
 
172
    /**
173
     * Returns the Root Delay.
174
     *
175
     * @return the Root Delay.
176
     */
177
    public double getRootDelay() {
178
        return dRootDelay;
179
    }
180
 
181
    /**
182
     * Sets the Root Delay.
183
     *
184
     * @param dRootDelay the Root Delay.
185
     */
186
    public void setRootDelay(final double dRootDelay) {
187
        this.dRootDelay = dRootDelay;
188
    }
189
 
190
    /**
191
     * Returns the Root Dispersion.
192
     *
193
     * @return the Root Dispersion.
194
     */
195
    public double getRootDispersion() {
196
        return dRootDispersion;
197
    }
198
 
199
    /**
200
     * Sets the Root Dispersion.
201
     *
202
     * @param dRootDispersion the Root Dispersion.
203
     */
204
    public void setRootDispersion(final double dRootDispersion) {
205
        this.dRootDispersion = dRootDispersion;
206
    }
207
 
208
    /**
209
     * Returns the Reference Identifier.
210
     *
211
     * @return the Reference Identifier.
212
     */
213
    public byte[] getReferenceIdentifier() {
214
        return sReferenceIdentifier;
215
    }
216
 
217
    /**
218
     * Sets the Reference Identifier.
219
     *
220
     * @param sReferenceIdentifier the Reference Identifier.
221
     */
222
    public void setReferenceIdentifier(final byte[] sReferenceIdentifier) {
223
        this.sReferenceIdentifier = sReferenceIdentifier;
224
    }
225
 
226
    /**
227
     * Returns the Reference Timestamp.
228
     *
229
     * @return the Reference Timestamp.
230
     */
231
    public Timestamp getReferenceTimestamp() {
232
        return tReferenceTimestamp;
233
    }
234
 
235
    /**
236
     * Sets the Reference Timestamp.
237
     *
238
     * @param tReferenceTimestamp the Reference Timestamp.
239
     */
240
    public void setReferenceTimestamp(final Timestamp tReferenceTimestamp) {
241
        this.tReferenceTimestamp = tReferenceTimestamp;
242
    }
243
 
244
    /**
245
     * Returns the Originate Timestamp.
246
     *
247
     * @return the Originate Timestamp.
248
     */
249
    public Timestamp getOriginateTimestamp() {
250
        return tOriginateTimestamp;
251
    }
252
 
253
    /**
254
     * Sets the Originate Timestamp.
255
     *
256
     * @param tOriginateTimestamp the Originate Timestamp.
257
     */
258
    public void setOriginateTimestamp(final Timestamp tOriginateTimestamp) {
259
        this.tOriginateTimestamp = tOriginateTimestamp;
260
    }
261
 
262
    /**
263
     * Returns the Receive Timestamp.
264
     *
265
     * @return the Receive Timestamp.
266
     */
267
    public Timestamp getReceiveTimestamp() {
268
        return tReceiveTimestamp;
269
    }
270
 
271
    /**
272
     * Sets the Receive Timestamp.
273
     *
274
     * @param tReceiveTimestamp the Receive Timestamp.
275
     */
276
    public void setReceiveTimestamp(final Timestamp tReceiveTimestamp) {
277
        this.tReceiveTimestamp = tReceiveTimestamp;
278
    }
279
 
280
    /**
281
     * Returns the Transmit Timestamp.
282
     *
283
     * @return the Transmit Timestamp.
284
     */
285
    public Timestamp getTransmitTimestamp() {
286
        return tTransmitTimestamp;
287
    }
288
 
289
    /**
290
     * Sets the Transmit Timestamp.
291
     *
292
     * @param tTransmitTimestamp the Transmit Timestamp.
293
     */
294
    public void setTransmitTimestamp(final Timestamp tTransmitTimestamp) {
295
        this.tTransmitTimestamp = tTransmitTimestamp;
296
    }
297
 
298
    /**
299
     * Encodes an SNTP message to a byte stream.
300
     *
301
     * @param output the byte stream.
302
     */
303
    public void encodeMessage(final OutputStream output) throws IOException {
304
        byte flags = (byte) (this.getLeapIndicator() << 6);
305
        flags += (byte) (this.getVersionNumber() << 3);
306
        flags += this.getMode();
307
        output.write(flags);
308
        output.write(this.getStratum());
309
        output.write(this.getPollInterval());
310
        output.write(this.getPrecision());
311
        encodeFixedPoint(this.getRootDelay(), output);
312
        encodeFixedPoint(this.getRootDispersion(), output);
313
        encodeBitstring(this.getReferenceIdentifier(), output);
314
        encodeTimestamp(this.getReferenceTimestamp(), output);
315
        encodeTimestamp(this.getOriginateTimestamp(), output);
316
        encodeTimestamp(this.getReceiveTimestamp(), output);
317
        encodeTimestamp(this.getTransmitTimestamp(), output);
318
    }
319
 
320
    /**
321
     * Decodes an SNTP message from a byte stream.
322
     *
323
     * @param input the byte stream.
324
     * @return the message.
325
     */
326
    public static Message decodeMessage(final InputStream input) throws IOException {
327
        final Message message = new Message();
328
        final byte flags = (byte) input.read();
329
        message.setLeapIndicator((byte) (flags >> 6));
330
        message.setVersionNumber((byte) ((flags >> 3) & 0x07));
331
        message.setMode((byte) (flags & 0x07));
332
        message.setStratum((byte) input.read());
333
        message.setPollInterval((byte) input.read());
334
        message.setPrecision((byte) input.read());
335
        message.setRootDelay(decodeFixedPoint(input));
336
        message.setRootDispersion(decodeFixedPoint(input));
337
        message.setReferenceIdentifier(decodeBitstring(input));
338
        message.setReferenceTimestamp(decodeTimestamp(input));
339
        message.setOriginateTimestamp(decodeTimestamp(input));
340
        message.setReceiveTimestamp(decodeTimestamp(input));
341
        message.setTransmitTimestamp(decodeTimestamp(input));
342
 
343
        return message;
344
    }
345
 
346
    /**
347
     * Encodes a 32 bit number to a byte stream.
348
     *
349
     * @param number the number to encode.
350
     * @param output the byte stream.
351
     * @throws IOException if an error occurs while writting to the stream.
352
     */
353
    private static void encode32(final long number, final OutputStream output) throws IOException {
354
        for (int i = 3; i >= 0; i--) {
355
            output.write((int) ((number >> (8 * i)) & 0xFF));
356
        }
357
    }
358
 
359
    /**
360
     * Decodes a 32 bit number from a byte stream.
361
     *
362
     * @param input the byte stream.
363
     * @return the decoded number.
364
     * @throws IOException if an error occurs while reading from the stream.
365
     */
366
    private static long decode32(final InputStream input) throws IOException {
367
        long number = 0;
368
        for (int i = 0; i < 4; i++) {
369
            number = (number << 8) + input.read();
370
        }
371
        return number;
372
    }
373
 
374
    /**
375
     * Encodes a 32-bit bitstring to a byte stream.
376
     *
377
     * @param bitstring the bitstring to encode.
378
     * @param output the byte stream.
379
     * @throws IOException if an error occurs while writting to the stream.
380
     */
381
    private static void encodeBitstring(final byte[] bitstring, final OutputStream output) throws IOException {
382
        final byte[] temp = { 0, 0, 0, 0 };
383
        System.arraycopy(bitstring, 0, temp, 0, bitstring.length);
384
        output.write(temp);
385
    }
386
 
387
    /**
388
     * Decodes a 32-bit bitstring from a byte stream.
389
     *
390
     * @param input the byte stream.
391
     * @return the decoded string.
392
     * @throws IOException if an error occurs while reading from the stream.
393
     */
394
    private static byte[] decodeBitstring(final InputStream input) throws IOException {
395
        final byte[] bitstring = new byte[4];
396
        input.read(bitstring, 0, 4);
397
 
398
        return bitstring;
399
    }
400
 
401
    /**
402
     * Encodes a 32 bit fixed-point number to a byte stream.
403
     *
404
     * @param number the fixed-point number to encode.
405
     * @param output the byte stream.
406
     * @throws IOException if an error occurs while writting to the stream.
407
     */
408
    private static void encodeFixedPoint(final double number, final OutputStream output) throws IOException {
409
        encode32((long) (number * 0x10000L), output);
410
    }
411
 
412
    /**
413
     * Decodes a 32 bit fixed-point number from a byte stream. The binary point is between bits 15
414
     * and 16.
415
     *
416
     * @param input the byte stream.
417
     * @return the decoded fixed-point number.
418
     * @throws IOException if an error occurs while reading from the stream.
419
     */
420
    private static double decodeFixedPoint(final InputStream input) throws IOException {
421
        return ((double) decode32(input)) / 0x10000L;
422
    }
423
 
424
    /**
425
     * Encodes a timestamp to a byte stream.
426
     *
427
     * @param timestamp the timestamp to encode.
428
     * @param output the byte stream.
429
     * @throws IOException if an error occurs while writting to the stream.
430
     */
431
    private static void encodeTimestamp(final Timestamp timestamp, final OutputStream output) throws IOException {
432
        encode32(timestamp.getInteger(), output);
433
        encode32(timestamp.getFraction(), output);
434
    }
435
 
436
    /**
437
     * Decodes a timestamp from a byte stream.
438
     *
439
     * @param input the byte stream.
440
     * @return the decoded timestamp.
441
     * @throws IOException if an error occurs while reading from the stream.
442
     */
443
    private static Timestamp decodeTimestamp(final InputStream input) throws IOException {
444
        final long integer = decode32(input);
445
        final long fraction = decode32(input);
446
        return new Timestamp(integer, fraction);
447
    }
448
}