diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/net/ssh.rb | 3 | ||||
-rw-r--r-- | lib/net/ssh/connection/keepalive.rb | 47 | ||||
-rw-r--r-- | lib/net/ssh/connection/session.rb | 29 | ||||
-rw-r--r-- | lib/net/ssh/errors.rb | 4 |
4 files changed, 57 insertions, 26 deletions
diff --git a/lib/net/ssh.rb b/lib/net/ssh.rb index d9a1f57..d4eb307 100644 --- a/lib/net/ssh.rb +++ b/lib/net/ssh.rb @@ -63,7 +63,7 @@ module Net VALID_OPTIONS = [ :auth_methods, :bind_address, :compression, :compression_level, :config, :encryption, :forward_agent, :hmac, :host_key, - :keepalive, :keepalive_interval, :kex, :keys, :key_data, + :keepalive, :keepalive_interval, :keepalive_maxcount, :kex, :keys, :key_data, :languages, :logger, :paranoid, :password, :port, :proxy, :rekey_blocks_limit,:rekey_limit, :rekey_packet_limit, :timeout, :verbose, :global_known_hosts_file, :user_known_hosts_file, :host_key_alias, @@ -130,6 +130,7 @@ module Net # the keepalive_interval seconds. Defaults to +false+. # :keepalive_interval => the interval seconds for keepalive. # Defaults to +300+ seconds. + # :keepalive_countmax => the maximun number of keepalive packet miss allowed. # * :kex => the key exchange algorithm (or algorithms) to use # * :keys => an array of file names of private keys to use for publickey # and hostbased authentication diff --git a/lib/net/ssh/connection/keepalive.rb b/lib/net/ssh/connection/keepalive.rb new file mode 100644 index 0000000..6b0daa8 --- /dev/null +++ b/lib/net/ssh/connection/keepalive.rb @@ -0,0 +1,47 @@ +module Net; module SSH; module Connection + +module Keepalive + # Default IO.select timeout threshold + DEFAULT_IO_SELECT_TIMEOUT = 300 + + def initialize_keepalive + @last_keepalive_sent_at = nil + @unresponded_keepalive_count = 0 + end + + def keepalive_enabled? + options[:keepalive] + end + + def keepalive_interval + options[:keepalive_interval] || DEFAULT_IO_SELECT_TIMEOUT + end + + def should_send_keepalive? + return false unless keepalive_enabled? + return true unless @last_keepalive_sent_at + Time.now - @last_keepalive_sent_at >= keepalive_interval + end + + def keepalive_maxcount + (options[:keepalive_maxcount] || 3).to_i + end + + def send_keepalive_as_needed(readers, writers) + return unless readers.nil? && writers.nil? + return unless should_send_keepalive? + info { "sending keepalive #{@unresponded_keepalive_count}" } + + @unresponded_keepalive_count += 1 + send_global_request("keepalive@openssh.com") { |success, response| + @unresponded_keepalive_count = 0 + } + if keepalive_maxcount > 0 && @unresponded_keepalive_count > keepalive_maxcount + error { "Timeout, server #{host} not responding. Missed #{@unresponded_keepalive_count} timeouts." } + raise Net::SSH::Timeout, "Timeout, server #{host} not responding." + end + @last_keepalive_sent_at = Time.now + end +end + +end; end; end
\ No newline at end of file diff --git a/lib/net/ssh/connection/session.rb b/lib/net/ssh/connection/session.rb index 9be74e8..3137514 100644 --- a/lib/net/ssh/connection/session.rb +++ b/lib/net/ssh/connection/session.rb @@ -3,6 +3,7 @@ require 'net/ssh/ruby_compat' require 'net/ssh/connection/channel' require 'net/ssh/connection/constants' require 'net/ssh/service/forward' +require 'net/ssh/connection/keepalive' module Net; module SSH; module Connection @@ -23,10 +24,7 @@ module Net; module SSH; module Connection # ssh.exec! "/etc/init.d/some_process start" # end class Session - include Constants, Loggable - - # Default IO.select timeout threshold - DEFAULT_IO_SELECT_TIMEOUT = 300 + include Constants, Loggable, Keepalive # The underlying transport layer abstraction (see Net::SSH::Transport::Session). attr_reader :transport @@ -79,7 +77,7 @@ module Net; module SSH; module Connection @max_pkt_size = (options.has_key?(:max_pkt_size) ? options[:max_pkt_size] : 0x8000) @max_win_size = (options.has_key?(:max_win_size) ? options[:max_win_size] : 0x20000) - @last_keepalive_sent_at = nil + initialize_keepalive end # Retrieves a custom property from this instance. This can be used to @@ -598,29 +596,10 @@ module Net; module SSH; module Connection def io_select_wait(wait) return wait if wait - return wait unless options[:keepalive] + return wait unless keepalive_enabled? keepalive_interval end - def keepalive_interval - options[:keepalive_interval] || DEFAULT_IO_SELECT_TIMEOUT - end - - def should_send_keepalive? - return false unless options[:keepalive] - return true unless @last_keepalive_sent_at - Time.now - @last_keepalive_sent_at >= keepalive_interval - end - - def send_keepalive_as_needed(readers, writers) - return unless readers.nil? && writers.nil? - return unless should_send_keepalive? - info { "sending keepalive" } - msg = Net::SSH::Buffer.from(:byte, Packet::IGNORE, :string, "keepalive") - send_message(msg) - @last_keepalive_sent_at = Time.now - end - MAP = Constants.constants.inject({}) do |memo, name| value = const_get(name) next unless Integer === value diff --git a/lib/net/ssh/errors.rb b/lib/net/ssh/errors.rb index 8f5a136..910c961 100644 --- a/lib/net/ssh/errors.rb +++ b/lib/net/ssh/errors.rb @@ -14,6 +14,10 @@ module Net; module SSH # unexpectedly. class Disconnect < Exception; end + # This exception is raised when the remote host has disconnected/ + # timeouted unexpectedly. + class Timeout < Disconnect; end + # This exception is primarily used internally, but if you have a channel # request handler (see Net::SSH::Connection::Channel#on_request) that you # want to fail in such a way that the server knows it failed, you can |