protocol-http2 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|