net-ping 1.6.2-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
1
+ require 'ffi'
2
+
3
+ module Windows
4
+ extend FFI::Library
5
+ ffi_lib :kernel32
6
+
7
+ attach_function :GetVersion, [], :ulong
8
+
9
+ def version
10
+ version = GetVersion()
11
+ major = LOBYTE(LOWORD(version))
12
+ minor = HIBYTE(LOWORD(version))
13
+ eval("Float(#{major}.#{minor})")
14
+ end
15
+
16
+ private
17
+
18
+ class << self
19
+ def LOWORD(l)
20
+ l & 0xffff
21
+ end
22
+
23
+ def LOBYTE(w)
24
+ w & 0xff
25
+ end
26
+
27
+ def HIBYTE(w)
28
+ w >> 8
29
+ end
30
+ end
31
+
32
+ module_function :version
33
+ end
@@ -0,0 +1,159 @@
1
+ require File.join(File.dirname(__FILE__), 'ping')
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'uri'
5
+ require 'open-uri'
6
+
7
+ # Force non-blocking Socket.getaddrinfo on Unix systems. Do not use on
8
+ # Windows because it (ironically) causes blocking problems.
9
+ unless File::ALT_SEPARATOR or RUBY_VERSION >= "1.9.3"
10
+ require 'resolv-replace'
11
+ end
12
+
13
+ # The Net module serves as a namespace only.
14
+ module Net
15
+
16
+ # The Ping::HTTP class encapsulates methods for HTTP pings.
17
+ class Ping::HTTP < Ping
18
+
19
+ # By default an http ping will follow a redirect and give you the result
20
+ # of the final URI. If this value is set to false, then it will not
21
+ # follow a redirect and will return false immediately on a redirect.
22
+ #
23
+ attr_accessor :follow_redirect
24
+
25
+ # The maximum number of redirects allowed. The default is 5.
26
+ attr_accessor :redirect_limit
27
+
28
+ # The user agent used for the HTTP request. The default is nil.
29
+ attr_accessor :user_agent
30
+
31
+ # OpenSSL certificate verification mode. The default is VERIFY_NONE.
32
+ attr_accessor :ssl_verify_mode
33
+
34
+ # Use GET request instead HEAD. The default is false.
35
+ attr_accessor :get_request
36
+
37
+ # was this ping proxied?
38
+ attr_accessor :proxied
39
+
40
+ # Creates and returns a new Ping::HTTP object. The default port is the
41
+ # port associated with the URI. The default timeout is 5 seconds.
42
+ #
43
+ def initialize(uri=nil, port=nil, timeout=5)
44
+ @follow_redirect = true
45
+ @redirect_limit = 5
46
+ @ssl_verify_mode = OpenSSL::SSL::VERIFY_NONE
47
+ @get_request = false
48
+
49
+ port ||= URI.parse(uri).port if uri
50
+
51
+ super(uri, port, timeout)
52
+ end
53
+
54
+ # Looks for an HTTP response from the URI passed to the constructor.
55
+ # If the result is a kind of Net::HTTPSuccess then the ping was
56
+ # successful and true is returned. Otherwise, false is returned
57
+ # and the Ping::HTTP#exception method should contain a string
58
+ # indicating what went wrong.
59
+ #
60
+ # If the HTTP#follow_redirect accessor is set to true (which it is
61
+ # by default) and a redirect occurs during the ping, then the
62
+ # HTTP#warning attribute is set to the redirect message, but the
63
+ # return result is still true. If it's set to false then a redirect
64
+ # response is considered a failed ping.
65
+ #
66
+ # If no file or path is specified in the URI, then '/' is assumed.
67
+ # If no scheme is present in the URI, then 'http' is assumed.
68
+ #
69
+ def ping(host = @host)
70
+ super(host)
71
+ bool = false
72
+
73
+ # See https://bugs.ruby-lang.org/issues/8645
74
+ host = "http://#{host}" unless host.include?("http")
75
+
76
+ uri = URI.parse(host)
77
+
78
+ start_time = Time.now
79
+
80
+ response = do_ping(uri)
81
+
82
+ if response.is_a?(Net::HTTPSuccess)
83
+ bool = true
84
+ elsif redirect?(response) # Check code, HTTPRedirection does not always work
85
+ if @follow_redirect
86
+ @warning = response.message
87
+ rlimit = 0
88
+
89
+ while redirect?(response)
90
+ if rlimit >= redirect_limit
91
+ @exception = "Redirect limit exceeded"
92
+ break
93
+ end
94
+ redirect = URI.parse(response['location'])
95
+ redirect = uri + redirect if redirect.relative?
96
+ response = do_ping(redirect)
97
+ rlimit += 1
98
+ end
99
+
100
+ if response.is_a?(Net::HTTPSuccess)
101
+ bool = true
102
+ else
103
+ @warning = nil
104
+ @exception ||= response.message
105
+ end
106
+
107
+ else
108
+ @exception = response.message
109
+ end
110
+ end
111
+
112
+ # There is no duration if the ping failed
113
+ @duration = Time.now - start_time if bool
114
+
115
+ bool
116
+ end
117
+
118
+ alias ping? ping
119
+ alias pingecho ping
120
+ alias follow_redirect? follow_redirect
121
+ alias uri host
122
+ alias uri= host=
123
+
124
+ private
125
+
126
+ def redirect?(response)
127
+ response && response.code.to_i >= 300 && response.code.to_i < 400
128
+ end
129
+
130
+ def do_ping(uri)
131
+ response = nil
132
+ proxy = uri.find_proxy || URI.parse("")
133
+ begin
134
+ uri_path = uri.path.empty? ? '/' : uri.path
135
+ headers = { }
136
+ headers["User-Agent"] = user_agent unless user_agent.nil?
137
+ Timeout.timeout(@timeout) do
138
+ http = Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password).new(uri.host, uri.port)
139
+ @proxied = http.proxy?
140
+ if @get_request == true
141
+ request = Net::HTTP::Get.new(uri_path)
142
+ else
143
+ request = Net::HTTP::Head.new(uri_path)
144
+ end
145
+
146
+ if uri.scheme == 'https'
147
+ http.use_ssl = true
148
+ http.verify_mode = @ssl_verify_mode
149
+ end
150
+
151
+ response = http.start { |h| h.request(request) }
152
+ end
153
+ rescue Exception => err
154
+ @exception = err.message
155
+ end
156
+ response
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,179 @@
1
+ require File.join(File.dirname(__FILE__), 'ping')
2
+
3
+ if File::ALT_SEPARATOR
4
+ require 'win32/security'
5
+ require File.join(File.dirname(__FILE__), 'helper')
6
+ end
7
+
8
+ # The Net module serves as a namespace only.
9
+ module Net
10
+
11
+ # The Net::Ping::ICMP class encapsulates an icmp ping.
12
+ class Ping::ICMP < Ping
13
+ ICMP_ECHOREPLY = 0 # Echo reply
14
+ ICMP_ECHO = 8 # Echo request
15
+ ICMP_SUBCODE = 0
16
+
17
+ # You cannot set or change the port value. A value of 0 is always
18
+ # used internally for ICMP pings.
19
+ #
20
+ undef_method :port=
21
+
22
+ # Returns the data size, i.e. number of bytes sent on the ping. The
23
+ # default size is 56.
24
+ #
25
+ attr_reader :data_size
26
+
27
+ # Creates and returns a new Ping::ICMP object. This is similar to its
28
+ # superclass constructor, but must be created with root privileges (on
29
+ # UNIX systems), and the port value is ignored.
30
+ #
31
+ def initialize(host=nil, port=nil, timeout=5)
32
+ raise 'requires root privileges' if Process.euid > 0
33
+
34
+ if File::ALT_SEPARATOR && Windows.version >= 6
35
+ unless Win32::Security.elevated_security?
36
+ raise 'requires elevated security'
37
+ end
38
+ end
39
+
40
+ @seq = 0
41
+ @bind_port = 0
42
+ @bind_host = nil
43
+ @data_size = 56
44
+ @data = ''
45
+
46
+ 0.upto(@data_size){ |n| @data << (n % 256).chr }
47
+
48
+ @pid = Process.pid & 0xffff
49
+
50
+ super(host, port, timeout)
51
+ @port = nil # This value is not used in ICMP pings.
52
+ end
53
+
54
+ # Sets the number of bytes sent in the ping method.
55
+ #
56
+ def data_size=(size)
57
+ @data_size = size
58
+ @data = ''
59
+ 0.upto(size){ |n| @data << (n % 256).chr }
60
+ end
61
+
62
+ # Associates the local end of the socket connection with the given
63
+ # +host+ and +port+. The default port is 0.
64
+ #
65
+ def bind(host, port = 0)
66
+ @bind_host = host
67
+ @bind_port = port
68
+ end
69
+
70
+ # Pings the +host+ specified in this method or in the constructor. If a
71
+ # host was not specified either here or in the constructor, an
72
+ # ArgumentError is raised.
73
+ #
74
+ def ping(host = @host)
75
+ super(host)
76
+ bool = false
77
+
78
+ socket = Socket.new(
79
+ Socket::PF_INET,
80
+ Socket::SOCK_RAW,
81
+ Socket::IPPROTO_ICMP
82
+ )
83
+
84
+ if @bind_host
85
+ saddr = Socket.pack_sockaddr_in(@bind_port, @bind_host)
86
+ socket.bind(saddr)
87
+ end
88
+
89
+ @seq = (@seq + 1) % 65536
90
+ pstring = 'C2 n3 A' << @data_size.to_s
91
+ timeout = @timeout
92
+
93
+ checksum = 0
94
+ msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
95
+
96
+ checksum = checksum(msg)
97
+ msg = [ICMP_ECHO, ICMP_SUBCODE, checksum, @pid, @seq, @data].pack(pstring)
98
+
99
+ begin
100
+ saddr = Socket.pack_sockaddr_in(0, host)
101
+ rescue Exception
102
+ socket.close unless socket.closed?
103
+ return bool
104
+ end
105
+
106
+ start_time = Time.now
107
+
108
+ socket.send(msg, 0, saddr) # Send the message
109
+
110
+ begin
111
+ Timeout.timeout(@timeout){
112
+ while true
113
+ io_array = select([socket], nil, nil, timeout)
114
+
115
+ if io_array.nil? || io_array[0].empty?
116
+ return false
117
+ end
118
+
119
+ pid = nil
120
+ seq = nil
121
+
122
+ data = socket.recvfrom(1500).first
123
+ type = data[20, 2].unpack('C2').first
124
+
125
+ case type
126
+ when ICMP_ECHOREPLY
127
+ if data.length >= 28
128
+ pid, seq = data[24, 4].unpack('n3')
129
+ end
130
+ else
131
+ if data.length > 56
132
+ pid, seq = data[52, 4].unpack('n3')
133
+ end
134
+ end
135
+
136
+ if pid == @pid && seq == @seq && type == ICMP_ECHOREPLY
137
+ bool = true
138
+ break
139
+ end
140
+ end
141
+ }
142
+ rescue Exception => err
143
+ @exception = err
144
+ ensure
145
+ socket.close if socket
146
+ end
147
+
148
+ # There is no duration if the ping failed
149
+ @duration = Time.now - start_time if bool
150
+
151
+ return bool
152
+ end
153
+
154
+ alias ping? ping
155
+ alias pingecho ping
156
+
157
+ private
158
+
159
+ # Perform a checksum on the message. This is the sum of all the short
160
+ # words and it folds the high order bits into the low order bits.
161
+ #
162
+ def checksum(msg)
163
+ length = msg.length
164
+ num_short = length / 2
165
+ check = 0
166
+
167
+ msg.unpack("n#{num_short}").each do |short|
168
+ check += short
169
+ end
170
+
171
+ if length % 2 > 0
172
+ check += msg[length-1, 1].unpack('C').first << 8
173
+ end
174
+
175
+ check = (check >> 16) + (check & 0xffff)
176
+ return (~((check >> 16) + check) & 0xffff)
177
+ end
178
+ end
179
+ end
@@ -0,0 +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.6.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