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 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.
@@ -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
@@ -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
@@ -0,0 +1,2 @@
1
+ require 'net/ntp/ntp'
2
+ require 'net/ntp/version'
@@ -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
@@ -0,0 +1,5 @@
1
+ module Net
2
+ module NTP
3
+ VERSION = '2.0.0'
4
+ end
5
+ 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
+