120 lines
3.2 KiB
Ruby
120 lines
3.2 KiB
Ruby
|
require File.join(File.dirname(__FILE__), 'ping')
|
||
|
|
||
|
# The Net module serves as a namespace only.
|
||
|
module Net
|
||
|
|
||
|
# The Ping::UDP class encapsulates methods for UDP pings.
|
||
|
class Ping::UDP < Ping
|
||
|
@@service_check = true
|
||
|
|
||
|
# Returns whether or not the connect behavior should enforce remote
|
||
|
# service availability as well as reachability. The default is true.
|
||
|
#
|
||
|
def self.service_check
|
||
|
@@service_check
|
||
|
end
|
||
|
|
||
|
# Set whether or not the connect behavior should enforce remote
|
||
|
# service availability as well as reachability. If set to false
|
||
|
# then Errno::ECONNREFUSED or Errno::ECONNRESET will be considered
|
||
|
# a successful ping, meaning no actual data handshaking is required.
|
||
|
# By default, if either of those errors occurs it is considered a failed
|
||
|
# ping.
|
||
|
#
|
||
|
def self.service_check=(bool)
|
||
|
unless bool.kind_of?(TrueClass) || bool.kind_of?(FalseClass)
|
||
|
raise ArgumentError, 'argument must be true or false'
|
||
|
end
|
||
|
@@service_check = bool
|
||
|
end
|
||
|
|
||
|
# The maximum data size that can be sent in a UDP ping.
|
||
|
MAX_DATA = 64
|
||
|
|
||
|
# The data to send to the remote host. By default this is 'ping'.
|
||
|
# This should be MAX_DATA size characters or less.
|
||
|
#
|
||
|
attr_reader :data
|
||
|
|
||
|
# Creates and returns a new Ping::UDP object. This is effectively
|
||
|
# identical to its superclass constructor.
|
||
|
#
|
||
|
def initialize(host=nil, port=nil, timeout=5)
|
||
|
@data = 'ping'
|
||
|
|
||
|
super(host, port, timeout)
|
||
|
|
||
|
@bind_host = nil
|
||
|
@bind_port = nil
|
||
|
end
|
||
|
|
||
|
# Sets the data string sent to the remote host. This value cannot have
|
||
|
# a size greater than MAX_DATA.
|
||
|
#
|
||
|
def data=(string)
|
||
|
if string.size > MAX_DATA
|
||
|
err = "cannot set data string larger than #{MAX_DATA} characters"
|
||
|
raise ArgumentError, err
|
||
|
end
|
||
|
|
||
|
@data = string
|
||
|
end
|
||
|
|
||
|
# Associates the local end of the UDP connection with the given +host+
|
||
|
# and +port+. This is essentially a wrapper for UDPSocket#bind.
|
||
|
#
|
||
|
def bind(host, port)
|
||
|
@bind_host = host
|
||
|
@bind_port = port
|
||
|
end
|
||
|
|
||
|
# Sends a simple text string to the host and checks the return string. If
|
||
|
# the string sent and the string returned are a match then the ping was
|
||
|
# successful and true is returned. Otherwise, false is returned.
|
||
|
#
|
||
|
def ping(host = @host)
|
||
|
super(host)
|
||
|
|
||
|
bool = false
|
||
|
udp = UDPSocket.open
|
||
|
array = []
|
||
|
|
||
|
if @bind_host
|
||
|
udp.bind(@bind_host, @bind_port)
|
||
|
end
|
||
|
|
||
|
start_time = Time.now
|
||
|
|
||
|
begin
|
||
|
Timeout.timeout(@timeout){
|
||
|
udp.connect(host, @port)
|
||
|
udp.send(@data, 0)
|
||
|
array = udp.recvfrom(MAX_DATA)
|
||
|
}
|
||
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET => err
|
||
|
if @@service_check
|
||
|
@exception = err
|
||
|
else
|
||
|
bool = true
|
||
|
end
|
||
|
rescue Exception => err
|
||
|
@exception = err
|
||
|
else
|
||
|
if array[0] == @data
|
||
|
bool = true
|
||
|
end
|
||
|
ensure
|
||
|
udp.close if udp
|
||
|
end
|
||
|
|
||
|
# There is no duration if the ping failed
|
||
|
@duration = Time.now - start_time if bool
|
||
|
|
||
|
bool
|
||
|
end
|
||
|
|
||
|
alias ping? ping
|
||
|
alias pingecho ping
|
||
|
end
|
||
|
end
|