Class: Protocol::HTTY::Stream
- Inherits:
-
Object
- Object
- Protocol::HTTY::Stream
- Defined in:
- lib/protocol/htty/stream.rb
Overview
Transport an opaque byte stream over HTTY chunks.
Constant Summary collapse
- PACKET_SIZE =
Since base64 encoding adds 33% overhead, we can fit 3KB of binary data into a single HTTY chunk without exceeding the typical MTU of 4KB:
1024*3
Instance Attribute Summary collapse
-
#framer ⇒ Object
readonly
Returns the value of attribute framer.
Instance Method Summary collapse
-
#close ⇒ Object
Close the local write side of this stream abstraction.
-
#closed? ⇒ Boolean
Check whether the local side of the transport is closed.
-
#flush ⇒ Object
Flush any buffered output through the underlying framer.
-
#initialize(input, output = input, packet_size: PACKET_SIZE) ⇒ Stream
constructor
Create a stream on top of HTTY framed input and output.
-
#io ⇒ Object
Return the writable IO object used by the underlying framer.
-
#read(length = nil) ⇒ Object
Read application bytes from the HTTY transport.
-
#readable? ⇒ Boolean
Check whether the remote side may still provide more data.
-
#write(data) ⇒ Object
Write application bytes as one or more HTTY chunks.
Constructor Details
#initialize(input, output = input, packet_size: PACKET_SIZE) ⇒ Stream
Create a stream on top of HTTY framed input and output.
19 20 21 22 23 24 25 |
# File 'lib/protocol/htty/stream.rb', line 19 def initialize(input, output = input, packet_size: PACKET_SIZE) @framer = Framer.new(::IO::Stream(input), ::IO::Stream(output)) @packet_size = packet_size @buffer = +"".b @local_closed = false @remote_closed = false end |
Instance Attribute Details
#framer ⇒ Object (readonly)
Returns the value of attribute framer.
27 28 29 |
# File 'lib/protocol/htty/stream.rb', line 27 def framer @framer end |
Instance Method Details
#close ⇒ Object
Close the local write side of this stream abstraction. HTTY does not define a close packet, and closing this object does not close the underlying terminal IO.
83 84 85 86 87 88 |
# File 'lib/protocol/htty/stream.rb', line 83 def close unless @local_closed @local_closed = true @framer.flush end end |
#closed? ⇒ Boolean
Check whether the local side of the transport is closed.
92 93 94 |
# File 'lib/protocol/htty/stream.rb', line 92 def closed? @local_closed end |
#flush ⇒ Object
Flush any buffered output through the underlying framer.
76 77 78 |
# File 'lib/protocol/htty/stream.rb', line 76 def flush @framer.flush end |
#io ⇒ Object
Return the writable IO object used by the underlying framer.
31 32 33 |
# File 'lib/protocol/htty/stream.rb', line 31 def io @framer.output end |
#read(length = nil) ⇒ Object
Read application bytes from the HTTY transport.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/protocol/htty/stream.rb', line 38 def read(length = nil) return +"".b if length == 0 fill(length) return nil if @buffer.empty? && @remote_closed return nil if @buffer.empty? return nil if length && @buffer.bytesize < length && !@remote_closed if length return @buffer.slice!(0, length) else return @buffer.slice!(0, @buffer.bytesize) end end |
#readable? ⇒ Boolean
Check whether the remote side may still provide more data.
98 99 100 |
# File 'lib/protocol/htty/stream.rb', line 98 def readable? !@remote_closed end |
#write(data) ⇒ Object
Write application bytes as one or more HTTY chunks.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/protocol/htty/stream.rb', line 58 def write(data) raise IOError, "HTTY stream is closed for writing!" if @local_closed data = data.to_s.b until data.empty? chunk = data.byteslice(0, @packet_size) @framer.write_chunk(chunk) data = data.byteslice(chunk.bytesize..) end @framer.flush return self end |