protocol-http2 0.10.4 → 0.11.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/.travis.yml +1 -0
- data/lib/protocol/http2/connection.rb +32 -43
- data/lib/protocol/http2/dependency.rb +151 -0
- data/lib/protocol/http2/flow_control.rb +1 -1
- data/lib/protocol/http2/stream.rb +28 -132
- data/lib/protocol/http2/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 014c5404c1c741f09ed296d51da864e5e50ed7ecf336da2d2360fe8bed69fff8
|
4
|
+
data.tar.gz: 8f7e6fcbedfe36e3eaea28f8e1fabd7488c82f0465dad54927a1a9216a191465
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d9f8ff2e36fdabb2aa72afd3903d410d0d0ebc660a78a865de6610768629d682f41e90ea39ece505159a97f50a4b87d6cb061c99af2759e0a4901b8a3275f9f
|
7
|
+
data.tar.gz: c66a7bf1538d34011cb2b40aa8ea1502079c88c8709cd6969216da8b355f26b301fd6e58e65b8e296333a2b4fc5f68a552f02b14fe15d8bad4c40fc378e0b077
|
data/.travis.yml
CHANGED
@@ -19,7 +19,7 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require_relative 'framer'
|
22
|
-
require_relative '
|
22
|
+
require_relative 'dependency'
|
23
23
|
|
24
24
|
require 'protocol/hpack'
|
25
25
|
|
@@ -32,10 +32,13 @@ module Protocol
|
|
32
32
|
super()
|
33
33
|
|
34
34
|
@state = :new
|
35
|
+
|
36
|
+
# Hash(Integer, Stream)
|
35
37
|
@streams = {}
|
36
|
-
@children = {}
|
37
38
|
|
38
|
-
|
39
|
+
# Hash(Integer, Dependency)
|
40
|
+
@dependency = Dependency.new(self, 0)
|
41
|
+
@dependencies = {0 => @dependency}
|
39
42
|
|
40
43
|
@framer = framer
|
41
44
|
@local_stream_id = local_stream_id
|
@@ -59,6 +62,10 @@ module Protocol
|
|
59
62
|
nil
|
60
63
|
end
|
61
64
|
|
65
|
+
def children
|
66
|
+
@dependency.streams
|
67
|
+
end
|
68
|
+
|
62
69
|
def [] id
|
63
70
|
if id.zero?
|
64
71
|
self
|
@@ -99,24 +106,18 @@ module Protocol
|
|
99
106
|
@state == :closed
|
100
107
|
end
|
101
108
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
def deactivate(stream)
|
109
|
-
@active -= 1
|
110
|
-
end
|
111
|
-
|
112
|
-
# The number of active streams.
|
113
|
-
def active_streams
|
114
|
-
@active
|
109
|
+
def delete(id)
|
110
|
+
@streams.delete(id)
|
111
|
+
|
112
|
+
if dependency = @dependencies[id]
|
113
|
+
dependency.delete! if dependency.irrelevant?
|
114
|
+
end
|
115
115
|
end
|
116
116
|
|
117
117
|
# Close the underlying framer and all streams.
|
118
118
|
def close(error = nil)
|
119
119
|
@framer.close
|
120
|
+
# @framer = nil
|
120
121
|
|
121
122
|
@streams.each_value{|stream| stream.close(error)}
|
122
123
|
end
|
@@ -139,26 +140,19 @@ module Protocol
|
|
139
140
|
end
|
140
141
|
|
141
142
|
attr :streams
|
142
|
-
attr :
|
143
|
-
|
144
|
-
def add_child(stream)
|
145
|
-
@children[stream.id] = stream
|
146
|
-
end
|
143
|
+
attr :dependencies
|
147
144
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
145
|
+
# Fetch (or create) the flow control windows for the specified stream id.
|
146
|
+
# @param id [Integer] the stream id.
|
147
|
+
def dependency_for(id)
|
148
|
+
@dependencies.fetch(id) do
|
149
|
+
dependency = Dependency.new(self, id)
|
150
|
+
|
151
|
+
# TODO this might be irrelevant, if initially processing priority frame.
|
152
|
+
@dependency.add_child(dependency)
|
153
|
+
|
154
|
+
@dependencies[id] = dependency
|
157
155
|
end
|
158
|
-
|
159
|
-
@children = {stream.id => stream}
|
160
|
-
|
161
|
-
stream.dependent_id = 0
|
162
156
|
end
|
163
157
|
|
164
158
|
# 6.8. GOAWAY
|
@@ -398,7 +392,7 @@ module Protocol
|
|
398
392
|
raise ProtocolError, "Invalid stream id: #{stream_id} <= #{@remote_stream_id}!"
|
399
393
|
end
|
400
394
|
|
401
|
-
if
|
395
|
+
if @streams.size < self.maximum_concurrent_streams
|
402
396
|
stream = accept_stream(stream_id)
|
403
397
|
@remote_stream_id = stream_id
|
404
398
|
|
@@ -418,13 +412,8 @@ module Protocol
|
|
418
412
|
|
419
413
|
# Sets the priority for an incoming stream.
|
420
414
|
def receive_priority(frame)
|
421
|
-
|
422
|
-
|
423
|
-
else
|
424
|
-
# Stream doesn't exist yet.
|
425
|
-
stream = accept_stream(frame.stream_id)
|
426
|
-
stream.receive_priority(frame)
|
427
|
-
end
|
415
|
+
dependency = dependency_for(frame.stream_id)
|
416
|
+
dependency.receive_priority(frame)
|
428
417
|
end
|
429
418
|
|
430
419
|
def receive_push_promise(frame)
|
@@ -450,7 +439,7 @@ module Protocol
|
|
450
439
|
rescue ProtocolError => error
|
451
440
|
stream.send_reset_stream(error.code)
|
452
441
|
end
|
453
|
-
|
442
|
+
elsif frame.stream_id > @remote_stream_id
|
454
443
|
# Receiving any frame other than HEADERS or PRIORITY on a stream in this state MUST be treated as a connection error of type PROTOCOL_ERROR.
|
455
444
|
raise ProtocolError, "Cannot update window of idle stream #{frame.stream_id}"
|
456
445
|
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require_relative 'flow_control'
|
22
|
+
|
23
|
+
module Protocol
|
24
|
+
module HTTP2
|
25
|
+
DEFAULT_WEIGHT = 16
|
26
|
+
|
27
|
+
class Dependency
|
28
|
+
def initialize(connection, id, dependent_id = 0, weight = DEFAULT_WEIGHT, children = nil)
|
29
|
+
@connection = connection
|
30
|
+
@id = id
|
31
|
+
|
32
|
+
# Stream priority:
|
33
|
+
@dependent_id = dependent_id
|
34
|
+
@weight = weight
|
35
|
+
|
36
|
+
# A cache of dependencies that have child.dependent_id = self.id
|
37
|
+
@children = children
|
38
|
+
end
|
39
|
+
|
40
|
+
def irrelevant?
|
41
|
+
(@weight == DEFAULT_WEIGHT) && (@children.nil? || @children.empty?)
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete!
|
45
|
+
@connection.dependencies.delete(@id)
|
46
|
+
self.parent&.remove_child(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Cache of dependent children.
|
50
|
+
attr_accessor :children
|
51
|
+
|
52
|
+
# The connection this stream belongs to.
|
53
|
+
attr :connection
|
54
|
+
|
55
|
+
# Stream ID (odd for client initiated streams, even otherwise).
|
56
|
+
attr :id
|
57
|
+
|
58
|
+
# The stream id that this stream depends on, according to the priority.
|
59
|
+
attr_accessor :dependent_id
|
60
|
+
|
61
|
+
# The weight of the stream relative to other siblings.
|
62
|
+
attr_accessor :weight
|
63
|
+
|
64
|
+
def stream
|
65
|
+
@connection.streams[@id]
|
66
|
+
end
|
67
|
+
|
68
|
+
def streams
|
69
|
+
if @children
|
70
|
+
# TODO this O(N) operation affects performance.
|
71
|
+
# It would be better to maintain a sorted list of children streams.
|
72
|
+
@children.map{|id, dependency| dependency.stream}.compact
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_child(dependency)
|
77
|
+
@children ||= {}
|
78
|
+
@children[dependency.id] = dependency
|
79
|
+
end
|
80
|
+
|
81
|
+
def remove_child(dependency)
|
82
|
+
@children&.delete(dependency.id)
|
83
|
+
end
|
84
|
+
|
85
|
+
def exclusive_child(parent)
|
86
|
+
parent.children = @children
|
87
|
+
|
88
|
+
@children.each_value do |child|
|
89
|
+
child.dependent_id = parent.id
|
90
|
+
end
|
91
|
+
|
92
|
+
@children = {parent.id => parent}
|
93
|
+
|
94
|
+
parent.dependent_id = @id
|
95
|
+
end
|
96
|
+
|
97
|
+
def parent(id = @dependent_id)
|
98
|
+
@connection.dependency_for(id)
|
99
|
+
end
|
100
|
+
|
101
|
+
def parent= dependency
|
102
|
+
self.parent&.remove_child(self)
|
103
|
+
|
104
|
+
@dependent_id = dependency.id
|
105
|
+
|
106
|
+
dependency.add_child(self)
|
107
|
+
end
|
108
|
+
|
109
|
+
def process_priority priority
|
110
|
+
dependent_id = priority.stream_dependency
|
111
|
+
|
112
|
+
if dependent_id == @id
|
113
|
+
raise ProtocolError, "Stream priority for stream id #{@id} cannot depend on itself!"
|
114
|
+
end
|
115
|
+
|
116
|
+
@weight = priority.weight
|
117
|
+
|
118
|
+
if priority.exclusive
|
119
|
+
self.parent&.remove_child(self)
|
120
|
+
|
121
|
+
self.parent(dependent_id).exclusive_child(self)
|
122
|
+
elsif dependent_id != @dependent_id
|
123
|
+
self.parent&.remove_child(self)
|
124
|
+
|
125
|
+
@dependent_id = dependent_id
|
126
|
+
|
127
|
+
self.parent.add_child(self)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Change the priority of the stream both locally and remotely.
|
132
|
+
def priority= priority
|
133
|
+
send_priority(priority)
|
134
|
+
process_priority(priority)
|
135
|
+
end
|
136
|
+
|
137
|
+
# The current local priority of the stream.
|
138
|
+
def priority(exclusive = false)
|
139
|
+
Priority.new(exclusive, @dependent_id, @weight)
|
140
|
+
end
|
141
|
+
|
142
|
+
def send_priority(priority)
|
143
|
+
@connection.send_priority(@id, priority)
|
144
|
+
end
|
145
|
+
|
146
|
+
def receive_priority(frame)
|
147
|
+
self.process_priority(frame.unpack)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -115,7 +115,7 @@ module Protocol
|
|
115
115
|
|
116
116
|
# Allow the current flow-controlled instance to use up the window:
|
117
117
|
if !self.window_updated(size) and children = self.children
|
118
|
-
children = children.
|
118
|
+
children = children.sort_by(&:weight)
|
119
119
|
|
120
120
|
# This must always be at least >= `children.size`, since stream weight can't be 0.
|
121
121
|
total = children.sum(&:weight)
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require_relative 'connection'
|
22
|
-
require_relative '
|
22
|
+
require_relative 'dependency'
|
23
23
|
|
24
24
|
module Protocol
|
25
25
|
module HTTP2
|
@@ -74,142 +74,63 @@ module Protocol
|
|
74
74
|
class Stream
|
75
75
|
include FlowControl
|
76
76
|
|
77
|
-
def self.create(connection, id
|
78
|
-
|
79
|
-
remote_window = Window.new(connection.remote_settings.initial_window_size)
|
77
|
+
def self.create(connection, id)
|
78
|
+
stream = self.new(connection, id)
|
80
79
|
|
81
|
-
stream = self.new(connection, id, local_window, remote_window)
|
82
|
-
|
83
|
-
# Create new stream:
|
84
80
|
connection.streams[id] = stream
|
85
|
-
stream.parent.add_child(stream)
|
86
|
-
|
87
|
-
return stream
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.replace(stream)
|
91
|
-
connection = stream.connection
|
92
|
-
stream.parent.remove_child(stream)
|
93
|
-
|
94
|
-
stream = self.new(
|
95
|
-
connection, stream.id, stream.local_window, stream.remote_window,
|
96
|
-
stream.state, stream.dependent_id, stream.weight, stream.children
|
97
|
-
)
|
98
|
-
|
99
|
-
# Replace existing stream:
|
100
|
-
connection.streams[stream.id] = stream
|
101
|
-
stream.parent.add_child(stream)
|
102
81
|
|
103
82
|
return stream
|
104
83
|
end
|
105
84
|
|
106
|
-
def
|
107
|
-
if stream = connection.streams[id]
|
108
|
-
self.replace(stream)
|
109
|
-
else
|
110
|
-
self.create(connection, id)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def initialize(connection, id, local_window, remote_window, state = :idle, dependent_id = 0, weight = 16, children = nil)
|
85
|
+
def initialize(connection, id, state = :idle)
|
115
86
|
@connection = connection
|
116
87
|
@id = id
|
117
88
|
|
118
|
-
@local_window = local_window
|
119
|
-
@remote_window = remote_window
|
120
|
-
|
121
89
|
@state = state
|
122
90
|
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
|
127
|
-
# Stream priority:
|
128
|
-
@dependent_id = dependent_id
|
129
|
-
@weight = weight
|
91
|
+
@local_window = Window.new(@connection.local_settings.initial_window_size)
|
92
|
+
@remote_window = Window.new(@connection.remote_settings.initial_window_size)
|
130
93
|
|
131
|
-
|
132
|
-
@children = children
|
94
|
+
@dependency = @connection.dependency_for(@id)
|
133
95
|
end
|
134
96
|
|
135
|
-
# Cache of dependent children.
|
136
|
-
attr_accessor :children
|
137
|
-
|
138
97
|
# The connection this stream belongs to.
|
139
98
|
attr :connection
|
140
99
|
|
141
100
|
# Stream ID (odd for client initiated streams, even otherwise).
|
142
101
|
attr :id
|
143
|
-
|
102
|
+
|
144
103
|
# Stream state, e.g. `idle`, `closed`.
|
145
104
|
attr_accessor :state
|
146
105
|
|
147
|
-
|
148
|
-
attr_accessor :dependent_id
|
149
|
-
|
150
|
-
# The weight of the stream relative to other siblings.
|
151
|
-
attr_accessor :weight
|
106
|
+
attr :dependency
|
152
107
|
|
153
108
|
attr :local_window
|
154
109
|
attr :remote_window
|
155
110
|
|
156
|
-
def
|
157
|
-
@
|
158
|
-
@children[stream.id] = stream
|
111
|
+
def weight
|
112
|
+
@dependency.weight
|
159
113
|
end
|
160
114
|
|
161
|
-
def
|
162
|
-
@
|
115
|
+
def priority
|
116
|
+
@dependency.priority
|
163
117
|
end
|
164
118
|
|
165
|
-
def
|
166
|
-
|
167
|
-
|
168
|
-
@children.each_value do |child|
|
169
|
-
child.dependent_id = stream.id
|
170
|
-
end
|
171
|
-
|
172
|
-
@children = {stream.id => stream}
|
173
|
-
|
174
|
-
stream.dependent_id = @id
|
119
|
+
def priority= priority
|
120
|
+
@dependency.priority = priority
|
175
121
|
end
|
176
122
|
|
177
|
-
def parent(
|
178
|
-
@
|
123
|
+
def parent=(stream)
|
124
|
+
@dependency.parent = stream.dependency
|
179
125
|
end
|
180
126
|
|
181
|
-
def
|
182
|
-
|
183
|
-
|
184
|
-
@dependent_id = stream.id
|
185
|
-
|
186
|
-
stream.add_child(self)
|
187
|
-
end
|
188
|
-
|
189
|
-
def process_priority priority
|
190
|
-
dependent_id = priority.stream_dependency
|
191
|
-
|
192
|
-
if dependent_id == @id
|
193
|
-
raise ProtocolError, "Stream priority for stream id #{@id} cannot depend on itself!"
|
194
|
-
end
|
195
|
-
|
196
|
-
@weight = priority.weight
|
197
|
-
|
198
|
-
if priority.exclusive
|
199
|
-
self.parent&.remove_child(self)
|
200
|
-
|
201
|
-
self.parent(dependent_id).exclusive_child(self)
|
202
|
-
elsif dependent_id != @dependent_id
|
203
|
-
self.parent&.remove_child(self)
|
204
|
-
|
205
|
-
@dependent_id = dependent_id
|
206
|
-
|
207
|
-
self.parent.add_child(self)
|
208
|
-
end
|
127
|
+
def children
|
128
|
+
@dependency&.streams
|
209
129
|
end
|
210
130
|
|
211
131
|
# The stream is being closed because the connection is being closed.
|
212
132
|
def close(error = nil)
|
133
|
+
@connection.delete(@id)
|
213
134
|
end
|
214
135
|
|
215
136
|
def maximum_frame_size
|
@@ -315,7 +236,6 @@ module Protocol
|
|
315
236
|
def open!
|
316
237
|
if @state == :idle
|
317
238
|
@state = :open
|
318
|
-
@connection.activate(self)
|
319
239
|
else
|
320
240
|
raise ProtocolError, "Cannot open stream in state: #{@state}"
|
321
241
|
end
|
@@ -328,9 +248,6 @@ module Protocol
|
|
328
248
|
def close!(error_code = nil)
|
329
249
|
@state = :closed
|
330
250
|
|
331
|
-
@connection.deactivate(self)
|
332
|
-
self.parent&.remove_child(self)
|
333
|
-
|
334
251
|
if error_code
|
335
252
|
error = StreamError.new("Stream closed!", error_code)
|
336
253
|
end
|
@@ -353,7 +270,7 @@ module Protocol
|
|
353
270
|
end
|
354
271
|
end
|
355
272
|
|
356
|
-
|
273
|
+
def process_headers(frame)
|
357
274
|
# Receiving request headers:
|
358
275
|
priority, data = frame.unpack
|
359
276
|
|
@@ -376,23 +293,23 @@ module Protocol
|
|
376
293
|
open!
|
377
294
|
end
|
378
295
|
|
379
|
-
|
296
|
+
process_headers(frame)
|
380
297
|
elsif @state == :reserved_remote
|
381
|
-
|
298
|
+
process_headers(frame)
|
382
299
|
|
383
|
-
|
300
|
+
@state = :half_closed_local
|
384
301
|
elsif @state == :open
|
302
|
+
process_headers(frame)
|
303
|
+
|
385
304
|
if frame.end_stream?
|
386
305
|
@state = :half_closed_remote
|
387
306
|
end
|
388
|
-
|
389
|
-
return process_headers(frame)
|
390
307
|
elsif @state == :half_closed_local
|
308
|
+
process_headers(frame)
|
309
|
+
|
391
310
|
if frame.end_stream?
|
392
311
|
close!
|
393
312
|
end
|
394
|
-
|
395
|
-
return process_headers(frame)
|
396
313
|
elsif self.closed?
|
397
314
|
ignore_headers(frame)
|
398
315
|
else
|
@@ -435,25 +352,6 @@ module Protocol
|
|
435
352
|
end
|
436
353
|
end
|
437
354
|
|
438
|
-
# Change the priority of the stream both locally and remotely.
|
439
|
-
def priority= priority
|
440
|
-
send_priority(priority)
|
441
|
-
process_priority(priority)
|
442
|
-
end
|
443
|
-
|
444
|
-
# The current local priority of the stream.
|
445
|
-
def priority(exclusive = false)
|
446
|
-
Priority.new(exclusive, @dependent_id, @weight)
|
447
|
-
end
|
448
|
-
|
449
|
-
def send_priority(priority)
|
450
|
-
@connection.send_priority(@id, priority)
|
451
|
-
end
|
452
|
-
|
453
|
-
def receive_priority(frame)
|
454
|
-
self.process_priority(frame.unpack)
|
455
|
-
end
|
456
|
-
|
457
355
|
def ignore_reset_stream(frame)
|
458
356
|
# Async.logger.warn(self) {"Received reset stream (#{error_code}) in state: #{@state}!"}
|
459
357
|
end
|
@@ -493,7 +391,6 @@ module Protocol
|
|
493
391
|
def reserved_local!
|
494
392
|
if @state == :idle
|
495
393
|
@state = :reserved_local
|
496
|
-
@connection.activate(self)
|
497
394
|
else
|
498
395
|
raise ProtocolError, "Cannot reserve stream in state: #{@state}"
|
499
396
|
end
|
@@ -502,7 +399,6 @@ module Protocol
|
|
502
399
|
def reserved_remote!
|
503
400
|
if @state == :idle
|
504
401
|
@state = :reserved_remote
|
505
|
-
@connection.activate(self)
|
506
402
|
else
|
507
403
|
raise ProtocolError, "Cannot reserve stream in state: #{@state}"
|
508
404
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-http2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: protocol-hpack
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/protocol/http2/connection.rb
|
115
115
|
- lib/protocol/http2/continuation_frame.rb
|
116
116
|
- lib/protocol/http2/data_frame.rb
|
117
|
+
- lib/protocol/http2/dependency.rb
|
117
118
|
- lib/protocol/http2/error.rb
|
118
119
|
- lib/protocol/http2/extensions/sum.rb
|
119
120
|
- lib/protocol/http2/extensions/unpack.rb
|
@@ -152,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
153
|
- !ruby/object:Gem::Version
|
153
154
|
version: '0'
|
154
155
|
requirements: []
|
155
|
-
rubygems_version: 3.
|
156
|
+
rubygems_version: 3.1.2
|
156
157
|
signing_key:
|
157
158
|
specification_version: 4
|
158
159
|
summary: A low level implementation of the HTTP/2 protocol.
|