Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[zend-timesync] fix ntp time sync #153

Merged
merged 2 commits into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions packages/zend-timesync/library/Zend/TimeSync/Ntp.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions tests/Zend/TimeSyncTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}