protocol-http2 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/protocol/http2/connection.rb +45 -28
- data/lib/protocol/http2/stream.rb +10 -2
- data/lib/protocol/http2/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5f71a68091b631d1c6a776ae1730539cf753ee6ec24d27dc3b1d739dd971426
|
4
|
+
data.tar.gz: ea202fecbfe30bfbe0b9facf5d507f09344a2a959822be6f22d2d082cf273477
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d1a0a6e6a8461e985fcb9dc83e64c622743cb3d05e52d3b72f1b8a0f48d8190ac01417070807ada1d4ee0434dd7daa775d054ca89d54ba2010d6c153d9fad91
|
7
|
+
data.tar.gz: a17e3d970e3a2539361f518aff2ccc5ec40ca77f9b639a0b6bd69aabab1d0ade8a2e1f7049c08f5a001acfa9eb2fca4c5f2e785475d09e0c21c8088cec050d97
|
@@ -31,7 +31,6 @@ module Protocol
|
|
31
31
|
def initialize(framer, local_stream_id)
|
32
32
|
@state = :new
|
33
33
|
@streams = {}
|
34
|
-
@closed = 0
|
35
34
|
|
36
35
|
@framer = framer
|
37
36
|
@local_stream_id = local_stream_id
|
@@ -76,28 +75,22 @@ module Protocol
|
|
76
75
|
# Our window for sending data. When we send data, it reduces this window.
|
77
76
|
attr :remote_window
|
78
77
|
|
78
|
+
# The highest stream_id that has been successfully accepted by this connection.
|
79
|
+
attr :remote_stream_id
|
80
|
+
|
79
81
|
def closed?
|
80
82
|
@state == :closed
|
81
83
|
end
|
82
84
|
|
83
|
-
def
|
84
|
-
@
|
85
|
-
end
|
86
|
-
|
87
|
-
def active_stream_count
|
88
|
-
@streams.size - @closed
|
85
|
+
def active_streams
|
86
|
+
@streams.each_value.select(&:active?)
|
89
87
|
end
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
send_goaway(error, message)
|
95
|
-
|
96
|
-
self.close
|
97
|
-
end
|
98
|
-
|
99
|
-
def close
|
89
|
+
# Close the underlying framer and all streams.
|
90
|
+
def close(error = nil)
|
100
91
|
@framer.close
|
92
|
+
|
93
|
+
@streams.each_value{|stream| stream.close(error)}
|
101
94
|
end
|
102
95
|
|
103
96
|
def encode_headers(headers, buffer = String.new.b)
|
@@ -121,31 +114,45 @@ module Protocol
|
|
121
114
|
|
122
115
|
attr :streams
|
123
116
|
|
117
|
+
# 6.8. GOAWAY
|
118
|
+
# There is an inherent race condition between an endpoint starting new streams and the remote sending a GOAWAY frame. To deal with this case, the GOAWAY contains the stream identifier of the last peer-initiated stream that was or might be processed on the sending endpoint in this connection. For instance, if the server sends a GOAWAY frame, the identified stream is the highest-numbered stream initiated by the client.
|
119
|
+
# Once sent, the sender will ignore frames sent on streams initiated by the receiver if the stream has an identifier higher than the included last stream identifier. Receivers of a GOAWAY frame MUST NOT open additional streams on the connection, although a new connection can be established for new streams.
|
120
|
+
def ignore_frame?(frame)
|
121
|
+
if self.closed?
|
122
|
+
puts "ignore_frame? #{frame.stream_id} -> #{valid_remote_stream_id?(frame.stream_id)} > #{@remote_stream_id}"
|
123
|
+
if valid_remote_stream_id?(frame.stream_id)
|
124
|
+
return frame.stream_id > @remote_stream_id
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Reads one frame from the network and processes. Processing the frame updates the state of the connection and related streams. If the frame triggers an error, e.g. a protocol error, the connection will typically emit a goaway frame and re-raise the exception. You should continue processing frames until the underlying connection is closed.
|
124
130
|
def read_frame
|
125
131
|
frame = @framer.read_frame(@local_settings.maximum_frame_size)
|
126
|
-
# puts "#{self.class} #{@state} read_frame: class=#{frame.class} flags=#{frame.flags} length=#{frame.length}"
|
132
|
+
# puts "#{self.class} #{@state} read_frame: class=#{frame.class} stream_id=#{frame.stream_id} flags=#{frame.flags} length=#{frame.length} (remote_stream_id=#{@remote_stream_id})"
|
127
133
|
# puts "Windows: local_window=#{@local_window.inspect}; remote_window=#{@remote_window.inspect}"
|
128
134
|
|
129
|
-
|
135
|
+
return if ignore_frame?(frame)
|
130
136
|
|
137
|
+
yield frame if block_given?
|
131
138
|
frame.apply(self)
|
132
139
|
|
133
140
|
return frame
|
134
|
-
rescue GoawayError
|
135
|
-
#
|
136
|
-
self.close
|
141
|
+
rescue GoawayError => error
|
142
|
+
# Go directly to jail. Do not pass go, do not collect $200.
|
143
|
+
self.close(error)
|
137
144
|
|
138
145
|
raise
|
139
146
|
rescue ProtocolError => error
|
140
|
-
|
147
|
+
send_goaway(error.code || PROTOCOL_ERROR, error.message)
|
141
148
|
|
142
149
|
raise
|
143
150
|
rescue HPACK::CompressionError => error
|
144
|
-
|
151
|
+
send_goaway(COMPRESSION_ERROR, error.message)
|
145
152
|
|
146
153
|
raise
|
147
154
|
rescue
|
148
|
-
|
155
|
+
send_goaway(PROTOCOL_ERROR, $!.message)
|
149
156
|
|
150
157
|
raise
|
151
158
|
end
|
@@ -159,21 +166,31 @@ module Protocol
|
|
159
166
|
write_frame(frame)
|
160
167
|
end
|
161
168
|
|
169
|
+
# Transition the connection into the closed state.
|
170
|
+
def close!
|
171
|
+
@state = :closed
|
172
|
+
|
173
|
+
return self
|
174
|
+
end
|
175
|
+
|
176
|
+
# Tell the remote end that the connection is being shut down. If the `error_code` is 0, this is a graceful shutdown. The other end of the connection should not make any new streams, but existing streams may be completed.
|
162
177
|
def send_goaway(error_code = 0, message = "")
|
163
178
|
frame = GoawayFrame.new
|
164
179
|
frame.pack @remote_stream_id, error_code, message
|
165
180
|
|
166
181
|
write_frame(frame)
|
167
182
|
|
168
|
-
|
183
|
+
self.close!
|
169
184
|
end
|
170
185
|
|
171
186
|
def receive_goaway(frame)
|
172
|
-
|
187
|
+
# We capture the last stream that was processed.
|
188
|
+
@remote_stream_id, error_code, message = frame.unpack
|
173
189
|
|
174
|
-
|
190
|
+
self.close!
|
175
191
|
|
176
192
|
if error_code != 0
|
193
|
+
# Shut down immediately.
|
177
194
|
raise GoawayError.new(message, error_code)
|
178
195
|
end
|
179
196
|
end
|
@@ -336,7 +353,7 @@ module Protocol
|
|
336
353
|
if stream = @streams[frame.stream_id]
|
337
354
|
stream.receive_headers(frame)
|
338
355
|
else
|
339
|
-
if self.
|
356
|
+
if self.active_streams.count < self.maximum_concurrent_streams
|
340
357
|
stream = accept_stream(frame.stream_id)
|
341
358
|
stream.receive_headers(frame)
|
342
359
|
else
|
@@ -90,6 +90,10 @@ module Protocol
|
|
90
90
|
@connection.streams[@id] = self
|
91
91
|
end
|
92
92
|
|
93
|
+
# The stream is being closed because the connection is being closed.
|
94
|
+
def close(error = nil)
|
95
|
+
end
|
96
|
+
|
93
97
|
# Stream ID (odd for client initiated streams, even otherwise).
|
94
98
|
attr :id
|
95
99
|
|
@@ -118,6 +122,10 @@ module Protocol
|
|
118
122
|
@connection.write_frame(frame)
|
119
123
|
end
|
120
124
|
|
125
|
+
def active?
|
126
|
+
@state != :closed && @state != :idle
|
127
|
+
end
|
128
|
+
|
121
129
|
def closed?
|
122
130
|
@state == :closed
|
123
131
|
end
|
@@ -217,11 +225,11 @@ module Protocol
|
|
217
225
|
end
|
218
226
|
end
|
219
227
|
|
220
|
-
#
|
228
|
+
# Transition the stream into the closed state.
|
221
229
|
def close!
|
222
230
|
@state = :closed
|
223
231
|
|
224
|
-
|
232
|
+
self.close
|
225
233
|
end
|
226
234
|
|
227
235
|
def send_reset_stream(error_code = 0)
|