http-2-next 0.2.6 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/http/2/next.rb +1 -4
- data/lib/http/2/next/connection.rb +42 -28
- data/lib/http/2/next/emitter.rb +3 -4
- data/lib/http/2/next/error.rb +1 -0
- data/lib/http/2/next/extensions.rb +28 -1
- data/lib/http/2/next/flow_buffer.rb +7 -3
- data/lib/http/2/next/framer.rb +26 -17
- data/lib/http/2/next/header.rb +35 -0
- data/lib/http/2/next/header/compressor.rb +137 -0
- data/lib/http/2/next/header/decompressor.rb +144 -0
- data/lib/http/2/next/{compressor.rb → header/encoding_context.rb} +7 -298
- data/lib/http/2/next/{huffman.rb → header/huffman.rb} +5 -2
- data/lib/http/2/next/{huffman_statemachine.rb → header/huffman_statemachine.rb} +0 -0
- data/lib/http/2/next/server.rb +8 -5
- data/lib/http/2/next/stream.rb +12 -8
- data/lib/http/2/next/version.rb +1 -1
- data/lib/tasks/generate_huffman_table.rb +4 -4
- data/sig/client.rbs +9 -0
- data/sig/connection.rbs +73 -0
- data/sig/emitter.rbs +13 -0
- data/sig/flow_buffer.rbs +23 -0
- data/sig/frame_buffer.rbs +13 -0
- data/sig/framer.rbs +25 -0
- data/sig/header.rbs +15 -0
- data/sig/header/compressor.rbs +23 -0
- data/sig/header/decompressor.rbs +22 -0
- data/sig/header/encoding_context.rbs +34 -0
- data/sig/header/huffman.rbs +9 -0
- data/sig/next.rbs +95 -0
- data/sig/server.rbs +12 -0
- data/sig/stream.rbs +77 -0
- metadata +26 -10
- data/lib/http/2/next/buffer.rb +0 -80
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aba29aa46e044dc37656a40df1cce81dcdc185fcb166d456592e5e05b5a45295
|
4
|
+
data.tar.gz: 95ada3112561c105b5d2a9e9545aab8a29809c49bd5a70d7c64690ce80b47ccc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e0e50d2c307de9733f7951f9abb1a67c111da2b2740f04b7d204343410258981d28917dd0c22e7b8f6e6be9dec4bfb73f20fa118183a54268d1f4d2db43ce85
|
7
|
+
data.tar.gz: 4c5b8b4a840853e6d785b9d7565753e7e011a5db6d0b5b59fe042cd09491c10c429761a929824af83378b318d3eff43e58949ab6967bf57f6d571a89738ba77e
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/http-2-next.svg)](http://rubygems.org/gems/http-2-next)
|
4
4
|
[![Build status](https://gitlab.com/honeyryderchuck/http-2-next/badges/master/pipeline.svg)](https://gitlab.com/honeyryderchuck/http-2-next/commits/master)
|
5
|
-
[![coverage report](https://gitlab.com/honeyryderchuck/http-2-next/badges/master/coverage.svg)](https://honeyryderchuck.gitlab.io/http-2-next/coverage/#_AllFiles)
|
5
|
+
[![coverage report](https://gitlab.com/honeyryderchuck/http-2-next/badges/master/coverage.svg?job=coverage)](https://honeyryderchuck.gitlab.io/http-2-next/coverage/#_AllFiles)
|
6
6
|
|
7
7
|
**Attention!** This is a fork of the [http-2](https://github.com/igrigorik/http-2) gem.
|
8
8
|
|
data/lib/http/2/next.rb
CHANGED
@@ -4,11 +4,8 @@ require "http/2/next/version"
|
|
4
4
|
require "http/2/next/extensions"
|
5
5
|
require "http/2/next/error"
|
6
6
|
require "http/2/next/emitter"
|
7
|
-
require "http/2/next/buffer"
|
8
7
|
require "http/2/next/flow_buffer"
|
9
|
-
require "http/2/next/
|
10
|
-
require "http/2/next/huffman_statemachine"
|
11
|
-
require "http/2/next/compressor"
|
8
|
+
require "http/2/next/header"
|
12
9
|
require "http/2/next/framer"
|
13
10
|
require "http/2/next/connection"
|
14
11
|
require "http/2/next/client"
|
@@ -51,18 +51,19 @@ module HTTP2Next
|
|
51
51
|
include Emitter
|
52
52
|
include Error
|
53
53
|
|
54
|
+
using StringExtensions
|
55
|
+
|
54
56
|
# Connection state (:new, :closed).
|
55
57
|
attr_reader :state
|
56
58
|
|
57
59
|
# Size of current connection flow control window (by default, set to
|
58
60
|
# infinity, but is automatically updated on receipt of peer settings).
|
59
61
|
attr_reader :local_window
|
60
|
-
attr_reader :remote_window
|
62
|
+
attr_reader :remote_window, :remote_settings
|
61
63
|
alias window local_window
|
62
64
|
|
63
65
|
# Current settings value for local and peer
|
64
66
|
attr_reader :local_settings
|
65
|
-
attr_reader :remote_settings
|
66
67
|
|
67
68
|
# Pending settings value
|
68
69
|
# Sent but not ack'ed settings
|
@@ -99,12 +100,13 @@ module HTTP2Next
|
|
99
100
|
@remote_window_limit = @remote_settings[:settings_initial_window_size]
|
100
101
|
@remote_window = @remote_window_limit
|
101
102
|
|
102
|
-
@recv_buffer =
|
103
|
+
@recv_buffer = "".b
|
103
104
|
@continuation = []
|
104
105
|
@error = nil
|
105
106
|
|
106
107
|
@h2c_upgrade = nil
|
107
108
|
@closed_since = nil
|
109
|
+
@received_frame = false
|
108
110
|
end
|
109
111
|
|
110
112
|
def closed?
|
@@ -159,7 +161,7 @@ module HTTP2Next
|
|
159
161
|
send(type: :goaway, last_stream: last_stream,
|
160
162
|
error: error, payload: payload)
|
161
163
|
@state = :closed
|
162
|
-
@closed_since =
|
164
|
+
@closed_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
163
165
|
end
|
164
166
|
|
165
167
|
# Sends a WINDOW_UPDATE frame to the peer.
|
@@ -176,7 +178,7 @@ module HTTP2Next
|
|
176
178
|
# @param settings [Array or Hash]
|
177
179
|
def settings(payload)
|
178
180
|
payload = payload.to_a
|
179
|
-
|
181
|
+
validate_settings(@local_role, payload)
|
180
182
|
@pending_settings << payload
|
181
183
|
send(type: :settings, stream: 0, payload: payload)
|
182
184
|
@pending_settings << payload
|
@@ -213,6 +215,11 @@ module HTTP2Next
|
|
213
215
|
end
|
214
216
|
|
215
217
|
while (frame = @framer.parse(@recv_buffer))
|
218
|
+
if is_a?(Client) && !@received_frame
|
219
|
+
connection_error(:protocol_error, msg: "didn't receive settings") if frame[:type] != :settings
|
220
|
+
@received_frame = true
|
221
|
+
end
|
222
|
+
|
216
223
|
# Implementations MUST discard frames
|
217
224
|
# that have unknown or unsupported types.
|
218
225
|
if frame[:type].nil?
|
@@ -240,7 +247,7 @@ module HTTP2Next
|
|
240
247
|
@continuation.clear
|
241
248
|
|
242
249
|
frame.delete(:length)
|
243
|
-
frame[:payload] =
|
250
|
+
frame[:payload] = payload
|
244
251
|
frame[:flags] << :end_headers
|
245
252
|
end
|
246
253
|
|
@@ -473,7 +480,7 @@ module HTTP2Next
|
|
473
480
|
# the connection, although a new connection can be established
|
474
481
|
# for new streams.
|
475
482
|
@state = :closed
|
476
|
-
@closed_since =
|
483
|
+
@closed_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
477
484
|
emit(:goaway, frame[:last_stream], frame[:error], frame[:payload])
|
478
485
|
when :altsvc
|
479
486
|
# 4. The ALTSVC HTTP/2 Frame
|
@@ -498,7 +505,7 @@ module HTTP2Next
|
|
498
505
|
when :ping
|
499
506
|
ping_management(frame)
|
500
507
|
else
|
501
|
-
connection_error if (
|
508
|
+
connection_error if (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @closed_since) > 15
|
502
509
|
end
|
503
510
|
else
|
504
511
|
connection_error
|
@@ -521,8 +528,6 @@ module HTTP2Next
|
|
521
528
|
def validate_settings(role, settings)
|
522
529
|
settings.each do |key, v|
|
523
530
|
case key
|
524
|
-
when :settings_header_table_size
|
525
|
-
# Any value is valid
|
526
531
|
when :settings_enable_push
|
527
532
|
case role
|
528
533
|
when :server
|
@@ -530,32 +535,41 @@ module HTTP2Next
|
|
530
535
|
# Clients MUST reject any attempt to change the
|
531
536
|
# SETTINGS_ENABLE_PUSH setting to a value other than 0 by treating the
|
532
537
|
# message as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
533
|
-
|
538
|
+
next if v.zero?
|
539
|
+
|
540
|
+
connection_error(:protocol_error, msg: "invalid #{key} value")
|
534
541
|
when :client
|
535
542
|
# Any value other than 0 or 1 MUST be treated as a
|
536
543
|
# connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
537
|
-
|
544
|
+
next if v.zero? || v == 1
|
545
|
+
|
546
|
+
connection_error(:protocol_error, msg: "invalid #{key} value")
|
538
547
|
end
|
539
|
-
when :settings_max_concurrent_streams
|
540
|
-
# Any value is valid
|
541
548
|
when :settings_initial_window_size
|
542
549
|
# Values above the maximum flow control window size of 2^31-1 MUST
|
543
550
|
# be treated as a connection error (Section 5.4.1) of type
|
544
551
|
# FLOW_CONTROL_ERROR.
|
545
|
-
|
552
|
+
next if v <= 0x7fffffff
|
553
|
+
|
554
|
+
connection_error(:flow_control_error, msg: "invalid #{key} value")
|
546
555
|
when :settings_max_frame_size
|
547
556
|
# The initial value is 2^14 (16,384) octets. The value advertised
|
548
557
|
# by an endpoint MUST be between this initial value and the maximum
|
549
558
|
# allowed frame size (2^24-1 or 16,777,215 octets), inclusive.
|
550
559
|
# Values outside this range MUST be treated as a connection error
|
551
560
|
# (Section 5.4.1) of type PROTOCOL_ERROR.
|
552
|
-
|
553
|
-
|
561
|
+
next if v >= 16_384 && v <= 16_777_215
|
562
|
+
|
563
|
+
connection_error(:protocol_error, msg: "invalid #{key} value")
|
564
|
+
# when :settings_max_concurrent_streams
|
565
|
+
# Any value is valid
|
566
|
+
# when :settings_header_table_size
|
567
|
+
# Any value is valid
|
568
|
+
# when :settings_max_header_list_size
|
554
569
|
# Any value is valid
|
555
570
|
# else # ignore unknown settings
|
556
571
|
end
|
557
572
|
end
|
558
|
-
nil
|
559
573
|
end
|
560
574
|
|
561
575
|
# Update connection settings based on parameters set by the peer.
|
@@ -572,8 +586,7 @@ module HTTP2Next
|
|
572
586
|
# Process pending settings we have sent.
|
573
587
|
[@pending_settings.shift, :local]
|
574
588
|
else
|
575
|
-
|
576
|
-
connection_error(check) if check
|
589
|
+
validate_settings(@remote_role, frame[:payload])
|
577
590
|
[frame[:payload], :remote]
|
578
591
|
end
|
579
592
|
|
@@ -660,7 +673,7 @@ module HTTP2Next
|
|
660
673
|
#
|
661
674
|
# @param frame [Hash]
|
662
675
|
def decode_headers(frame)
|
663
|
-
frame[:payload] = @decompressor.decode(frame[:payload], frame) if frame[:payload].is_a?
|
676
|
+
frame[:payload] = @decompressor.decode(frame[:payload], frame) if frame[:payload].is_a?(String)
|
664
677
|
rescue CompressionError => e
|
665
678
|
connection_error(:compression_error, e: e)
|
666
679
|
rescue ProtocolError => e
|
@@ -675,15 +688,16 @@ module HTTP2Next
|
|
675
688
|
# @return [Array of Frame]
|
676
689
|
def encode_headers(frame)
|
677
690
|
payload = frame[:payload]
|
678
|
-
payload = @compressor.encode(payload) unless payload.is_a?
|
691
|
+
payload = @compressor.encode(payload) unless payload.is_a?(String)
|
679
692
|
|
680
693
|
frames = []
|
681
694
|
|
682
|
-
while payload.bytesize > 0
|
695
|
+
while payload && payload.bytesize > 0
|
683
696
|
cont = frame.dup
|
684
697
|
cont[:type] = :continuation
|
685
698
|
cont[:flags] = []
|
686
|
-
cont[:payload] = payload.
|
699
|
+
cont[:payload] = payload.byteslice(0, @remote_settings[:settings_max_frame_size])
|
700
|
+
payload = payload.byteslice(@remote_settings[:settings_max_frame_size]..-1)
|
687
701
|
frames << cont
|
688
702
|
end
|
689
703
|
if frames.empty?
|
@@ -707,7 +721,7 @@ module HTTP2Next
|
|
707
721
|
# @param priority [Integer]
|
708
722
|
# @param window [Integer]
|
709
723
|
# @param parent [Stream]
|
710
|
-
def activate_stream(id
|
724
|
+
def activate_stream(id:, **args)
|
711
725
|
connection_error(msg: "Stream ID already exists") if @streams.key?(id)
|
712
726
|
|
713
727
|
raise StreamLimitExceeded if @active_stream_count >= (@max_streams || @local_settings[:settings_max_concurrent_streams])
|
@@ -724,11 +738,11 @@ module HTTP2Next
|
|
724
738
|
# References to such streams will be purged whenever another stream
|
725
739
|
# is closed, with a minimum of 15s RTT time window.
|
726
740
|
@streams_recently_closed.reject! do |stream_id, v|
|
727
|
-
to_delete = (
|
741
|
+
to_delete = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - v) > 15
|
728
742
|
@streams.delete stream_id if to_delete
|
729
743
|
to_delete
|
730
744
|
end
|
731
|
-
@streams_recently_closed[id] =
|
745
|
+
@streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
732
746
|
end
|
733
747
|
|
734
748
|
stream.on(:promise, &method(:promise)) if is_a? Server
|
@@ -746,7 +760,7 @@ module HTTP2Next
|
|
746
760
|
|
747
761
|
def verify_pseudo_headers(frame, mandatory_headers)
|
748
762
|
headers = frame[:payload]
|
749
|
-
return if headers.is_a?(
|
763
|
+
return if headers.is_a?(String)
|
750
764
|
|
751
765
|
pseudo_headers = headers.take_while do |field, value|
|
752
766
|
# use this loop to validate pseudo-headers
|
data/lib/http/2/next/emitter.rb
CHANGED
@@ -9,19 +9,18 @@ module HTTP2Next
|
|
9
9
|
#
|
10
10
|
# @param event [Symbol]
|
11
11
|
# @param block [Proc] callback function
|
12
|
-
def
|
12
|
+
def on(event, &block)
|
13
13
|
raise ArgumentError, "must provide callback" unless block_given?
|
14
14
|
|
15
15
|
listeners(event.to_sym).push block
|
16
16
|
end
|
17
|
-
alias on add_listener
|
18
17
|
|
19
18
|
# Subscribe to next event (at most once) for specified type.
|
20
19
|
#
|
21
20
|
# @param event [Symbol]
|
22
21
|
# @param block [Proc] callback function
|
23
22
|
def once(event, &block)
|
24
|
-
|
23
|
+
on(event) do |*args, &callback|
|
25
24
|
block.call(*args, &callback)
|
26
25
|
:delete
|
27
26
|
end
|
@@ -34,7 +33,7 @@ module HTTP2Next
|
|
34
33
|
# @param block [Proc] callback function
|
35
34
|
def emit(event, *args, &block)
|
36
35
|
listeners(event).delete_if do |cb|
|
37
|
-
cb.call(*args, &block)
|
36
|
+
:delete == cb.call(*args, &block) # rubocop:disable Style/YodaCondition
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
data/lib/http/2/next/error.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HTTP2Next
|
4
|
-
module
|
4
|
+
module RegexpExtensions
|
5
5
|
unless Regexp.method_defined?(:match?)
|
6
6
|
refine Regexp do
|
7
7
|
def match?(*args)
|
@@ -10,4 +10,31 @@ module HTTP2Next
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
module StringExtensions
|
15
|
+
refine String do
|
16
|
+
def read(n)
|
17
|
+
return "".b if n == 0
|
18
|
+
|
19
|
+
chunk = byteslice(0..n - 1)
|
20
|
+
remaining = byteslice(n..-1)
|
21
|
+
remaining ? replace(remaining) : clear
|
22
|
+
chunk
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_uint32
|
26
|
+
read(4).unpack1("N")
|
27
|
+
end
|
28
|
+
|
29
|
+
def shift_byte
|
30
|
+
read(1).ord
|
31
|
+
end
|
32
|
+
|
33
|
+
unless String.method_defined?(:unpack1)
|
34
|
+
def unpack1(format)
|
35
|
+
unpack(format).first
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
13
40
|
end
|
@@ -73,6 +73,7 @@ module HTTP2Next
|
|
73
73
|
|
74
74
|
while (frame = send_buffer.retrieve(@remote_window))
|
75
75
|
|
76
|
+
# puts "#{self.class} -> #{@remote_window}"
|
76
77
|
sent = frame[:payload].bytesize
|
77
78
|
|
78
79
|
manage_state(frame) do
|
@@ -137,10 +138,13 @@ module HTTP2Next
|
|
137
138
|
|
138
139
|
# Split frame so that it fits in the window
|
139
140
|
# TODO: consider padding!
|
140
|
-
|
141
|
-
|
142
|
-
|
141
|
+
frame_bytes = payload.byteslice(0, window_size)
|
142
|
+
payload = payload.byteslice(window_size..-1)
|
143
|
+
|
144
|
+
frame[:payload] = frame_bytes
|
145
|
+
frame[:length] = frame_bytes.bytesize
|
143
146
|
chunk[:payload] = payload
|
147
|
+
chunk[:length] = payload.bytesize
|
144
148
|
|
145
149
|
# if no longer last frame in sequence...
|
146
150
|
frame[:flags] -= [:end_stream] if end_stream
|
data/lib/http/2/next/framer.rb
CHANGED
@@ -4,6 +4,8 @@ module HTTP2Next
|
|
4
4
|
# Performs encoding, decoding, and validation of binary HTTP/2 frames.
|
5
5
|
#
|
6
6
|
class Framer
|
7
|
+
using StringExtensions
|
8
|
+
|
7
9
|
include Error
|
8
10
|
|
9
11
|
# Default value of max frame size (16384 bytes)
|
@@ -154,9 +156,10 @@ module HTTP2Next
|
|
154
156
|
# Decodes common 9-byte header.
|
155
157
|
#
|
156
158
|
# @param buf [Buffer]
|
159
|
+
# @return [Hash] the corresponding frame
|
157
160
|
def read_common_header(buf)
|
158
161
|
frame = {}
|
159
|
-
len_hi, len_lo, type, flags, stream = buf.
|
162
|
+
len_hi, len_lo, type, flags, stream = buf.byteslice(0, 9).unpack(HEADERPACK)
|
160
163
|
|
161
164
|
frame[:length] = (len_hi << FRAME_LENGTH_HISHIFT) | len_lo
|
162
165
|
frame[:type], = FRAME_TYPES.find { |_t, pos| type == pos }
|
@@ -175,7 +178,7 @@ module HTTP2Next
|
|
175
178
|
#
|
176
179
|
# @param frame [Hash]
|
177
180
|
def generate(frame)
|
178
|
-
bytes =
|
181
|
+
bytes = "".b
|
179
182
|
length = 0
|
180
183
|
|
181
184
|
frame[:flags] ||= []
|
@@ -184,6 +187,7 @@ module HTTP2Next
|
|
184
187
|
case frame[:type]
|
185
188
|
when :data
|
186
189
|
bytes << frame[:payload]
|
190
|
+
bytes.force_encoding(Encoding::BINARY)
|
187
191
|
length += frame[:payload].bytesize
|
188
192
|
|
189
193
|
when :headers
|
@@ -221,7 +225,7 @@ module HTTP2Next
|
|
221
225
|
raise CompressionError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
|
222
226
|
|
223
227
|
frame[:payload].each do |(k, v)|
|
224
|
-
if k.is_a? Integer
|
228
|
+
if k.is_a? Integer # rubocop:disable Style/GuardClause
|
225
229
|
DEFINED_SETTINGS.value?(k) || next
|
226
230
|
else
|
227
231
|
k = DEFINED_SETTINGS[k]
|
@@ -333,10 +337,10 @@ module HTTP2Next
|
|
333
337
|
#
|
334
338
|
# @param buf [Buffer]
|
335
339
|
def parse(buf)
|
336
|
-
return
|
340
|
+
return if buf.size < 9
|
337
341
|
|
338
342
|
frame = read_common_header(buf)
|
339
|
-
return
|
343
|
+
return if buf.size < 9 + frame[:length]
|
340
344
|
|
341
345
|
raise ProtocolError, "payload too large" if frame[:length] > @local_max_frame_size
|
342
346
|
|
@@ -353,11 +357,11 @@ module HTTP2Next
|
|
353
357
|
if FRAME_TYPES_WITH_PADDING.include?(frame[:type])
|
354
358
|
padded = frame[:flags].include?(:padded)
|
355
359
|
if padded
|
356
|
-
padlen = payload.read(1).
|
360
|
+
padlen = payload.read(1).unpack1(UINT8)
|
357
361
|
frame[:padding] = padlen + 1
|
358
362
|
raise ProtocolError, "padding too long" if padlen > payload.bytesize
|
359
363
|
|
360
|
-
payload.
|
364
|
+
payload = payload.byteslice(0, payload.bytesize - padlen) if padlen > 0
|
361
365
|
frame[:length] -= frame[:padding]
|
362
366
|
frame[:flags].delete(:padded)
|
363
367
|
end
|
@@ -371,7 +375,9 @@ module HTTP2Next
|
|
371
375
|
e_sd = payload.read_uint32
|
372
376
|
frame[:dependency] = e_sd & RBIT
|
373
377
|
frame[:exclusive] = (e_sd & EBIT) != 0
|
374
|
-
|
378
|
+
weight = payload.byteslice(0, 1).ord + 1
|
379
|
+
frame[:weight] = weight
|
380
|
+
payload = payload.byteslice(1..-1)
|
375
381
|
end
|
376
382
|
frame[:payload] = payload.read(frame[:length])
|
377
383
|
when :priority
|
@@ -380,7 +386,9 @@ module HTTP2Next
|
|
380
386
|
e_sd = payload.read_uint32
|
381
387
|
frame[:dependency] = e_sd & RBIT
|
382
388
|
frame[:exclusive] = (e_sd & EBIT) != 0
|
383
|
-
|
389
|
+
weight = payload.byteslice(0, 1).ord + 1
|
390
|
+
frame[:weight] = weight
|
391
|
+
payload = payload.byteslice(1..-1)
|
384
392
|
when :rst_stream
|
385
393
|
raise FrameSizeError, "Invalid length for RST_STREAM (#{frame[:length]} != 4)" if frame[:length] != 4
|
386
394
|
|
@@ -395,7 +403,7 @@ module HTTP2Next
|
|
395
403
|
raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
|
396
404
|
|
397
405
|
(frame[:length] / 6).times do
|
398
|
-
id = payload.read(2).
|
406
|
+
id = payload.read(2).unpack1(UINT16)
|
399
407
|
val = payload.read_uint32
|
400
408
|
|
401
409
|
# Unsupported or unrecognized settings MUST be ignored.
|
@@ -425,10 +433,12 @@ module HTTP2Next
|
|
425
433
|
when :altsvc
|
426
434
|
frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
|
427
435
|
|
428
|
-
len = payload.
|
436
|
+
len = payload.byteslice(0, 1).ord
|
437
|
+
payload = payload.byteslice(1..-1)
|
429
438
|
frame[:proto] = payload.read(len) if len > 0
|
430
439
|
|
431
|
-
len = payload.
|
440
|
+
len = payload.byteslice(0, 1).ord
|
441
|
+
payload = payload.byteslice(1..-1)
|
432
442
|
frame[:host] = payload.read(len) if len > 0
|
433
443
|
|
434
444
|
frame[:origin] = payload.read(payload.size) unless payload.empty?
|
@@ -437,7 +447,7 @@ module HTTP2Next
|
|
437
447
|
origins = []
|
438
448
|
|
439
449
|
until payload.empty?
|
440
|
-
len = payload.read(2).
|
450
|
+
len = payload.read(2).unpack1(UINT16)
|
441
451
|
origins << payload.read(len)
|
442
452
|
end
|
443
453
|
|
@@ -452,17 +462,16 @@ module HTTP2Next
|
|
452
462
|
|
453
463
|
def pack_error(e)
|
454
464
|
unless e.is_a? Integer
|
455
|
-
raise CompressionError, "Unknown error ID for #{e}" if DEFINED_ERRORS[e].nil?
|
456
|
-
|
457
465
|
e = DEFINED_ERRORS[e]
|
466
|
+
|
467
|
+
raise CompressionError, "Unknown error ID for #{e}" unless e
|
458
468
|
end
|
459
469
|
|
460
470
|
[e].pack(UINT32)
|
461
471
|
end
|
462
472
|
|
463
473
|
def unpack_error(error)
|
464
|
-
|
465
|
-
name || error
|
474
|
+
DEFINED_ERRORS.key(error) || error
|
466
475
|
end
|
467
476
|
end
|
468
477
|
end
|