IsPortOpen utility

This commit is contained in:
Mitchell Hashimoto 2012-03-23 10:26:29 -04:00
parent 3877b71983
commit d08a65e7f7
2 changed files with 91 additions and 0 deletions

View File

@ -0,0 +1,38 @@
require "socket"
require "timeout"
module Vagrant
module Util
# Contains the method {#is_ruby_open?} to check if a port is open
# (listening) or closed (not in use). This method isn't completely
# fool-proof, but it works enough of the time to be useful.
module IsPortOpen
# Checks if a port is open (listening) on a given host and port.
#
# @param [String] host Hostname or IP address.
# @param [Integer] port Port to check.
# @return [Boolean] `true` if the port is open (listening), `false`
# otherwise.
def is_port_open?(host, port)
# We wrap this in a timeout because once in awhile the TCPSocket
# _will_ hang, but this signals that the port is closed.
Timeout.timeout(1) do
# Attempt to make a connection
s = TCPSocket.new(host, port)
# A connection was made! Properly clean up the socket, not caring
# at all if any exception is raised, because we already know the
# result.
s.close rescue nil
# The port is open if we reached this point, since we were able
# to connect.
return true
end
rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
# Any of the above exceptions signal that the port is closed.
return false
end
end
end
end

View File

@ -0,0 +1,53 @@
require File.expand_path("../../../base", __FILE__)
require "socket"
require "vagrant/util/is_port_open"
describe Vagrant::Util::IsPortOpen do
let(:klass) do
Class.new do
extend Vagrant::Util::IsPortOpen
end
end
let(:open_port) { 52811 }
let(:closed_port) { 52811 }
it "should report open ports" do
# Start a thread which listens on a port
thr = Thread.new do
server = TCPServer.new(open_port)
Thread.current[:running] = true
# Wait until we're told to die
Thread.current[:die] = false
while !Thread.current[:die]
Thread.pass
end
# Die!
server.close
end
# Wait until the server is running
while !thr[:running]
Thread.pass
end
# Verify that we report the port is open
klass.is_port_open?("localhost", open_port).should be
# Kill the thread
thr[:die] = true
thr.join
end
it "should report closed ports" do
# This CAN fail, since port 52811 might actually be in use, but I'm
# not sure what to do except choose some random port and hope for the
# best, really.
klass.is_port_open?("localhost", closed_port).should_not be
end
end