Skip to content

Commit

Permalink
Merge ef837cc into 2c127ae
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Apr 13, 2018
2 parents 2c127ae + ef837cc commit 0edae0b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 15 deletions.
27 changes: 19 additions & 8 deletions lib/http/2/client.rb
Expand Up @@ -25,6 +25,8 @@ def initialize(**settings)
@local_role = :client
@remote_role = :server

@connection_preface_sent = false

super
end

Expand All @@ -35,7 +37,12 @@ def initialize(**settings)
# @param frame [Hash]
def send(frame)
send_connection_preface
super(frame)
super
end

def connection_management(frame)
send_connection_preface
super
end

# sends the preface and initializes the first stream in half-closed state
Expand All @@ -45,19 +52,23 @@ def upgrade
new_stream(state: :half_closed_local)
end

def self.settings_header(**settings)
frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
Base64.urlsafe_encode64(frame[9..-1])
end

private

# Emit the connection preface if not yet
def send_connection_preface
return unless @state == :waiting_connection_preface
@state = :connected
return if @connection_preface_sent

@connection_preface_sent = true

emit(:frame, CONNECTION_PREFACE_MAGIC)

payload = @local_settings.select { |k, v| v != SPEC_DEFAULT_CONNECTION_SETTINGS[k] }
settings(payload)
end

def self.settings_header(**settings)
frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
Base64.urlsafe_encode64(frame[9..-1])
end
end
end
3 changes: 2 additions & 1 deletion lib/http/2/connection.rb
Expand Up @@ -350,8 +350,9 @@ def receive(data)
end
end

rescue Error::Error
raise
rescue => e
raise if e.is_a?(Error::Error)
connection_error(e: e)
end
alias << receive
Expand Down
16 changes: 16 additions & 0 deletions spec/client_spec.rb
Expand Up @@ -21,6 +21,22 @@
expect(f.parse(frames[1])[:type]).to eq :settings
end

it 'should emit connection header and SETTINGS when receiving data' do
frames = []

@client.on(:frame) { |bytes| frames << bytes }

# Force client to send connection prefix:
# @client.send_connection_preface
# @client.ping("foobar12")

# Server sends a settings frame.
@client << f.generate(SETTINGS.dup)

expect(frames[0]).to eq CONNECTION_PREFACE_MAGIC
expect(f.parse(frames[1])[:type]).to eq :settings
end

it 'should initialize client with custom connection settings' do
frames = []

Expand Down
19 changes: 13 additions & 6 deletions spec/connection_spec.rb
Expand Up @@ -8,12 +8,14 @@
let(:f) { Framer.new }

context 'initialization and settings' do
it 'should raise error if first frame is not SETTINGS' do
(FRAME_TYPES - [SETTINGS]).each do |frame|
(FRAME_TYPES - [SETTINGS]).each do |frame|
it "should raise error if first frame is #{frame[:type]}" do
frame = set_stream_id(f.generate(frame.deep_dup), 0x0)
expect { @conn.dup << frame }.to raise_error(ProtocolError)
end
end

it 'should not raise error if first frame is SETTINGS' do
expect { @conn << f.generate(SETTINGS.dup) }.to_not raise_error
expect(@conn.state).to eq :connected
end
Expand Down Expand Up @@ -50,13 +52,18 @@
settings = SETTINGS.dup
settings[:payload] = [[:settings_header_table_size, 256]]

expect(@conn).to receive(:send) do |frame|
expect(frame[:type]).to eq :settings
expect(frame[:flags]).to eq [:ack]
expect(frame[:payload]).to eq []
# We expect two frames here - one for the connection setup, and one for the settings ack.
frames = []
expect(@conn).to receive(:send).twice do |frame|
frames << frame
end

@conn << f.generate(settings)

frame = frames.last
expect(frame[:type]).to eq :settings
expect(frame[:flags]).to eq [:ack]
expect(frame[:payload]).to eq []
end
end

Expand Down

0 comments on commit 0edae0b

Please sign in to comment.