Sha256: 2eaced60b0f576d09a43b856d12f0bc16ef1b36bb45fec466d81e1794590f442

Contents?: true

Size: 1.66 KB

Versions: 1

Compression:

Stored size: 1.66 KB

Contents

require "net/empty_port/version"
require "socket"

module Net
  module EmptyPort
    class << self
      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

      def used?(port, proto = :tcp)
        if proto == :udp
          udp_used?(port)
        else
          tcp_used?(port)
        end
      end

      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

      def valid_port?(port)
        num = Integer(port)
        if (num < 49152 or num > 65535)
          false
        else
          true
        end
      rescue
        false
      end

      def random_port
        50000 + (rand * 1000).to_i
      end

      def tcp_used?(port)
        TCPSocket.new('127.0.0.1', port).close
        true
      rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
        false
      end

      def udp_used?(port)
        s = UDPSocket.new()
        s.bind('127.0.0.1', port)
        s.close
        false
      rescue Errno::EADDRINUSE, Errno::EACCES
        true
      end

      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
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
net-empty_port-0.0.2 lib/net/empty_port.rb