Module Net::SSH::BufferedIo
In: lib/net/ssh/buffered_io.rb
lib/net/ssh/buffered_io.rb

This module is used to extend sockets and other IO objects, to allow them to be buffered for both read and write. This abstraction makes it quite easy to write a select-based event loop (see Net::SSH::Connection::Session#listen_to).

The general idea is that instead of calling read directly on an IO that has been extended with this module, you call fill (to add pending input to the internal read buffer), and then read_available (to read from that buffer). Likewise, you don‘t call write directly, you call enqueue to add data to the write buffer, and then send_pending or wait_for_pending_sends to actually send the data across the wire.

In this way you can easily use the object as an argument to IO.select, calling fill when it is available for read, or send_pending when it is available for write, and then call enqueue and read_available during the idle times.

  socket = TCPSocket.new(address, port)
  socket.extend(Net::SSH::BufferedIo)

  ssh.listen_to(socket)

  ssh.loop do
    if socket.available > 0
      puts socket.read_available
      socket.enqueue("response\n")
    end
  end

Note that this module must be used to extend an instance, and should not be included in a class. If you do want to use it via an include, then you must make sure to invoke the private initialize_buffered_io method in your class’ initialize method:

  class Foo < IO
    include Net::SSH::BufferedIo

    def initialize
      initialize_buffered_io
      # ...
    end
  end

Methods

Included Modules

Loggable Loggable

Public Instance methods

Returns the number of bytes available to be read from the input buffer. (See read_available.)

[Source]

    # File lib/net/ssh/buffered_io.rb, line 78
78:     def available
79:       input.available
80:     end

Returns the number of bytes available to be read from the input buffer. (See read_available.)

[Source]

    # File lib/net/ssh/buffered_io.rb, line 78
78:     def available
79:       input.available
80:     end

Enqueues data in the output buffer, to be written when send_pending is called. Note that the data is not sent immediately by this method!

[Source]

    # File lib/net/ssh/buffered_io.rb, line 84
84:     def enqueue(data)
85:       output.append(data)
86:     end

Enqueues data in the output buffer, to be written when send_pending is called. Note that the data is not sent immediately by this method!

[Source]

    # File lib/net/ssh/buffered_io.rb, line 84
84:     def enqueue(data)
85:       output.append(data)
86:     end

Tries to read up to n bytes of data from the remote end, and appends the data to the input buffer. It returns the number of bytes read, or 0 if no data was available to be read.

[Source]

    # File lib/net/ssh/buffered_io.rb, line 62
62:     def fill(n=8192)
63:       input.consume!
64:       data = recv(n)
65:       debug { "read #{data.length} bytes" }
66:       input.append(data)
67:       return data.length
68:     end

Tries to read up to n bytes of data from the remote end, and appends the data to the input buffer. It returns the number of bytes read, or 0 if no data was available to be read.

[Source]

    # File lib/net/ssh/buffered_io.rb, line 62
62:     def fill(n=8192)
63:       input.consume!
64:       data = recv(n)
65:       debug { "read #{data.length} bytes" }
66:       input.append(data)
67:       return data.length
68:     end

Returns true if there is data waiting in the output buffer, and false otherwise.

[Source]

    # File lib/net/ssh/buffered_io.rb, line 90
90:     def pending_write?
91:       output.length > 0
92:     end

Returns true if there is data waiting in the output buffer, and false otherwise.

[Source]

    # File lib/net/ssh/buffered_io.rb, line 90
90:     def pending_write?
91:       output.length > 0
92:     end

Read up to length bytes from the input buffer. If length is nil, all available data is read from the buffer. (See available.)

[Source]

    # File lib/net/ssh/buffered_io.rb, line 72
72:     def read_available(length=nil)
73:       input.read(length || available)
74:     end

Read up to length bytes from the input buffer. If length is nil, all available data is read from the buffer. (See available.)

[Source]

    # File lib/net/ssh/buffered_io.rb, line 72
72:     def read_available(length=nil)
73:       input.read(length || available)
74:     end

Sends as much of the pending output as possible. Returns true if any data was sent, and false otherwise.

[Source]

     # File lib/net/ssh/buffered_io.rb, line 96
 96:     def send_pending
 97:       if output.length > 0
 98:         sent = send(output.to_s, 0)
 99:         debug { "sent #{sent} bytes" }
100:         output.consume!(sent)
101:         return sent > 0
102:       else
103:         return false
104:       end
105:     end

Sends as much of the pending output as possible. Returns true if any data was sent, and false otherwise.

[Source]

     # File lib/net/ssh/buffered_io.rb, line 96
 96:     def send_pending
 97:       if output.length > 0
 98:         sent = send(output.to_s, 0)
 99:         debug { "sent #{sent} bytes" }
100:         output.consume!(sent)
101:         return sent > 0
102:       else
103:         return false
104:       end
105:     end

Calls send_pending repeatedly, if necessary, blocking until the output buffer is empty.

[Source]

     # File lib/net/ssh/buffered_io.rb, line 109
109:     def wait_for_pending_sends
110:       send_pending
111:       while output.length > 0
112:         result = IO.select(nil, [self]) or next
113:         next unless result[1].any?
114:         send_pending
115:       end
116:     end

Calls send_pending repeatedly, if necessary, blocking until the output buffer is empty.

[Source]

     # File lib/net/ssh/buffered_io.rb, line 109
109:     def wait_for_pending_sends
110:       send_pending
111:       while output.length > 0
112:         result = IO.select(nil, [self]) or next
113:         next unless result[1].any?
114:         send_pending
115:       end
116:     end

[Validate]