net-ntp 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+