From cf95e6c3fefcb21e5c4784497544af0143f45200 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 8 Nov 2015 15:47:26 +0900 Subject: client/client_session: fix flow control handling --- lib/plum/client.rb | 8 ++++++-- lib/plum/client/client_session.rb | 25 ++++++++++++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/plum/client.rb b/lib/plum/client.rb index 6e53ade..28f0cdd 100644 --- a/lib/plum/client.rb +++ b/lib/plum/client.rb @@ -5,7 +5,9 @@ module Plum tls: true, scheme: "https", verify_mode: OpenSSL::SSL::VERIFY_PEER, - ssl_context: nil + ssl_context: nil, + hostname: nil, + http2_settings: {}, }.freeze attr_reader :host, :port, :config @@ -80,6 +82,7 @@ module Plum # @param body [String] the request body # @param block [Proc] if passed, it will be called when received response headers. def request_async(headers, body = nil, &block) + raise ArgumentError, ":method and :path headers are required" unless headers[":method"] && headers[":path"] @session.request(headers, body, &block) end @@ -87,7 +90,7 @@ module Plum # @param headers [Hash] the request headers # @param body [String] the request body def request(headers, body = nil, &block) - wait @session.request(headers, body, &block) + wait request_async(headers, body, &block) end # @!method get @@ -171,6 +174,7 @@ module Plum ctx = OpenSSL::SSL::SSLContext.new ctx.ssl_version = :TLSv1_2 ctx.verify_mode = @config[:verify_mode] + ctx.ciphers = "ALL:!" + HTTPSServerConnection::CIPHER_BLACKLIST.join(":!") cert_store = OpenSSL::X509::Store.new cert_store.set_default_paths ctx.cert_store = cert_store diff --git a/lib/plum/client/client_session.rb b/lib/plum/client/client_session.rb index 470f100..c637aa5 100644 --- a/lib/plum/client/client_session.rb +++ b/lib/plum/client/client_session.rb @@ -1,14 +1,16 @@ # -*- frozen-string-literal: true -*- module Plum + # HTTP/2 client session. class ClientSession HTTP2_DEFAULT_SETTINGS = { enable_push: 0, # TODO: api? - initial_window_size: (1 << 30) - 1, # TODO: maximum size: disable flow control + initial_window_size: 2 ** 30, # TODO } def initialize(socket, config) @socket = socket @config = config + @http2_settings = HTTP2_DEFAULT_SETTINGS.merge(@config[:http2_settings]) @plum = setup_plum @responses = Set.new @@ -26,22 +28,20 @@ module Plum def close @closed = true - @responses.each { |response| response._fail } + @responses.each(&:_fail) @responses.clear @plum.close end def request(headers, body = nil, &headers_cb) - raise ArgumentError, ":method and :path headers are required" unless headers[":method"] && headers[":path"] - - @responses << (response = Response.new) - headers = { ":method" => nil, ":path" => nil, ":authority" => @config[:hostname], ":scheme" => @config[:scheme] - }.merge(headers) + }.merge(headers) + response = Response.new + @responses << response stream = @plum.open_stream stream.send_headers(headers, end_stream: !body) stream.send_data(body, end_stream: true) if body @@ -52,6 +52,7 @@ module Plum } stream.on(:data) { |chunk| response._chunk(chunk) + check_window(stream) } stream.on(:end_stream) { response._finish @@ -61,7 +62,6 @@ module Plum response._fail raise ex } - response end @@ -72,11 +72,18 @@ module Plum end def setup_plum - plum = ClientConnection.new(@socket.method(:write), HTTP2_DEFAULT_SETTINGS) + plum = ClientConnection.new(@socket.method(:write), @http2_settings) plum.on(:connection_error) { |ex| fail(ex) } + plum.window_update(@http2_settings[:initial_window_size]) plum end + + def check_window(stream) + ws = @http2_settings[:initial_window_size] + stream.window_update(ws) if stream.recv_remaining_window < (ws / 2) + @plum.window_update(ws) if @plum.recv_remaining_window < (ws / 2) + end end end -- cgit v1.2.3