net-ping 1.5.2 → 1.5.3

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/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ == 1.5.3 - 29-Feb-2012
2
+ * Removed the Windows::Console dependency and replaced it with FFI since there
3
+ were only two functions needed. This had the nice side effect of making it
4
+ work with JRuby, too.
5
+ * Minor cleanup on some multi-variable assignment.
6
+ * Fixed require statements and one test for 1.9.
7
+
1
8
  == 1.5.2 - 4-Nov-2011
2
9
  * The Net::Ping::HTTP class now defaults to using HEAD instead of GET
3
10
  for its ping test. You can alter this via the get_request accessor.
data/README CHANGED
@@ -6,6 +6,8 @@
6
6
  MS Windows when using the Net::Ping::External class unless you're
7
7
  using JRuby.
8
8
 
9
+ JRuby users should use 1.6.7 or later.
10
+
9
11
  == Installation
10
12
  gem install net-ping
11
13
 
@@ -34,9 +36,13 @@
34
36
 
35
37
  == Known Issues
36
38
  Older versions of Ruby 1.9.x may not work with UDP pings.
39
+
37
40
  Older versions of JRuby will return false positives in UDP pings
38
41
  because of an incorrect error class being raised. See JRuby-4896.
39
42
 
43
+ JRuby 1.6.7 or later is required for external pings because of a bug
44
+ in earlier versions with open3 and stream handling.
45
+
40
46
  == License
41
47
  Artistic 2.0
42
48
 
@@ -1,17 +1,12 @@
1
+ require 'ffi'
1
2
  require 'rbconfig'
2
- require File.join(File.dirname(__FILE__), 'ping')
3
3
 
4
- RbConfig = Config unless Object.const_defined?(:RbConfig)
4
+ require File.join(File.dirname(__FILE__), 'ping')
5
5
 
6
- if RbConfig::CONFIG['host_os'] =~ /mswin|win32|msdos|cygwin|mingw|windows/i &&
7
- RUBY_PLATFORM != 'java'
8
- then
9
- if RUBY_VERSION.to_f < 1.9
10
- require 'win32/open3'
11
- end
12
- require 'windows/console'
6
+ if File::ALT_SEPARATOR && RUBY_VERSION.to_f < 1.9 && RUBY_PLATFORM != 'java'
7
+ require 'win32/open3'
13
8
  else
14
- require 'open3'
9
+ require 'open3'
15
10
  end
16
11
 
17
12
  # The Net module serves as a namespace only.
@@ -20,28 +15,29 @@ module Net
20
15
  # The Ping::External class encapsulates methods for external (system) pings.
21
16
  class Ping::External < Ping
22
17
 
23
- CWINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|win32|msdos|cygwin|mingw|windows/i &&
24
- RUBY_PLATFORM != 'java'
25
-
26
- if CWINDOWS
27
- include Windows::Console
28
- end
29
-
18
+ if File::ALT_SEPARATOR
19
+ extend FFI::Library
20
+ ffi_lib 'kernel32'
21
+
22
+ attach_function :SetConsoleCP, [:uint], :bool
23
+ attach_function :GetConsoleCP, [], :uint
24
+ end
25
+
30
26
  # Pings the host using your system's ping utility and checks for any
31
27
  # errors or warnings. Returns true if successful, or false if not.
32
- #
28
+ #
33
29
  # If the ping failed then the Ping::External#exception method should
34
30
  # contain a string indicating what went wrong. If the ping succeeded then
35
31
  # the Ping::External#warning method may or may not contain a value.
36
- #
32
+ #
37
33
  def ping(host = @host)
38
34
  super(host)
39
35
 
40
- stdin, stdout, stderr = ""
36
+ stdin = stdout = stderr = nil
41
37
  pstring = "ping "
42
38
  bool = false
43
39
  orig_cp = nil
44
-
40
+
45
41
  case RbConfig::CONFIG['host_os']
46
42
  when /linux|bsd|osx|mach|darwin/i
47
43
  pstring += "-c 1 #{host}"
@@ -50,17 +46,15 @@ module Net
50
46
  when /hpux/i
51
47
  pstring += "#{host} -n 1"
52
48
  when /win32|windows|msdos|mswin|cygwin|mingw/i
53
- if RUBY_PLATFORM != 'java'
54
- orig_cp = GetConsoleCP()
55
- SetConsoleCP(437) if orig_cp != 437 # United States
56
- end
49
+ orig_cp = GetConsoleCP()
50
+ SetConsoleCP(437) if orig_cp != 437 # United States
57
51
  pstring += "-n 1 #{host}"
58
52
  else
59
53
  pstring += "#{host}"
60
54
  end
61
-
55
+
62
56
  start_time = Time.now
63
-
57
+
64
58
  begin
65
59
  err = nil
66
60
 
@@ -72,10 +66,10 @@ module Net
72
66
  stdin.close
73
67
  stderr.close
74
68
 
75
- if CWINDOWS && GetConsoleCP() != orig_cp
69
+ if File::ALT_SEPARATOR && GetConsoleCP() != orig_cp
76
70
  SetConsoleCP(orig_cp)
77
71
  end
78
-
72
+
79
73
  unless err.nil?
80
74
  if err =~ /warning/i
81
75
  @warning = err.chomp
@@ -109,7 +103,7 @@ module Net
109
103
  end
110
104
  end
111
105
  rescue Exception => error
112
- @exception = error.message
106
+ @exception = error.message
113
107
  ensure
114
108
  stdin.close if stdin && !stdin.closed?
115
109
  stdout.close if stdout && !stdout.closed?
data/lib/net/ping/icmp.rb CHANGED
@@ -1,168 +1,180 @@
1
1
  require File.join(File.dirname(__FILE__), 'ping')
2
2
 
3
+ if File::ALT_SEPARATOR
4
+ require 'win32/security'
5
+ require 'windows/system_info'
6
+ include Windows::SystemInfo
7
+ end
8
+
3
9
  # The Net module serves as a namespace only.
4
10
  module Net
5
11
 
6
- # The Net::Ping::ICMP class encapsulates an icmp ping.
7
- class Ping::ICMP < Ping
8
- ICMP_ECHOREPLY = 0 # Echo reply
9
- ICMP_ECHO = 8 # Echo request
10
- ICMP_SUBCODE = 0
11
-
12
- # You cannot set or change the port value. A value of 0 is always
13
- # used internally for ICMP pings.
14
- #
15
- undef_method :port=
16
-
17
- # Returns the data size, i.e. number of bytes sent on the ping. The
18
- # default size is 56.
19
- #
20
- attr_reader :data_size
21
-
22
- # Creates and returns a new Ping::ICMP object. This is similar to its
23
- # superclass constructor, but must be created with root privileges (on
24
- # UNIX systems), and the port value is ignored.
25
- #
26
- def initialize(host=nil, port=nil, timeout=5)
27
- raise 'requires root privileges' if Process.euid > 0
28
-
29
- @seq = 0
30
- @bind_port = 0
31
- @bind_host = nil
32
- @data_size = 56
33
- @data = ''
34
-
35
- 0.upto(@data_size){ |n| @data << (n % 256).chr }
36
-
37
- @pid = Process.pid & 0xffff
38
-
39
- super(host, port, timeout)
40
- @port = nil # This value is not used in ICMP pings.
12
+ # The Net::Ping::ICMP class encapsulates an icmp ping.
13
+ class Ping::ICMP < Ping
14
+ ICMP_ECHOREPLY = 0 # Echo reply
15
+ ICMP_ECHO = 8 # Echo request
16
+ ICMP_SUBCODE = 0
17
+
18
+ # You cannot set or change the port value. A value of 0 is always
19
+ # used internally for ICMP pings.
20
+ #
21
+ undef_method :port=
22
+
23
+ # Returns the data size, i.e. number of bytes sent on the ping. The
24
+ # default size is 56.
25
+ #
26
+ attr_reader :data_size
27
+
28
+ # Creates and returns a new Ping::ICMP object. This is similar to its
29
+ # superclass constructor, but must be created with root privileges (on
30
+ # UNIX systems), and the port value is ignored.
31
+ #
32
+ def initialize(host=nil, port=nil, timeout=5)
33
+ raise 'requires root privileges' if Process.euid > 0
34
+
35
+ if File::ALT_SEPARATOR && windows_version >= 6
36
+ unless Win32::Security.elevated_security?
37
+ raise 'requires elevated security'
38
+ end
41
39
  end
42
40
 
43
- # Sets the number of bytes sent in the ping method.
44
- #
45
- def data_size=(size)
46
- @data_size = size
47
- @data = ''
48
- 0.upto(size){ |n| @data << (n % 256).chr }
41
+ @seq = 0
42
+ @bind_port = 0
43
+ @bind_host = nil
44
+ @data_size = 56
45
+ @data = ''
46
+
47
+ 0.upto(@data_size){ |n| @data << (n % 256).chr }
48
+
49
+ @pid = Process.pid & 0xffff
50
+
51
+ super(host, port, timeout)
52
+ @port = nil # This value is not used in ICMP pings.
53
+ end
54
+
55
+ # Sets the number of bytes sent in the ping method.
56
+ #
57
+ def data_size=(size)
58
+ @data_size = size
59
+ @data = ''
60
+ 0.upto(size){ |n| @data << (n % 256).chr }
61
+ end
62
+
63
+ # Associates the local end of the socket connection with the given
64
+ # +host+ and +port+. The default port is 0.
65
+ #
66
+ def bind(host, port = 0)
67
+ @bind_host = host
68
+ @bind_port = port
69
+ end
70
+
71
+ # Pings the +host+ specified in this method or in the constructor. If a
72
+ # host was not specified either here or in the constructor, an
73
+ # ArgumentError is raised.
74
+ #
75
+ def ping(host = @host)
76
+ super(host)
77
+ bool = false
78
+
79
+ socket = Socket.new(
80
+ Socket::PF_INET,
81
+ Socket::SOCK_RAW,
82
+ Socket::IPPROTO_ICMP
83
+ )
84
+
85
+ if @bind_host
86
+ saddr = Socket.pack_sockaddr_in(@bind_port, @bind_host)
87
+ socket.bind(saddr)
49
88
  end
50
89
 
51
- # Associates the local end of the socket connection with the given
52
- # +host+ and +port+. The default port is 0.
53
- #
54
- def bind(host, port = 0)
55
- @bind_host = host
56
- @bind_port = port
90
+ @seq = (@seq + 1) % 65536
91
+ pstring = 'C2 n3 A' << @data_size.to_s
92
+ timeout = @timeout
93
+
94
+ checksum = 0
95
+ msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
96
+
97
+ checksum = checksum(msg)
98
+ msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
99
+
100
+ begin
101
+ saddr = Socket.pack_sockaddr_in(0, host)
102
+ rescue Exception
103
+ socket.close unless socket.closed?
104
+ return bool
57
105
  end
58
-
59
- # Pings the +host+ specified in this method or in the constructor. If a
60
- # host was not specified either here or in the constructor, an
61
- # ArgumentError is raised.
62
- #
63
- def ping(host = @host)
64
- super(host)
65
- bool = false
66
-
67
- socket = Socket.new(
68
- Socket::PF_INET,
69
- Socket::SOCK_RAW,
70
- Socket::IPPROTO_ICMP
71
- )
72
-
73
- if @bind_host
74
- saddr = Socket.pack_sockaddr_in(@bind_port, @bind_host)
75
- socket.bind(saddr)
76
- end
77
-
78
- @seq = (@seq + 1) % 65536
79
- pstring = 'C2 n3 A' << @data_size.to_s
80
- timeout = @timeout
81
-
82
- checksum = 0
83
- msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
84
- checksum = checksum(msg)
85
- msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
86
-
87
- begin
88
- saddr = Socket.pack_sockaddr_in(0, host)
89
- rescue Exception
90
- socket.close unless socket.closed?
91
- return bool
92
- end
93
-
94
- start_time = Time.now
95
-
96
- socket.send(msg, 0, saddr) # Send the message
97
-
98
- begin
99
- Timeout.timeout(@timeout){
100
- while true
101
- io_array = select([socket], nil, nil, timeout)
102
-
103
- if io_array.nil? || io_array[0].empty?
104
- return false
105
- end
106
-
107
- pid = nil
108
- seq = nil
109
-
110
- data, sender = socket.recvfrom(1500)
111
- port, host = Socket.unpack_sockaddr_in(sender)
112
- type, subcode = data[20, 2].unpack('C2')
113
-
114
- case type
115
- when ICMP_ECHOREPLY
116
- if data.length >= 28
117
- pid, seq = data[24, 4].unpack('n3')
118
- end
119
- else
120
- if data.length > 56
121
- pid, seq = data[52, 4].unpack('n3')
122
- end
123
- end
124
-
125
- if pid == @pid && seq == @seq && type == ICMP_ECHOREPLY
126
- bool = true
127
- break
128
- end
129
- end
130
- }
131
- rescue Exception => err
132
- @exception = err
133
- ensure
134
- socket.close if socket
135
- end
136
-
137
- # There is no duration if the ping failed
138
- @duration = Time.now - start_time if bool
139
-
140
- return bool
106
+
107
+ start_time = Time.now
108
+
109
+ socket.send(msg, 0, saddr) # Send the message
110
+
111
+ begin
112
+ Timeout.timeout(@timeout){
113
+ while true
114
+ io_array = select([socket], nil, nil, timeout)
115
+
116
+ if io_array.nil? || io_array[0].empty?
117
+ return false
118
+ end
119
+
120
+ pid = nil
121
+ seq = nil
122
+
123
+ data = socket.recvfrom(1500).first
124
+ type = data[20, 2].unpack('C2').first
125
+
126
+ case type
127
+ when ICMP_ECHOREPLY
128
+ if data.length >= 28
129
+ pid, seq = data[24, 4].unpack('n3')
130
+ end
131
+ else
132
+ if data.length > 56
133
+ pid, seq = data[52, 4].unpack('n3')
134
+ end
135
+ end
136
+
137
+ if pid == @pid && seq == @seq && type == ICMP_ECHOREPLY
138
+ bool = true
139
+ break
140
+ end
141
+ end
142
+ }
143
+ rescue Exception => err
144
+ @exception = err
145
+ ensure
146
+ socket.close if socket
141
147
  end
142
148
 
143
- alias ping? ping
144
- alias pingecho ping
149
+ # There is no duration if the ping failed
150
+ @duration = Time.now - start_time if bool
151
+
152
+ return bool
153
+ end
145
154
 
146
- private
155
+ alias ping? ping
156
+ alias pingecho ping
147
157
 
148
- # Perform a checksum on the message. This is the sum of all the short
149
- # words and it folds the high order bits into the low order bits.
150
- #
151
- def checksum(msg)
152
- length = msg.length
153
- num_short = length / 2
154
- check = 0
158
+ private
155
159
 
156
- msg.unpack("n#{num_short}").each do |short|
157
- check += short
158
- end
160
+ # Perform a checksum on the message. This is the sum of all the short
161
+ # words and it folds the high order bits into the low order bits.
162
+ #
163
+ def checksum(msg)
164
+ length = msg.length
165
+ num_short = length / 2
166
+ check = 0
159
167
 
160
- if length % 2 > 0
161
- check += msg[length-1, 1].unpack('C').first << 8
162
- end
168
+ msg.unpack("n#{num_short}").each do |short|
169
+ check += short
170
+ end
171
+
172
+ if length % 2 > 0
173
+ check += msg[length-1, 1].unpack('C').first << 8
174
+ end
163
175
 
164
- check = (check >> 16) + (check & 0xffff)
165
- return (~((check >> 16) + check) & 0xffff)
166
- end
167
- end
176
+ check = (check >> 16) + (check & 0xffff)
177
+ return (~((check >> 16) + check) & 0xffff)
178
+ end
179
+ end
168
180
  end
data/net-ping.gemspec CHANGED
@@ -1,37 +1,41 @@
1
1
  require 'rubygems'
2
2
  require 'rbconfig'
3
3
 
4
- Gem::Specification.new do |gem|
5
- gem.name = 'net-ping'
6
- gem.version = '1.5.2'
7
- gem.license = 'Artistic 2.0'
8
- gem.author = 'Daniel J. Berger'
9
- gem.email = 'djberg96@gmail.com'
10
- gem.homepage = 'http://www.rubyforge.org/projects/shards'
11
- gem.summary = 'A ping interface for Ruby.'
12
- gem.test_file = 'test/test_net_ping.rb'
13
- gem.files = Dir['**/*'].reject{ |f| f.include?('git') }
14
-
15
- gem.rubyforge_project = 'shards'
16
- gem.extra_rdoc_files = ['README', 'CHANGES', 'doc/ping.txt']
17
-
18
- gem.add_dependency('net-ldap', '~> 0.2.2')
19
- gem.add_development_dependency('test-unit', '>= 2.1.2')
20
- gem.add_development_dependency('fakeweb', '>= 1.3.0')
21
- gem.add_development_dependency('fakeldap', '~> 0.0.1')
22
-
23
- # These dependencies are for Net::Ping::External
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'net-ping'
6
+ spec.version = '1.5.3'
7
+ spec.license = 'Artistic 2.0'
8
+ spec.author = 'Daniel J. Berger'
9
+ spec.email = 'djberg96@gmail.com'
10
+ spec.homepage = 'http://www.rubyforge.org/projects/shards'
11
+ spec.summary = 'A ping interface for Ruby.'
12
+ spec.test_file = 'test/test_net_ping.rb'
13
+ spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
14
+
15
+ spec.rubyforge_project = 'shards'
16
+ spec.extra_rdoc_files = ['README', 'CHANGES', 'doc/ping.txt']
17
+
18
+ spec.add_dependency('net-ldap', '~> 0.2.2')
19
+ spec.add_dependency('ffi', '>= 1.0.0')
20
+
21
+ spec.add_development_dependency('test-unit', '>= 2.1.2')
22
+ spec.add_development_dependency('fakeweb', '>= 1.3.0')
23
+ spec.add_development_dependency('fakeldap', '~> 0.0.1')
24
+
24
25
  if File::ALT_SEPARATOR && RUBY_PLATFORM != 'java'
25
- gem.platform = Gem::Platform::CURRENT
26
- gem.add_dependency('windows-pr', '>= 1.0.8')
27
- gem.add_development_dependency('win32-security', '>= 1.0.8')
26
+ spec.platform = Gem::Platform::CURRENT
27
+ spec.platform.cpu = 'universal'
28
+ spec.platform.version = nil
29
+
30
+ # Used primarily for icmp pings.
31
+ spec.add_development_dependency('win32-security', '>= 1.0.8')
28
32
 
29
33
  if RUBY_VERSION.to_f < 1.9
30
- gem.add_dependency('win32-open3', '>= 0.3.1')
34
+ spec.add_dependency('win32-open3', '>= 0.3.1')
31
35
  end
32
36
  end
33
37
 
34
- gem.description = <<-EOF
38
+ spec.description = <<-EOF
35
39
  The net-ping library provides a ping interface for Ruby. It includes
36
40
  separate TCP, HTTP, LDAP, ICMP, UDP, WMI (for Windows) and external ping
37
41
  classes.
@@ -28,7 +28,7 @@ end
28
28
 
29
29
  class TC_PingICMP < Test::Unit::TestCase
30
30
  def setup
31
- @host = 'localhost'
31
+ @host = '127.0.0.1' # 'localhost'
32
32
  @icmp = Ping::ICMP.new(@host)
33
33
  end
34
34
 
@@ -50,6 +50,10 @@ class TC_PingICMP < Test::Unit::TestCase
50
50
  assert_boolean(@icmp.pingecho(@host))
51
51
  end
52
52
 
53
+ def test_ping_expected_success
54
+ assert_true(Ping::ICMP.new(@host).ping?)
55
+ end
56
+
53
57
  def test_ping_expected_failure
54
58
  assert_false(Ping::ICMP.new('bogus').ping?)
55
59
  assert_false(Ping::ICMP.new('http://www.asdfhjklasdfhlkj.com').ping?)
@@ -70,7 +74,7 @@ class TC_PingICMP < Test::Unit::TestCase
70
74
  def test_host
71
75
  assert_respond_to(@icmp, :host)
72
76
  assert_respond_to(@icmp, :host=)
73
- assert_equal('localhost', @icmp.host)
77
+ assert_equal(@host, @icmp.host)
74
78
  end
75
79
 
76
80
  def test_port
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-ping
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- - 2
10
- version: 1.5.2
9
+ - 3
10
+ version: 1.5.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Daniel J. Berger
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-05 00:00:00 Z
18
+ date: 2012-02-29 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: net-ldap
@@ -34,9 +34,25 @@ dependencies:
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
37
- name: test-unit
37
+ name: ffi
38
38
  prerelease: false
39
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 0
49
+ version: 1.0.0
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: test-unit
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
40
56
  none: false
41
57
  requirements:
42
58
  - - ">="
@@ -48,11 +64,11 @@ dependencies:
48
64
  - 2
49
65
  version: 2.1.2
50
66
  type: :development
51
- version_requirements: *id002
67
+ version_requirements: *id003
52
68
  - !ruby/object:Gem::Dependency
53
69
  name: fakeweb
54
70
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
71
+ requirement: &id004 !ruby/object:Gem::Requirement
56
72
  none: false
57
73
  requirements:
58
74
  - - ">="
@@ -64,11 +80,11 @@ dependencies:
64
80
  - 0
65
81
  version: 1.3.0
66
82
  type: :development
67
- version_requirements: *id003
83
+ version_requirements: *id004
68
84
  - !ruby/object:Gem::Dependency
69
85
  name: fakeldap
70
86
  prerelease: false
71
- requirement: &id004 !ruby/object:Gem::Requirement
87
+ requirement: &id005 !ruby/object:Gem::Requirement
72
88
  none: false
73
89
  requirements:
74
90
  - - ~>
@@ -80,7 +96,7 @@ dependencies:
80
96
  - 1
81
97
  version: 0.0.1
82
98
  type: :development
83
- version_requirements: *id004
99
+ version_requirements: *id005
84
100
  description: " The net-ping library provides a ping interface for Ruby. It includes\n separate TCP, HTTP, LDAP, ICMP, UDP, WMI (for Windows) and external ping\n classes.\n"
85
101
  email: djberg96@gmail.com
86
102
  executables: []