http-2 0.10.2 → 0.12.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/README.md +0 -2
- data/lib/http/2/buffer.rb +6 -4
- data/lib/http/2/client.rb +5 -1
- data/lib/http/2/compressor.rb +44 -36
- data/lib/http/2/connection.rb +76 -89
- data/lib/http/2/emitter.rb +4 -1
- data/lib/http/2/error.rb +2 -0
- data/lib/http/2/flow_buffer.rb +8 -3
- data/lib/http/2/framer.rb +83 -94
- data/lib/http/2/huffman.rb +19 -17
- data/lib/http/2/server.rb +9 -7
- data/lib/http/2/stream.rb +48 -48
- data/lib/http/2/version.rb +3 -1
- data/lib/http/2.rb +2 -0
- metadata +10 -63
- data/.autotest +0 -20
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -20
- data/.gitmodules +0 -3
- data/.rspec +0 -5
- data/.rubocop.yml +0 -93
- data/.rubocop_todo.yml +0 -122
- data/.travis.yml +0 -14
- data/Gemfile +0 -16
- data/Guardfile +0 -18
- data/Guardfile.h2spec +0 -12
- data/Rakefile +0 -49
- data/example/Gemfile +0 -3
- data/example/README.md +0 -44
- data/example/client.rb +0 -122
- data/example/helper.rb +0 -19
- data/example/keys/server.crt +0 -20
- data/example/keys/server.key +0 -27
- data/example/server.rb +0 -139
- data/example/upgrade_client.rb +0 -153
- data/example/upgrade_server.rb +0 -203
- data/http-2.gemspec +0 -22
- data/lib/tasks/generate_huffman_table.rb +0 -166
- data/spec/buffer_spec.rb +0 -28
- data/spec/client_spec.rb +0 -188
- data/spec/compressor_spec.rb +0 -666
- data/spec/connection_spec.rb +0 -665
- data/spec/emitter_spec.rb +0 -54
- data/spec/framer_spec.rb +0 -487
- data/spec/h2spec/h2spec.darwin +0 -0
- data/spec/h2spec/output/non_secure.txt +0 -317
- data/spec/helper.rb +0 -147
- data/spec/hpack_test_spec.rb +0 -84
- data/spec/huffman_spec.rb +0 -68
- data/spec/server_spec.rb +0 -52
- data/spec/stream_spec.rb +0 -878
- data/spec/support/deep_dup.rb +0 -55
- data/spec/support/duplicable.rb +0 -98
data/lib/http/2/framer.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTP2
|
2
4
|
# Performs encoding, decoding, and validation of binary HTTP/2 frames.
|
3
5
|
#
|
4
|
-
# rubocop:disable ClassLength
|
5
6
|
class Framer
|
6
7
|
include Error
|
7
8
|
|
@@ -19,82 +20,82 @@ module HTTP2
|
|
19
20
|
|
20
21
|
# HTTP/2 frame type mapping as defined by the spec
|
21
22
|
FRAME_TYPES = {
|
22
|
-
data:
|
23
|
-
headers:
|
24
|
-
priority:
|
25
|
-
rst_stream:
|
26
|
-
settings:
|
27
|
-
push_promise:
|
28
|
-
ping:
|
29
|
-
goaway:
|
23
|
+
data: 0x0,
|
24
|
+
headers: 0x1,
|
25
|
+
priority: 0x2,
|
26
|
+
rst_stream: 0x3,
|
27
|
+
settings: 0x4,
|
28
|
+
push_promise: 0x5,
|
29
|
+
ping: 0x6,
|
30
|
+
goaway: 0x7,
|
30
31
|
window_update: 0x8,
|
31
|
-
continuation:
|
32
|
-
altsvc:
|
32
|
+
continuation: 0x9,
|
33
|
+
altsvc: 0xa
|
33
34
|
}.freeze
|
34
35
|
|
35
|
-
FRAME_TYPES_WITH_PADDING = [
|
36
|
+
FRAME_TYPES_WITH_PADDING = %i[data headers push_promise].freeze
|
36
37
|
|
37
38
|
# Per frame flags as defined by the spec
|
38
39
|
FRAME_FLAGS = {
|
39
40
|
data: {
|
40
|
-
end_stream:
|
41
|
+
end_stream: 0,
|
41
42
|
padded: 3,
|
42
|
-
compressed: 5
|
43
|
+
compressed: 5
|
43
44
|
},
|
44
45
|
headers: {
|
45
|
-
end_stream:
|
46
|
+
end_stream: 0,
|
46
47
|
end_headers: 2,
|
47
48
|
padded: 3,
|
48
|
-
priority: 5
|
49
|
+
priority: 5
|
49
50
|
},
|
50
|
-
priority:
|
51
|
-
rst_stream:
|
52
|
-
settings:
|
51
|
+
priority: {},
|
52
|
+
rst_stream: {},
|
53
|
+
settings: { ack: 0 },
|
53
54
|
push_promise: {
|
54
55
|
end_headers: 2,
|
55
|
-
padded: 3
|
56
|
+
padded: 3
|
56
57
|
},
|
57
|
-
ping:
|
58
|
-
goaway:
|
58
|
+
ping: { ack: 0 },
|
59
|
+
goaway: {},
|
59
60
|
window_update: {},
|
60
61
|
continuation: { end_headers: 2 },
|
61
|
-
altsvc: {}
|
62
|
+
altsvc: {}
|
62
63
|
}.each_value(&:freeze).freeze
|
63
64
|
|
64
65
|
# Default settings as defined by the spec
|
65
66
|
DEFINED_SETTINGS = {
|
66
|
-
settings_header_table_size:
|
67
|
-
settings_enable_push:
|
67
|
+
settings_header_table_size: 1,
|
68
|
+
settings_enable_push: 2,
|
68
69
|
settings_max_concurrent_streams: 3,
|
69
|
-
settings_initial_window_size:
|
70
|
-
settings_max_frame_size:
|
71
|
-
settings_max_header_list_size:
|
70
|
+
settings_initial_window_size: 4,
|
71
|
+
settings_max_frame_size: 5,
|
72
|
+
settings_max_header_list_size: 6
|
72
73
|
}.freeze
|
73
74
|
|
74
75
|
# Default error types as defined by the spec
|
75
76
|
DEFINED_ERRORS = {
|
76
|
-
no_error:
|
77
|
-
protocol_error:
|
78
|
-
internal_error:
|
77
|
+
no_error: 0,
|
78
|
+
protocol_error: 1,
|
79
|
+
internal_error: 2,
|
79
80
|
flow_control_error: 3,
|
80
|
-
settings_timeout:
|
81
|
-
stream_closed:
|
82
|
-
frame_size_error:
|
83
|
-
refused_stream:
|
84
|
-
cancel:
|
85
|
-
compression_error:
|
86
|
-
connect_error:
|
87
|
-
enhance_your_calm:
|
81
|
+
settings_timeout: 4,
|
82
|
+
stream_closed: 5,
|
83
|
+
frame_size_error: 6,
|
84
|
+
refused_stream: 7,
|
85
|
+
cancel: 8,
|
86
|
+
compression_error: 9,
|
87
|
+
connect_error: 10,
|
88
|
+
enhance_your_calm: 11,
|
88
89
|
inadequate_security: 12,
|
89
|
-
http_1_1_required:
|
90
|
+
http_1_1_required: 13
|
90
91
|
}.freeze
|
91
92
|
|
92
93
|
RBIT = 0x7fffffff
|
93
94
|
RBYTE = 0x0fffffff
|
94
95
|
EBIT = 0x80000000
|
95
|
-
UINT32 = 'N'
|
96
|
-
UINT16 = 'n'
|
97
|
-
UINT8 = 'C'
|
96
|
+
UINT32 = 'N'
|
97
|
+
UINT16 = 'n'
|
98
|
+
UINT8 = 'C'
|
98
99
|
HEADERPACK = (UINT8 + UINT16 + UINT8 + UINT8 + UINT32).freeze
|
99
100
|
FRAME_LENGTH_HISHIFT = 16
|
100
101
|
FRAME_LENGTH_LOMASK = 0xFFFF
|
@@ -115,24 +116,16 @@ module HTTP2
|
|
115
116
|
def common_header(frame)
|
116
117
|
header = []
|
117
118
|
|
118
|
-
unless FRAME_TYPES[frame[:type]]
|
119
|
-
fail CompressionError, "Invalid frame type (#{frame[:type]})"
|
120
|
-
end
|
119
|
+
raise CompressionError, "Invalid frame type (#{frame[:type]})" unless FRAME_TYPES[frame[:type]]
|
121
120
|
|
122
|
-
if frame[:length] > @max_frame_size
|
123
|
-
fail CompressionError, "Frame size is too large: #{frame[:length]}"
|
124
|
-
end
|
121
|
+
raise CompressionError, "Frame size is too large: #{frame[:length]}" if frame[:length] > @max_frame_size
|
125
122
|
|
126
|
-
|
127
|
-
fail CompressionError, "Frame size is invalid: #{frame[:length]}"
|
128
|
-
end
|
123
|
+
raise CompressionError, "Frame size is invalid: #{frame[:length]}" if (frame[:length]).negative?
|
129
124
|
|
130
|
-
if frame[:stream] > MAX_STREAM_ID
|
131
|
-
fail CompressionError, "Stream ID (#{frame[:stream]}) is too large"
|
132
|
-
end
|
125
|
+
raise CompressionError, "Stream ID (#{frame[:stream]}) is too large" if frame[:stream] > MAX_STREAM_ID
|
133
126
|
|
134
127
|
if frame[:type] == :window_update && frame[:increment] > MAX_WINDOWINC
|
135
|
-
|
128
|
+
raise CompressionError, "Window increment (#{frame[:increment]}) is too large"
|
136
129
|
end
|
137
130
|
|
138
131
|
header << (frame[:length] >> FRAME_LENGTH_HISHIFT)
|
@@ -140,9 +133,7 @@ module HTTP2
|
|
140
133
|
header << FRAME_TYPES[frame[:type]]
|
141
134
|
header << frame[:flags].reduce(0) do |acc, f|
|
142
135
|
position = FRAME_FLAGS[frame[:type]][f]
|
143
|
-
unless position
|
144
|
-
fail CompressionError, "Invalid frame flag (#{f}) for #{frame[:type]}"
|
145
|
-
end
|
136
|
+
raise CompressionError, "Invalid frame flag (#{f}) for #{frame[:type]}" unless position
|
146
137
|
|
147
138
|
acc | (1 << position)
|
148
139
|
end
|
@@ -159,10 +150,10 @@ module HTTP2
|
|
159
150
|
len_hi, len_lo, type, flags, stream = buf.slice(0, 9).unpack(HEADERPACK)
|
160
151
|
|
161
152
|
frame[:length] = (len_hi << FRAME_LENGTH_HISHIFT) | len_lo
|
162
|
-
frame[:type],
|
153
|
+
frame[:type], = FRAME_TYPES.find { |_t, pos| type == pos }
|
163
154
|
if frame[:type]
|
164
155
|
frame[:flags] = FRAME_FLAGS[frame[:type]].each_with_object([]) do |(name, pos), acc|
|
165
|
-
acc << name if (flags & (1 << pos))
|
156
|
+
acc << name if (flags & (1 << pos)).positive?
|
166
157
|
end
|
167
158
|
end
|
168
159
|
|
@@ -189,8 +180,9 @@ module HTTP2
|
|
189
180
|
when :headers
|
190
181
|
if frame[:weight] || frame[:stream_dependency] || !frame[:exclusive].nil?
|
191
182
|
unless frame[:weight] && frame[:stream_dependency] && !frame[:exclusive].nil?
|
192
|
-
|
183
|
+
raise CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
|
193
184
|
end
|
185
|
+
|
194
186
|
frame[:flags] += [:priority] unless frame[:flags].include? :priority
|
195
187
|
end
|
196
188
|
|
@@ -205,8 +197,9 @@ module HTTP2
|
|
205
197
|
|
206
198
|
when :priority
|
207
199
|
unless frame[:weight] && frame[:stream_dependency] && !frame[:exclusive].nil?
|
208
|
-
|
200
|
+
raise CompressionError, "Must specify all of priority parameters for #{frame[:type]}"
|
209
201
|
end
|
202
|
+
|
210
203
|
bytes << [(frame[:exclusive] ? EBIT : 0) | (frame[:stream_dependency] & RBIT)].pack(UINT32)
|
211
204
|
bytes << [frame[:weight] - 1].pack(UINT8)
|
212
205
|
length += 5
|
@@ -216,9 +209,7 @@ module HTTP2
|
|
216
209
|
length += 4
|
217
210
|
|
218
211
|
when :settings
|
219
|
-
if (frame[:stream]).nonzero?
|
220
|
-
fail CompressionError, "Invalid stream ID (#{frame[:stream]})"
|
221
|
-
end
|
212
|
+
raise CompressionError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
|
222
213
|
|
223
214
|
frame[:payload].each do |(k, v)|
|
224
215
|
if k.is_a? Integer
|
@@ -226,7 +217,7 @@ module HTTP2
|
|
226
217
|
else
|
227
218
|
k = DEFINED_SETTINGS[k]
|
228
219
|
|
229
|
-
|
220
|
+
raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
|
230
221
|
end
|
231
222
|
|
232
223
|
bytes << [k].pack(UINT16)
|
@@ -241,8 +232,9 @@ module HTTP2
|
|
241
232
|
|
242
233
|
when :ping
|
243
234
|
if frame[:payload].bytesize != 8
|
244
|
-
|
235
|
+
raise CompressionError, "Invalid payload size (#{frame[:payload].size} != 8 bytes)"
|
245
236
|
end
|
237
|
+
|
246
238
|
bytes << frame[:payload]
|
247
239
|
length += 8
|
248
240
|
|
@@ -268,7 +260,8 @@ module HTTP2
|
|
268
260
|
bytes << [frame[:max_age], frame[:port]].pack(UINT32 + UINT16)
|
269
261
|
length += 6
|
270
262
|
if frame[:proto]
|
271
|
-
|
263
|
+
raise CompressionError, 'Proto too long' if frame[:proto].bytesize > 255
|
264
|
+
|
272
265
|
bytes << [frame[:proto].bytesize].pack(UINT8)
|
273
266
|
bytes << frame[:proto].force_encoding(Encoding::BINARY)
|
274
267
|
length += 1 + frame[:proto].bytesize
|
@@ -277,7 +270,8 @@ module HTTP2
|
|
277
270
|
length += 1
|
278
271
|
end
|
279
272
|
if frame[:host]
|
280
|
-
|
273
|
+
raise CompressionError, 'Host too long' if frame[:host].bytesize > 255
|
274
|
+
|
281
275
|
bytes << [frame[:host].bytesize].pack(UINT8)
|
282
276
|
bytes << frame[:host].force_encoding(Encoding::BINARY)
|
283
277
|
length += 1 + frame[:host].bytesize
|
@@ -296,13 +290,13 @@ module HTTP2
|
|
296
290
|
# - http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-6.1
|
297
291
|
if frame[:padding]
|
298
292
|
unless FRAME_TYPES_WITH_PADDING.include?(frame[:type])
|
299
|
-
|
293
|
+
raise CompressionError, "Invalid padding flag for #{frame[:type]}"
|
300
294
|
end
|
301
295
|
|
302
296
|
padlen = frame[:padding]
|
303
297
|
|
304
298
|
if padlen <= 0 || padlen > 256 || padlen + length > @max_frame_size
|
305
|
-
|
299
|
+
raise CompressionError, "Invalid padding #{padlen}"
|
306
300
|
end
|
307
301
|
|
308
302
|
length += padlen
|
@@ -312,7 +306,7 @@ module HTTP2
|
|
312
306
|
# Padding: Padding octets that contain no application semantic value.
|
313
307
|
# Padding octets MUST be set to zero when sending and ignored when
|
314
308
|
# receiving.
|
315
|
-
bytes << "\0" * padlen
|
309
|
+
bytes << ("\0" * padlen)
|
316
310
|
end
|
317
311
|
|
318
312
|
frame[:length] = length
|
@@ -325,10 +319,11 @@ module HTTP2
|
|
325
319
|
# @param buf [Buffer]
|
326
320
|
def parse(buf)
|
327
321
|
return nil if buf.size < 9
|
322
|
+
|
328
323
|
frame = read_common_header(buf)
|
329
324
|
return nil if buf.size < 9 + frame[:length]
|
330
325
|
|
331
|
-
|
326
|
+
raise ProtocolError, 'payload too large' if frame[:length] > DEFAULT_MAX_FRAME_SIZE
|
332
327
|
|
333
328
|
buf.read(9)
|
334
329
|
payload = buf.read(frame[:length])
|
@@ -343,10 +338,11 @@ module HTTP2
|
|
343
338
|
if FRAME_TYPES_WITH_PADDING.include?(frame[:type])
|
344
339
|
padded = frame[:flags].include?(:padded)
|
345
340
|
if padded
|
346
|
-
padlen = payload.read(1).
|
341
|
+
padlen = payload.read(1).unpack1(UINT8)
|
347
342
|
frame[:padding] = padlen + 1
|
348
|
-
|
349
|
-
|
343
|
+
raise ProtocolError, 'padding too long' if padlen > payload.bytesize
|
344
|
+
|
345
|
+
payload.slice!(-padlen, padlen) if padlen.positive?
|
350
346
|
frame[:length] -= frame[:padding]
|
351
347
|
frame[:flags].delete(:padded)
|
352
348
|
end
|
@@ -375,21 +371,17 @@ module HTTP2
|
|
375
371
|
# NOTE: frame[:length] might not match the number of frame[:payload]
|
376
372
|
# because unknown extensions are ignored.
|
377
373
|
frame[:payload] = []
|
378
|
-
unless (frame[:length] % 6).zero?
|
379
|
-
fail ProtocolError, 'Invalid settings payload length'
|
380
|
-
end
|
374
|
+
raise ProtocolError, 'Invalid settings payload length' unless (frame[:length] % 6).zero?
|
381
375
|
|
382
|
-
if (frame[:stream]).nonzero?
|
383
|
-
fail ProtocolError, "Invalid stream ID (#{frame[:stream]})"
|
384
|
-
end
|
376
|
+
raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
|
385
377
|
|
386
378
|
(frame[:length] / 6).times do
|
387
|
-
id = payload.read(2).
|
379
|
+
id = payload.read(2).unpack1(UINT16)
|
388
380
|
val = payload.read_uint32
|
389
381
|
|
390
382
|
# Unsupported or unrecognized settings MUST be ignored.
|
391
383
|
# Here we send it along.
|
392
|
-
name,
|
384
|
+
name, = DEFINED_SETTINGS.find { |_name, v| v == id }
|
393
385
|
frame[:payload] << [name, val] if name
|
394
386
|
end
|
395
387
|
when :push_promise
|
@@ -402,7 +394,7 @@ module HTTP2
|
|
402
394
|
frame[:error] = unpack_error payload.read_uint32
|
403
395
|
|
404
396
|
size = frame[:length] - 8 # for last_stream and error
|
405
|
-
frame[:payload] = payload.read(size) if size
|
397
|
+
frame[:payload] = payload.read(size) if size.positive?
|
406
398
|
when :window_update
|
407
399
|
frame[:increment] = payload.read_uint32 & RBIT
|
408
400
|
when :continuation
|
@@ -411,12 +403,12 @@ module HTTP2
|
|
411
403
|
frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
|
412
404
|
|
413
405
|
len = payload.getbyte
|
414
|
-
frame[:proto] = payload.read(len) if len
|
406
|
+
frame[:proto] = payload.read(len) if len.positive?
|
415
407
|
|
416
408
|
len = payload.getbyte
|
417
|
-
frame[:host] = payload.read(len) if len
|
409
|
+
frame[:host] = payload.read(len) if len.positive?
|
418
410
|
|
419
|
-
frame[:origin] = payload.read(payload.size)
|
411
|
+
frame[:origin] = payload.read(payload.size) unless payload.empty?
|
420
412
|
# else # Unknown frame type is explicitly allowed
|
421
413
|
end
|
422
414
|
|
@@ -427,9 +419,7 @@ module HTTP2
|
|
427
419
|
|
428
420
|
def pack_error(e)
|
429
421
|
unless e.is_a? Integer
|
430
|
-
if DEFINED_ERRORS[e].nil?
|
431
|
-
fail CompressionError, "Unknown error ID for #{e}"
|
432
|
-
end
|
422
|
+
raise CompressionError, "Unknown error ID for #{e}" if DEFINED_ERRORS[e].nil?
|
433
423
|
|
434
424
|
e = DEFINED_ERRORS[e]
|
435
425
|
end
|
@@ -438,9 +428,8 @@ module HTTP2
|
|
438
428
|
end
|
439
429
|
|
440
430
|
def unpack_error(e)
|
441
|
-
name,
|
431
|
+
name, = DEFINED_ERRORS.find { |_name, v| v == e }
|
442
432
|
name || error
|
443
433
|
end
|
444
434
|
end
|
445
|
-
# rubocop:enable ClassLength
|
446
435
|
end
|
data/lib/http/2/huffman.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'error'
|
2
4
|
|
3
5
|
module HTTP2
|
@@ -20,7 +22,7 @@ module HTTP2
|
|
20
22
|
# @return [String] binary string
|
21
23
|
def encode(str)
|
22
24
|
bitstring = str.each_byte.map { |chr| ENCODE_TABLE[chr] }.join
|
23
|
-
bitstring << '1' * ((8 - bitstring.size) % 8)
|
25
|
+
bitstring << ('1' * ((8 - bitstring.size) % 8))
|
24
26
|
[bitstring].pack('B*')
|
25
27
|
end
|
26
28
|
|
@@ -30,12 +32,12 @@ module HTTP2
|
|
30
32
|
# @return [String] binary string
|
31
33
|
# @raise [CompressionError] when Huffman coded string is malformed
|
32
34
|
def decode(buf)
|
33
|
-
emit =
|
35
|
+
emit = String.new
|
34
36
|
state = 0 # start state
|
35
37
|
|
36
38
|
mask = (1 << BITS_AT_ONCE) - 1
|
37
39
|
buf.each_byte do |chr|
|
38
|
-
(8 / BITS_AT_ONCE - 1).downto(0) do |shift|
|
40
|
+
((8 / BITS_AT_ONCE) - 1).downto(0) do |shift|
|
39
41
|
branch = (chr >> (shift * BITS_AT_ONCE)) & mask
|
40
42
|
# MACHINE[state] = [final, [transitions]]
|
41
43
|
# [final] unfinished bits so far are prefix of the EOS code.
|
@@ -43,15 +45,15 @@ module HTTP2
|
|
43
45
|
# [emit] character to be emitted on this transition, empty string, or EOS.
|
44
46
|
# [next] next state number.
|
45
47
|
trans = MACHINE[state][branch]
|
46
|
-
|
48
|
+
raise CompressionError, 'Huffman decode error (EOS found)' if trans.first == EOS
|
49
|
+
|
47
50
|
emit << trans.first.chr if trans.first
|
48
51
|
state = trans.last
|
49
52
|
end
|
50
53
|
end
|
51
54
|
# Check whether partial input is correctly filled
|
52
|
-
unless state <= MAX_FINAL_STATE
|
53
|
-
|
54
|
-
end
|
55
|
+
raise CompressionError, 'Huffman decode error (EOS invalid)' unless state <= MAX_FINAL_STATE
|
56
|
+
|
55
57
|
emit.force_encoding(Encoding::BINARY)
|
56
58
|
end
|
57
59
|
|
@@ -153,23 +155,23 @@ module HTTP2
|
|
153
155
|
[0x7fff0, 19],
|
154
156
|
[0x1ffc, 13],
|
155
157
|
[0x3ffc, 14],
|
156
|
-
[0x22,
|
158
|
+
[0x22, 6],
|
157
159
|
[0x7ffd, 15],
|
158
|
-
[0x3,
|
159
|
-
[0x23,
|
160
|
-
[0x4,
|
161
|
-
[0x24,
|
162
|
-
[0x5,
|
160
|
+
[0x3, 5],
|
161
|
+
[0x23, 6],
|
162
|
+
[0x4, 5],
|
163
|
+
[0x24, 6],
|
164
|
+
[0x5, 5],
|
163
165
|
[0x25, 6],
|
164
166
|
[0x26, 6],
|
165
167
|
[0x27, 6],
|
166
|
-
[0x6,
|
168
|
+
[0x6, 5],
|
167
169
|
[0x74, 7],
|
168
170
|
[0x75, 7],
|
169
171
|
[0x28, 6],
|
170
172
|
[0x29, 6],
|
171
173
|
[0x2a, 6],
|
172
|
-
[0x7,
|
174
|
+
[0x7, 5],
|
173
175
|
[0x2b, 6],
|
174
176
|
[0x76, 7],
|
175
177
|
[0x2c, 6],
|
@@ -314,10 +316,10 @@ module HTTP2
|
|
314
316
|
[0x7ffffef, 27],
|
315
317
|
[0x7fffff0, 27],
|
316
318
|
[0x3ffffee, 26],
|
317
|
-
[0x3fffffff, 30]
|
319
|
+
[0x3fffffff, 30]
|
318
320
|
].each(&:freeze).freeze
|
319
321
|
|
320
|
-
ENCODE_TABLE = CODES.map { |c, l| [c].pack('N').
|
322
|
+
ENCODE_TABLE = CODES.map { |c, l| [c].pack('N').unpack1('B*')[-l..-1] }.each(&:freeze).freeze
|
321
323
|
end
|
322
324
|
end
|
323
325
|
end
|
data/lib/http/2/server.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'base64'
|
2
4
|
module HTTP2
|
3
5
|
# HTTP 2.0 server connection class that implements appropriate header
|
@@ -77,7 +79,7 @@ module HTTP2
|
|
77
79
|
length: buf.bytesize,
|
78
80
|
type: :settings,
|
79
81
|
stream: 0,
|
80
|
-
flags: []
|
82
|
+
flags: []
|
81
83
|
)
|
82
84
|
buf.prepend(header)
|
83
85
|
receive(buf)
|
@@ -87,12 +89,12 @@ module HTTP2
|
|
87
89
|
emit(:stream, stream)
|
88
90
|
|
89
91
|
headers_frame = {
|
90
|
-
type:
|
91
|
-
stream:
|
92
|
-
weight:
|
92
|
+
type: :headers,
|
93
|
+
stream: 1,
|
94
|
+
weight: DEFAULT_WEIGHT,
|
93
95
|
dependency: 0,
|
94
|
-
exclusive:
|
95
|
-
payload: headers
|
96
|
+
exclusive: false,
|
97
|
+
payload: headers
|
96
98
|
}
|
97
99
|
|
98
100
|
if body.empty?
|
@@ -124,7 +126,7 @@ module HTTP2
|
|
124
126
|
flags: flags,
|
125
127
|
stream: parent.id,
|
126
128
|
promise_stream: promise.id,
|
127
|
-
payload: headers.to_a
|
129
|
+
payload: headers.to_a
|
128
130
|
)
|
129
131
|
|
130
132
|
callback.call(promise)
|