1 package org.apache.commons.net.ntp;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.net.DatagramPacket;
20
21
22
23
24
25
26
27
28
29
30 public class NtpV3Impl implements NtpV3Packet
31 {
32
33 private static final int MODE_INDEX = 0;
34 private static final int MODE_SHIFT = 0;
35
36 private static final int VERSION_INDEX = 0;
37 private static final int VERSION_SHIFT = 3;
38
39 private static final int LI_INDEX = 0;
40 private static final int LI_SHIFT = 6;
41
42 private static final int STRATUM_INDEX = 1;
43 private static final int POLL_INDEX = 2;
44 private static final int PRECISION_INDEX = 3;
45
46 private static final int ROOT_DELAY_INDEX = 4;
47 private static final int ROOT_DISPERSION_INDEX = 8;
48 private static final int REFERENCE_ID_INDEX = 12;
49
50 private static final int REFERENCE_TIMESTAMP_INDEX = 16;
51 private static final int ORIGINATE_TIMESTAMP_INDEX = 24;
52 private static final int RECEIVE_TIMESTAMP_INDEX = 32;
53 private static final int TRANSMIT_TIMESTAMP_INDEX = 40;
54
55
56
57
58 private final byte[] buf = new byte[48];
59
60 private volatile DatagramPacket dp;
61
62
63 public NtpV3Impl()
64 {
65 }
66
67
68
69
70
71
72
73
74 public int getMode()
75 {
76 return (ui(buf[MODE_INDEX]) >> MODE_SHIFT) & 0x7;
77 }
78
79
80
81
82
83
84
85 public String getModeName()
86 {
87 return NtpUtils.getModeName(getMode());
88 }
89
90
91
92
93
94
95 public void setMode(int mode)
96 {
97 buf[MODE_INDEX] = (byte) (buf[MODE_INDEX] & 0xF8 | mode & 0x7);
98 }
99
100
101
102
103
104
105
106
107
108
109
110 public int getLeapIndicator()
111 {
112 return (ui(buf[LI_INDEX]) >> LI_SHIFT) & 0x3;
113 }
114
115
116
117
118
119
120 public void setLeapIndicator(int li)
121 {
122 buf[LI_INDEX] = (byte) (buf[LI_INDEX] & 0x3F | ((li & 0x3) << LI_SHIFT));
123 }
124
125
126
127
128
129
130
131
132
133
134
135 public int getPoll()
136 {
137 return buf[POLL_INDEX];
138 }
139
140
141
142
143
144
145
146 public void setPoll(int poll)
147 {
148 buf[POLL_INDEX] = (byte) (poll & 0xFF);
149 }
150
151
152
153
154
155
156
157
158
159 public int getPrecision()
160 {
161 return buf[PRECISION_INDEX];
162 }
163
164
165
166
167
168 public void setPrecision(int precision)
169 {
170 buf[PRECISION_INDEX] = (byte) (precision & 0xFF);
171 }
172
173
174
175
176
177
178
179 public int getVersion()
180 {
181 return (ui(buf[VERSION_INDEX]) >> VERSION_SHIFT) & 0x7;
182 }
183
184
185
186
187
188
189
190 public void setVersion(int version)
191 {
192 buf[VERSION_INDEX] = (byte) (buf[VERSION_INDEX] & 0xC7 | ((version & 0x7) << VERSION_SHIFT));
193 }
194
195
196
197
198
199
200
201
202
203 public int getStratum()
204 {
205 return ui(buf[STRATUM_INDEX]);
206 }
207
208
209
210
211
212
213
214 public void setStratum(int stratum)
215 {
216 buf[STRATUM_INDEX] = (byte) (stratum & 0xFF);
217 }
218
219
220
221
222
223
224
225
226
227 public int getRootDelay()
228 {
229 return getInt(ROOT_DELAY_INDEX);
230 }
231
232
233
234
235
236
237
238
239
240
241 public double getRootDelayInMillisDouble()
242 {
243 double l = getRootDelay();
244 return l / 65.536;
245 }
246
247
248
249
250
251
252 public int getRootDispersion()
253 {
254 return getInt(ROOT_DISPERSION_INDEX);
255 }
256
257
258
259
260
261
262
263 public long getRootDispersionInMillis()
264 {
265 long l = getRootDispersion();
266 return (l * 1000) / 65536L;
267 }
268
269
270
271
272
273
274
275
276 public double getRootDispersionInMillisDouble()
277 {
278 double l = getRootDispersion();
279 return l / 65.536;
280 }
281
282
283
284
285
286
287
288
289 public void setReferenceId(int refId)
290 {
291 for (int i = 3; i >= 0; i--) {
292 buf[REFERENCE_ID_INDEX + i] = (byte) (refId & 0xff);
293 refId >>>= 8;
294 }
295 }
296
297
298
299
300
301
302
303
304 public int getReferenceId()
305 {
306 return getInt(REFERENCE_ID_INDEX);
307 }
308
309
310
311
312
313
314
315
316
317
318 public String getReferenceIdString()
319 {
320 int version = getVersion();
321 int stratum = getStratum();
322 if (version == VERSION_3 || version == VERSION_4) {
323 if (stratum == 0 || stratum == 1) {
324 return idAsString();
325 }
326
327 if (version == VERSION_4) {
328 return idAsHex();
329 }
330 }
331
332
333
334 if (stratum >= 2) {
335 return idAsIPAddress();
336 }
337 return idAsHex();
338 }
339
340
341
342
343
344 private String idAsIPAddress()
345 {
346 return ui(buf[REFERENCE_ID_INDEX]) + "." +
347 ui(buf[REFERENCE_ID_INDEX + 1]) + "." +
348 ui(buf[REFERENCE_ID_INDEX + 2]) + "." +
349 ui(buf[REFERENCE_ID_INDEX + 3]);
350 }
351
352 private String idAsString()
353 {
354 StringBuilder id = new StringBuilder();
355 for (int i = 0; i <= 3; i++) {
356 char c = (char) buf[REFERENCE_ID_INDEX + i];
357 if (c == 0) {
358 break;
359 }
360 id.append(c);
361 }
362 return id.toString();
363 }
364
365 private String idAsHex()
366 {
367 return Integer.toHexString(getReferenceId());
368 }
369
370
371
372
373
374
375
376
377 public TimeStamp getTransmitTimeStamp()
378 {
379 return getTimestamp(TRANSMIT_TIMESTAMP_INDEX);
380 }
381
382
383
384
385
386
387
388
389 public void setTransmitTime(TimeStamp ts)
390 {
391 setTimestamp(TRANSMIT_TIMESTAMP_INDEX, ts);
392 }
393
394
395
396
397
398
399
400
401 public void setOriginateTimeStamp(TimeStamp ts)
402 {
403 setTimestamp(ORIGINATE_TIMESTAMP_INDEX, ts);
404 }
405
406
407
408
409
410
411
412
413 public TimeStamp getOriginateTimeStamp()
414 {
415 return getTimestamp(ORIGINATE_TIMESTAMP_INDEX);
416 }
417
418
419
420
421
422
423
424
425 public TimeStamp getReferenceTimeStamp()
426 {
427 return getTimestamp(REFERENCE_TIMESTAMP_INDEX);
428 }
429
430
431
432
433
434
435
436
437 public void setReferenceTime(TimeStamp ts)
438 {
439 setTimestamp(REFERENCE_TIMESTAMP_INDEX, ts);
440 }
441
442
443
444
445
446
447
448
449 public TimeStamp getReceiveTimeStamp()
450 {
451 return getTimestamp(RECEIVE_TIMESTAMP_INDEX);
452 }
453
454
455
456
457
458
459
460
461 public void setReceiveTimeStamp(TimeStamp ts)
462 {
463 setTimestamp(RECEIVE_TIMESTAMP_INDEX, ts);
464 }
465
466
467
468
469
470
471
472
473 public String getType()
474 {
475 return "NTP";
476 }
477
478
479
480
481 private int getInt(int index)
482 {
483 int i = ui(buf[index]) << 24 |
484 ui(buf[index + 1]) << 16 |
485 ui(buf[index + 2]) << 8 |
486 ui(buf[index + 3]);
487
488 return i;
489 }
490
491
492
493
494
495
496
497 private TimeStamp getTimestamp(int index)
498 {
499 return new TimeStamp(getLong(index));
500 }
501
502
503
504
505
506
507 private long getLong(int index)
508 {
509 long i = ul(buf[index]) << 56 |
510 ul(buf[index + 1]) << 48 |
511 ul(buf[index + 2]) << 40 |
512 ul(buf[index + 3]) << 32 |
513 ul(buf[index + 4]) << 24 |
514 ul(buf[index + 5]) << 16 |
515 ul(buf[index + 6]) << 8 |
516 ul(buf[index + 7]);
517 return i;
518 }
519
520
521
522
523
524
525
526 private void setTimestamp(int index, TimeStamp t)
527 {
528 long ntpTime = (t == null) ? 0 : t.ntpValue();
529
530
531 for (int i = 7; i >= 0; i--) {
532 buf[index + i] = (byte) (ntpTime & 0xFF);
533 ntpTime >>>= 8;
534 }
535
536 }
537
538
539
540
541
542
543
544 public synchronized DatagramPacket getDatagramPacket()
545 {
546 if (dp == null) {
547 dp = new DatagramPacket(buf, buf.length);
548 dp.setPort(NTP_PORT);
549 }
550 return dp;
551 }
552
553
554
555
556
557
558
559 public void setDatagramPacket(DatagramPacket srcDp)
560 {
561 byte[] incomingBuf = srcDp.getData();
562 int len = srcDp.getLength();
563 if (len > buf.length) {
564 len = buf.length;
565 }
566
567 System.arraycopy(incomingBuf, 0, buf, 0, len);
568 }
569
570
571
572
573
574
575
576
577
578 protected final static int ui(byte b)
579 {
580 int i = b & 0xFF;
581 return i;
582 }
583
584
585
586
587
588
589
590
591
592 protected final static long ul(byte b)
593 {
594 long i = b & 0xFF;
595 return i;
596 }
597
598
599
600
601
602
603 @Override
604 public String toString()
605 {
606 return "[" +
607 "version:" + getVersion() +
608 ", mode:" + getMode() +
609 ", poll:" + getPoll() +
610 ", precision:" + getPrecision() +
611 ", delay:" + getRootDelay() +
612 ", dispersion(ms):" + getRootDispersionInMillisDouble() +
613 ", id:" + getReferenceIdString() +
614 ", xmitTime:" + getTransmitTimeStamp().toDateString() +
615 " ]";
616 }
617
618 }