diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/plum.rb | 11 | ||||
-rw-r--r-- | lib/plum/connection.rb | 10 | ||||
-rw-r--r-- | lib/plum/flow_control.rb | 3 | ||||
-rw-r--r-- | lib/plum/frame.rb | 181 | ||||
-rw-r--r-- | lib/plum/frame/continuation.rb | 16 | ||||
-rw-r--r-- | lib/plum/frame/data.rb | 31 | ||||
-rw-r--r-- | lib/plum/frame/goaway.rb | 20 | ||||
-rw-r--r-- | lib/plum/frame/headers.rb | 32 | ||||
-rw-r--r-- | lib/plum/frame/ping.rb | 24 | ||||
-rw-r--r-- | lib/plum/frame/priority.rb | 12 | ||||
-rw-r--r-- | lib/plum/frame/push_promise.rb | 33 | ||||
-rw-r--r-- | lib/plum/frame/rst_stream.rb | 16 | ||||
-rw-r--r-- | lib/plum/frame/settings.rb | 43 | ||||
-rw-r--r-- | lib/plum/frame/unknown.rb | 12 | ||||
-rw-r--r-- | lib/plum/frame/window_update.rb | 16 | ||||
-rw-r--r-- | lib/plum/server/http_connection.rb | 6 | ||||
-rw-r--r-- | lib/plum/stream.rb | 10 |
17 files changed, 313 insertions, 163 deletions
diff --git a/lib/plum.rb b/lib/plum.rb index 3220bbc..fa70317 100644 --- a/lib/plum.rb +++ b/lib/plum.rb @@ -13,6 +13,17 @@ require "plum/hpack/context" require "plum/hpack/decoder" require "plum/hpack/encoder" require "plum/frame" +require "plum/frame/data" +require "plum/frame/headers" +require "plum/frame/priority" +require "plum/frame/rst_stream" +require "plum/frame/settings" +require "plum/frame/push_promise" +require "plum/frame/ping" +require "plum/frame/goaway" +require "plum/frame/window_update" +require "plum/frame/continuation" +require "plum/frame/unknown" require "plum/flow_control" require "plum/connection" require "plum/stream" diff --git a/lib/plum/connection.rb b/lib/plum/connection.rb index 1eac16e..36faedd 100644 --- a/lib/plum/connection.rb +++ b/lib/plum/connection.rb @@ -85,7 +85,7 @@ module Plum # Sends local settings to the peer. # @param new_settings [Hash<Symbol, Integer>] def settings(**new_settings) - send_immediately Frame.settings(**new_settings) + send_immediately Frame::Settings.new(**new_settings) old_settings = @local_settings.dup @local_settings.merge!(new_settings) @@ -98,14 +98,14 @@ module Plum # @param data [String] Must be 8 octets. # @raise [ArgumentError] If the data is not 8 octets. def ping(data = "plum\x00\x00\x00\x00") - send_immediately Frame.ping(data) + send_immediately Frame::Ping.new(data) end # Sends GOAWAY frame to the peer and closes the connection. # @param error_type [Symbol] The error type to be contained in the GOAWAY frame. def goaway(error_type = :no_error, message = "") last_id = @max_stream_ids.max - send_immediately Frame.goaway(last_id, error_type, message) + send_immediately Frame::Goaway.new(last_id, error_type, message) end # Returns whether peer enables server push or not @@ -202,7 +202,7 @@ module Plum callback(:remote_settings, @remote_settings, old_remote_settings) - send_immediately Frame.settings(:ack) if send_ack + send_immediately Frame::Settings.new(:ack) if send_ack if @state == :waiting_settings @state = :open @@ -223,7 +223,7 @@ module Plum else opaque_data = frame.payload callback(:ping, opaque_data) - send_immediately Frame.ping(:ack, opaque_data) + send_immediately Frame::Ping.new(:ack, opaque_data) end end diff --git a/lib/plum/flow_control.rb b/lib/plum/flow_control.rb index 9a2aa1d..f28fa3a 100644 --- a/lib/plum/flow_control.rb +++ b/lib/plum/flow_control.rb @@ -29,9 +29,8 @@ module Plum # @param wsi [Integer] The amount to increase receiving window size. The legal range is 1 to 2^32-1. def window_update(wsi) @recv_remaining_window += wsi - payload = String.new.push_uint32(wsi) sid = (Stream === self) ? self.id : 0 - send_immediately Frame.new(type: :window_update, stream_id: sid, payload: payload) + send_immediately Frame::WindowUpdate.new(sid, wsi) end protected diff --git a/lib/plum/frame.rb b/lib/plum/frame.rb index 57b3061..4ac0596 100644 --- a/lib/plum/frame.rb +++ b/lib/plum/frame.rb @@ -1,7 +1,6 @@ # frozen-string-literal: true using Plum::BinaryString - module Plum class Frame FRAME_TYPES = { @@ -53,15 +52,6 @@ module Plum # @!visibility private FRAME_FLAGS_MAP = FRAME_FLAGS.values.inject(:merge).freeze - SETTINGS_TYPE = { - header_table_size: 0x01, - enable_push: 0x02, - max_concurrent_streams: 0x03, - initial_window_size: 0x04, - max_frame_size: 0x05, - max_header_list_size: 0x06 - }.freeze - # RFC7540: 4.1 Frame format # +-----------------------------------------------+ # | Length (24) | @@ -82,12 +72,29 @@ module Plum # [String] The payload. Value is frozen. attr_reader :payload - def initialize(type: nil, type_value: nil, flags: nil, flags_value: nil, stream_id: nil, payload: nil) + # @private + protected def initialize_base(type: nil, type_value: nil, flags: nil, flags_value: nil, stream_id: nil, payload: nil) @payload = payload || "" @length = @payload.bytesize - @type_value = type_value or self.type = type + @type_value = type_value || FRAME_TYPES[type] or raise ArgumentError.new("unknown frame type: #{type}") @flags_value = flags_value or self.flags = flags @stream_id = stream_id or raise ArgumentError.new("stream_id is necessary") + self + end + + # @private + def initialize(*, **) + raise ArgumentError, "can't instantiate abstract class" + end + + # Creates a new instance of Frame or an subclass of Frame. + # @private + def self.craft(type: nil, type_value: nil, **args) + type_value ||= type && FRAME_TYPES[type] or (raise ArgumentError, "unknown frame type") + klass = SUB_CLASSES[type_value] || Frame::Unknown + instance = klass.allocate + instance.send(:initialize_base, type_value: type_value, **args) + instance end # Returns the length of payload. @@ -102,12 +109,6 @@ module Plum FRAME_TYPES_INVERSE[@type_value] || ("unknown_%02x" % @type_value).to_sym end - # Sets the frame type. - # @param value [Symbol] The type. - def type=(value) - @type_value = FRAME_TYPES[value] or raise ArgumentError.new("unknown frame type: #{value}") - end - # Returns the set flags on the frame. # @return [Array<Symbol>] The flags. def flags @@ -147,44 +148,7 @@ module Plum # @private def inspect - "#<Plum::Frame:0x%04x} length=%d, type=%p, flags=%p, stream_id=0x%04x, payload=%p>" % [__id__, length, type, flags, stream_id, payload] - end - - # Splits this frame into multiple frames not to exceed MAX_FRAME_SIZE. - # @param max [Integer] The maximum size of a frame payload. - # @yield [Frame] The splitted frames. - def split(max) - return yield self if @length <= max - first, *mid, last = @payload.chunk(max) - case type - when :data - yield Frame.new(type_value: 0, stream_id: @stream_id, payload: first, flags_value: @flags_value & ~1) - mid.each { |slice| - yield Frame.new(type_value: 0, stream_id: @stream_id, payload: slice, flags_value: 0) - } - yield Frame.new(type_value: 0, stream_id: @stream_id, payload: last, flags_value: @flags_value & 1) - when :headers, :push_promise - yield Frame.new(type_value: @type_value, stream_id: @stream_id, payload: first, flags_value: @flags_value & ~4) - mid.each { |slice| - yield Frame.new(type: :continuation, stream_id: @stream_id, payload: slice, flags_value: 0) - } - yield Frame.new(type: :continuation, stream_id: @stream_id, payload: last, flags_value: @flags_value & 4) - else - raise NotImplementedError.new("frame split of frame with type #{type} is not supported") - end - end - - # Parses SETTINGS frame payload. Ignores unknown settings type (see RFC7540 6.5.2). - # @return [Hash<Symbol, Integer>] The parsed strings. - def parse_settings - settings = {} - payload.each_byteslice(6) do |param| - id = param.uint16 - name = Frame::SETTINGS_TYPE.key(id) - # ignore unknown settings type - settings[name] = param.uint32(2) if name - end - settings + "#<%s:0x%04x length=%d, flags=%p, stream_id=0x%04x, payload=%p>" % [self.class, __id__, length, flags, stream_id, payload] end # Parses a frame from given buffer. It changes given buffer. @@ -200,100 +164,21 @@ module Plum # r = r_sid >> 31 # currently not used stream_id = r_sid # & ~(1 << 31) - self.new(type_value: type_value, - flags_value: flags_value, - stream_id: stream_id, - payload: cur.byteslice(9, length)).freeze + frame = (SUB_CLASSES[type_value] || Frame::Unknown).allocate + frame.send(:initialize_base, + type_value: type_value, + flags_value: flags_value, + stream_id: stream_id, + payload: cur.byteslice(9, length)) + frame.freeze end - # Creates a RST_STREAM frame. - # @param stream_id [Integer] The stream ID. - # @param error_type [Symbol] The error type defined in RFC 7540 Section 7. - def self.rst_stream(stream_id, error_type) - payload = String.new.push_uint32(HTTPError::ERROR_CODES[error_type]) - Frame.new(type: :rst_stream, stream_id: stream_id, payload: payload) - end - - # Creates a GOAWAY frame. - # @param last_id [Integer] The biggest processed stream ID. - # @param error_type [Symbol] The error type defined in RFC 7540 Section 7. - # @param message [String] Additional debug data. - # @see RFC 7540 Section 6.8 - def self.goaway(last_id, error_type, message = "") - payload = String.new.push_uint32(last_id) - .push_uint32(HTTPError::ERROR_CODES[error_type]) - .push(message) - Frame.new(type: :goaway, stream_id: 0, payload: payload) - end - - # Creates a SETTINGS frame. - # @param ack [Symbol] Pass :ack to create an ACK frame. - # @param args [Hash<Symbol, Integer>] The settings values to send. - def self.settings(ack = nil, **args) - payload = String.new - args.each { |key, value| - id = Frame::SETTINGS_TYPE[key] or raise ArgumentError.new("invalid settings type") - payload.push_uint16(id) - payload.push_uint32(value) - } - Frame.new(type: :settings, stream_id: 0, flags: [ack], payload: payload) - end - - # Creates a PING frame. - # @overload ping(ack, payload) - # @param ack [Symbol] Pass :ack to create an ACK frame. - # @param payload [String] 8 bytes length data to send. - # @overload ping(payload = "plum\x00\x00\x00\x00") - # @param payload [String] 8 bytes length data to send. - def self.ping(arg1 = "plum\x00\x00\x00\x00".b, arg2 = nil) - if !arg2 - raise ArgumentError.new("data must be 8 octets") if arg1.bytesize != 8 - arg1 = arg1.b if arg1.encoding != Encoding::BINARY - Frame.new(type: :ping, stream_id: 0, payload: arg1) - else - Frame.new(type: :ping, stream_id: 0, flags: [:ack], payload: arg2) - end - end - - # Creates a DATA frame. - # @param stream_id [Integer] The stream ID. - # @param payload [String] Payload. - # @param end_stream [Boolean] add END_STREAM flag - def self.data(stream_id, payload = "", end_stream: false) - payload = payload.b if payload&.encoding != Encoding::BINARY - fval = end_stream ? 1 : 0 - Frame.new(type_value: 0, stream_id: stream_id, flags_value: fval, payload: payload) - end - - # Creates a HEADERS frame. - # @param stream_id [Integer] The stream ID. - # @param encoded [String] Headers. - # @param end_stream [Boolean] add END_STREAM flag - # @param end_headers [Boolean] add END_HEADERS flag - def self.headers(stream_id, encoded, end_stream: false, end_headers: false) - fval = end_stream ? 1 : 0 - fval += 4 if end_headers - Frame.new(type_value: 1, stream_id: stream_id, flags_value: fval, payload: encoded) - end - - # Creates a PUSH_PROMISE frame. - # @param stream_id [Integer] The stream ID. - # @param new_id [Integer] The stream ID to create. - # @param encoded [String] Request headers. - # @param end_headers [Boolean] add END_HEADERS flag - def self.push_promise(stream_id, new_id, encoded, end_headers: false) - payload = String.new.push_uint32(new_id) - .push(encoded) - fval = end_headers ? 4 : 0 - Frame.new(type: :push_promise, stream_id: stream_id, flags_value: fval, payload: payload) - end - - # Creates a CONTINUATION frame. - # @param stream_id [Integer] The stream ID. - # @param payload [String] Payload. - # @param end_headers [Boolean] add END_HEADERS flag - def self.continuation(stream_id, payload, end_headers: false) - Frame.new(type: :continuation, stream_id: stream_id, flags_value: (end_headers ? 4 : 0), payload: payload) + # @private + # type_value = 0x00 - 0x09 are known, but these classes aren't defined yet... + SUB_CLASSES = [] + private_constant :SUB_CLASSES + def self.register_subclass(type_value) + SUB_CLASSES[type_value] = self end end end diff --git a/lib/plum/frame/continuation.rb b/lib/plum/frame/continuation.rb new file mode 100644 index 0000000..1c5232c --- /dev/null +++ b/lib/plum/frame/continuation.rb @@ -0,0 +1,16 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Continuation < Frame + register_subclass 0x09 + + # Creates a CONTINUATION frame. + # @param stream_id [Integer] The stream ID. + # @param payload [String] Payload. + # @param end_headers [Boolean] add END_HEADERS flag + def initialize(stream_id, payload, end_headers: false) + initialize_base(type: :continuation, stream_id: stream_id, flags_value: (end_headers ? 4 : 0), payload: payload) + end + end +end diff --git a/lib/plum/frame/data.rb b/lib/plum/frame/data.rb new file mode 100644 index 0000000..7c02029 --- /dev/null +++ b/lib/plum/frame/data.rb @@ -0,0 +1,31 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Data < Frame + register_subclass 0x00 + + # Creates a DATA frame. + # @param stream_id [Integer] The stream ID. + # @param payload [String] Payload. + # @param end_stream [Boolean] add END_STREAM flag + def initialize(stream_id, payload = "", end_stream: false) + payload = payload.b if payload&.encoding != Encoding::BINARY + fval = end_stream ? 1 : 0 + initialize_base(type_value: 0, stream_id: stream_id, flags_value: fval, payload: payload) + end + + # Splits this frame into multiple frames not to exceed MAX_FRAME_SIZE. + # @param max [Integer] The maximum size of a frame payload. + # @yield [Frame] The splitted frames. + def split(max) + return yield self if @length <= max + first, *mid, last = @payload.chunk(max) + yield Frame.craft(type_value: 0, stream_id: @stream_id, payload: first, flags_value: @flags_value & ~1) + mid.each { |slice| + yield Frame.craft(type_value: 0, stream_id: @stream_id, payload: slice, flags_value: 0) + } + yield Frame.craft(type_value: 0, stream_id: @stream_id, payload: last, flags_value: @flags_value & 1) + end + end +end diff --git a/lib/plum/frame/goaway.rb b/lib/plum/frame/goaway.rb new file mode 100644 index 0000000..e1e0097 --- /dev/null +++ b/lib/plum/frame/goaway.rb @@ -0,0 +1,20 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Goaway < Frame + register_subclass 0x07 + + # Creates a GOAWAY frame. + # @param last_id [Integer] The biggest processed stream ID. + # @param error_type [Symbol] The error type defined in RFC 7540 Section 7. + # @param message [String] Additional debug data. + # @see RFC 7540 Section 6.8 + def initialize(last_id, error_type, message = "") + payload = String.new.push_uint32(last_id) + .push_uint32(HTTPError::ERROR_CODES[error_type]) + .push(message) + initialize_base(type: :goaway, stream_id: 0, payload: payload) + end + end +end diff --git a/lib/plum/frame/headers.rb b/lib/plum/frame/headers.rb new file mode 100644 index 0000000..12d6a61 --- /dev/null +++ b/lib/plum/frame/headers.rb @@ -0,0 +1,32 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Headers < Frame + register_subclass 0x01 + + # Creates a HEADERS frame. + # @param stream_id [Integer] The stream ID. + # @param encoded [String] Headers. + # @param end_stream [Boolean] add END_STREAM flag + # @param end_headers [Boolean] add END_HEADERS flag + def initialize(stream_id, encoded, end_stream: false, end_headers: false) + fval = end_stream ? 1 : 0 + fval += 4 if end_headers + initialize_base(type_value: 1, stream_id: stream_id, flags_value: fval, payload: encoded) + end + + # Splits this frame into multiple frames not to exceed MAX_FRAME_SIZE. + # @param max [Integer] The maximum size of a frame payload. + # @yield [Frame] The splitted frames. + def split(max) + return yield self if @length <= max + first, *mid, last = @payload.chunk(max) + yield Frame.craft(type_value: @type_value, stream_id: @stream_id, payload: first, flags_value: @flags_value & ~4) + mid.each { |slice| + yield Frame.craft(type: :continuation, stream_id: @stream_id, payload: slice, flags_value: 0) + } + yield Frame.craft(type: :continuation, stream_id: @stream_id, payload: last, flags_value: @flags_value & 4) + end + end +end diff --git a/lib/plum/frame/ping.rb b/lib/plum/frame/ping.rb new file mode 100644 index 0000000..b0b3804 --- /dev/null +++ b/lib/plum/frame/ping.rb @@ -0,0 +1,24 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Ping < Frame + register_subclass 0x06 + + # Creates a PING frame. + # @overload ping(ack, payload) + # @param ack [Symbol] Pass :ack to create an ACK frame. + # @param payload [String] 8 bytes length data to send. + # @overload ping(payload = "plum\x00\x00\x00\x00") + # @param payload [String] 8 bytes length data to send. + def initialize(arg1 = "plum\x00\x00\x00\x00".b, arg2 = nil) + if !arg2 + raise ArgumentError.new("data must be 8 octets") if arg1.bytesize != 8 + arg1 = arg1.b if arg1.encoding != Encoding::BINARY + initialize_base(type: :ping, stream_id: 0, payload: arg1) + else + initialize_base(type: :ping, stream_id: 0, flags: [:ack], payload: arg2) + end + end + end +end diff --git a/lib/plum/frame/priority.rb b/lib/plum/frame/priority.rb new file mode 100644 index 0000000..2d081ce --- /dev/null +++ b/lib/plum/frame/priority.rb @@ -0,0 +1,12 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Priority < Frame + register_subclass 0x02 + + # Creates a PRIORITY frame. + def initialize + end + end +end diff --git a/lib/plum/frame/push_promise.rb b/lib/plum/frame/push_promise.rb new file mode 100644 index 0000000..e07b8e6 --- /dev/null +++ b/lib/plum/frame/push_promise.rb @@ -0,0 +1,33 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::PushPromise < Frame + register_subclass 0x05 + + # Creates a PUSH_PROMISE frame. + # @param stream_id [Integer] The stream ID. + # @param new_id [Integer] The stream ID to create. + # @param encoded [String] Request headers. + # @param end_headers [Boolean] add END_HEADERS flag + def initialize(stream_id, new_id, encoded, end_headers: false) + payload = String.new.push_uint32(new_id) + .push(encoded) + fval = end_headers ? 4 : 0 + initialize_base(type: :push_promise, stream_id: stream_id, flags_value: fval, payload: payload) + end + + # Splits this frame into multiple frames not to exceed MAX_FRAME_SIZE. + # @param max [Integer] The maximum size of a frame payload. + # @yield [Frame] The splitted frames. + def split(max) + return yield self if @length <= max + first, *mid, last = @payload.chunk(max) + yield Frame.craft(type_value: @type_value, stream_id: @stream_id, payload: first, flags_value: @flags_value & ~4) + mid.each { |slice| + yield Frame.craft(type: :continuation, stream_id: @stream_id, payload: slice, flags_value: 0) + } + yield Frame.craft(type: :continuation, stream_id: @stream_id, payload: last, flags_value: @flags_value & 4) + end + end +end diff --git a/lib/plum/frame/rst_stream.rb b/lib/plum/frame/rst_stream.rb new file mode 100644 index 0000000..a8004d5 --- /dev/null +++ b/lib/plum/frame/rst_stream.rb @@ -0,0 +1,16 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::RstStream < Frame + register_subclass 0x03 + + # Creates a RST_STREAM frame. + # @param stream_id [Integer] The stream ID. + # @param error_type [Symbol] The error type defined in RFC 7540 Section 7. + def initialize(stream_id, error_type) + payload = String.new.push_uint32(HTTPError::ERROR_CODES[error_type]) + initialize_base(type: :rst_stream, stream_id: stream_id, payload: payload) + end + end +end diff --git a/lib/plum/frame/settings.rb b/lib/plum/frame/settings.rb new file mode 100644 index 0000000..3bd13d4 --- /dev/null +++ b/lib/plum/frame/settings.rb @@ -0,0 +1,43 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Settings < Frame + register_subclass 0x04 + + SETTINGS_TYPE = { + header_table_size: 0x01, + enable_push: 0x02, + max_concurrent_streams: 0x03, + initial_window_size: 0x04, + max_frame_size: 0x05, + max_header_list_size: 0x06 + }.freeze + + # Creates a SETTINGS frame. + # @param ack [Symbol] Pass :ack to create an ACK frame. + # @param args [Hash<Symbol, Integer>] The settings values to send. + def initialize(ack = nil, **args) + payload = String.new + args.each { |key, value| + id = SETTINGS_TYPE[key] or raise ArgumentError.new("invalid settings type: #{key}") + payload.push_uint16(id) + payload.push_uint32(value) + } + initialize_base(type: :settings, stream_id: 0, flags: [ack], payload: payload) + end + + # Parses SETTINGS frame payload. Ignores unknown settings type (see RFC7540 6.5.2). + # @return [Hash<Symbol, Integer>] The parsed strings. + def parse_settings + settings = {} + payload.each_byteslice(6) do |param| + id = param.uint16 + name = SETTINGS_TYPE.key(id) + # ignore unknown settings type + settings[name] = param.uint32(2) if name + end + settings + end + end +end diff --git a/lib/plum/frame/unknown.rb b/lib/plum/frame/unknown.rb new file mode 100644 index 0000000..6e9decb --- /dev/null +++ b/lib/plum/frame/unknown.rb @@ -0,0 +1,12 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::Unknown < Frame + # Creates a frame with unknown type value. + def initialize(type_value, **args) + initialize_base(type_value: type_value, **args) + end + end +end + diff --git a/lib/plum/frame/window_update.rb b/lib/plum/frame/window_update.rb new file mode 100644 index 0000000..6e36b2c --- /dev/null +++ b/lib/plum/frame/window_update.rb @@ -0,0 +1,16 @@ +# frozen-string-literal: true + +using Plum::BinaryString +module Plum + class Frame::WindowUpdate < Frame + register_subclass 0x08 + + # Creates a WINDOW_UPDATE frame. + # @param stream_id [Integer] the stream ID or 0. + # @param wsi [Integer] the amount to increase + def initialize(stream_id, wsi) + payload = String.new.push_uint32(wsi) + initialize_base(type: :window_update, stream_id: stream_id, payload: payload) + end + end +end diff --git a/lib/plum/server/http_connection.rb b/lib/plum/server/http_connection.rb index b257137..1cf80dc 100644 --- a/lib/plum/server/http_connection.rb +++ b/lib/plum/server/http_connection.rb @@ -49,7 +49,7 @@ module Plum def switch_protocol(settings, parser, headers, data) self.on(:negotiated) { - _frame = Frame.new(type: :settings, stream_id: 0, payload: Base64.urlsafe_decode64(settings)) + _frame = Frame.craft(type: :settings, stream_id: 0, payload: Base64.urlsafe_decode64(settings)) receive_settings(_frame, send_ack: false) # HTTP2-Settings process_first_request(parser, headers, data) } @@ -71,8 +71,8 @@ module Plum ":authority" => headers["host"] }) .reject { |n, v| ["connection", "http2-settings", "upgrade", "host"].include?(n) } - stream.receive_frame Frame.headers(1, encoder.encode(nheaders), end_headers: true) - stream.receive_frame Frame.data(1, body, end_stream: true) + stream.receive_frame Frame::Headers.new(1, encoder.encode(nheaders), end_headers: true) + stream.receive_frame Frame::Data.new(1, body, end_stream: true) end end end diff --git a/lib/plum/stream.rb b/lib/plum/stream.rb index 733aeaf..420ee23 100644 --- a/lib/plum/stream.rb +++ b/lib/plum/stream.rb @@ -53,7 +53,7 @@ module Plum end rescue RemoteStreamError => e callback(:stream_error, e) - send_immediately Frame.rst_stream(id, e.http2_error_type) + send_immediately Frame::RstStream.new(id, e.http2_error_type) close end @@ -97,7 +97,7 @@ module Plum def promise(headers) stream = @connection.reserve_stream(weight: self.weight + 1, parent: self) encoded = @connection.hpack_encoder.encode(headers) - frame = Frame.push_promise(id, stream.id, encoded, end_headers: true) + frame = Frame::PushPromise.new(id, stream.id, encoded, end_headers: true) send frame stream end @@ -107,7 +107,7 @@ module Plum # @param end_stream [Boolean] Set END_STREAM flag or not. def send_headers(headers, end_stream:) encoded = @connection.hpack_encoder.encode(headers) - frame = Frame.headers(id, encoded, end_headers: true, end_stream: end_stream) + frame = Frame::Headers.new(id, encoded, end_headers: true, end_stream: end_stream) send frame @state = :half_closed_local if end_stream end @@ -120,10 +120,10 @@ module Plum if data.is_a?(IO) until data.eof? fragment = data.readpartial(max) - send Frame.data(id, fragment, end_stream: end_stream && data.eof?) + send Frame::Data.new(id, fragment, end_stream: end_stream && data.eof?) end else - send Frame.data(id, data, end_stream: end_stream) + send Frame::Data.new(id, data, end_stream: end_stream) end @state = :half_closed_local if end_stream end |