diff --git a/packages/zend-timesync/library/Zend/TimeSync/Ntp.php b/packages/zend-timesync/library/Zend/TimeSync/Ntp.php index 139d1c66b..dfb87bbad 100644 --- a/packages/zend-timesync/library/Zend/TimeSync/Ntp.php +++ b/packages/zend-timesync/library/Zend/TimeSync/Ntp.php @@ -56,28 +56,49 @@ public function __construct($timeserver, $port = 123) } /** - * Prepare local timestamp for transmission in our request packet + * Convert microtime (result of microtime() as string "msec sec") to NTP timestamp * * NTP timestamps are represented as a 64-bit fixed-point number, in * seconds relative to 0000 UT on 1 January 1900. The integer part is * in the first 32 bits and the fraction part in the last 32 bits * + * @param string $microtime * @return string */ - protected function _prepare() + public static function microtimeToNtp($microtime) { - list($frac, $sec) = explode(' ', microtime()); + list($frac, $sec) = explode(' ', $microtime); + $frac = (int) round((float) $frac * 0x100000000); // represent fraction in 0:(2^32)-1 range (32bit) $fracba = ($frac & 0xff000000) >> 24; $fracbb = ($frac & 0x00ff0000) >> 16; $fracbc = ($frac & 0x0000ff00) >> 8; $fracbd = ($frac & 0x000000ff); - $sec = $sec + 2208988800; + $sec = $sec + 2208988800; // add 70 years in seconds, as ntp counts from 1900 $secba = ($sec & 0xff000000) >> 24; $secbb = ($sec & 0x00ff0000) >> 16; $secbc = ($sec & 0x0000ff00) >> 8; $secbd = ($sec & 0x000000ff); + $ntp = chr($secba) . chr($secbb) . chr($secbc) . chr($secbd); + $ntp .= chr($fracba) . chr($fracbb) . chr($fracbc) . chr($fracbd); + + return $ntp; + } + + /** + * Prepare local timestamp for transmission in our request packet + * + * NTP timestamps are represented as a 64-bit fixed-point number, in + * seconds relative to 0000 UT on 1 January 1900. The integer part is + * in the first 32 bits and the fraction part in the last 32 bits + * + * @return string + */ + protected function _prepare() + { + $ntptime = self::microtimeToNtp(microtime()); + // Flags $nul = chr(0x00); $nulbyte = $nul . $nul . $nul . $nul; @@ -110,8 +131,7 @@ protected function _prepare() * The local time, in timestamp format, at the peer when its latest NTP message * was sent. Contanis an integer and a fractional part */ - $ntppacket .= chr($secba) . chr($secbb) . chr($secbc) . chr($secbd); - $ntppacket .= chr($fracba) . chr($fracbb) . chr($fracbc) . chr($fracbd); + $ntppacket .= $ntptime; /* * The local time, in timestamp format, at the peer. Contains an integer @@ -132,8 +152,7 @@ protected function _prepare() * NTP message departed the sender. Contanis an integer * and a fractional part. */ - $ntppacket .= chr($secba) . chr($secbb) . chr($secbc) . chr($secbd); - $ntppacket .= chr($fracba) . chr($fracbb) . chr($fracbc) . chr($fracbd); + $ntppacket .= $ntptime; return $ntppacket; } diff --git a/tests/Zend/TimeSyncTest.php b/tests/Zend/TimeSyncTest.php index 4164fef56..429412395 100644 --- a/tests/Zend/TimeSyncTest.php +++ b/tests/Zend/TimeSyncTest.php @@ -344,4 +344,10 @@ public function testGetInfo() // nothing } } + + public function testMicrotimeToNtp() + { + $ntp = Zend_TimeSync_Ntp::microtimeToNtp('0.123456 1234567890'); + $this->assertSame(pack('NN', 0xcd408152, 0x1f9acffa), $ntp); + } }