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