Class: CemAcpt::LocalPortAllocator

Inherits:
Object
  • Object
show all
Defined in:
lib/cem_acpt/shared_objects.rb

Overview

Handles local port allocation for things like local SSH tunnels. This class is thread-safe as the port range is a Concurrent::Array, which blocks when modified. When this class is initialized, it's total assignable ports are set to all ports in the ephemeral port range. When a port is allocated, it's removed from the port range.

Constant Summary collapse

EPHEMERAL_PORT_RANGE =
(49_152..65_535).to_a.freeze

Instance Method Summary collapse

Constructor Details

#initializeLocalPortAllocator

Returns a new instance of LocalPortAllocator.



489
490
491
# File 'lib/cem_acpt/shared_objects.rb', line 489

def initialize
  @port_range = Concurrent::Array.new(EPHEMERAL_PORT_RANGE.dup).shuffle!
end

Instance Method Details

#allocate(number_of_ports = 1) ⇒ Integer+

Returns an open port(s) in the ephemeral port range on the local machine. If 'number_of_ports' is specified and greater than one, returns an array of ports. If 'number_of_ports' is not specified or is one, returns a single port.

Parameters:

  • number_of_ports (Integer) (defaults to: 1)

    the number of ports to allocate

Returns:

  • (Integer, Array<Integer>)

    the port(s) allocated

Raises:

  • (ArgumentError)

    if number_of_ports is not an Integer or is less than one

  • (LocalPortAllocationError)

    if there are no ports available



500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
# File 'lib/cem_acpt/shared_objects.rb', line 500

def allocate(number_of_ports = 1)
  unless number_of_ports.is_a?(Integer) && number_of_ports.positive?
    raise ArgumentError, 'number_of_ports must be a positive integer'
  end
  raise LocalPortAllocationError, 'No ports available' if @port_range.empty?

  ports = []
  while ports.length < number_of_ports
    port = @port_range.pop
    next unless local_port_open?(port)

    ports << port
  end
  if ports.length == 1
    ports[0]
  else
    ports
  end
end