http-2-next 0.2.3 → 0.4.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 +2 -2
- data/lib/http/2/next.rb +1 -4
- data/lib/http/2/next/connection.rb +49 -31
- data/lib/http/2/next/emitter.rb +2 -3
- data/lib/http/2/next/error.rb +1 -0
- data/lib/http/2/next/extensions.rb +26 -1
- data/lib/http/2/next/flow_buffer.rb +8 -4
- data/lib/http/2/next/framer.rb +25 -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 +142 -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 +4 -5
- 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: 7db81040e42ff1170fbbcc93611c502b3b7fb1f3e4dcad7dd0ede42eaf08d0a4
|
4
|
+
data.tar.gz: 3f6027a4d12dc034726040554a5ba4aab96c145ff7acc7fc6c8287afdc4b49d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edb1d8dcf5509b2d51c64a66bf5396f7603817988b57894ba9529e877714c4c3ea847fd403ce75bb285a545a17758a8405277c9c36323425a2cd83d52ce842d7
|
7
|
+
data.tar.gz: fff64e2206e276c3b174d309d8a32181058dfde60f507953a215d6d5850abb754e6db5c5a54247d946b61bf6a74b57a748d8f4138e9c8c533e18000bb69d40e3
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# HTTP-2-Next
|
2
2
|
|
3
|
-
[](http://rubygems.org/gems/http-2)
|
3
|
+
[](http://rubygems.org/gems/http-2-next)
|
4
4
|
[](https://gitlab.com/honeyryderchuck/http-2-next/commits/master)
|
5
|
-
[](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
|
@@ -72,6 +73,9 @@ module HTTP2Next
|
|
72
73
|
# are not counted towards the stream limit).
|
73
74
|
attr_reader :active_stream_count
|
74
75
|
|
76
|
+
# Max number of streams that can be in-transit in this connection.
|
77
|
+
attr_writer :max_streams
|
78
|
+
|
75
79
|
# Initializes new connection object.
|
76
80
|
#
|
77
81
|
def initialize(settings = {})
|
@@ -82,6 +86,7 @@ module HTTP2Next
|
|
82
86
|
@decompressor = Header::Decompressor.new(settings)
|
83
87
|
|
84
88
|
@active_stream_count = 0
|
89
|
+
@max_streams = nil
|
85
90
|
@last_activated_stream = 0
|
86
91
|
@last_stream_id = 0
|
87
92
|
@streams = {}
|
@@ -95,12 +100,13 @@ module HTTP2Next
|
|
95
100
|
@remote_window_limit = @remote_settings[:settings_initial_window_size]
|
96
101
|
@remote_window = @remote_window_limit
|
97
102
|
|
98
|
-
@recv_buffer =
|
103
|
+
@recv_buffer = "".b
|
99
104
|
@continuation = []
|
100
105
|
@error = nil
|
101
106
|
|
102
107
|
@h2c_upgrade = nil
|
103
108
|
@closed_since = nil
|
109
|
+
@received_frame = false
|
104
110
|
end
|
105
111
|
|
106
112
|
def closed?
|
@@ -114,7 +120,7 @@ module HTTP2Next
|
|
114
120
|
# @param parent [Stream]
|
115
121
|
def new_stream(**args)
|
116
122
|
raise ConnectionClosed if @state == :closed
|
117
|
-
raise StreamLimitExceeded if @active_stream_count >= @remote_settings[:settings_max_concurrent_streams]
|
123
|
+
raise StreamLimitExceeded if @active_stream_count >= (@max_streams || @remote_settings[:settings_max_concurrent_streams])
|
118
124
|
|
119
125
|
connection_error(:protocol_error, msg: "id is smaller than previous") if @stream_id < @last_activated_stream
|
120
126
|
|
@@ -155,7 +161,7 @@ module HTTP2Next
|
|
155
161
|
send(type: :goaway, last_stream: last_stream,
|
156
162
|
error: error, payload: payload)
|
157
163
|
@state = :closed
|
158
|
-
@closed_since =
|
164
|
+
@closed_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
159
165
|
end
|
160
166
|
|
161
167
|
# Sends a WINDOW_UPDATE frame to the peer.
|
@@ -172,7 +178,7 @@ module HTTP2Next
|
|
172
178
|
# @param settings [Array or Hash]
|
173
179
|
def settings(payload)
|
174
180
|
payload = payload.to_a
|
175
|
-
|
181
|
+
validate_settings(@local_role, payload)
|
176
182
|
@pending_settings << payload
|
177
183
|
send(type: :settings, stream: 0, payload: payload)
|
178
184
|
@pending_settings << payload
|
@@ -209,6 +215,11 @@ module HTTP2Next
|
|
209
215
|
end
|
210
216
|
|
211
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
|
+
|
212
223
|
# Implementations MUST discard frames
|
213
224
|
# that have unknown or unsupported types.
|
214
225
|
if frame[:type].nil?
|
@@ -236,7 +247,7 @@ module HTTP2Next
|
|
236
247
|
@continuation.clear
|
237
248
|
|
238
249
|
frame.delete(:length)
|
239
|
-
frame[:payload] =
|
250
|
+
frame[:payload] = payload
|
240
251
|
frame[:flags] << :end_headers
|
241
252
|
end
|
242
253
|
|
@@ -469,7 +480,7 @@ module HTTP2Next
|
|
469
480
|
# the connection, although a new connection can be established
|
470
481
|
# for new streams.
|
471
482
|
@state = :closed
|
472
|
-
@closed_since =
|
483
|
+
@closed_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
473
484
|
emit(:goaway, frame[:last_stream], frame[:error], frame[:payload])
|
474
485
|
when :altsvc
|
475
486
|
# 4. The ALTSVC HTTP/2 Frame
|
@@ -494,7 +505,7 @@ module HTTP2Next
|
|
494
505
|
when :ping
|
495
506
|
ping_management(frame)
|
496
507
|
else
|
497
|
-
connection_error if (
|
508
|
+
connection_error if (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @closed_since) > 15
|
498
509
|
end
|
499
510
|
else
|
500
511
|
connection_error
|
@@ -517,8 +528,6 @@ module HTTP2Next
|
|
517
528
|
def validate_settings(role, settings)
|
518
529
|
settings.each do |key, v|
|
519
530
|
case key
|
520
|
-
when :settings_header_table_size
|
521
|
-
# Any value is valid
|
522
531
|
when :settings_enable_push
|
523
532
|
case role
|
524
533
|
when :server
|
@@ -526,32 +535,41 @@ module HTTP2Next
|
|
526
535
|
# Clients MUST reject any attempt to change the
|
527
536
|
# SETTINGS_ENABLE_PUSH setting to a value other than 0 by treating the
|
528
537
|
# message as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
529
|
-
|
538
|
+
next if v.zero?
|
539
|
+
|
540
|
+
connection_error(:protocol_error, msg: "invalid #{key} value")
|
530
541
|
when :client
|
531
542
|
# Any value other than 0 or 1 MUST be treated as a
|
532
543
|
# connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
533
|
-
|
544
|
+
next if v.zero? || v == 1
|
545
|
+
|
546
|
+
connection_error(:protocol_error, msg: "invalid #{key} value")
|
534
547
|
end
|
535
|
-
when :settings_max_concurrent_streams
|
536
|
-
# Any value is valid
|
537
548
|
when :settings_initial_window_size
|
538
549
|
# Values above the maximum flow control window size of 2^31-1 MUST
|
539
550
|
# be treated as a connection error (Section 5.4.1) of type
|
540
551
|
# FLOW_CONTROL_ERROR.
|
541
|
-
|
552
|
+
next if v <= 0x7fffffff
|
553
|
+
|
554
|
+
connection_error(:flow_control_error, msg: "invalid #{key} value")
|
542
555
|
when :settings_max_frame_size
|
543
556
|
# The initial value is 2^14 (16,384) octets. The value advertised
|
544
557
|
# by an endpoint MUST be between this initial value and the maximum
|
545
558
|
# allowed frame size (2^24-1 or 16,777,215 octets), inclusive.
|
546
559
|
# Values outside this range MUST be treated as a connection error
|
547
560
|
# (Section 5.4.1) of type PROTOCOL_ERROR.
|
548
|
-
|
549
|
-
|
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
|
550
569
|
# Any value is valid
|
551
570
|
# else # ignore unknown settings
|
552
571
|
end
|
553
572
|
end
|
554
|
-
nil
|
555
573
|
end
|
556
574
|
|
557
575
|
# Update connection settings based on parameters set by the peer.
|
@@ -568,8 +586,7 @@ module HTTP2Next
|
|
568
586
|
# Process pending settings we have sent.
|
569
587
|
[@pending_settings.shift, :local]
|
570
588
|
else
|
571
|
-
|
572
|
-
connection_error(check) if check
|
589
|
+
validate_settings(@remote_role, frame[:payload])
|
573
590
|
[frame[:payload], :remote]
|
574
591
|
end
|
575
592
|
|
@@ -656,7 +673,7 @@ module HTTP2Next
|
|
656
673
|
#
|
657
674
|
# @param frame [Hash]
|
658
675
|
def decode_headers(frame)
|
659
|
-
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)
|
660
677
|
rescue CompressionError => e
|
661
678
|
connection_error(:compression_error, e: e)
|
662
679
|
rescue ProtocolError => e
|
@@ -671,15 +688,16 @@ module HTTP2Next
|
|
671
688
|
# @return [Array of Frame]
|
672
689
|
def encode_headers(frame)
|
673
690
|
payload = frame[:payload]
|
674
|
-
payload = @compressor.encode(payload) unless payload.is_a?
|
691
|
+
payload = @compressor.encode(payload) unless payload.is_a?(String)
|
675
692
|
|
676
693
|
frames = []
|
677
694
|
|
678
|
-
while payload.bytesize > 0
|
695
|
+
while payload && payload.bytesize > 0
|
679
696
|
cont = frame.dup
|
680
697
|
cont[:type] = :continuation
|
681
698
|
cont[:flags] = []
|
682
|
-
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)
|
683
701
|
frames << cont
|
684
702
|
end
|
685
703
|
if frames.empty?
|
@@ -703,10 +721,10 @@ module HTTP2Next
|
|
703
721
|
# @param priority [Integer]
|
704
722
|
# @param window [Integer]
|
705
723
|
# @param parent [Stream]
|
706
|
-
def activate_stream(id
|
724
|
+
def activate_stream(id:, **args)
|
707
725
|
connection_error(msg: "Stream ID already exists") if @streams.key?(id)
|
708
726
|
|
709
|
-
raise StreamLimitExceeded if @active_stream_count >= @local_settings[:settings_max_concurrent_streams]
|
727
|
+
raise StreamLimitExceeded if @active_stream_count >= (@max_streams || @local_settings[:settings_max_concurrent_streams])
|
710
728
|
|
711
729
|
stream = Stream.new(connection: self, id: id, **args)
|
712
730
|
|
@@ -719,12 +737,12 @@ module HTTP2Next
|
|
719
737
|
# to any in-flight frames while close is registered on both sides.
|
720
738
|
# References to such streams will be purged whenever another stream
|
721
739
|
# is closed, with a minimum of 15s RTT time window.
|
722
|
-
@streams_recently_closed.reject do |
|
723
|
-
to_delete = (
|
740
|
+
@streams_recently_closed.reject! do |stream_id, v|
|
741
|
+
to_delete = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - v) > 15
|
724
742
|
@streams.delete stream_id if to_delete
|
725
743
|
to_delete
|
726
744
|
end
|
727
|
-
@streams_recently_closed[id] =
|
745
|
+
@streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
728
746
|
end
|
729
747
|
|
730
748
|
stream.on(:promise, &method(:promise)) if is_a? Server
|
@@ -742,7 +760,7 @@ module HTTP2Next
|
|
742
760
|
|
743
761
|
def verify_pseudo_headers(frame, mandatory_headers)
|
744
762
|
headers = frame[:payload]
|
745
|
-
return if headers.is_a?(
|
763
|
+
return if headers.is_a?(String)
|
746
764
|
|
747
765
|
pseudo_headers = headers.take_while do |field, value|
|
748
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
|
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,29 @@ module HTTP2Next
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
module StringExtensions
|
15
|
+
refine String do
|
16
|
+
def read(n)
|
17
|
+
chunk = byteslice(0..n - 1)
|
18
|
+
remaining = byteslice(n..-1)
|
19
|
+
remaining ? replace(remaining) : clear
|
20
|
+
chunk
|
21
|
+
end
|
22
|
+
|
23
|
+
def read_uint32
|
24
|
+
read(4).unpack1("N")
|
25
|
+
end
|
26
|
+
|
27
|
+
def shift_byte
|
28
|
+
read(1).ord
|
29
|
+
end
|
30
|
+
|
31
|
+
unless String.method_defined?(:unpack1)
|
32
|
+
def unpack1(format)
|
33
|
+
unpack(format).first
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
13
38
|
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
|
@@ -127,7 +128,7 @@ module HTTP2Next
|
|
127
128
|
# Frames with zero length with the END_STREAM flag set (that
|
128
129
|
# is, an empty DATA frame) MAY be sent if there is no available space
|
129
130
|
# in either flow control window.
|
130
|
-
return if window_size
|
131
|
+
return if window_size <= 0 && !(frame_size == 0 && end_stream)
|
131
132
|
|
132
133
|
@buffer.shift
|
133
134
|
|
@@ -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] ||= []
|
@@ -221,7 +224,7 @@ module HTTP2Next
|
|
221
224
|
raise CompressionError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
|
222
225
|
|
223
226
|
frame[:payload].each do |(k, v)|
|
224
|
-
if k.is_a? Integer
|
227
|
+
if k.is_a? Integer # rubocop:disable Style/GuardClause
|
225
228
|
DEFINED_SETTINGS.value?(k) || next
|
226
229
|
else
|
227
230
|
k = DEFINED_SETTINGS[k]
|
@@ -333,10 +336,10 @@ module HTTP2Next
|
|
333
336
|
#
|
334
337
|
# @param buf [Buffer]
|
335
338
|
def parse(buf)
|
336
|
-
return
|
339
|
+
return if buf.size < 9
|
337
340
|
|
338
341
|
frame = read_common_header(buf)
|
339
|
-
return
|
342
|
+
return if buf.size < 9 + frame[:length]
|
340
343
|
|
341
344
|
raise ProtocolError, "payload too large" if frame[:length] > @local_max_frame_size
|
342
345
|
|
@@ -353,11 +356,11 @@ module HTTP2Next
|
|
353
356
|
if FRAME_TYPES_WITH_PADDING.include?(frame[:type])
|
354
357
|
padded = frame[:flags].include?(:padded)
|
355
358
|
if padded
|
356
|
-
padlen = payload.read(1).
|
359
|
+
padlen = payload.read(1).unpack1(UINT8)
|
357
360
|
frame[:padding] = padlen + 1
|
358
361
|
raise ProtocolError, "padding too long" if padlen > payload.bytesize
|
359
362
|
|
360
|
-
payload.
|
363
|
+
payload = payload.byteslice(0, payload.bytesize - padlen) if padlen > 0
|
361
364
|
frame[:length] -= frame[:padding]
|
362
365
|
frame[:flags].delete(:padded)
|
363
366
|
end
|
@@ -371,7 +374,9 @@ module HTTP2Next
|
|
371
374
|
e_sd = payload.read_uint32
|
372
375
|
frame[:dependency] = e_sd & RBIT
|
373
376
|
frame[:exclusive] = (e_sd & EBIT) != 0
|
374
|
-
|
377
|
+
weight = payload.byteslice(0, 1).ord + 1
|
378
|
+
frame[:weight] = weight
|
379
|
+
payload = payload.byteslice(1..-1)
|
375
380
|
end
|
376
381
|
frame[:payload] = payload.read(frame[:length])
|
377
382
|
when :priority
|
@@ -380,7 +385,9 @@ module HTTP2Next
|
|
380
385
|
e_sd = payload.read_uint32
|
381
386
|
frame[:dependency] = e_sd & RBIT
|
382
387
|
frame[:exclusive] = (e_sd & EBIT) != 0
|
383
|
-
|
388
|
+
weight = payload.byteslice(0, 1).ord + 1
|
389
|
+
frame[:weight] = weight
|
390
|
+
payload = payload.byteslice(1..-1)
|
384
391
|
when :rst_stream
|
385
392
|
raise FrameSizeError, "Invalid length for RST_STREAM (#{frame[:length]} != 4)" if frame[:length] != 4
|
386
393
|
|
@@ -395,7 +402,7 @@ module HTTP2Next
|
|
395
402
|
raise ProtocolError, "Invalid stream ID (#{frame[:stream]})" if (frame[:stream]).nonzero?
|
396
403
|
|
397
404
|
(frame[:length] / 6).times do
|
398
|
-
id = payload.read(2).
|
405
|
+
id = payload.read(2).unpack1(UINT16)
|
399
406
|
val = payload.read_uint32
|
400
407
|
|
401
408
|
# Unsupported or unrecognized settings MUST be ignored.
|
@@ -425,10 +432,12 @@ module HTTP2Next
|
|
425
432
|
when :altsvc
|
426
433
|
frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
|
427
434
|
|
428
|
-
len = payload.
|
435
|
+
len = payload.byteslice(0, 1).ord
|
436
|
+
payload = payload.byteslice(1..-1)
|
429
437
|
frame[:proto] = payload.read(len) if len > 0
|
430
438
|
|
431
|
-
len = payload.
|
439
|
+
len = payload.byteslice(0, 1).ord
|
440
|
+
payload = payload.byteslice(1..-1)
|
432
441
|
frame[:host] = payload.read(len) if len > 0
|
433
442
|
|
434
443
|
frame[:origin] = payload.read(payload.size) unless payload.empty?
|
@@ -437,7 +446,7 @@ module HTTP2Next
|
|
437
446
|
origins = []
|
438
447
|
|
439
448
|
until payload.empty?
|
440
|
-
len = payload.read(2).
|
449
|
+
len = payload.read(2).unpack1(UINT16)
|
441
450
|
origins << payload.read(len)
|
442
451
|
end
|
443
452
|
|
@@ -452,17 +461,16 @@ module HTTP2Next
|
|
452
461
|
|
453
462
|
def pack_error(e)
|
454
463
|
unless e.is_a? Integer
|
455
|
-
raise CompressionError, "Unknown error ID for #{e}" if DEFINED_ERRORS[e].nil?
|
456
|
-
|
457
464
|
e = DEFINED_ERRORS[e]
|
465
|
+
|
466
|
+
raise CompressionError, "Unknown error ID for #{e}" unless e
|
458
467
|
end
|
459
468
|
|
460
469
|
[e].pack(UINT32)
|
461
470
|
end
|
462
471
|
|
463
472
|
def unpack_error(error)
|
464
|
-
|
465
|
-
name || error
|
473
|
+
DEFINED_ERRORS.key(error) || error
|
466
474
|
end
|
467
475
|
end
|
468
476
|
end
|