001package org.apache.commons.net.ntp; 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019import java.net.DatagramPacket; 020 021/*** 022 * Implementation of NtpV3Packet with methods converting Java objects to/from 023 * the Network Time Protocol (NTP) data message header format described in RFC-1305. 024 * 025 * @author Naz Irizarry, MITRE Corp 026 * @author Jason Mathews, MITRE Corp 027 * 028 * @version $Revision: 1489361 $ 029 */ 030public class NtpV3Impl implements NtpV3Packet 031{ 032 033 private static final int MODE_INDEX = 0; 034 private static final int MODE_SHIFT = 0; 035 036 private static final int VERSION_INDEX = 0; 037 private static final int VERSION_SHIFT = 3; 038 039 private static final int LI_INDEX = 0; 040 private static final int LI_SHIFT = 6; 041 042 private static final int STRATUM_INDEX = 1; 043 private static final int POLL_INDEX = 2; 044 private static final int PRECISION_INDEX = 3; 045 046 private static final int ROOT_DELAY_INDEX = 4; 047 private static final int ROOT_DISPERSION_INDEX = 8; 048 private static final int REFERENCE_ID_INDEX = 12; 049 050 private static final int REFERENCE_TIMESTAMP_INDEX = 16; 051 private static final int ORIGINATE_TIMESTAMP_INDEX = 24; 052 private static final int RECEIVE_TIMESTAMP_INDEX = 32; 053 private static final int TRANSMIT_TIMESTAMP_INDEX = 40; 054 055// private static final int KEY_IDENTIFIER_INDEX = 48; 056// private static final int MESSAGE_DIGEST = 54; /* len 16 bytes */ 057 058 private final byte[] buf = new byte[48]; 059 060 private volatile DatagramPacket dp; 061 062 /** Creates a new instance of NtpV3Impl */ 063 public NtpV3Impl() 064 { 065 } 066 067 /*** 068 * Returns mode as defined in RFC-1305 which is a 3-bit integer 069 * whose value is indicated by the MODE_xxx parameters. 070 * 071 * @return mode as defined in RFC-1305. 072 */ 073// @Override 074 public int getMode() 075 { 076 return (ui(buf[MODE_INDEX]) >> MODE_SHIFT) & 0x7; 077 } 078 079 /*** 080 * Return human-readable name of message mode type as described in 081 * RFC 1305. 082 * @return mode name as string. 083 */ 084// @Override 085 public String getModeName() 086 { 087 return NtpUtils.getModeName(getMode()); 088 } 089 090 /*** 091 * Set mode as defined in RFC-1305. 092 * @param mode 093 */ 094// @Override 095 public void setMode(int mode) 096 { 097 buf[MODE_INDEX] = (byte) (buf[MODE_INDEX] & 0xF8 | mode & 0x7); 098 } 099 100 /*** 101 * Returns leap indicator as defined in RFC-1305 which is a two-bit code: 102 * 0=no warning 103 * 1=last minute has 61 seconds 104 * 2=last minute has 59 seconds 105 * 3=alarm condition (clock not synchronized) 106 * 107 * @return leap indicator as defined in RFC-1305. 108 */ 109// @Override 110 public int getLeapIndicator() 111 { 112 return (ui(buf[LI_INDEX]) >> LI_SHIFT) & 0x3; 113 } 114 115 /*** 116 * Set leap indicator as defined in RFC-1305. 117 * @param li leap indicator. 118 */ 119// @Override 120 public void setLeapIndicator(int li) 121 { 122 buf[LI_INDEX] = (byte) (buf[LI_INDEX] & 0x3F | ((li & 0x3) << LI_SHIFT)); 123 } 124 125 /*** 126 * Returns poll interval as defined in RFC-1305, which is an eight-bit 127 * signed integer indicating the maximum interval between successive 128 * messages, in seconds to the nearest power of two (e.g. value of six 129 * indicates an interval of 64 seconds. The values that can appear in 130 * this field range from NTP_MINPOLL to NTP_MAXPOLL inclusive. 131 * 132 * @return poll interval as defined in RFC-1305. 133 */ 134// @Override 135 public int getPoll() 136 { 137 return buf[POLL_INDEX]; 138 } 139 140 /*** 141 * Set poll interval as defined in RFC-1305. 142 * 143 * @param poll poll interval. 144 */ 145// @Override 146 public void setPoll(int poll) 147 { 148 buf[POLL_INDEX] = (byte) (poll & 0xFF); 149 } 150 151 /*** 152 * Returns precision as defined in RFC-1305 encoded as an 8-bit signed 153 * integer (seconds to nearest power of two). 154 * Values normally range from -6 to -20. 155 * 156 * @return precision as defined in RFC-1305. 157 */ 158// @Override 159 public int getPrecision() 160 { 161 return buf[PRECISION_INDEX]; 162 } 163 164 /*** 165 * Set precision as defined in RFC-1305. 166 * @param precision 167 */ 168 public void setPrecision(int precision) 169 { 170 buf[PRECISION_INDEX] = (byte) (precision & 0xFF); 171 } 172 173 /*** 174 * Returns NTP version number as defined in RFC-1305. 175 * 176 * @return NTP version number. 177 */ 178// @Override 179 public int getVersion() 180 { 181 return (ui(buf[VERSION_INDEX]) >> VERSION_SHIFT) & 0x7; 182 } 183 184 /*** 185 * Set NTP version as defined in RFC-1305. 186 * 187 * @param version NTP version. 188 */ 189// @Override 190 public void setVersion(int version) 191 { 192 buf[VERSION_INDEX] = (byte) (buf[VERSION_INDEX] & 0xC7 | ((version & 0x7) << VERSION_SHIFT)); 193 } 194 195 /*** 196 * Returns Stratum as defined in RFC-1305, which indicates the stratum level 197 * of the local clock, with values defined as follows: 0=unspecified, 198 * 1=primary ref clock, and all others a secondary reference (via NTP). 199 * 200 * @return Stratum level as defined in RFC-1305. 201 */ 202// @Override 203 public int getStratum() 204 { 205 return ui(buf[STRATUM_INDEX]); 206 } 207 208 /*** 209 * Set stratum level as defined in RFC-1305. 210 * 211 * @param stratum stratum level. 212 */ 213// @Override 214 public void setStratum(int stratum) 215 { 216 buf[STRATUM_INDEX] = (byte) (stratum & 0xFF); 217 } 218 219 /*** 220 * Return root delay as defined in RFC-1305, which is the total roundtrip delay 221 * to the primary reference source, in seconds. Values can take positive and 222 * negative values, depending on clock precision and skew. 223 * 224 * @return root delay as defined in RFC-1305. 225 */ 226// @Override 227 public int getRootDelay() 228 { 229 return getInt(ROOT_DELAY_INDEX); 230 } 231 232 /*** 233 * Return root delay as defined in RFC-1305 in milliseconds, which is 234 * the total roundtrip delay to the primary reference source, in 235 * seconds. Values can take positive and negative values, depending 236 * on clock precision and skew. 237 * 238 * @return root delay in milliseconds 239 */ 240// @Override 241 public double getRootDelayInMillisDouble() 242 { 243 double l = getRootDelay(); 244 return l / 65.536; 245 } 246 247 /*** 248 * Returns root dispersion as defined in RFC-1305. 249 * @return root dispersion. 250 */ 251// @Override 252 public int getRootDispersion() 253 { 254 return getInt(ROOT_DISPERSION_INDEX); 255 } 256 257 /*** 258 * Returns root dispersion (as defined in RFC-1305) in milliseconds. 259 * 260 * @return root dispersion in milliseconds 261 */ 262// @Override 263 public long getRootDispersionInMillis() 264 { 265 long l = getRootDispersion(); 266 return (l * 1000) / 65536L; 267 } 268 269 /*** 270 * Returns root dispersion (as defined in RFC-1305) in milliseconds 271 * as double precision value. 272 * 273 * @return root dispersion in milliseconds 274 */ 275// @Override 276 public double getRootDispersionInMillisDouble() 277 { 278 double l = getRootDispersion(); 279 return l / 65.536; 280 } 281 282 /*** 283 * Set reference clock identifier field with 32-bit unsigned integer value. 284 * See RFC-1305 for description. 285 * 286 * @param refId reference clock identifier. 287 */ 288// @Override 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; // shift right one-byte 294 } 295 } 296 297 /*** 298 * Returns the reference id as defined in RFC-1305, which is 299 * a 32-bit integer whose value is dependent on several criteria. 300 * 301 * @return the reference id as defined in RFC-1305. 302 */ 303// @Override 304 public int getReferenceId() 305 { 306 return getInt(REFERENCE_ID_INDEX); 307 } 308 309 /*** 310 * Returns the reference id string. String cannot be null but 311 * value is dependent on the version of the NTP spec supported 312 * and stratum level. Value can be an empty string, clock type string, 313 * IP address, or a hex string. 314 * 315 * @return the reference id string. 316 */ 317// @Override 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(); // 4-character ASCII string (e.g. GPS, USNO) 325 } 326 // in NTPv4 servers this is latest transmit timestamp of ref source 327 if (version == VERSION_4) { 328 return idAsHex(); 329 } 330 } 331 332 // Stratum 2 and higher this is a four-octet IPv4 address 333 // of the primary reference host. 334 if (stratum >= 2) { 335 return idAsIPAddress(); 336 } 337 return idAsHex(); 338 } 339 340 /*** 341 * Returns Reference id as dotted IP address. 342 * @return refId as IP address string. 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) { // 0-terminated string 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 * Returns the transmit timestamp as defined in RFC-1305. 372 * 373 * @return the transmit timestamp as defined in RFC-1305. 374 * Never returns a null object. 375 */ 376// @Override 377 public TimeStamp getTransmitTimeStamp() 378 { 379 return getTimestamp(TRANSMIT_TIMESTAMP_INDEX); 380 } 381 382 /*** 383 * Set transmit time with NTP timestamp. 384 * If <code>ts</code> is null then zero time is used. 385 * 386 * @param ts NTP timestamp 387 */ 388// @Override 389 public void setTransmitTime(TimeStamp ts) 390 { 391 setTimestamp(TRANSMIT_TIMESTAMP_INDEX, ts); 392 } 393 394 /*** 395 * Set originate timestamp given NTP TimeStamp object. 396 * If <code>ts</code> is null then zero time is used. 397 * 398 * @param ts NTP timestamp 399 */ 400// @Override 401 public void setOriginateTimeStamp(TimeStamp ts) 402 { 403 setTimestamp(ORIGINATE_TIMESTAMP_INDEX, ts); 404 } 405 406 /*** 407 * Returns the originate time as defined in RFC-1305. 408 * 409 * @return the originate time. 410 * Never returns null. 411 */ 412// @Override 413 public TimeStamp getOriginateTimeStamp() 414 { 415 return getTimestamp(ORIGINATE_TIMESTAMP_INDEX); 416 } 417 418 /*** 419 * Returns the reference time as defined in RFC-1305. 420 * 421 * @return the reference time as <code>TimeStamp</code> object. 422 * Never returns null. 423 */ 424// @Override 425 public TimeStamp getReferenceTimeStamp() 426 { 427 return getTimestamp(REFERENCE_TIMESTAMP_INDEX); 428 } 429 430 /*** 431 * Set Reference time with NTP timestamp. If <code>ts</code> is null 432 * then zero time is used. 433 * 434 * @param ts NTP timestamp 435 */ 436// @Override 437 public void setReferenceTime(TimeStamp ts) 438 { 439 setTimestamp(REFERENCE_TIMESTAMP_INDEX, ts); 440 } 441 442 /*** 443 * Returns receive timestamp as defined in RFC-1305. 444 * 445 * @return the receive time. 446 * Never returns null. 447 */ 448// @Override 449 public TimeStamp getReceiveTimeStamp() 450 { 451 return getTimestamp(RECEIVE_TIMESTAMP_INDEX); 452 } 453 454 /*** 455 * Set receive timestamp given NTP TimeStamp object. 456 * If <code>ts</code> is null then zero time is used. 457 * 458 * @param ts timestamp 459 */ 460// @Override 461 public void setReceiveTimeStamp(TimeStamp ts) 462 { 463 setTimestamp(RECEIVE_TIMESTAMP_INDEX, ts); 464 } 465 466 /*** 467 * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...) 468 * correspond to the protocol used to obtain the timing information. 469 * 470 * @return packet type string identifier which in this case is "NTP". 471 */ 472// @Override 473 public String getType() 474 { 475 return "NTP"; 476 } 477 478 /*** 479 * @return 4 bytes as 32-bit int 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 * Get NTP Timestamp at specified starting index. 493 * 494 * @param index index into data array 495 * @return TimeStamp object for 64 bits starting at index 496 */ 497 private TimeStamp getTimestamp(int index) 498 { 499 return new TimeStamp(getLong(index)); 500 } 501 502 /*** 503 * Get Long value represented by bits starting at specified index. 504 * 505 * @return 8 bytes as 64-bit long 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 * Sets the NTP timestamp at the given array index. 522 * 523 * @param index index into the byte array. 524 * @param t TimeStamp. 525 */ 526 private void setTimestamp(int index, TimeStamp t) 527 { 528 long ntpTime = (t == null) ? 0 : t.ntpValue(); 529 // copy 64-bits from Long value into 8 x 8-bit bytes of array 530 // one byte at a time shifting 8-bits for each position. 531 for (int i = 7; i >= 0; i--) { 532 buf[index + i] = (byte) (ntpTime & 0xFF); 533 ntpTime >>>= 8; // shift to next byte 534 } 535 // buf[index] |= 0x80; // only set if 1900 baseline.... 536 } 537 538 /*** 539 * Returns the datagram packet with the NTP details already filled in. 540 * 541 * @return a datagram packet. 542 */ 543// @Override 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 * Set the contents of this object from source datagram packet. 555 * 556 * @param srcDp source DatagramPacket to copy contents from. 557 */ 558// @Override 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 * Convert byte to unsigned integer. 572 * Java only has signed types so we have to do 573 * more work to get unsigned ops. 574 * 575 * @param b 576 * @return unsigned int value of byte 577 */ 578 protected final static int ui(byte b) 579 { 580 int i = b & 0xFF; 581 return i; 582 } 583 584 /*** 585 * Convert byte to unsigned long. 586 * Java only has signed types so we have to do 587 * more work to get unsigned ops 588 * 589 * @param b 590 * @return unsigned long value of byte 591 */ 592 protected final static long ul(byte b) 593 { 594 long i = b & 0xFF; 595 return i; 596 } 597 598 /*** 599 * Returns details of NTP packet as a string. 600 * 601 * @return details of NTP packet as a string. 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}