Module: Lich::Main::DetachableClientTarget Private

Defined in:
documented/main/detachable_client_target.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Parses the value of --detachable-client=VALUE (and the --headless alias) into a bind host token and a port, without touching the network. Keyword hosts (tailscale/lan/any) are resolved to concrete addresses later by Lich::Common::BindHostResolver.

Accepted forms: PORT, auto, HOST:PORT, HOST:auto, [IPV6]:PORT

Since:

  • 5.18.0

Defined Under Namespace

Classes: Target

Constant Summary collapse

ParseError =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Raised when the flag value does not match any accepted form.

Since:

  • 5.18.0

Class.new(ArgumentError)
USAGE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 5.18.0

'--detachable-client requires PORT, auto, or HOST:PORT ' \
'(HOST may be tailscale, lan, any, an IP address, or a hostname)'

Class Method Summary collapse

Class Method Details

.parse(value) ⇒ Target

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parses a flag value into a Target.

Parameters:

  • value (String)

    text after the = in --detachable-client=VALUE

Returns:

Raises:

  • (ParseError)

    when the value matches no accepted form

Since:

  • 5.18.0



30
31
32
33
34
35
36
37
38
39
# File 'documented/main/detachable_client_target.rb', line 30

def self.parse(value)
  token = value.to_s.strip
  raise ParseError, USAGE if token.empty?
  return Target.new(host: nil, port: 0) if token.casecmp('auto').zero?
  return Target.new(host: nil, port: parse_port(token)) if token.match?(/\A\d+\z/)

  host, port_token = split_host_port(token)
  port = port_token.casecmp('auto').zero? ? 0 : parse_port(port_token)
  Target.new(host: host, port: port)
end

.parse_port(port_token) ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Converts a port string to an integer and validates it is in the range 0–65535.

Port 0 is accepted and signals that the operating system should assign an available port.

Examples:

parse_port("8080") #=> 8080

Parameters:

  • port_token (String)

    a decimal port number (e.g., "8080", "0")

Returns:

  • (Integer)

    the port number, guaranteed to be in range 0–65535

Raises:

  • (ParseError)

    when the token cannot be parsed as an integer or is outside the valid range

Since:

  • 5.18.0



74
75
76
77
78
79
80
81
82
83
84
# File 'documented/main/detachable_client_target.rb', line 74

def self.parse_port(port_token)
  port = begin
    Integer(port_token, 10)
  rescue ArgumentError, TypeError
    raise ParseError, USAGE
  end
  unless port.between?(0, 65_535)
    raise ParseError, 'detachable client port must be between 0 and 65535 (0 or auto lets the OS choose)'
  end
  port
end

.split_host_port(token) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Splits a HOST:PORT token into its components, handling bracketed IPv6 addresses.

Accepts plain HOST:PORT or [IPV6]:PORT forms. The method does not validate the host or port values—it merely extracts them as strings.

Examples:

Split plain host:port

split_host_port("example.com:8080") #=> ["example.com", "8080"]

Split bracketed IPv6 address

split_host_port("[::1]:9000") #=> ["::1", "9000"]

Parameters:

  • token (String)

    a HOST:PORT or [IPV6]:PORT string

Returns:

  • (Array<String>)

    a two-element array [host, port_token]

Raises:

  • (ParseError)

    when the token does not match either accepted form

Since:

  • 5.18.0



54
55
56
57
58
59
60
61
62
# File 'documented/main/detachable_client_target.rb', line 54

def self.split_host_port(token)
  if (bracketed = token.match(/\A\[([^\]]+)\]:([^:]+)\z/))
    bracketed.captures
  elsif (plain = token.match(/\A([^:]+):([^:]+)\z/))
    plain.captures
  else
    raise ParseError, USAGE
  end
end