diff options
author | delano <delano@delanotes.com> | 2014-02-01 11:32:20 -0500 |
---|---|---|
committer | delano <delano@delanotes.com> | 2014-02-01 11:32:20 -0500 |
commit | d181edf8c3c9c71b3683a1752012ffd19df13148 (patch) | |
tree | 504b1f38efdcf42684fc3f6a371947f48aec2a2d | |
parent | f41ba9750e549ee1822201c9fabf37fd49150638 (diff) | |
parent | cbe2861162e4bd5f8658a008566d98b3f01c6cd9 (diff) | |
download | net-ssh-aderouineau-master.tar.gz |
Merge branch 'master' of github.com:aderouineau/net-ssh into aderouineau-masteraderouineau-master
-rw-r--r-- | THANKS.txt | 1 | ||||
-rw-r--r-- | lib/net/ssh/service/forward.rb | 25 | ||||
-rw-r--r-- | test/manual/test_forward.rb | 41 |
3 files changed, 47 insertions, 20 deletions
@@ -83,3 +83,4 @@ watsonian Grant Hutchins Michael Schubert mtrudel +Aurélien Derouineau diff --git a/lib/net/ssh/service/forward.rb b/lib/net/ssh/service/forward.rb index 3b0face..0d5d55d 100644 --- a/lib/net/ssh/service/forward.rb +++ b/lib/net/ssh/service/forward.rb @@ -47,8 +47,12 @@ module Net; module SSH; module Service # If three arguments are given, it is as if the local bind address is # "127.0.0.1", and the rest are applied as above. # + # To request an ephemeral port on the remote server, provide 0 (zero) for + # the port number. In all cases, this method will return the port that + # has been assigned. + # # ssh.forward.local(1234, "www.capify.org", 80) - # ssh.forward.local("0.0.0.0", 1234, "www.capify.org", 80) + # assigned_port = ssh.forward.local("0.0.0.0", 0, "www.capify.org", 80) def local(*args) if args.length < 3 || args.length > 4 raise ArgumentError, "expected 3 or 4 parameters, got #{args.length}" @@ -69,6 +73,7 @@ module Net; module SSH; module Service end end + local_port = socket.addr[1] if local_port == 0 # ephemeral port was requested remote_host = args.shift remote_port = args.shift.to_i @@ -89,6 +94,8 @@ module Net; module SSH; module Service channel[:socket].close end end + + local_port end # Terminates an active local forwarded port. If no such forwarded port @@ -120,15 +127,21 @@ module Net; module SSH; module Service # forwarded immediately. If the remote server is not able to begin the # listener for this request, an exception will be raised asynchronously. # - # If you want to know when the connection is active, it will show up in the - # #active_remotes list. If you want to block until the port is active, you - # could do something like this: + # To request an ephemeral port on the remote server, provide 0 (zero) for + # the port number. The assigned port will show up in the # #active_remotes + # list. + # + # If you want to block until the port is active, you could do something + # like this: # - # ssh.forward.remote(80, "www.google.com", 1234, "0.0.0.0") - # ssh.loop { !ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) } + # old_active_remotes = ssh.forward.active_remotes + # ssh.forward.remote(80, "www.google.com", 0, "0.0.0.0") + # ssh.loop { !(ssh.forward.active_remotes.length > old_active_remotes.length) } + # assigned_port = (ssh.forward.active_remotes - old_active_remotes).first[0] def remote(port, host, remote_port, remote_host="127.0.0.1") session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response| if success + remote_port = response.read_long if remote_port == 0 debug { "remote forward from remote #{remote_host}:#{remote_port} to #{host}:#{port} established" } @remote_forwarded_ports[[remote_port, remote_host]] = Remote.new(host, port) else diff --git a/test/manual/test_forward.rb b/test/manual/test_forward.rb index 8e27818..5794077 100644 --- a/test/manual/test_forward.rb +++ b/test/manual/test_forward.rb @@ -1,4 +1,4 @@ -# $ ruby -Ilib -Itest -rrubygems test/test_forward.rb +# $ ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb # Tests for the following patch: # @@ -30,14 +30,6 @@ class TestForward < Test::Unit::TestCase [localhost ,ENV['USER'], {:keys => "~/.ssh/id_rsa", :verbose => :debug}] end - def find_free_port - server = TCPServer.open(0) - server.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR,true) - port = server.addr[1] - server.close - port - end - def start_server_sending_lot_of_data(exceptions) server = TCPServer.open(0) Thread.start do @@ -77,12 +69,34 @@ class TestForward < Test::Unit::TestCase return server end + def test_local_ephemeral_port_should_work_correctly + session = Net::SSH.start(*ssh_start_params) + + assert_nothing_raised do + assigned_port = session.forward.local(0, localhost, 22) + assert_not_nil assigned_port + assert_operator assigned_port, :>, 0 + end + end + + def test_remote_ephemeral_port_should_work_correctly + session = Net::SSH.start(*ssh_start_params) + + assert_nothing_raised do + session.forward.remote(22, localhost, 0, localhost) + session.loop { !(session.forward.active_remotes.length > 0) } + assigned_port = session.forward.active_remotes.first[0] + assert_not_nil assigned_port + assert_operator assigned_port, :>, 0 + end + end + def test_loop_should_not_abort_when_local_side_of_forward_is_closed session = Net::SSH.start(*ssh_start_params) server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] - local_port = find_free_port + local_port = 0 # request ephemeral port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do @@ -104,7 +118,7 @@ class TestForward < Test::Unit::TestCase server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] - local_port = find_free_port + local_port = 0 # request ephemeral port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do @@ -163,7 +177,7 @@ class TestForward < Test::Unit::TestCase session = Net::SSH.start(*ssh_start_params) server = start_server_closing_soon remote_port = server.addr[1] - local_port = find_free_port + local_port = 0 # request ephemeral port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do @@ -203,8 +217,7 @@ class TestForward < Test::Unit::TestCase client_exception = Queue.new client_data = Queue.new remote_port = server.addr[1] - local_port = find_free_port - session.forward.local(local_port, localhost, remote_port) + local_port = session.forward.local(0, localhost, remote_port) Thread.start do begin client = TCPSocket.new(localhost, local_port) |