module Net::EmptyPort

Constants

VERSION

Public Class Methods

empty_port(port = 0, proto = :tcp) click to toggle source
# File lib/net/empty_port.rb, line 7
def empty_port(port = 0, proto = :tcp)
  port  = random_port unless valid_port?(port)

  while (port += 1) < 60000
    next if (proto == :tcp and used?(port))

    begin
      TCPServer.new('127.0.0.1', port).close
      return port
    rescue Errno::EADDRINUSE, Errno::EACCES
    end
  end
end
used?(port, proto = :tcp) click to toggle source
# File lib/net/empty_port.rb, line 21
def used?(port, proto = :tcp)
  if proto == :udp
    udp_used?(port)
  else
    tcp_used?(port)
  end
end
wait(port, max_wait, proto = :tcp) click to toggle source
# File lib/net/empty_port.rb, line 29
def wait(port, max_wait, proto = :tcp)
  waiter = make_waiter(max_wait)
  while waiter.call
    return true if used?(port, proto)
  end
  return false
end

Private Class Methods

make_waiter(max_wait) click to toggle source
# File lib/net/empty_port.rb, line 70
def make_waiter(max_wait)
  waited = 0
  interval = 0.001
  Proc.new {
    next false if waited > max_wait
    sleep interval
    waited += interval
    interval *= 2
    next true
  }
end
random_port() click to toggle source
# File lib/net/empty_port.rb, line 50
def random_port
  50000 + (rand * 1000).to_i
end
tcp_used?(port) click to toggle source
# File lib/net/empty_port.rb, line 54
def tcp_used?(port)
  TCPSocket.new('127.0.0.1', port).close
  true
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
  false
end
udp_used?(port) click to toggle source
# File lib/net/empty_port.rb, line 61
def udp_used?(port)
  s = UDPSocket.new()
  s.bind('127.0.0.1', port)
  s.close
  false
rescue Errno::EADDRINUSE, Errno::EACCES
  true
end
valid_port?(port) click to toggle source
# File lib/net/empty_port.rb, line 39
def valid_port?(port)
  num = Integer(port)
  if (num < 49152 or num > 65535)
    false
  else
    true
  end
rescue
  false
end