class Bones::RPC::Address

Encapsulates behaviour around addresses and resolving dns.

@since 0.0.1

Attributes

host[R]

@!attribute host

@return [ String ] The host name.

@!attribute ip

@return [ String ] The ip address.

@!attribute original

@return [ String ] The original host name.

@!attribute port

@return [ Integer ] The port.

@!attribute resolved

@return [ String ] The full resolved address.
ip[R]

@!attribute host

@return [ String ] The host name.

@!attribute ip

@return [ String ] The ip address.

@!attribute original

@return [ String ] The original host name.

@!attribute port

@return [ Integer ] The port.

@!attribute resolved

@return [ String ] The full resolved address.
original[R]

@!attribute host

@return [ String ] The host name.

@!attribute ip

@return [ String ] The ip address.

@!attribute original

@return [ String ] The original host name.

@!attribute port

@return [ Integer ] The port.

@!attribute resolved

@return [ String ] The full resolved address.
path[R]

@!attribute host

@return [ String ] The host name.

@!attribute ip

@return [ String ] The ip address.

@!attribute original

@return [ String ] The original host name.

@!attribute port

@return [ Integer ] The port.

@!attribute resolved

@return [ String ] The full resolved address.
port[R]

@!attribute host

@return [ String ] The host name.

@!attribute ip

@return [ String ] The ip address.

@!attribute original

@return [ String ] The original host name.

@!attribute port

@return [ Integer ] The port.

@!attribute resolved

@return [ String ] The full resolved address.

Public Class Methods

new(address, port = nil) click to toggle source

Instantiate the new address.

@example Instantiate the address.

Bones::RPC::Address.new("localhost:27017")

@param [ String ] address The host:port pair as a string.

@since 0.0.1

# File lib/bones/rpc/address.rb, line 32
def initialize(address, port = nil)
  if address.is_a?(Bones::RPC::Address)
    @host     = address.host
    @ip       = address.ip
    @original = address.original
    @port     = address.port
    @path     = address.path
    return
  end

  if port.nil?
    @original = address
  else
    @original = "#{address}:#{port}"
  end
end

Public Instance Methods

connectable?()
Alias for: valid?
inspect() click to toggle source
# File lib/bones/rpc/address.rb, line 49
def inspect
  "<#{self.class} \"#{to_s}\">"
end
ipv4?() click to toggle source
# File lib/bones/rpc/address.rb, line 53
def ipv4?
  ip.is_a?(Resolv::IPv4)
end
ipv6?() click to toggle source
# File lib/bones/rpc/address.rb, line 57
def ipv6?
  ip.is_a?(Resolv::IPv6)
end
resolve(node) click to toggle source

Resolve the address for the provided node. If the address cannot be resolved the node will be flagged as down.

@example Resolve the address.

address.resolve(node)

@param [ Node ] node The node to resolve for.

@return [ String ] The resolved address.

@since 0.0.1

# File lib/bones/rpc/address.rb, line 103
def resolve(node)
  begin
    resolve! unless valid?
    valid?
  rescue Resolv::ResolvError, SocketError => e
    node.instrument(Node::WARN, prefix: "  BONES-RPC:", message: "Could not resolve IP or UNIX path for: #{original}")
    node.down and false
  end
end
resolve!() click to toggle source
# File lib/bones/rpc/address.rb, line 113
def resolve!
  address = @original

  host = nil
  path = nil

  if address.is_a?(String) && port.nil?
    if !!(address =~ /\Aunix:/) # UNIX
      path = address.gsub(/\Aunix:/, '')
    elsif !!(address =~ /\A\[.+\]\:\d+\z/) # IPv6
      host, port = address.split(']:')
      host.gsub!(/\A\[/, '')
    else # IPv4 (hopefully)
      host, port = address.split(':')
    end
  end

  if path
    # Ensure path is valid
    @path = ::Socket.unpack_sockaddr_un(::Socket.pack_sockaddr_un(path))
    return
  elsif port.nil?
    raise ArgumentError, "wrong number of arguments (1 for 2)"
  else
    @host = host || address
    @port = port.to_i
  end

  # Is it an IPv4 address?
  if !!(Resolv::IPv4::Regex =~ @host)
    @ip = Resolv::IPv4.create(@host)
  end

  # Guess it's not IPv4! Is it IPv6?
  unless @ip
    if !!(Resolv::IPv6::Regex =~ @host)
      @original = "[#{@host}]:#{@port}"
      @ip = Resolv::IPv6.create(@host)
    end
  end

  # Guess it's not an IP address, so let's try DNS
  unless @ip
    addrs = Array(::Bones::RPC::DNSResolver.new.resolve(@host))
    raise Resolv::ResolvError, "DNS result has no information for #{@host}" if addrs.empty?

    # Pseudorandom round-robin DNS support :/
    @ip = addrs[rand(addrs.size)]
  end

  if !valid_ip?
    raise ArgumentError, "unsupported address class: #{@ip.class}"
  end
end
resolved() click to toggle source
# File lib/bones/rpc/address.rb, line 61
def resolved
  if valid?
    if unix?
      "unix:#{path}"
    else
      host_string = ipv6? ? "[#{ip}]" : ip.to_s
      [host_string, port].join(':')
    end
  else
    original
  end
end
Also aliased as: to_s
to_s()
Alias for: resolved
unix?() click to toggle source
# File lib/bones/rpc/address.rb, line 75
def unix?
  path.is_a?(String)
end
valid?() click to toggle source
# File lib/bones/rpc/address.rb, line 79
def valid?
  unix? or (valid_ip? and valid_port?)
end
Also aliased as: connectable?
valid_ip?() click to toggle source
# File lib/bones/rpc/address.rb, line 84
def valid_ip?
  ipv4? or ipv6?
end
valid_port?() click to toggle source
# File lib/bones/rpc/address.rb, line 88
def valid_port?
  !port.nil? && port != 0
end