lib/http/2/stream.rb in http-2-0.11.0 vs lib/http/2/stream.rb in http-2-0.12.0

- old
+ new

@@ -1,5 +1,7 @@ +# frozen_string_literal: true + module HTTP2 # A single HTTP 2.0 connection can multiplex multiple streams in parallel: # multiple requests and responses can be in flight simultaneously and stream # data can be interleaved and prioritized. # @@ -47,15 +49,14 @@ # Request parent stream of push stream. attr_reader :parent # Stream priority as set by initiator. attr_reader :weight - attr_reader :dependency + attr_reader :dependency, :remote_window # Size of current stream flow control window. attr_reader :local_window - attr_reader :remote_window alias window local_window # Reason why connection was closed. attr_reader :closed @@ -118,13 +119,11 @@ when :altsvc # 4. The ALTSVC HTTP/2 Frame # An ALTSVC frame on a # stream other than stream 0 containing non-empty "Origin" information # is invalid and MUST be ignored. - if !frame[:origin] || frame[:origin].empty? - emit(frame[:type], frame) - end + emit(frame[:type], frame) if !frame[:origin] || frame[:origin].empty? when :blocked emit(frame[:type], frame) end complete_transition(frame) @@ -168,11 +167,11 @@ send(type: :headers, flags: flags, payload: headers) end def promise(headers, end_headers: true, &block) - fail ArgumentError, 'must provide callback' unless block_given? + raise ArgumentError, 'must provide callback' unless block_given? flags = end_headers ? [:end_headers] : [] emit(:promise, self, headers, flags, &block) end @@ -241,10 +240,11 @@ # # @param increment [Integer] def window_update(increment) # emit stream-level WINDOW_UPDATE unless stream is closed return if @state == :closed || @state == :remote_closed + send(type: :window_update, increment: increment) end private @@ -343,22 +343,22 @@ # Receiving any type of frame other than RST_STREAM, PRIORITY or # WINDOW_UPDATE on a stream in this state MUST be treated as a # connection error (Section 5.4.1) of type PROTOCOL_ERROR. when :reserved_local @state = if sending - case frame[:type] - when :headers then event(:half_closed_remote) - when :rst_stream then event(:local_rst) - else stream_error - end - else - case frame[:type] - when :rst_stream then event(:remote_rst) - when :priority, :window_update then @state - else stream_error - end - end + case frame[:type] + when :headers then event(:half_closed_remote) + when :rst_stream then event(:local_rst) + else stream_error + end + else + case frame[:type] + when :rst_stream then event(:remote_rst) + when :priority, :window_update then @state + else stream_error + end + end # A stream in the "reserved (remote)" state has been reserved by a # remote peer. # In this state, only the following transitions are possible: # * Receiving a HEADERS frame causes the stream to transition to @@ -372,22 +372,22 @@ # Receiving any type of frame other than HEADERS, RST_STREAM or # PRIORITY on a stream in this state MUST be treated as a connection # error (Section 5.4.1) of type PROTOCOL_ERROR. when :reserved_remote @state = if sending - case frame[:type] - when :rst_stream then event(:local_rst) - when :priority, :window_update then @state - else stream_error - end - else - case frame[:type] - when :headers then event(:half_closed_local) - when :rst_stream then event(:remote_rst) - else stream_error - end - end + case frame[:type] + when :rst_stream then event(:local_rst) + when :priority, :window_update then @state + else stream_error + end + else + case frame[:type] + when :headers then event(:half_closed_local) + when :rst_stream then event(:remote_rst) + else stream_error + end + end # A stream in the "open" state may be used by both peers to send # frames of any type. In this state, sending peers observe # advertised stream level flow control limits (Section 5.2). # From this state either endpoint can send a frame with an @@ -521,30 +521,28 @@ # even if the associated stream has been reset. Therefore, a # RST_STREAM is needed to close an unwanted promised stream. when :closed if sending case frame[:type] - when :rst_stream then # ignore - when :priority then + when :rst_stream # ignore + when :priority process_priority(frame) else - stream_error(:stream_closed) unless (frame[:type] == :rst_stream) + stream_error(:stream_closed) unless frame[:type] == :rst_stream end + elsif frame[:type] == :priority + process_priority(frame) else - if frame[:type] == :priority - process_priority(frame) - else - case @closed - when :remote_rst, :remote_closed - case frame[:type] - when :rst_stream, :window_update # nop here - else - stream_error(:stream_closed) - end - when :local_rst, :local_closed - frame[:ignore] = true if frame[:type] != :window_update + case @closed + when :remote_rst, :remote_closed + case frame[:type] + when :rst_stream, :window_update # nop here + else + stream_error(:stream_closed) end + when :local_rst, :local_closed + frame[:ignore] = true if frame[:type] != :window_update end end end end @@ -585,13 +583,13 @@ def process_priority(frame) @weight = frame[:weight] @dependency = frame[:stream_dependency] emit( :priority, - weight: frame[:weight], + weight: frame[:weight], dependency: frame[:stream_dependency], - exclusive: frame[:exclusive], + exclusive: frame[:exclusive] ) # TODO: implement dependency tree housekeeping # Latest draft defines a fairly complex priority control. # See https://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-5.3 # We currently have no prioritization among streams. @@ -599,20 +597,22 @@ end def end_stream?(frame) case frame[:type] when :data, :headers, :continuation + return false unless frame[:flags] + frame[:flags].include?(:end_stream) else false end end def stream_error(error = :internal_error, msg: nil) @error = error close(error) if @state != :closed klass = error.to_s.split('_').map(&:capitalize).join - fail Error.const_get(klass), msg + raise Error.const_get(klass), msg end alias error stream_error def manage_state(frame) transition(frame, true)