aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2015-11-08 15:47:26 +0900
committerKazuki Yamaguchi <k@rhe.jp>2015-11-08 15:47:26 +0900
commitcf95e6c3fefcb21e5c4784497544af0143f45200 (patch)
tree23d170cd6e4f3e73f9d49632c1c9e5e4947b0ab1
parentebc34c914a07cb8ae543b3ac5113718eefa6b87a (diff)
downloadplum-cf95e6c3fefcb21e5c4784497544af0143f45200.tar.gz
client/client_session: fix flow control handling
-rw-r--r--lib/plum/client.rb8
-rw-r--r--lib/plum/client/client_session.rb25
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<String, String>] 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