summaryrefslogtreecommitdiff
path: root/pkg/net-ssh-multi-1.1/lib/net/ssh/multi/channel.rb
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/net-ssh-multi-1.1/lib/net/ssh/multi/channel.rb')
-rw-r--r--pkg/net-ssh-multi-1.1/lib/net/ssh/multi/channel.rb230
1 files changed, 230 insertions, 0 deletions
diff --git a/pkg/net-ssh-multi-1.1/lib/net/ssh/multi/channel.rb b/pkg/net-ssh-multi-1.1/lib/net/ssh/multi/channel.rb
new file mode 100644
index 0000000..34bd117
--- /dev/null
+++ b/pkg/net-ssh-multi-1.1/lib/net/ssh/multi/channel.rb
@@ -0,0 +1,230 @@
+module Net; module SSH; module Multi
+ # Net::SSH::Multi::Channel encapsulates a collection of Net::SSH::Connection::Channel
+ # instances from multiple different connections. It allows for operations to
+ # be performed on all contained channels, simultaneously, using an interface
+ # mostly identical to Net::SSH::Connection::Channel itself.
+ #
+ # You typically obtain a Net::SSH::Multi::Channel instance via
+ # Net::SSH::Multi::Session#open_channel or Net::SSH::Multi::Session#exec,
+ # though there is nothing stopping you from instantiating one yourself with
+ # a handful of Net::SSH::Connection::Channel objects (though they should be
+ # associated with connections managed by a Net::SSH::Multi::Session object
+ # for consistent behavior).
+ #
+ # channel = session.open_channel do |ch|
+ # # ...
+ # end
+ #
+ # channel.wait
+ class Channel
+ include Enumerable
+
+ # The Net::SSH::Multi::Session instance that controls this channel collection.
+ attr_reader :connection
+
+ # The collection of Net::SSH::Connection::Channel instances that this multi-channel aggregates.
+ attr_reader :channels
+
+ # A Hash of custom properties that may be set and queried on this object.
+ attr_reader :properties
+
+ # Instantiate a new Net::SSH::Multi::Channel instance, controlled by the
+ # given +connection+ (a Net::SSH::Multi::Session object) and wrapping the
+ # given +channels+ (Net::SSH::Connection::Channel instances).
+ #
+ # You will typically never call this directly; rather, you'll get your
+ # multi-channel references via Net::SSH::Multi::Session#open_channel and
+ # friends.
+ def initialize(connection, channels)
+ @connection = connection
+ @channels = channels
+ @properties = {}
+ end
+
+ # Iterate over each component channel object, yielding each in order to the
+ # associated block.
+ def each
+ @channels.each { |channel| yield channel }
+ end
+
+ # Retrieve the property (see #properties) with the given +key+.
+ #
+ # host = channel[:host]
+ def [](key)
+ @properties[key]
+ end
+
+ # Set the property (see #properties) with the given +key+ to the given
+ # +value+.
+ #
+ # channel[:visited] = true
+ def []=(key, value)
+ @properties[key] = value
+ end
+
+ # Perform an +exec+ command on all component channels. The block, if given,
+ # is passed to each component channel, so it will (potentially) be invoked
+ # once for every channel in the collection. The block will receive two
+ # parameters: the specific channel object being operated on, and a boolean
+ # indicating whether the exec succeeded or not.
+ #
+ # channel.exec "ls -l" do |ch, success|
+ # # ...
+ # end
+ #
+ # See the documentation in Net::SSH for Net::SSH::Connection::Channel#exec
+ # for more information on how to work with the callback.
+ def exec(command, &block)
+ channels.each { |channel| channel.exec(command, &block) }
+ self
+ end
+
+ # Perform a +request_pty+ command on all component channels. The block, if
+ # given, is passed to each component channel, so it will (potentially) be
+ # invoked once for every channel in the collection. The block will
+ # receive two parameters: the specific channel object being operated on,
+ # and a boolean indicating whether the pty request succeeded or not.
+ #
+ # channel.request_pty do |ch, success|
+ # # ...
+ # end
+ #
+ # See the documentation in Net::SSH for
+ # Net::SSH::Connection::Channel#request_pty for more information on how to
+ # work with the callback.
+ def request_pty(opts={}, &block)
+ channels.each { |channel| channel.request_pty(opts, &block) }
+ self
+ end
+
+ # Send the given +data+ to each component channel. It will be sent to the
+ # remote process, typically being received on the process' +stdin+ stream.
+ #
+ # channel.send_data "password\n"
+ def send_data(data)
+ channels.each { |channel| channel.send_data(data) }
+ self
+ end
+
+ # Returns true as long as any of the component channels are active.
+ #
+ # connection.loop { channel.active? }
+ def active?
+ channels.any? { |channel| channel.active? }
+ end
+
+ # Runs the connection's event loop until the channel is no longer active
+ # (see #active?).
+ #
+ # channel.exec "something"
+ # channel.wait
+ def wait
+ connection.loop { active? }
+ self
+ end
+
+ # Closes all component channels.
+ def close
+ channels.each { |channel| channel.close }
+ self
+ end
+
+ # Tells the remote process for each component channel not to expect any
+ # further data from this end of the channel.
+ def eof!
+ channels.each { |channel| channel.eof! }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked when the
+ # remote process emits data (usually on its +stdout+ stream). The block
+ # will be invoked with two arguments: the specific channel object, and the
+ # data that was received.
+ #
+ # channel.on_data do |ch, data|
+ # puts "got data: #{data}"
+ # end
+ def on_data(&block)
+ channels.each { |channel| channel.on_data(&block) }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked when the
+ # remote process emits "extended" data (typically on its +stderr+ stream).
+ # The block will be invoked with three arguments: the specific channel
+ # object, an integer describing the data type (usually a 1 for +stderr+)
+ # and the data that was received.
+ #
+ # channel.on_extended_data do |ch, type, data|
+ # puts "got extended data: #{data}"
+ # end
+ def on_extended_data(&block)
+ channels.each { |channel| channel.on_extended_data(&block) }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked during the
+ # idle portion of the connection event loop. The callback will be invoked
+ # with one argument: the specific channel object being processed.
+ #
+ # channel.on_process do |ch|
+ # # ...
+ # end
+ def on_process(&block)
+ channels.each { |channel| channel.on_process(&block) }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked when the
+ # remote server terminates the channel. The callback will be invoked
+ # with one argument: the specific channel object being closed.
+ #
+ # channel.on_close do |ch|
+ # # ...
+ # end
+ def on_close(&block)
+ channels.each { |channel| channel.on_close(&block) }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked when the
+ # remote server has no further data to send. The callback will be invoked
+ # with one argument: the specific channel object being marked EOF.
+ #
+ # channel.on_eof do |ch|
+ # # ...
+ # end
+ def on_eof(&block)
+ channels.each { |channel| channel.on_eof(&block) }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked when the
+ # remote server is unable to open the channel. The callback will be
+ # invoked with three arguments: the channel object that couldn't be
+ # opened, a description of the error (as a string), and an integer code
+ # representing the error.
+ #
+ # channel.on_open_failed do |ch, description, code|
+ # # ...
+ # end
+ def on_open_failed(&block)
+ channels.each { |channel| channel.on_open_failed(&block) }
+ self
+ end
+
+ # Registers a callback on all component channels, to be invoked when the
+ # remote server sends a channel request of the given +type+. The callback
+ # will be invoked with two arguments: the specific channel object receiving
+ # the request, and a Net::SSH::Buffer instance containing the request-specific
+ # data.
+ #
+ # channel.on_request("exit-status") do |ch, data|
+ # puts "exited with #{data.read_long}"
+ # end
+ def on_request(type, &block)
+ channels.each { |channel| channel.on_request(type, &block) }
+ self
+ end
+ end
+end; end; end \ No newline at end of file