From f09d124a2b4cbf6e03549f1bb32cace57601738c Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Sat, 31 Jan 2009 22:08:47 -0700 Subject: [PATCH] Ignore requests for non-existent channels This works around a bug in some ssh servers, where channel requests are sent to channels after the channels have been closed. --- CHANGELOG.rdoc | 2 ++ lib/net/ssh/connection/session.rb | 12 +++++++++++- test/connection/test_session.rb | 7 ++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index a78ad4b7f..9f208dde0 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,5 +1,7 @@ === unreleased +* Ignore requests for non-existent channels (workaround ssh server bug) [Jamis Buck] + * Add terminate! method for hard shutdown scenarios [Jamis Buck] * Revert to pre-2.0.7 key-loading behavior by default, but load private-key if public-key doesn't exist [Jamis Buck] diff --git a/lib/net/ssh/connection/session.rb b/lib/net/ssh/connection/session.rb index eb9b25983..4dd32f734 100644 --- a/lib/net/ssh/connection/session.rb +++ b/lib/net/ssh/connection/session.rb @@ -46,6 +46,16 @@ class Session # The list of callbacks for pending requests. See #send_global_request. attr_reader :pending_requests #:nodoc: + class NilChannel + def initialize(session) + @session = session + end + + def method_missing(sym, *args) + @session.lwarn { "ignoring request #{sym.inspect} for non-existent (closed?) channel; probably ssh server bug" } + end + end + # Create a new connection service instance atop the given transport # layer. Initializes the listeners to be only the underlying socket object. def initialize(transport, options={}) @@ -55,7 +65,7 @@ def initialize(transport, options={}) @options = options @channel_id_counter = -1 - @channels = {} + @channels = Hash.new(NilChannel.new(self)) @listeners = { transport.socket => nil } @pending_requests = [] @channel_open_handlers = {} diff --git a/test/connection/test_session.rb b/test/connection/test_session.rb index ba9c34f1f..05c3ad856 100644 --- a/test/connection/test_session.rb +++ b/test/connection/test_session.rb @@ -257,6 +257,11 @@ def test_channel_window_adjust_packet_should_be_routed_to_corresponding_channel process_times(2) end + def test_channel_request_for_nonexistant_channel_should_be_ignored + transport.return(CHANNEL_REQUEST, :long, 14, :string, "testing", :bool, false) + assert_nothing_raised { process_times(2) } + end + def test_channel_request_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_request).with("testing", false, Net::SSH::Buffer.new) transport.return(CHANNEL_REQUEST, :long, 14, :string, "testing", :bool, false) @@ -480,4 +485,4 @@ def process_times(n) end end -end \ No newline at end of file +end