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)