PageRenderTime 27ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/standard/tags/release-0.6.0/incubator/library/Zend/TimeSync/Ntp.php

https://github.com/jorgenils/zend-framework
PHP | 243 lines | 167 code | 30 blank | 46 comment | 29 complexity | 397291919a5ad1a12a5d78c5fab98cbf MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_TimeSync
  17. * @copyright Copyright (c) 2006 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @version $Id$
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * Zend_TimeSync_Protocol
  23. */
  24. require_once 'Zend/TimeSync/Protocol.php';
  25. /**
  26. * @category Zend
  27. * @package Zend_TimeSync
  28. * @copyright Copyright (c) 2006 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_TimeSync_Ntp extends Zend_TimeSync_Protocol
  32. {
  33. protected $_info;
  34. /**
  35. * Class constructor, sets the timeserver and port number
  36. *
  37. * @param string $timeserver
  38. * @param int $port
  39. * @return void
  40. */
  41. public function __construct($timeserver, $port)
  42. {
  43. $this->_timeserver = $timeserver;
  44. $this->_port = $port;
  45. }
  46. /**
  47. * Writes/receives data to/from the timeserver
  48. *
  49. * @return int unix timestamp
  50. */
  51. protected function _query()
  52. {
  53. $frac = microtime();
  54. $fracb1 = ($frac & 0xff000000) >> 24;
  55. $fracb2 = ($frac & 0x00ff0000) >> 16;
  56. $fracb3 = ($frac & 0x0000ff00) >> 8;
  57. $fracb4 = ($frac & 0x000000ff);
  58. $sec = time() + 2208988800;
  59. $secb1 = ($sec & 0xff000000) >> 24;
  60. $secb2 = ($sec & 0x00ff0000) >> 16;
  61. $secb3 = ($sec & 0x0000ff00) >> 8;
  62. $secb4 = ($sec & 0x000000ff);
  63. $ntppacket = chr(0xd9).chr(0x00).chr(0x0a).chr(0xfa); // Flags
  64. $ntppacket .= chr(0x00).chr(0x00).chr(0x1c).chr(0x9b); // Root Delay
  65. $ntppacket .= chr(0x00).chr(0x08).chr(0xd7).chr(0xff); // Clock Dispersion
  66. $ntppacket .= chr(0x00).chr(0x00).chr(0x00).chr(0x00); // ReferenceClockID
  67. $ntppacket .= chr($secb1) .chr($secb2) .chr($secb3) .chr($secb4); // Reference Timestamp Seconds
  68. $ntppacket .= chr($fracb1).chr($fracb2).chr($fracb3).chr($fracb4); // Reference Timestamp Fractional
  69. $ntppacket .= chr(0x00).chr(0x00).chr(0x00).chr(0x00); // Originate Timestamp Seconds
  70. $ntppacket .= chr(0x00).chr(0x00).chr(0x00).chr(0x00); // Originate Timestamp Fractional
  71. $ntppacket .= chr(0x00).chr(0x00).chr(0x00).chr(0x00); // Receive Timestamp Seconds
  72. $ntppacket .= chr(0x00).chr(0x00).chr(0x00).chr(0x00); // Receive Timestamp Fractional
  73. $ntppacket .= chr($secb1) .chr($secb2) .chr($secb3) .chr($secb4); // Transmit Timestamp Seconds
  74. $ntppacket .= chr($fracb1).chr($fracb2).chr($fracb3).chr($fracb4); // Transmit Timestamp Fractional
  75. $this->_connect();
  76. fwrite($this->_socket, $ntppacket);
  77. stream_set_timeout($this->_socket, Zend_TimeSync::$options['timeout']);
  78. $flags = ord(fread($this->_socket, 1));
  79. $info = stream_get_meta_data($this->_socket);
  80. if ($info['timed_out']) {
  81. fclose($this->disconnect);
  82. throw Zend::exception(
  83. 'Zend_TimeSync_ProtocolException',
  84. "could not connect to '$this->_timeserver' on port '$this->_port', reason: 'server timed out'"
  85. );
  86. }
  87. $stratum = ord(fread($this->_socket, 1));
  88. $this->_info['poll'] = ord(fread($this->_socket, 1));
  89. $this->_info['precision'] = ord(fread($this->_socket, 1));
  90. $rootdelay = ord(fread($this->_socket, 4));
  91. $rootdispersion = ord(fread($this->_socket, 4));
  92. $referenceid = ord(fread($this->_socket, 4));
  93. $referencestamp = ord(fread($this->_socket, 4));
  94. $referencemicro = ord(fread($this->_socket, 4));
  95. $originatestamp = ord(fread($this->_socket, 4));
  96. $originatemicro = ord(fread($this->_socket, 4));
  97. $receivestamp = ord(fread($this->_socket, 4));
  98. $receivemicro = ord(fread($this->_socket, 4));
  99. $transmitstamp = ord(fread($this->_socket, 4));
  100. $transmitmicro = ord(fread($this->_socket, 4));
  101. $clientreceived = 0;
  102. $this->_disconnect();
  103. $leap = ($flags & 0xc0) >> 6; // Leap Indicator bit 1100 0000
  104. // 0 = no warning, 1 = last min. 61 sec., 2 = last min. 59 sec., 3 = not synconised
  105. switch($leap) {
  106. case 0 :
  107. $this->_info['leap'] = '0 - no warning';
  108. break;
  109. case 1 :
  110. $this->_info['leap'] = '1 - last minute has 61 seconds';
  111. break;
  112. case 2 :
  113. $this->_info['leap'] = '2 - last minute has 59 seconds';
  114. break;
  115. default:
  116. $this->_info['leap'] = '3 - not syncronised';
  117. }
  118. $this->_info['version'] = ($flags & 0x38) >> 3; // Version Number bit 0011 1000
  119. // should be 3
  120. $mode = ($flags & 0x07); // Mode bit 0000 0111
  121. // 0 = reserved, 1 = symetric active, 2 = symetric passive, 3 = client
  122. // 4 = server, 5 = broadcast, 6 & 7 = reserved
  123. switch($mode) {
  124. case 1 :
  125. $this->_info['mode'] = 'symetric active';
  126. break;
  127. case 2 :
  128. $this->_info['mode'] = 'symetric passive';
  129. break;
  130. case 3 :
  131. $this->_info['mode'] = 'client';
  132. break;
  133. case 4 :
  134. $this->_info['mode'] = 'server';
  135. break;
  136. case 5 :
  137. $this->_info['mode'] = 'broadcast';
  138. break;
  139. default:
  140. $this->_info['mode'] = 'reserved';
  141. break;
  142. }
  143. $ntpserviceid = 'Unknown Stratum ' . $stratum . ' Service';
  144. $refid = strtoupper($referenceid);
  145. switch($stratum) {
  146. case 0:
  147. if (substr($refid, 0, 3) == 'DCN') {
  148. $ntpserviceid = 'DCN routing protocol';
  149. } else if (substr($refid, 0, 4) == 'NIST') {
  150. $ntpserviceid = 'NIST public modem';
  151. } else if (substr($refid, 0, 3) == 'TSP') {
  152. $ntpserviceid = 'TSP time protocol';
  153. } else if (substr($refid, 0, 3) == 'DTS') {
  154. $ntpserviceid = 'Digital Time Service';
  155. }
  156. break;
  157. case 1:
  158. if (substr($refid, 0, 4) == 'ATOM') {
  159. $ntpserviceid = 'Atomic Clock (calibrated)';
  160. } else if (substr($refid, 0, 3) == 'VLF') {
  161. $ntpserviceid = 'VLF radio';
  162. } else if ($refid == 'CALLSIGN') {
  163. $ntpserviceid = 'Generic radio';
  164. } else if (substr($refid, 0, 4) == 'LORC') {
  165. $ntpserviceid = 'LORAN-C radionavigation';
  166. } else if (substr($refid, 0, 4) == 'GOES') {
  167. $ntpserviceid = 'GOES UHF environment satellite';
  168. } else if (substr($refid, 0, 3) == 'GPS') {
  169. $ntpserviceid = 'GPS UHF satellite positioning';
  170. }
  171. break;
  172. default:
  173. $ntpserviceid = ord(substr($referenceid, 0, 1));
  174. $ntpserviceid .= ".";
  175. $ntpserviceid .= ord(substr($referenceid, 1, 1));
  176. $ntpserviceid .= ".";
  177. $ntpserviceid .= ord(substr($referenceid, 2, 1));
  178. $ntpserviceid .= ".";
  179. $ntpserviceid .= ord(substr($referenceid, 3, 1));
  180. break;
  181. }
  182. $this->_info['ntpid'] = $ntpserviceid;
  183. switch($stratum) {
  184. case 0:
  185. $this->_info['stratum'] = 'undefined';
  186. break;
  187. case 1:
  188. $this->_info['stratum'] = 'primary reference';
  189. break;
  190. default:
  191. $this->_info['stratum'] = 'secondary reference';
  192. break;
  193. }
  194. $this->_info['rootdelay'] = $rootdelay >> 15;
  195. $this->_info['rootdelayfrac'] = ($rootdelay << 17) >> 17;
  196. $this->_info['rootdispersion'] = $rootdispersion >> 15;
  197. $this->_info['rootdispersionfrac'] = ($rootdispersion << 17) >> 17;
  198. // seconds for message to the server
  199. $original = (float) $originatestamp;
  200. $original += (float) $originatemicro / 4294967296;
  201. $received = (float) $receivestamp;
  202. $received += (float) $receivemicro / 4294967296;
  203. $transmit = (float) $transmitstamp;
  204. $transmit += (float) $transmitmicro / 4294967296;
  205. $roundtrip = ($clientreceived - $original) - ($transmit - $received);
  206. $this->_info['roundtrip'] = $roundtrip / 2;
  207. // seconds to add for local clock
  208. $offset = $received - $original + $transmit - $clientreceived;
  209. $this->_info['offset'] = $offset / 2;
  210. $time = time() - $offset;
  211. return $time;
  212. }
  213. }