net-ping 1.7.2-universal-mingw32 → 1.7.3-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/lib/net/ping/icmp.rb CHANGED
@@ -1,178 +1,177 @@
1
- require File.join(File.dirname(__FILE__), 'ping')
2
-
3
- if File::ALT_SEPARATOR
4
- require 'win32/security'
5
- end
6
-
7
- # The Net module serves as a namespace only.
8
- module Net
9
-
10
- # The Net::Ping::ICMP class encapsulates an icmp ping.
11
- class Ping::ICMP < Ping
12
- ICMP_ECHOREPLY = 0 # Echo reply
13
- ICMP_ECHO = 8 # Echo request
14
- ICMP_SUBCODE = 0
15
-
16
- # You cannot set or change the port value. A value of 0 is always
17
- # used internally for ICMP pings.
18
- #
19
- undef_method :port=
20
-
21
- # Returns the data size, i.e. number of bytes sent on the ping. The
22
- # default size is 56.
23
- #
24
- attr_reader :data_size
25
-
26
- # Creates and returns a new Ping::ICMP object. This is similar to its
27
- # superclass constructor, but must be created with root privileges (on
28
- # UNIX systems), and the port value is ignored.
29
- #
30
- def initialize(host=nil, port=nil, timeout=5)
31
- raise 'requires root privileges' if Process.euid > 0
32
-
33
- if File::ALT_SEPARATOR
34
- unless Win32::Security.elevated_security?
35
- raise 'requires elevated security'
36
- end
37
- end
38
-
39
- @seq = 0
40
- @bind_port = 0
41
- @bind_host = nil
42
- @data_size = 56
43
- @data = ''
44
-
45
- 0.upto(@data_size){ |n| @data << (n % 256).chr }
46
-
47
- @pid = Process.pid & 0xffff
48
-
49
- super(host, port, timeout)
50
- @port = nil # This value is not used in ICMP pings.
51
- end
52
-
53
- # Sets the number of bytes sent in the ping method.
54
- #
55
- def data_size=(size)
56
- @data_size = size
57
- @data = ''
58
- 0.upto(size){ |n| @data << (n % 256).chr }
59
- end
60
-
61
- # Associates the local end of the socket connection with the given
62
- # +host+ and +port+. The default port is 0.
63
- #
64
- def bind(host, port = 0)
65
- @bind_host = host
66
- @bind_port = port
67
- end
68
-
69
- # Pings the +host+ specified in this method or in the constructor. If a
70
- # host was not specified either here or in the constructor, an
71
- # ArgumentError is raised.
72
- #
73
- def ping(host = @host)
74
- super(host)
75
- bool = false
76
-
77
- socket = Socket.new(
78
- Socket::PF_INET,
79
- Socket::SOCK_RAW,
80
- Socket::IPPROTO_ICMP
81
- )
82
-
83
- if @bind_host
84
- saddr = Socket.pack_sockaddr_in(@bind_port, @bind_host)
85
- socket.bind(saddr)
86
- end
87
-
88
- @seq = (@seq + 1) % 65536
89
- pstring = 'C2 n3 A' << @data_size.to_s
90
- timeout = @timeout
91
-
92
- checksum = 0
93
- msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
94
-
95
- checksum = checksum(msg)
96
- msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
97
-
98
- begin
99
- saddr = Socket.pack_sockaddr_in(0, host)
100
- rescue Exception
101
- socket.close unless socket.closed?
102
- return bool
103
- end
104
-
105
- start_time = Time.now
106
-
107
- socket.send(msg, 0, saddr) # Send the message
108
-
109
- begin
110
- Timeout.timeout(@timeout){
111
- while true
112
- io_array = select([socket], nil, nil, timeout)
113
-
114
- if io_array.nil? || io_array[0].empty?
115
- return false
116
- end
117
-
118
- pid = nil
119
- seq = nil
120
-
121
- data = socket.recvfrom(1500).first
122
- type = data[20, 2].unpack('C2').first
123
-
124
- case type
125
- when ICMP_ECHOREPLY
126
- if data.length >= 28
127
- pid, seq = data[24, 4].unpack('n3')
128
- end
129
- else
130
- if data.length > 56
131
- pid, seq = data[52, 4].unpack('n3')
132
- end
133
- end
134
-
135
- if pid == @pid && seq == @seq && type == ICMP_ECHOREPLY
136
- bool = true
137
- break
138
- end
139
- end
140
- }
141
- rescue Exception => err
142
- @exception = err
143
- ensure
144
- socket.close if socket
145
- end
146
-
147
- # There is no duration if the ping failed
148
- @duration = Time.now - start_time if bool
149
-
150
- return bool
151
- end
152
-
153
- alias ping? ping
154
- alias pingecho ping
155
-
156
- private
157
-
158
- # Perform a checksum on the message. This is the sum of all the short
159
- # words and it folds the high order bits into the low order bits.
160
- #
161
- def checksum(msg)
162
- length = msg.length
163
- num_short = length / 2
164
- check = 0
165
-
166
- msg.unpack("n#{num_short}").each do |short|
167
- check += short
168
- end
169
-
170
- if length % 2 > 0
171
- check += msg[length-1, 1].unpack('C').first << 8
172
- end
173
-
174
- check = (check >> 16) + (check & 0xffff)
175
- return (~((check >> 16) + check) & 0xffff)
176
- end
177
- end
178
- end
1
+ require File.join(File.dirname(__FILE__), 'ping')
2
+
3
+ if File::ALT_SEPARATOR
4
+ require 'win32/security'
5
+ end
6
+
7
+ # The Net module serves as a namespace only.
8
+ module Net
9
+
10
+ # The Net::Ping::ICMP class encapsulates an icmp ping.
11
+ class Ping::ICMP < Ping
12
+ ICMP_ECHOREPLY = 0 # Echo reply
13
+ ICMP_ECHO = 8 # Echo request
14
+ ICMP_SUBCODE = 0
15
+
16
+ # You cannot set or change the port value. A value of 0 is always
17
+ # used internally for ICMP pings.
18
+ #
19
+ undef_method :port=
20
+
21
+ # Returns the data size, i.e. number of bytes sent on the ping. The
22
+ # default size is 56.
23
+ #
24
+ attr_reader :data_size
25
+
26
+ # Creates and returns a new Ping::ICMP object. This is similar to its
27
+ # superclass constructor, but must be created with root privileges (on
28
+ # UNIX systems), and the port value is ignored.
29
+ #
30
+ def initialize(host=nil, port=nil, timeout=5)
31
+ raise 'requires root privileges' if Process.euid > 0
32
+
33
+ if File::ALT_SEPARATOR
34
+ unless Win32::Security.elevated_security?
35
+ raise 'requires elevated security'
36
+ end
37
+ end
38
+
39
+ @seq = 0
40
+ @bind_port = 0
41
+ @bind_host = nil
42
+ @data_size = 56
43
+ @data = ''
44
+
45
+ 0.upto(@data_size){ |n| @data << (n % 256).chr }
46
+
47
+ @ping_id = (Thread.current.object_id ^ Process.pid) & 0xffff
48
+
49
+ super(host, port, timeout)
50
+ @port = nil # This value is not used in ICMP pings.
51
+ end
52
+
53
+ # Sets the number of bytes sent in the ping method.
54
+ #
55
+ def data_size=(size)
56
+ @data_size = size
57
+ @data = ''
58
+ 0.upto(size){ |n| @data << (n % 256).chr }
59
+ end
60
+
61
+ # Associates the local end of the socket connection with the given
62
+ # +host+ and +port+. The default port is 0.
63
+ #
64
+ def bind(host, port = 0)
65
+ @bind_host = host
66
+ @bind_port = port
67
+ end
68
+
69
+ # Pings the +host+ specified in this method or in the constructor. If a
70
+ # host was not specified either here or in the constructor, an
71
+ # ArgumentError is raised.
72
+ #
73
+ def ping(host = @host)
74
+ super(host)
75
+ bool = false
76
+
77
+ socket = Socket.new(
78
+ Socket::PF_INET,
79
+ Socket::SOCK_RAW,
80
+ Socket::IPPROTO_ICMP
81
+ )
82
+
83
+ if @bind_host
84
+ saddr = Socket.pack_sockaddr_in(@bind_port, @bind_host)
85
+ socket.bind(saddr)
86
+ end
87
+
88
+ @seq = (@seq + 1) % 65536
89
+ pstring = 'C2 n3 A' << @data_size.to_s
90
+ timeout = @timeout
91
+
92
+ checksum = 0
93
+ msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @ping_id, @seq, @data].pack(pstring)
94
+
95
+ checksum = checksum(msg)
96
+ msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @ping_id, @seq, @data].pack(pstring)
97
+
98
+ begin
99
+ saddr = Socket.pack_sockaddr_in(0, host)
100
+ rescue Exception
101
+ socket.close unless socket.closed?
102
+ return bool
103
+ end
104
+
105
+ start_time = Time.now
106
+
107
+ socket.send(msg, 0, saddr) # Send the message
108
+
109
+ begin
110
+ while true
111
+ io_array = select([socket], nil, nil, timeout)
112
+
113
+ if io_array.nil? || io_array[0].empty?
114
+ @exception = "timeout" if io_array.nil?
115
+ return false
116
+ end
117
+
118
+ ping_id = nil
119
+ seq = nil
120
+
121
+ data = socket.recvfrom(1500).first
122
+ type = data[20, 2].unpack('C2').first
123
+
124
+ case type
125
+ when ICMP_ECHOREPLY
126
+ if data.length >= 28
127
+ ping_id, seq = data[24, 4].unpack('n3')
128
+ end
129
+ else
130
+ if data.length > 56
131
+ ping_id, seq = data[52, 4].unpack('n3')
132
+ end
133
+ end
134
+
135
+ if ping_id == @ping_id && seq == @seq && type == ICMP_ECHOREPLY
136
+ bool = true
137
+ break
138
+ end
139
+ end
140
+ rescue Exception => err
141
+ @exception = err
142
+ ensure
143
+ socket.close if socket
144
+ end
145
+
146
+ # There is no duration if the ping failed
147
+ @duration = Time.now - start_time if bool
148
+
149
+ return bool
150
+ end
151
+
152
+ alias ping? ping
153
+ alias pingecho ping
154
+
155
+ private
156
+
157
+ # Perform a checksum on the message. This is the sum of all the short
158
+ # words and it folds the high order bits into the low order bits.
159
+ #
160
+ def checksum(msg)
161
+ length = msg.length
162
+ num_short = length / 2
163
+ check = 0
164
+
165
+ msg.unpack("n#{num_short}").each do |short|
166
+ check += short
167
+ end
168
+
169
+ if length % 2 > 0
170
+ check += msg[length-1, 1].unpack('C').first << 8
171
+ end
172
+
173
+ check = (check >> 16) + (check & 0xffff)
174
+ return (~((check >> 16) + check) & 0xffff)
175
+ end
176
+ end
177
+ end
data/lib/net/ping/ping.rb CHANGED
@@ -1,89 +1,89 @@
1
- require 'socket'
2
- require 'timeout'
3
-
4
- # The Net module serves as a namespace only.
5
- #
6
- module Net
7
-
8
- # The Ping class serves as an abstract base class for all other Ping class
9
- # types. You should not instantiate this class directly.
10
- #
11
- class Ping
12
- # The version of the net-ping library.
13
- VERSION = '1.7.2'
14
-
15
- # The host to ping. In the case of Ping::HTTP, this is the URI.
16
- attr_accessor :host
17
-
18
- # The port to ping. This is set to the echo port (7) by default. The
19
- # Ping::HTTP class defaults to port 80.
20
- #
21
- attr_accessor :port
22
-
23
- # The maximum time a ping attempt is made.
24
- attr_accessor :timeout
25
-
26
- # If a ping fails, this value is set to the error that occurred which
27
- # caused it to fail.
28
- #
29
- attr_reader :exception
30
-
31
- # This value is set if a ping succeeds, but some other condition arose
32
- # during the ping attempt which merits warning, e.g a redirect in the
33
- # case of Ping::HTTP#ping.
34
- #
35
- attr_reader :warning
36
-
37
- # The number of seconds (returned as a Float) that it took to ping
38
- # the host. This is not a precise value, but rather a good estimate
39
- # since there is a small amount of internal calculation that is added
40
- # to the overall time.
41
- #
42
- attr_reader :duration
43
-
44
- # The default constructor for the Net::Ping class. Accepts an optional
45
- # +host+, +port+ and +timeout+. The port defaults to your echo port, or
46
- # 7 if that happens to be undefined. The default timeout is 5 seconds.
47
- #
48
- # The host, although optional in the constructor, must be specified at
49
- # some point before the Net::Ping#ping method is called, or else an
50
- # ArgumentError will be raised.
51
- #
52
- # Yields +self+ in block context.
53
- #
54
- # This class is not meant to be instantiated directly. It is strictly
55
- # meant as an interface for subclasses.
56
- #
57
- def initialize(host=nil, port=nil, timeout=5)
58
- @host = host
59
- @port = port || Socket.getservbyname('echo') || 7
60
- @timeout = timeout
61
- @exception = nil
62
- @warning = nil
63
- @duration = nil
64
-
65
- yield self if block_given?
66
- end
67
-
68
- # The default interface for the Net::Ping#ping method. Each subclass
69
- # should call super() before continuing with their own implementation in
70
- # order to ensure that the @exception and @warning instance variables
71
- # are reset.
72
- #
73
- # If +host+ is nil here, then it will use the host specified in the
74
- # constructor. If the +host+ is nil and there was no host specified
75
- # in the constructor then an ArgumentError is raised.
76
- #--
77
- # The @duration should be set in the subclass' ping method.
78
- #
79
- def ping(host = @host)
80
- raise ArgumentError, 'no host specified' unless host
81
- @exception = nil
82
- @warning = nil
83
- @duration = nil
84
- end
85
-
86
- alias ping? ping
87
- alias pingecho ping
88
- end
89
- end
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ # The Net module serves as a namespace only.
5
+ #
6
+ module Net
7
+
8
+ # The Ping class serves as an abstract base class for all other Ping class
9
+ # types. You should not instantiate this class directly.
10
+ #
11
+ class Ping
12
+ # The version of the net-ping library.
13
+ VERSION = '1.7.3'
14
+
15
+ # The host to ping. In the case of Ping::HTTP, this is the URI.
16
+ attr_accessor :host
17
+
18
+ # The port to ping. This is set to the echo port (7) by default. The
19
+ # Ping::HTTP class defaults to port 80.
20
+ #
21
+ attr_accessor :port
22
+
23
+ # The maximum time a ping attempt is made.
24
+ attr_accessor :timeout
25
+
26
+ # If a ping fails, this value is set to the error that occurred which
27
+ # caused it to fail.
28
+ #
29
+ attr_reader :exception
30
+
31
+ # This value is set if a ping succeeds, but some other condition arose
32
+ # during the ping attempt which merits warning, e.g a redirect in the
33
+ # case of Ping::HTTP#ping.
34
+ #
35
+ attr_reader :warning
36
+
37
+ # The number of seconds (returned as a Float) that it took to ping
38
+ # the host. This is not a precise value, but rather a good estimate
39
+ # since there is a small amount of internal calculation that is added
40
+ # to the overall time.
41
+ #
42
+ attr_reader :duration
43
+
44
+ # The default constructor for the Net::Ping class. Accepts an optional
45
+ # +host+, +port+ and +timeout+. The port defaults to your echo port, or
46
+ # 7 if that happens to be undefined. The default timeout is 5 seconds.
47
+ #
48
+ # The host, although optional in the constructor, must be specified at
49
+ # some point before the Net::Ping#ping method is called, or else an
50
+ # ArgumentError will be raised.
51
+ #
52
+ # Yields +self+ in block context.
53
+ #
54
+ # This class is not meant to be instantiated directly. It is strictly
55
+ # meant as an interface for subclasses.
56
+ #
57
+ def initialize(host=nil, port=nil, timeout=5)
58
+ @host = host
59
+ @port = port || Socket.getservbyname('echo') || 7
60
+ @timeout = timeout
61
+ @exception = nil
62
+ @warning = nil
63
+ @duration = nil
64
+
65
+ yield self if block_given?
66
+ end
67
+
68
+ # The default interface for the Net::Ping#ping method. Each subclass
69
+ # should call super() before continuing with their own implementation in
70
+ # order to ensure that the @exception and @warning instance variables
71
+ # are reset.
72
+ #
73
+ # If +host+ is nil here, then it will use the host specified in the
74
+ # constructor. If the +host+ is nil and there was no host specified
75
+ # in the constructor then an ArgumentError is raised.
76
+ #--
77
+ # The @duration should be set in the subclass' ping method.
78
+ #
79
+ def ping(host = @host)
80
+ raise ArgumentError, 'no host specified' unless host
81
+ @exception = nil
82
+ @warning = nil
83
+ @duration = nil
84
+ end
85
+
86
+ alias ping? ping
87
+ alias pingecho ping
88
+ end
89
+ end