class Net::SSH::Transport::Session

SSH session via Net::SSH.start.
but will instead be created for you automatically when you create a new
never be instantiated directly (unless you really know what you’re about),
implements basic message exchanging and protocol initialization. It will
The transport layer represents the lowest level of the SSH protocol, and

def close

Cleans up (see PacketStream#cleanup) and closes the underlying socket.
def close
  socket.cleanup
  socket.close
end

def closed?

Returns true if the underlying socket has been closed.
def closed?
  socket.closed?
end

def configure_client(options = {})

hmac algorithms to use when sending packets to the server.
options. This is typically used to define the cipher, compression, and
Configure's the packet stream's client state with the given set of
def configure_client(options = {})
  socket.client.set(options)
end

def configure_server(options = {})

hmac algorithms to use when reading packets from the server.
options. This is typically used to define the cipher, compression, and
Configure's the packet stream's server state with the given set of
def configure_server(options = {})
  socket.server.set(options)
end

def enqueue_message(message)

opportunity. This does not block, but returns immediately.
Enqueues the given message, such that it will be sent at the earliest
def enqueue_message(message)
  socket.enqueue_packet(message)
end

def hint(which, value = true)

to change its behavior. (See PacketStream#hints).
Sets a new hint for the packet stream, which the packet stream may use
def hint(which, value = true)
  socket.hints[which] = value
end

def host_as_string

SSH known-host files.
Returns the host (and possibly IP address) in a format compatible with
def host_as_string
  @host_as_string ||= begin
    string = "#{host}"
    string = "[#{string}]:#{port}" if port != DEFAULT_PORT
    peer_ip = socket.peer_ip
    if peer_ip != Net::SSH::Transport::PacketStream::PROXY_COMMAND_HOST_IP &&
       peer_ip != host
      string2 = peer_ip
      string2 = "[#{string2}]:#{port}" if port != DEFAULT_PORT
      string << "," << string2
    end
    string
  end
end

def host_keys

def host_keys
  @host_keys ||= begin
    known_hosts = options.fetch(:known_hosts, KnownHosts)
    known_hosts.search_for(options[:host_key_alias] || host_as_string, options)
  end
end

def initialize(host, options = {})

transport session.
the initial key exchange completes, leaving you with a ready-to-use
Instantiates a new transport layer abstraction. This will block until
def initialize(host, options = {})
  self.logger = options[:logger]
  @host = host
  @port = options[:port] || DEFAULT_PORT
  @bind_address = options[:bind_address] || nil
  @options = options
  @socket =
    if (factory = options[:proxy])
      debug { "establishing connection to #{@host}:#{@port} through proxy" }
      factory.open(@host, @port, options)
    else
      debug { "establishing connection to #{@host}:#{@port}" }
      Socket.tcp(@host, @port, @bind_address, nil,
                 connect_timeout: options[:timeout])
    end
  @socket.extend(PacketStream)
  @socket.logger = @logger
  debug { "connection established" }
  @queue = []
  @host_key_verifier = select_host_key_verifier(options[:verify_host_key])
  @server_version = ServerVersion.new(socket, logger, options[:timeout])
  @algorithms = Algorithms.new(self, options)
  @algorithms.start
  wait { algorithms.initialized? }
rescue Errno::ETIMEDOUT
  raise Net::SSH::ConnectionTimeout
end

def next_message

packet. See #poll_message.
Blocks until a new packet is available to be read, and returns that
def next_message
  poll_message(:block)
end

def peer

including :ip, :port, :host, and :canonized (see #host_as_string).
Returns a hash of information about the peer (remote) side of the socket,
def peer
  @peer ||= { ip: socket.peer_ip, port: @port.to_i, host: @host, canonized: host_as_string }
end

def poll_message(mode = :nonblock, consume_queue = true)

read from the queue before the socket is queried.
is not in process, and consume_queue is true, packets will be first
received, it will be enqueued and otherwise ignored. When a key-exchange
If a key-exchange is in process and a disallowed packet type is

be returned.
DEBUG, and KEXINIT) are handled silently by this method, and will never
available. Note that some packet types (DISCONNECT, IGNORE, UNIMPLEMENTED,
waiting to be read. Otherwise, this will block until a packet is
default), this will not block and will return nil if there are no packets
Tries to read the next packet from the socket. If mode is :nonblock (the
def poll_message(mode = :nonblock, consume_queue = true)
  loop do
    return @queue.shift if consume_queue && @queue.any? && algorithms.allow?(@queue.first)
    packet = socket.next_packet(mode, options[:timeout])
    return nil if packet.nil?
    case packet.type
    when DISCONNECT
      raise Net::SSH::Disconnect, "disconnected: #{packet[:description]} (#{packet[:reason_code]})"
    when IGNORE
      debug { "IGNORE packet received: #{packet[:data].inspect}" }
    when UNIMPLEMENTED
      lwarn { "UNIMPLEMENTED: #{packet[:number]}" }
    when DEBUG
      send(packet[:always_display] ? :fatal : :debug) { packet[:message] }
    when KEXINIT
      algorithms.accept_kexinit(packet)
    else
      return packet if algorithms.allow?(packet)
      push(packet)
    end
  end
end

def push(packet)

were received.
#poll_message will return packets from the queue in the order they
Adds the given packet to the packet queue. If the queue is non-empty,
def push(packet)
  @queue.push(packet)
end

def rekey!

effect.
If a rekey is already pending, this returns immediately, having no
Requests a rekey operation, and blocks until the operation completes.
def rekey!
  if !algorithms.pending?
    algorithms.rekey!
    wait { algorithms.initialized? }
  end
end

def rekey_as_needed

one is performed, causing this method to block until it completes.
rekey is needed (as indicated by the socket, see PacketStream#if_needs_rekey?)
Returns immediately if a rekey is already in process. Otherwise, if a
def rekey_as_needed
  return if algorithms.pending?
  socket.if_needs_rekey? { rekey! }
end

def select_host_key_verifier(verifier)

[#595](https://github.com/net-ssh/net-ssh/pull/595)
Values false, true, and :very were deprecated in

it is returned directly. Otherwise, an exception is raised.
If the argument happens to respond to :verify and :verify_signature,

- :always (secure)
- :accept_new (insecure)
- :accept_new_or_local_tunnel (insecure)
- :never (very insecure)

a verifier, like `::Net::SSH::Verifiers::Never`.
Usually, the argument is a symbol like `:never` which corresponds to

the parameter.
Instantiates a new host-key verification class, based on the value of
def select_host_key_verifier(verifier)
  case verifier
  when false
    Kernel.warn('verify_host_key: false is deprecated, use :never')
    Net::SSH::Verifiers::Never.new
  when :never then
    Net::SSH::Verifiers::Never.new
  when true
    Kernel.warn('verify_host_key: true is deprecated, use :accept_new_or_local_tunnel')
    Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
  when :accept_new_or_local_tunnel, nil then
    Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
  when :very
    Kernel.warn('verify_host_key: :very is deprecated, use :accept_new')
    Net::SSH::Verifiers::AcceptNew.new
  when :accept_new then
    Net::SSH::Verifiers::AcceptNew.new
  when :secure then
    Kernel.warn('verify_host_key: :secure is deprecated, use :always')
    Net::SSH::Verifiers::Always.new
  when :always then
    Net::SSH::Verifiers::Always.new
  else
    if verifier.respond_to?(:verify)
      if verifier.respond_to?(:verify_signature)
        verifier
      else
        Kernel.warn("Warning: verifier without :verify_signature is deprecated")
        CompatibleVerifier.new(verifier)
      end
    else
      raise(
        ArgumentError,
        "Invalid argument to :verify_host_key (or deprecated " \
        ":paranoid): #{verifier.inspect}"
      )
    end
  end
end

def send_message(message)

entire message has been sent.
Sends the given message via the packet stream, blocking until the
def send_message(message)
  socket.send_packet(message)
end

def service_request(service)

for sending to the server.
Returns a new service_request packet for the given service name, ready
def service_request(service)
  Net::SSH::Buffer.from(:byte, SERVICE_REQUEST, :string, service)
end

def shutdown!

underlying protocol's state).
when the connection needs to close but you don't know the status of the
never be done, but it might be necessary (in a rescue clause, for instance,
Performs a "hard" shutdown of the connection. In general, this should
def shutdown!
  error { "forcing connection closed" }
  socket.close
end

def wait

packets read are enqueued (see #push).
this just waits long enough to see if there are any pending packets. Any
Waits (blocks) until the given block returns true. If no block is given,
def wait
  loop do
    break if block_given? && yield
    message = poll_message(:nonblock, false)
    push(message) if message
    break if !block_given?
  end
end