net-ping 1.5.2 → 1.5.3

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