net-ntp 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/README.markdown +26 -0
- data/Rakefile +35 -0
- data/lib/net/ntp.rb +2 -0
- data/lib/net/ntp/ntp.rb +215 -0
- data/lib/net/ntp/version.rb +5 -0
- metadata +71 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2010 Jerome Waibel & Zencoder, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
net-ntp
|
2
|
+
=======
|
3
|
+
|
4
|
+
Originally by Jerome Waibel in 2007
|
5
|
+
http://rubyforge.org/projects/net-ntp/
|
6
|
+
|
7
|
+
Revised by Zencoder in 2010
|
8
|
+
http://github.com/zencoder/net-ntp
|
9
|
+
|
10
|
+
DESCRIPTION
|
11
|
+
-----------
|
12
|
+
|
13
|
+
Began as a 'Rubyfied' version of perl's Net::NTP module, (C) 2004 by James G. Willmore. Refactored and re-released in 2010 by Zencoder.
|
14
|
+
|
15
|
+
SYNOPSIS
|
16
|
+
--------
|
17
|
+
|
18
|
+
require 'net/ntp'
|
19
|
+
|
20
|
+
Net::NTP.get("us.pool.ntp.org") # => a Net::NTP::Response object
|
21
|
+
Net::NTP.get.time # => A Time object
|
22
|
+
|
23
|
+
INSTALL
|
24
|
+
-------
|
25
|
+
|
26
|
+
gem install net-ntp
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
Rake::TestTask.new(:test) do |test|
|
6
|
+
test.libs << 'lib' << 'test'
|
7
|
+
test.pattern = 'test/**/*_test.rb'
|
8
|
+
test.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :test
|
12
|
+
|
13
|
+
require 'rake/rdoctask'
|
14
|
+
require 'lib/net/ntp/version'
|
15
|
+
|
16
|
+
Rake::RDocTask.new do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = "net-ntp #{Net::NTP::VERSION}"
|
19
|
+
rdoc.rdoc_files.include('README*')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'rcov/rcovtask'
|
25
|
+
Rcov::RcovTask.new do |test|
|
26
|
+
test.libs << 'test'
|
27
|
+
test.pattern = 'test/**/*_test.rb'
|
28
|
+
test.verbose = true
|
29
|
+
test.rcov_opts << '--exclude "gems/*"'
|
30
|
+
end
|
31
|
+
rescue LoadError
|
32
|
+
task :rcov do
|
33
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install rcov"
|
34
|
+
end
|
35
|
+
end
|
data/lib/net/ntp.rb
ADDED
data/lib/net/ntp/ntp.rb
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
module Net #:nodoc:
|
5
|
+
module NTP
|
6
|
+
TIMEOUT = 60 #:nodoc:
|
7
|
+
NTP_ADJ = 2208988800 #:nodoc:
|
8
|
+
NTP_FIELDS = [ :byte1, :stratum, :poll, :precision, :delay, :delay_fb,
|
9
|
+
:disp, :disp_fb, :ident, :ref_time, :ref_time_fb, :org_time,
|
10
|
+
:org_time_fb, :recv_time, :recv_time_fb, :trans_time,
|
11
|
+
:trans_time_fb ]
|
12
|
+
|
13
|
+
MODE = {
|
14
|
+
0 => 'reserved',
|
15
|
+
1 => 'symmetric active',
|
16
|
+
2 => 'symmetric passive',
|
17
|
+
3 => 'client',
|
18
|
+
4 => 'server',
|
19
|
+
5 => 'broadcast',
|
20
|
+
6 => 'reserved for NTP control message',
|
21
|
+
7 => 'reserved for private use'
|
22
|
+
}
|
23
|
+
|
24
|
+
STRATUM = {
|
25
|
+
0 => 'unspecified or unavailable',
|
26
|
+
1 => 'primary reference (e.g., radio clock)'
|
27
|
+
}
|
28
|
+
|
29
|
+
2.upto(15) do |i|
|
30
|
+
STRATUM[i] = 'secondary reference (via NTP or SNTP)'
|
31
|
+
end
|
32
|
+
|
33
|
+
16.upto(255) do |i|
|
34
|
+
STRATUM[i] = 'reserved'
|
35
|
+
end
|
36
|
+
|
37
|
+
REFERENCE_CLOCK_IDENTIFIER = {
|
38
|
+
'LOCL' => 'uncalibrated local clock used as a primary reference for a subnet without external means of synchronization',
|
39
|
+
'PPS' => 'atomic clock or other pulse-per-second source individually calibrated to national standards',
|
40
|
+
'ACTS' => 'NIST dialup modem service',
|
41
|
+
'USNO' => 'USNO modem service',
|
42
|
+
'PTB' => 'PTB (Germany) modem service',
|
43
|
+
'TDF' => 'Allouis (France) Radio 164 kHz',
|
44
|
+
'DCF' => 'Mainflingen (Germany) Radio 77.5 kHz',
|
45
|
+
'MSF' => 'Rugby (UK) Radio 60 kHz',
|
46
|
+
'WWV' => 'Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz',
|
47
|
+
'WWVB' => 'Boulder (US) Radio 60 kHz',
|
48
|
+
'WWVH' => 'Kaui Hawaii (US) Radio 2.5, 5, 10, 15 MHz',
|
49
|
+
'CHU' => 'Ottawa (Canada) Radio 3330, 7335, 14670 kHz',
|
50
|
+
'LORC' => 'LORAN-C radionavigation system',
|
51
|
+
'OMEG' => 'OMEGA radionavigation system',
|
52
|
+
'GPS' => 'Global Positioning Service',
|
53
|
+
'GOES' => 'Geostationary Orbit Environment Satellite'
|
54
|
+
}
|
55
|
+
|
56
|
+
LEAP_INDICATOR = {
|
57
|
+
0 => 'no warning',
|
58
|
+
1 => 'last minute has 61 seconds',
|
59
|
+
2 => 'last minute has 59 seconds)',
|
60
|
+
3 => 'alarm condition (clock not synchronized)'
|
61
|
+
}
|
62
|
+
|
63
|
+
###
|
64
|
+
# Sends an NTP datagram to the specified NTP server and returns
|
65
|
+
# a hash based upon RFC1305 and RFC2030.
|
66
|
+
def self.get(host="pool.ntp.org", port="ntp")
|
67
|
+
sock = UDPSocket.new
|
68
|
+
sock.connect(host, port)
|
69
|
+
|
70
|
+
client_time_send = Time.new.to_i
|
71
|
+
client_localtime = client_time_send
|
72
|
+
client_adj_localtime = client_localtime + NTP_ADJ
|
73
|
+
client_frac_localtime = frac2bin(client_adj_localtime)
|
74
|
+
|
75
|
+
ntp_msg = (['00011011']+Array.new(12, 0)+[client_localtime, client_frac_localtime.to_s]).pack("B8 C3 N10 B32")
|
76
|
+
|
77
|
+
sock.print ntp_msg
|
78
|
+
sock.flush
|
79
|
+
|
80
|
+
data = nil
|
81
|
+
Timeout::timeout(TIMEOUT) do |t|
|
82
|
+
data = sock.recvfrom(960)[0]
|
83
|
+
end
|
84
|
+
|
85
|
+
Response.new(data)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.frac2bin(frac) #:nodoc:
|
89
|
+
bin = ''
|
90
|
+
|
91
|
+
while bin.length < 32
|
92
|
+
bin += ( frac * 2 ).to_i.to_s
|
93
|
+
frac = ( frac * 2 ) - ( frac * 2 ).to_i
|
94
|
+
end
|
95
|
+
|
96
|
+
bin
|
97
|
+
end
|
98
|
+
private_class_method :frac2bin
|
99
|
+
|
100
|
+
class Response
|
101
|
+
def initialize(raw_data)
|
102
|
+
@raw_data = raw_data
|
103
|
+
@client_time_receive = Time.new.to_i
|
104
|
+
end
|
105
|
+
|
106
|
+
def leap_indicator
|
107
|
+
@leap_indicator ||= (packet_data_by_field[:byte1][0] & 0xC0) >> 6
|
108
|
+
end
|
109
|
+
|
110
|
+
def leap_indicator_text
|
111
|
+
@leap_indicator_text ||= LEAP_INDICATOR[leap_indicator]
|
112
|
+
end
|
113
|
+
|
114
|
+
def version_number
|
115
|
+
@version_number ||= (packet_data_by_field[:byte1][0] & 0x38) >> 3
|
116
|
+
end
|
117
|
+
|
118
|
+
def mode
|
119
|
+
@mode ||= (packet_data_by_field[:byte1][0] & 0x07)
|
120
|
+
end
|
121
|
+
|
122
|
+
def mode_text
|
123
|
+
@mode_text ||= MODE[mode]
|
124
|
+
end
|
125
|
+
|
126
|
+
def stratum
|
127
|
+
@stratum ||= packet_data_by_field[:stratum]
|
128
|
+
end
|
129
|
+
|
130
|
+
def stratum_text
|
131
|
+
@stratum_text ||= STRATUM[stratum]
|
132
|
+
end
|
133
|
+
|
134
|
+
def poll_interval
|
135
|
+
@poll_interval ||= packet_data_by_field[:poll]
|
136
|
+
end
|
137
|
+
|
138
|
+
def precision
|
139
|
+
@precision ||= packet_data_by_field[:precision] - 255
|
140
|
+
end
|
141
|
+
|
142
|
+
def root_delay
|
143
|
+
@root_delay ||= bin2frac(packet_data_by_field[:delay_fb])
|
144
|
+
end
|
145
|
+
|
146
|
+
def root_dispersion
|
147
|
+
@root_dispersion ||= packet_data_by_field[:disp]
|
148
|
+
end
|
149
|
+
|
150
|
+
def reference_clock_identifier
|
151
|
+
@reference_clock_identifier ||= unpack_ip(packet_data_by_field[:stratum], packet_data_by_field[:ident])
|
152
|
+
end
|
153
|
+
|
154
|
+
def reference_clock_identifier_text
|
155
|
+
@reference_clock_identifier_text ||= REFERENCE_CLOCK_IDENTIFIER[reference_clock_identifier]
|
156
|
+
end
|
157
|
+
|
158
|
+
def reference_timestamp
|
159
|
+
@reference_timestamp ||= ((packet_data_by_field[:ref_time] + bin2frac(packet_data_by_field[:ref_time_fb])) - NTP_ADJ)
|
160
|
+
end
|
161
|
+
|
162
|
+
def originate_timestamp
|
163
|
+
@originate_timestamp ||= (packet_data_by_field[:org_time] + bin2frac(packet_data_by_field[:org_time_fb]))
|
164
|
+
end
|
165
|
+
|
166
|
+
def receive_timestamp
|
167
|
+
@receive_timestamp ||= ((packet_data_by_field[:recv_time] + bin2frac(packet_data_by_field[:recv_time_fb])) - NTP_ADJ)
|
168
|
+
end
|
169
|
+
|
170
|
+
def transmit_timestamp
|
171
|
+
@transmit_timestamp ||= ((packet_data_by_field[:trans_time] + bin2frac(packet_data_by_field[:trans_time_fb])) - NTP_ADJ)
|
172
|
+
end
|
173
|
+
|
174
|
+
def time
|
175
|
+
@time ||= Time.at(receive_timestamp)
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
protected
|
180
|
+
|
181
|
+
def packet_data_by_field #:nodoc:
|
182
|
+
if !@packet_data_by_field
|
183
|
+
@packetdata = @raw_data.unpack("a C3 n B16 n B16 H8 N B32 N B32 N B32 N B32");
|
184
|
+
@packet_data_by_field = {}
|
185
|
+
NTP_FIELDS.each do |field|
|
186
|
+
@packet_data_by_field[field] = @packetdata.shift
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
@packet_data_by_field
|
191
|
+
end
|
192
|
+
|
193
|
+
def bin2frac(bin) #:nodoc:
|
194
|
+
frac = 0
|
195
|
+
|
196
|
+
bin.reverse.split("").each do |b|
|
197
|
+
frac = ( frac + b.to_i ) / 2.0
|
198
|
+
end
|
199
|
+
|
200
|
+
frac
|
201
|
+
end
|
202
|
+
|
203
|
+
def unpack_ip(stratum, tmp_ip) #:nodoc:
|
204
|
+
if stratum < 2
|
205
|
+
[tmp_ip].pack("H8").unpack("A4")[0]
|
206
|
+
else
|
207
|
+
ipbytes = [tmp_ip].pack("H8").unpack("C4")
|
208
|
+
sprintf("%d.%d.%d.%d", ipbytes[0], ipbytes[1], ipbytes[2], ipbytes[3])
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: net-ntp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 2
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 2.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jerome Waibel
|
13
|
+
- Nathan Sutton
|
14
|
+
- Brandon Arbini
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-12-09 00:00:00 -06:00
|
20
|
+
default_executable:
|
21
|
+
dependencies: []
|
22
|
+
|
23
|
+
description: This project was a rubyfied version of perl's Net::NTP module, (C) 2004 by James G. Willmore. It provides a method to query an NTP server as specified in RFC1305 and RFC2030. Updated and re-released in 2010 by Zencoder.
|
24
|
+
email:
|
25
|
+
- nate@zencoder.com
|
26
|
+
- brandon@zencoder.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- lib/net/ntp/ntp.rb
|
35
|
+
- lib/net/ntp/version.rb
|
36
|
+
- lib/net/ntp.rb
|
37
|
+
- LICENSE
|
38
|
+
- README.markdown
|
39
|
+
- Rakefile
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/zencoder/net-ntp
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.6
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: NTP client for ruby.
|
70
|
+
test_files: []
|
71
|
+
|