http-2 0.12.0 → 1.0.2
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 +10 -7
- data/lib/http/2/base64.rb +45 -0
- data/lib/http/2/client.rb +14 -5
- data/lib/http/2/connection.rb +184 -90
- data/lib/http/2/emitter.rb +4 -5
- data/lib/http/2/error.rb +22 -1
- data/lib/http/2/extensions.rb +51 -0
- data/lib/http/2/flow_buffer.rb +88 -35
- data/lib/http/2/framer.rb +145 -108
- data/lib/http/2/header/compressor.rb +157 -0
- data/lib/http/2/header/decompressor.rb +144 -0
- data/lib/http/2/header/encoding_context.rb +339 -0
- data/lib/http/2/{huffman.rb → header/huffman.rb} +9 -7
- data/lib/http/2/{huffman_statemachine.rb → header/huffman_statemachine.rb} +3 -1
- data/lib/http/2/header.rb +35 -0
- data/lib/http/2/server.rb +39 -14
- data/lib/http/2/stream.rb +86 -17
- data/lib/http/2/version.rb +1 -1
- data/lib/http/2.rb +12 -13
- data/sig/client.rbs +9 -0
- data/sig/connection.rbs +94 -0
- data/sig/emitter.rbs +13 -0
- data/sig/error.rbs +35 -0
- data/sig/extensions.rbs +13 -0
- data/sig/flow_buffer.rbs +21 -0
- data/sig/frame_buffer.rbs +13 -0
- data/sig/framer.rbs +55 -0
- data/sig/header/compressor.rbs +27 -0
- data/sig/header/decompressor.rbs +24 -0
- data/sig/header/encoding_context.rbs +34 -0
- data/sig/header/huffman.rbs +9 -0
- data/sig/header.rbs +27 -0
- data/sig/next.rbs +101 -0
- data/sig/server.rbs +12 -0
- data/sig/stream.rbs +91 -0
- metadata +37 -25
- data/LICENSE +0 -21
- data/lib/http/2/buffer.rb +0 -78
- data/lib/http/2/compressor.rb +0 -580
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Machine generated Huffman decoder state machine.
|
2
4
|
# DO NOT EDIT THIS FILE.
|
3
5
|
|
@@ -266,7 +268,7 @@ module HTTP2
|
|
266
268
|
[[28, 29], [28, 5], [29, 29], [29, 5], [30, 29], [30, 5], [31, 29], [31, 5], [127, 29], [127, 5], [220, 29], [220, 5], [249, 29], [249, 5], [nil, 254], [nil, 255]],
|
267
269
|
[[10, 17], [10, 18], [10, 19], [10, 20], [10, 21], [10, 22], [10, 23], [10, 7], [13, 17], [13, 18], [13, 19], [13, 20], [13, 21], [13, 22], [13, 23], [13, 7]],
|
268
270
|
[[22, 17], [22, 18], [22, 19], [22, 20], [22, 21], [22, 22], [22, 23], [22, 7], [256, 17], [256, 18], [256, 19], [256, 20], [256, 21], [256, 22], [256, 23], [256, 7]],
|
269
|
-
].each { |arr| arr.each { |subarr| subarr.
|
271
|
+
].each { |arr| arr.each { |subarr| subarr.freeze }.freeze }.freeze
|
270
272
|
end
|
271
273
|
end
|
272
274
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTP2
|
4
|
+
# Implementation of header compression for HTTP 2.0 (HPACK) format adapted
|
5
|
+
# to efficiently represent HTTP headers in the context of HTTP 2.0.
|
6
|
+
#
|
7
|
+
# - http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-10
|
8
|
+
module Header
|
9
|
+
# Header representation as defined by the spec.
|
10
|
+
HEADREP = {
|
11
|
+
indexed: { prefix: 7, pattern: 0x80 },
|
12
|
+
incremental: { prefix: 6, pattern: 0x40 },
|
13
|
+
noindex: { prefix: 4, pattern: 0x00 },
|
14
|
+
neverindexed: { prefix: 4, pattern: 0x10 },
|
15
|
+
changetablesize: { prefix: 5, pattern: 0x20 }
|
16
|
+
}.each_value(&:freeze).freeze
|
17
|
+
|
18
|
+
# Predefined options set for Compressor
|
19
|
+
# http://mew.org/~kazu/material/2014-hpack.pdf
|
20
|
+
NAIVE = { index: :never, huffman: :never }.freeze
|
21
|
+
LINEAR = { index: :all, huffman: :never }.freeze
|
22
|
+
STATIC = { index: :static, huffman: :never }.freeze
|
23
|
+
SHORTER = { index: :all, huffman: :never }.freeze
|
24
|
+
NAIVEH = { index: :never, huffman: :always }.freeze
|
25
|
+
LINEARH = { index: :all, huffman: :always }.freeze
|
26
|
+
STATICH = { index: :static, huffman: :always }.freeze
|
27
|
+
SHORTERH = { index: :all, huffman: :shorter }.freeze
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require "http/2/header/huffman"
|
32
|
+
require "http/2/header/huffman_statemachine"
|
33
|
+
require "http/2/header/encoding_context"
|
34
|
+
require "http/2/header/compressor"
|
35
|
+
require "http/2/header/decompressor"
|
data/lib/http/2/server.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'base64'
|
4
3
|
module HTTP2
|
5
4
|
# HTTP 2.0 server connection class that implements appropriate header
|
6
5
|
# compression / decompression algorithms and stream management logic.
|
@@ -22,14 +21,19 @@ module HTTP2
|
|
22
21
|
# end
|
23
22
|
#
|
24
23
|
class Server < Connection
|
24
|
+
attr_reader :origin_set
|
25
|
+
|
25
26
|
# Initialize new HTTP 2.0 server object.
|
26
|
-
def initialize(
|
27
|
+
def initialize(settings = {})
|
27
28
|
@stream_id = 2
|
28
29
|
@state = :waiting_magic
|
29
30
|
|
30
31
|
@local_role = :server
|
31
32
|
@remote_role = :client
|
32
33
|
|
34
|
+
@origin_set = []
|
35
|
+
@origins_sent = true
|
36
|
+
|
33
37
|
super
|
34
38
|
end
|
35
39
|
|
@@ -74,14 +78,17 @@ module HTTP2
|
|
74
78
|
receive(CONNECTION_PREFACE_MAGIC)
|
75
79
|
|
76
80
|
# Process received HTTP2-Settings payload
|
77
|
-
buf =
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
buf = "".b
|
82
|
+
buf << Base64.urlsafe_decode64(settings.to_s)
|
83
|
+
@framer.common_header(
|
84
|
+
{
|
85
|
+
length: buf.bytesize,
|
86
|
+
type: :settings,
|
87
|
+
stream: 0,
|
88
|
+
flags: []
|
89
|
+
},
|
90
|
+
buffer: buf
|
83
91
|
)
|
84
|
-
buf.prepend(header)
|
85
92
|
receive(buf)
|
86
93
|
|
87
94
|
# Activate stream (id: 1) with on HTTP/1.1 request parameters
|
@@ -90,6 +97,7 @@ module HTTP2
|
|
90
97
|
|
91
98
|
headers_frame = {
|
92
99
|
type: :headers,
|
100
|
+
flags: [:end_headers],
|
93
101
|
stream: 1,
|
94
102
|
weight: DEFAULT_WEIGHT,
|
95
103
|
dependency: 0,
|
@@ -98,7 +106,7 @@ module HTTP2
|
|
98
106
|
}
|
99
107
|
|
100
108
|
if body.empty?
|
101
|
-
headers_frame
|
109
|
+
headers_frame[:flags] << [:end_stream]
|
102
110
|
stream << headers_frame
|
103
111
|
else
|
104
112
|
stream << headers_frame
|
@@ -112,14 +120,31 @@ module HTTP2
|
|
112
120
|
@state = :waiting_magic
|
113
121
|
end
|
114
122
|
|
123
|
+
def origin_set=(origins)
|
124
|
+
@origin_set = Array(origins).map(&:to_s)
|
125
|
+
@origins_sent = @origin_set.empty?
|
126
|
+
end
|
127
|
+
|
115
128
|
private
|
116
129
|
|
130
|
+
def connection_settings(frame)
|
131
|
+
super
|
132
|
+
return unless frame[:flags].include?(:ack) && !@origins_sent
|
133
|
+
|
134
|
+
send(type: :origin, stream: 0, payload: @origin_set)
|
135
|
+
end
|
136
|
+
|
137
|
+
def verify_pseudo_headers(frame)
|
138
|
+
_verify_pseudo_headers(frame, REQUEST_MANDATORY_HEADERS)
|
139
|
+
end
|
140
|
+
|
117
141
|
# Handle locally initiated server-push event emitted by the stream.
|
118
142
|
#
|
119
|
-
# @param
|
143
|
+
# @param parent [Stream]
|
144
|
+
# @param headers [Enumerable[String, String]]
|
145
|
+
# @param flags [Array[Symbol]]
|
120
146
|
# @param callback [Proc]
|
121
|
-
def promise(
|
122
|
-
parent, headers, flags = *args
|
147
|
+
def promise(parent, headers, flags)
|
123
148
|
promise = new_stream(parent: parent)
|
124
149
|
promise.send(
|
125
150
|
type: :push_promise,
|
@@ -129,7 +154,7 @@ module HTTP2
|
|
129
154
|
payload: headers.to_a
|
130
155
|
)
|
131
156
|
|
132
|
-
|
157
|
+
yield(promise)
|
133
158
|
end
|
134
159
|
end
|
135
160
|
end
|
data/lib/http/2/stream.rb
CHANGED
@@ -74,19 +74,24 @@ module HTTP2
|
|
74
74
|
# @param parent [Stream]
|
75
75
|
# @param state [Symbol]
|
76
76
|
def initialize(connection:, id:, weight: 16, dependency: 0, exclusive: false, parent: nil, state: :idle)
|
77
|
+
stream_error(:protocol_error, msg: "stream can't depend on itself") if id == dependency
|
78
|
+
|
77
79
|
@connection = connection
|
78
80
|
@id = id
|
79
81
|
@weight = weight
|
80
82
|
@dependency = dependency
|
81
|
-
process_priority(weight: weight,
|
83
|
+
process_priority(weight: weight, dependency: dependency, exclusive: exclusive)
|
82
84
|
@local_window_max_size = connection.local_settings[:settings_initial_window_size]
|
83
|
-
@local_window
|
85
|
+
@local_window = connection.local_settings[:settings_initial_window_size]
|
84
86
|
@remote_window = connection.remote_settings[:settings_initial_window_size]
|
85
87
|
@parent = parent
|
86
88
|
@state = state
|
87
89
|
@error = false
|
88
90
|
@closed = false
|
89
|
-
@
|
91
|
+
@_method = @_content_length = @_status_code = nil
|
92
|
+
@_waiting_on_trailers = false
|
93
|
+
@received_data = false
|
94
|
+
@activated = false
|
90
95
|
|
91
96
|
on(:window) { |v| @remote_window = v }
|
92
97
|
on(:local_window) { |v| @local_window_max_size = @local_window = v }
|
@@ -104,18 +109,46 @@ module HTTP2
|
|
104
109
|
|
105
110
|
case frame[:type]
|
106
111
|
when :data
|
112
|
+
# 6.1. DATA
|
113
|
+
# If a DATA frame is received whose stream is not in "open" or
|
114
|
+
# "half closed (local)" state, the recipient MUST respond with a
|
115
|
+
# stream error (Section 5.4.2) of type STREAM_CLOSED.
|
116
|
+
stream_error(:stream_closed) unless @state == :open ||
|
117
|
+
@state == :half_closed_local ||
|
118
|
+
@state == :half_closing || @state == :closing ||
|
119
|
+
(@state == :closed && @closed == :local_rst)
|
120
|
+
@received_data = true
|
121
|
+
calculate_content_length(frame[:length])
|
107
122
|
update_local_window(frame)
|
108
123
|
# Emit DATA frame
|
109
124
|
emit(:data, frame[:payload]) unless frame[:ignore]
|
110
125
|
calculate_window_update(@local_window_max_size)
|
111
126
|
when :headers
|
127
|
+
stream_error(:stream_closed) if (@state == :closed && @closed != :local_rst) ||
|
128
|
+
@state == :remote_closed
|
129
|
+
@_method ||= frame[:method]
|
130
|
+
@_status_code ||= frame[:status]
|
131
|
+
@_content_length ||= frame[:content_length]
|
132
|
+
@_trailers ||= frame[:trailer]
|
133
|
+
if @_waiting_on_trailers ||
|
134
|
+
(@received_data &&
|
135
|
+
(!@_status_code || @_status_code >= 200))
|
136
|
+
|
137
|
+
# An endpoint that receives a HEADERS frame without the END_STREAM flag set after receiving a final
|
138
|
+
# (non-informational) status code MUST treat the corresponding request or response as malformed.
|
139
|
+
verify_trailers(frame)
|
140
|
+
end
|
112
141
|
emit(:headers, frame[:payload]) unless frame[:ignore]
|
142
|
+
@_waiting_on_trailers = !@_trailers.nil?
|
113
143
|
when :push_promise
|
114
144
|
emit(:promise_headers, frame[:payload]) unless frame[:ignore]
|
145
|
+
when :continuation
|
146
|
+
stream_error(:stream_closed) if (@state == :closed && @closed != :local_rst) || @state == :remote_closed
|
147
|
+
stream_error(:protocol_error) if @received_data
|
115
148
|
when :priority
|
116
149
|
process_priority(frame)
|
117
150
|
when :window_update
|
118
|
-
process_window_update(frame)
|
151
|
+
process_window_update(frame: frame)
|
119
152
|
when :altsvc
|
120
153
|
# 4. The ALTSVC HTTP/2 Frame
|
121
154
|
# An ALTSVC frame on a
|
@@ -130,6 +163,29 @@ module HTTP2
|
|
130
163
|
end
|
131
164
|
alias << receive
|
132
165
|
|
166
|
+
def verify_trailers(frame)
|
167
|
+
stream_error(:protocol_error, msg: "trailer headers frame must close the stream") unless end_stream?(frame)
|
168
|
+
return unless @_trailers
|
169
|
+
|
170
|
+
trailers = frame[:payload]
|
171
|
+
return unless trailers.respond_to?(:each)
|
172
|
+
|
173
|
+
trailers.each do |field, _| # rubocop:disable Style/HashEachMethods
|
174
|
+
@_trailers.delete(field)
|
175
|
+
break if @_trailers.empty?
|
176
|
+
end
|
177
|
+
stream_error(:protocol_error, msg: "didn't receive all expected trailer headers") unless @_trailers.empty?
|
178
|
+
end
|
179
|
+
|
180
|
+
def calculate_content_length(data_length)
|
181
|
+
return unless @_content_length && data_length
|
182
|
+
|
183
|
+
@_content_length -= data_length
|
184
|
+
return if @_content_length >= 0
|
185
|
+
|
186
|
+
stream_error(:protocol_error, msg: "received more data than what was defined in content-length")
|
187
|
+
end
|
188
|
+
|
133
189
|
# Processes outgoing HTTP 2.0 frames. Data frames may be automatically
|
134
190
|
# split and buffered based on maximum frame size and current stream flow
|
135
191
|
# control window size.
|
@@ -163,13 +219,13 @@ module HTTP2
|
|
163
219
|
def headers(headers, end_headers: true, end_stream: false)
|
164
220
|
flags = []
|
165
221
|
flags << :end_headers if end_headers
|
166
|
-
flags << :end_stream if end_stream
|
222
|
+
flags << :end_stream if end_stream || @_method == "HEAD"
|
167
223
|
|
168
224
|
send(type: :headers, flags: flags, payload: headers)
|
169
225
|
end
|
170
226
|
|
171
227
|
def promise(headers, end_headers: true, &block)
|
172
|
-
raise ArgumentError,
|
228
|
+
raise ArgumentError, "must provide callback" unless block
|
173
229
|
|
174
230
|
flags = end_headers ? [:end_headers] : []
|
175
231
|
emit(:promise, self, headers, flags, &block)
|
@@ -182,7 +238,7 @@ module HTTP2
|
|
182
238
|
# @param dependency [Integer] new stream dependency stream
|
183
239
|
def reprioritize(weight: 16, dependency: 0, exclusive: false)
|
184
240
|
stream_error if @id.even?
|
185
|
-
send(type: :priority, weight: weight,
|
241
|
+
send(type: :priority, weight: weight, dependency: dependency, exclusive: exclusive)
|
186
242
|
end
|
187
243
|
|
188
244
|
# Sends DATA frame containing response payload.
|
@@ -550,7 +606,7 @@ module HTTP2
|
|
550
606
|
case newstate
|
551
607
|
when :open
|
552
608
|
@state = newstate
|
553
|
-
|
609
|
+
activate_stream_in_conn
|
554
610
|
|
555
611
|
when :reserved_local, :reserved_remote
|
556
612
|
@state = newstate
|
@@ -558,7 +614,7 @@ module HTTP2
|
|
558
614
|
|
559
615
|
when :half_closed_local, :half_closed_remote
|
560
616
|
@closed = newstate
|
561
|
-
|
617
|
+
activate_stream_in_conn unless @state == :open
|
562
618
|
@state = :half_closing
|
563
619
|
|
564
620
|
when :local_closed, :remote_closed, :local_rst, :remote_rst
|
@@ -569,11 +625,25 @@ module HTTP2
|
|
569
625
|
@state
|
570
626
|
end
|
571
627
|
|
628
|
+
# Streams that are in the "open" state, or either of the "half closed"
|
629
|
+
# states count toward the maximum number of streams that an endpoint is
|
630
|
+
# permitted to open.
|
631
|
+
def activate_stream_in_conn
|
632
|
+
@connection.active_stream_count += 1
|
633
|
+
@activated = true
|
634
|
+
emit(:active)
|
635
|
+
end
|
636
|
+
|
637
|
+
def close_stream_in_conn(*args)
|
638
|
+
@connection.active_stream_count -= 1 if @activated
|
639
|
+
emit(:close, *args)
|
640
|
+
end
|
641
|
+
|
572
642
|
def complete_transition(frame)
|
573
643
|
case @state
|
574
644
|
when :closing
|
575
645
|
@state = :closed
|
576
|
-
|
646
|
+
close_stream_in_conn(frame[:error])
|
577
647
|
when :half_closing
|
578
648
|
@state = @closed
|
579
649
|
emit(:half_close)
|
@@ -582,11 +652,11 @@ module HTTP2
|
|
582
652
|
|
583
653
|
def process_priority(frame)
|
584
654
|
@weight = frame[:weight]
|
585
|
-
@dependency = frame[:
|
655
|
+
@dependency = frame[:dependency]
|
586
656
|
emit(
|
587
657
|
:priority,
|
588
658
|
weight: frame[:weight],
|
589
|
-
dependency: frame[:
|
659
|
+
dependency: frame[:dependency],
|
590
660
|
exclusive: frame[:exclusive]
|
591
661
|
)
|
592
662
|
# TODO: implement dependency tree housekeeping
|
@@ -599,19 +669,18 @@ module HTTP2
|
|
599
669
|
def end_stream?(frame)
|
600
670
|
case frame[:type]
|
601
671
|
when :data, :headers, :continuation
|
602
|
-
|
603
|
-
|
604
|
-
frame[:flags].include?(:end_stream)
|
672
|
+
frame[:flags] && frame[:flags].include?(:end_stream)
|
605
673
|
else false
|
606
674
|
end
|
607
675
|
end
|
608
676
|
|
609
677
|
def stream_error(error = :internal_error, msg: nil)
|
678
|
+
# if the stream already broke with an error, ignore subsequent
|
679
|
+
|
610
680
|
@error = error
|
611
681
|
close(error) if @state != :closed
|
612
682
|
|
613
|
-
|
614
|
-
raise Error.const_get(klass), msg
|
683
|
+
raise Error.types[error], msg
|
615
684
|
end
|
616
685
|
alias error stream_error
|
617
686
|
|
data/lib/http/2/version.rb
CHANGED
data/lib/http/2.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require 'http/2/stream'
|
3
|
+
require "http/2/version"
|
4
|
+
require "http/2/extensions"
|
5
|
+
require "http/2/base64"
|
6
|
+
require "http/2/error"
|
7
|
+
require "http/2/emitter"
|
8
|
+
require "http/2/flow_buffer"
|
9
|
+
require "http/2/header"
|
10
|
+
require "http/2/framer"
|
11
|
+
require "http/2/connection"
|
12
|
+
require "http/2/client"
|
13
|
+
require "http/2/server"
|
14
|
+
require "http/2/stream"
|
data/sig/client.rbs
ADDED
data/sig/connection.rbs
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module HTTP2
|
2
|
+
class Connection
|
3
|
+
include FlowBuffer
|
4
|
+
include Emitter
|
5
|
+
include BufferUtils
|
6
|
+
|
7
|
+
REQUEST_MANDATORY_HEADERS: Array[String]
|
8
|
+
RESPONSE_MANDATORY_HEADERS: Array[String]
|
9
|
+
|
10
|
+
attr_reader state: Symbol
|
11
|
+
|
12
|
+
attr_reader local_window: Integer
|
13
|
+
attr_reader remote_window: Integer
|
14
|
+
|
15
|
+
alias window local_window
|
16
|
+
|
17
|
+
attr_reader remote_settings: settings_hash
|
18
|
+
attr_reader local_settings: settings_hash
|
19
|
+
attr_reader pending_settings: settings_ary
|
20
|
+
|
21
|
+
attr_accessor active_stream_count: Integer
|
22
|
+
|
23
|
+
@stream_id: Integer
|
24
|
+
@active_stream_count: Integer
|
25
|
+
@last_activated_stream: Integer
|
26
|
+
@last_stream_id: Integer
|
27
|
+
|
28
|
+
@streams: Hash[Integer, Stream]
|
29
|
+
@streams_recently_closed: Hash[Integer, Stream]
|
30
|
+
|
31
|
+
@framer: Framer
|
32
|
+
|
33
|
+
@local_window_limit: Integer
|
34
|
+
@remote_window_limit: Integer
|
35
|
+
|
36
|
+
@compressor: Header::Compressor
|
37
|
+
@decompressor: Header::Decompressor
|
38
|
+
@error: Symbol?
|
39
|
+
|
40
|
+
@recv_buffer: String
|
41
|
+
@continuation: Array[frame]
|
42
|
+
|
43
|
+
@closed_since: Float?
|
44
|
+
@received_frame: bool
|
45
|
+
|
46
|
+
def closed?: () -> bool
|
47
|
+
|
48
|
+
def new_stream: (**untyped) -> Stream
|
49
|
+
|
50
|
+
def ping: (String) -> void
|
51
|
+
| (String) { () -> void } -> void
|
52
|
+
|
53
|
+
def goaway: (?Symbol, ?String) -> void
|
54
|
+
|
55
|
+
def window_update: (Integer increment) -> void
|
56
|
+
|
57
|
+
def settings: (settings_enum) -> void
|
58
|
+
|
59
|
+
def receive: (string data) -> void
|
60
|
+
alias << receive
|
61
|
+
|
62
|
+
def initialize: (?settings_hash) -> void
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def send: (frame) -> void
|
67
|
+
|
68
|
+
def encode: (frame) -> Array[String]
|
69
|
+
|
70
|
+
def connection_frame?: (frame) -> bool
|
71
|
+
|
72
|
+
def connection_management: (frame) -> void
|
73
|
+
|
74
|
+
def ping_management: (frame) -> void
|
75
|
+
|
76
|
+
def validate_settings: (:client | :server, settings_enum) -> void
|
77
|
+
|
78
|
+
def connection_settings: (frame) -> void
|
79
|
+
|
80
|
+
def decode_headers: (frame) -> void
|
81
|
+
|
82
|
+
def encode_headers: (frame) -> Array[frame]
|
83
|
+
|
84
|
+
def activate_stream: (id: Integer, **untyped) -> Stream
|
85
|
+
|
86
|
+
def verify_stream_order: (Integer id) -> void
|
87
|
+
|
88
|
+
def verify_pseudo_headers: (frame) -> void
|
89
|
+
|
90
|
+
def _verify_pseudo_headers: (frame, Array[String]) -> void
|
91
|
+
|
92
|
+
def connection_error: (?Symbol error, ?msg: String?, ?e: StandardError?) -> void
|
93
|
+
end
|
94
|
+
end
|
data/sig/emitter.rbs
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module HTTP2
|
2
|
+
module Emitter
|
3
|
+
def on: (Symbol event) { (*untyped) -> void } -> void
|
4
|
+
|
5
|
+
def once: (Symbol event) { (*untyped) -> void } -> void
|
6
|
+
|
7
|
+
def emit: (Symbol event, *untyped args) ?{ (*untyped) -> void } -> void
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def listeners: (Symbol event) -> Array[Proc]
|
12
|
+
end
|
13
|
+
end
|
data/sig/error.rbs
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module HTTP2
|
2
|
+
module Error
|
3
|
+
def self?.types: () -> Hash[Symbol, singleton(Error)]
|
4
|
+
|
5
|
+
class Error < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class HandshakeError < Error
|
9
|
+
end
|
10
|
+
|
11
|
+
class ProtocolError < Error
|
12
|
+
end
|
13
|
+
|
14
|
+
class CompressionError < ProtocolError
|
15
|
+
end
|
16
|
+
|
17
|
+
class FlowControlError < ProtocolError
|
18
|
+
end
|
19
|
+
|
20
|
+
class InternalError < ProtocolError
|
21
|
+
end
|
22
|
+
|
23
|
+
class StreamClosed < Error
|
24
|
+
end
|
25
|
+
|
26
|
+
class ConnectionClosed < Error
|
27
|
+
end
|
28
|
+
|
29
|
+
class StreamLimitExceeded < Error
|
30
|
+
end
|
31
|
+
|
32
|
+
class FrameSizeError < Error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/sig/extensions.rbs
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module HTTP2
|
2
|
+
module BufferUtils
|
3
|
+
def read_str: (String str, Integer n) -> String
|
4
|
+
|
5
|
+
def read_uint32: (String str) -> Integer
|
6
|
+
|
7
|
+
def shift_byte: (String str) -> Integer
|
8
|
+
end
|
9
|
+
|
10
|
+
module PackingExtensions
|
11
|
+
def pack: (Array[Integer] array_to_pack, String template, buffer: String, ?offset: Integer) -> String
|
12
|
+
end
|
13
|
+
end
|
data/sig/flow_buffer.rbs
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module HTTP2
|
2
|
+
module FlowBuffer
|
3
|
+
MAX_WINDOW_SIZE: Integer
|
4
|
+
|
5
|
+
def buffered_amount: () -> Integer
|
6
|
+
|
7
|
+
def flush: () -> void
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def send_buffer: () -> FrameBuffer
|
12
|
+
|
13
|
+
def update_local_window: (frame) -> void
|
14
|
+
|
15
|
+
def calculate_window_update: (Integer) -> void
|
16
|
+
|
17
|
+
def send_data: (?frame? frame, ?bool encode) -> void
|
18
|
+
|
19
|
+
def process_window_update: (frame: frame, ?encode: bool) -> void
|
20
|
+
end
|
21
|
+
end
|
data/sig/framer.rbs
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module HTTP2
|
2
|
+
class Framer
|
3
|
+
include PackingExtensions
|
4
|
+
include BufferUtils
|
5
|
+
|
6
|
+
DEFAULT_MAX_FRAME_SIZE: Integer
|
7
|
+
|
8
|
+
MAX_STREAM_ID: Integer
|
9
|
+
|
10
|
+
MAX_WINDOWINC: Integer
|
11
|
+
|
12
|
+
FRAME_TYPES: Hash[Symbol, Integer]
|
13
|
+
|
14
|
+
FRAME_TYPES_WITH_PADDING: Array[Symbol]
|
15
|
+
|
16
|
+
FRAME_FLAGS: Hash[Symbol, Hash[Symbol, Integer]]
|
17
|
+
|
18
|
+
DEFINED_SETTINGS: Hash[Symbol, Integer]
|
19
|
+
|
20
|
+
DEFINED_ERRORS: Hash[Symbol, Integer]
|
21
|
+
|
22
|
+
RBIT: Integer
|
23
|
+
RBYTE: Integer
|
24
|
+
EBIT: Integer
|
25
|
+
UINT32: String
|
26
|
+
UINT16: String
|
27
|
+
UINT8: String
|
28
|
+
HEADERPACK: String
|
29
|
+
FRAME_LENGTH_HISHIFT: Integer
|
30
|
+
FRAME_LENGTH_LOMASK: Integer
|
31
|
+
|
32
|
+
@local_max_frame_size: Integer
|
33
|
+
@remote_max_frame_size: Integer
|
34
|
+
|
35
|
+
attr_accessor local_max_frame_size: Integer
|
36
|
+
|
37
|
+
attr_accessor remote_max_frame_size: Integer
|
38
|
+
|
39
|
+
def common_header: (frame, buffer: String) -> String
|
40
|
+
|
41
|
+
def read_common_frame: (String) -> frame
|
42
|
+
|
43
|
+
def generate: (frame) -> String
|
44
|
+
|
45
|
+
def parse: (String) -> frame?
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def initialize: (?Integer local_max_frame_size, ?Integer remote_max_frame_size) -> untyped
|
50
|
+
|
51
|
+
def pack_error: (Integer | Symbol error, buffer: String) -> String
|
52
|
+
|
53
|
+
def unpack_error: (Integer) -> (Symbol | Integer)
|
54
|
+
end
|
55
|
+
end
|