Skip to content

Commit fa7565f

Browse files
committed
Better TTY integration - no read-ahead.
1 parent e253918 commit fa7565f

8 files changed

Lines changed: 27 additions & 12 deletions

File tree

async-htty.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
2727
spec.add_dependency "async", "~> 2.39"
2828
spec.add_dependency "async-http", "~> 0.88"
2929
spec.add_dependency "protocol-http", "~> 0.62"
30-
spec.add_dependency "protocol-htty", "~> 0.2"
30+
spec.add_dependency "protocol-htty", "~> 0.3"
3131
end

fixtures/async/htty/pty_stream.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ def initialize(input, output)
1414
@buffer = +"".b
1515
end
1616

17+
attr :input
18+
attr :output
19+
1720
def read(length)
1821
while @buffer.bytesize < length
1922
@buffer << @input.readpartial(4096).b

lib/async/htty/protocol/htty.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ module HTTY
1313
module Protocol
1414
module HTTY
1515
def self.client(stream, settings: ::Async::HTTP::Protocol::HTTP2::CLIENT_SETTINGS)
16-
stream = ::Protocol::HTTY::Stream.open(stream, bootstrap: :read)
16+
mode = stream.read_bootstrap
17+
18+
unless mode == ::Protocol::HTTY::Stream::RAW_MODE
19+
raise ::Protocol::HTTY::ProtocolError, "Expected HTTY bootstrap mode #{::Protocol::HTTY::Stream::RAW_MODE.inspect}, got #{mode.inspect}"
20+
end
1721

1822
client = ::Async::HTTP::Protocol::HTTP2::Client.new(stream)
1923
client.send_connection_preface(settings)
@@ -23,7 +27,7 @@ def self.client(stream, settings: ::Async::HTTP::Protocol::HTTP2::CLIENT_SETTING
2327
end
2428

2529
def self.server(stream, settings: ::Async::HTTP::Protocol::HTTP2::SERVER_SETTINGS)
26-
stream = ::Protocol::HTTY::Stream.open(stream, bootstrap: :write)
30+
stream.write_bootstrap
2731

2832
server = Server.new(stream)
2933
server.read_connection_preface(settings)

lib/async/htty/protocol/htty/server.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ module HTTY
1212
class Server < ::Async::HTTP::Protocol::HTTP2::Server
1313
def receive_goaway(frame)
1414
super
15-
16-
unless self.framer.nil?
15+
16+
if framer = self.framer
1717
self.send_goaway
18+
framer.flush
1819
end
1920
end
2021
end

lib/async/htty/server.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def self.open(app = nil, input: $stdin, output: $stdout, error: $stderr, env: EN
4545
original_output = output.dup
4646
original_error = error.dup
4747

48-
stream = ::IO::Stream::Duplex(original_input, original_output)
48+
stream = ::Protocol::HTTY::Stream.new(original_input, original_output)
4949
input.reopen(File::NULL)
5050
output.reopen(File::NULL)
5151
error.reopen(File::NULL)

releases.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- Pass explicit terminal input and output endpoints into `Protocol::HTTY::Stream`, avoiding buffered duplex reads across the HTTY HTTP/2 transport.
6+
- Expect the HTTY protocol adapter to receive a prepared `Protocol::HTTY::Stream` instance before performing bootstrap and HTTP/2 setup.
7+
38
## v0.2.1
49

510
- Send a server-side GOAWAY when the HTTY client closes an HTTP/2 session, allowing terminal clients to detach cleanly.

test/async/htty/protocol/htty.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ def close_pipes(pipes)
6565
end
6666

6767
def client_stream(pipes)
68-
IO::Stream::Duplex(pipes[:client_input], pipes[:client_output])
68+
Protocol::HTTY::Stream.new(pipes[:client_input], pipes[:client_output])
6969
end
7070

7171
def server_stream(pipes)
72-
IO::Stream::Duplex(pipes[:server_input], pipes[:server_output])
72+
Protocol::HTTY::Stream.new(pipes[:server_input], pipes[:server_output])
7373
end
7474

7575
def spawn_fixture(name)
@@ -123,7 +123,8 @@ def with_fixture(name)
123123
payload = (0x00..0xff).to_a.pack("C*")
124124

125125
with_fixture("echo_body.rb") do |stream|
126-
Protocol::HTTY::Stream.new(stream).read_bootstrap
126+
stream = Protocol::HTTY::Stream.new(stream.input, stream.output)
127+
stream.read_bootstrap
127128

128129
framer = Protocol::HTTP2::Framer.new(stream)
129130
client = EchoClient.new(framer)
@@ -174,7 +175,8 @@ def with_fixture(name)
174175
server_finished.signal
175176
end
176177

177-
stream = Protocol::HTTY::Stream.open(client_stream(pipes), bootstrap: :read)
178+
stream = client_stream(pipes)
179+
stream.read_bootstrap
178180
framer = Protocol::HTTP2::Framer.new(stream)
179181
client = Protocol::HTTP2::Client.new(framer)
180182
client.send_connection_preface

test/async/htty/server.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ def connection.close
8888

8989
protocol.define_singleton_method(:server) do |stream|
9090
reopened_to_null = [input.reopened_to_null?, output.reopened_to_null?, error.reopened_to_null?]
91-
duplex_input = stream.io.input
92-
duplex_output = stream.io.output
91+
duplex_input = stream.input
92+
duplex_output = stream.output
9393

9494
stream.write("response", flush: true)
9595

0 commit comments

Comments
 (0)