http-2 0.12.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +176 -90
- data/lib/http/2/emitter.rb +4 -5
- data/lib/http/2/error.rb +22 -1
- data/lib/http/2/extensions.rb +53 -0
- data/lib/http/2/flow_buffer.rb +88 -35
- data/lib/http/2/framer.rb +127 -89
- 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 +337 -0
- data/lib/http/2/{huffman.rb → header/huffman.rb} +11 -7
- data/lib/http/2/{huffman_statemachine.rb → header/huffman_statemachine.rb} +2 -0
- 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 +93 -0
- data/sig/emitter.rbs +13 -0
- data/sig/error.rbs +35 -0
- data/sig/extensions.rbs +5 -0
- data/sig/flow_buffer.rbs +21 -0
- data/sig/frame_buffer.rbs +13 -0
- data/sig/framer.rbs +54 -0
- data/sig/header/compressor.rbs +27 -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/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
@@ -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,93 @@
|
|
1
|
+
module HTTP2
|
2
|
+
class Connection
|
3
|
+
include FlowBuffer
|
4
|
+
include Emitter
|
5
|
+
|
6
|
+
REQUEST_MANDATORY_HEADERS: Array[String]
|
7
|
+
RESPONSE_MANDATORY_HEADERS: Array[String]
|
8
|
+
|
9
|
+
attr_reader state: Symbol
|
10
|
+
|
11
|
+
attr_reader local_window: Integer
|
12
|
+
attr_reader remote_window: Integer
|
13
|
+
|
14
|
+
alias window local_window
|
15
|
+
|
16
|
+
attr_reader remote_settings: settings_hash
|
17
|
+
attr_reader local_settings: settings_hash
|
18
|
+
attr_reader pending_settings: settings_ary
|
19
|
+
|
20
|
+
attr_accessor active_stream_count: Integer
|
21
|
+
|
22
|
+
@stream_id: Integer
|
23
|
+
@active_stream_count: Integer
|
24
|
+
@last_activated_stream: Integer
|
25
|
+
@last_stream_id: Integer
|
26
|
+
|
27
|
+
@streams: Hash[Integer, Stream]
|
28
|
+
@streams_recently_closed: Hash[Integer, Stream]
|
29
|
+
|
30
|
+
@framer: Framer
|
31
|
+
|
32
|
+
@local_window_limit: Integer
|
33
|
+
@remote_window_limit: Integer
|
34
|
+
|
35
|
+
@compressor: Header::Compressor
|
36
|
+
@decompressor: Header::Decompressor
|
37
|
+
@error: Symbol?
|
38
|
+
|
39
|
+
@recv_buffer: String
|
40
|
+
@continuation: Array[frame]
|
41
|
+
|
42
|
+
@closed_since: Float?
|
43
|
+
@received_frame: bool
|
44
|
+
|
45
|
+
def closed?: () -> bool
|
46
|
+
|
47
|
+
def new_stream: (**untyped) -> Stream
|
48
|
+
|
49
|
+
def ping: (String) -> void
|
50
|
+
| (String) { () -> void } -> void
|
51
|
+
|
52
|
+
def goaway: (?Symbol, ?String) -> void
|
53
|
+
|
54
|
+
def window_update: (Integer increment) -> void
|
55
|
+
|
56
|
+
def settings: (settings_enum) -> void
|
57
|
+
|
58
|
+
def receive: (string data) -> void
|
59
|
+
alias << receive
|
60
|
+
|
61
|
+
def initialize: (?settings_hash) -> void
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def send: (frame) -> void
|
66
|
+
|
67
|
+
def encode: (frame) -> Array[String]
|
68
|
+
|
69
|
+
def connection_frame?: (frame) -> bool
|
70
|
+
|
71
|
+
def connection_management: (frame) -> void
|
72
|
+
|
73
|
+
def ping_management: (frame) -> void
|
74
|
+
|
75
|
+
def validate_settings: (:client | :server, settings_enum) -> void
|
76
|
+
|
77
|
+
def connection_settings: (frame) -> void
|
78
|
+
|
79
|
+
def decode_headers: (frame) -> void
|
80
|
+
|
81
|
+
def encode_headers: (frame) -> Array[frame]
|
82
|
+
|
83
|
+
def activate_stream: (id: Integer, **untyped) -> Stream
|
84
|
+
|
85
|
+
def verify_stream_order: (Integer id) -> void
|
86
|
+
|
87
|
+
def verify_pseudo_headers: (frame) -> void
|
88
|
+
|
89
|
+
def _verify_pseudo_headers: (frame, Array[String]) -> void
|
90
|
+
|
91
|
+
def connection_error: (?Symbol error, ?msg: String?, ?e: StandardError?) -> void
|
92
|
+
end
|
93
|
+
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
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,54 @@
|
|
1
|
+
module HTTP2
|
2
|
+
class Framer
|
3
|
+
include PackingExtensions
|
4
|
+
|
5
|
+
DEFAULT_MAX_FRAME_SIZE: Integer
|
6
|
+
|
7
|
+
MAX_STREAM_ID: Integer
|
8
|
+
|
9
|
+
MAX_WINDOWINC: Integer
|
10
|
+
|
11
|
+
FRAME_TYPES: Hash[Symbol, Integer]
|
12
|
+
|
13
|
+
FRAME_TYPES_WITH_PADDING: Array[Symbol]
|
14
|
+
|
15
|
+
FRAME_FLAGS: Hash[Symbol, Hash[Symbol, Integer]]
|
16
|
+
|
17
|
+
DEFINED_SETTINGS: Hash[Symbol, Integer]
|
18
|
+
|
19
|
+
DEFINED_ERRORS: Hash[Symbol, Integer]
|
20
|
+
|
21
|
+
RBIT: Integer
|
22
|
+
RBYTE: Integer
|
23
|
+
EBIT: Integer
|
24
|
+
UINT32: String
|
25
|
+
UINT16: String
|
26
|
+
UINT8: String
|
27
|
+
HEADERPACK: String
|
28
|
+
FRAME_LENGTH_HISHIFT: Integer
|
29
|
+
FRAME_LENGTH_LOMASK: Integer
|
30
|
+
|
31
|
+
@local_max_frame_size: Integer
|
32
|
+
@remote_max_frame_size: Integer
|
33
|
+
|
34
|
+
attr_accessor local_max_frame_size: Integer
|
35
|
+
|
36
|
+
attr_accessor remote_max_frame_size: Integer
|
37
|
+
|
38
|
+
def common_header: (frame, buffer: String) -> String
|
39
|
+
|
40
|
+
def read_common_frame: (String) -> frame
|
41
|
+
|
42
|
+
def generate: (frame) -> String
|
43
|
+
|
44
|
+
def parse: (String) -> frame?
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def initialize: (?Integer local_max_frame_size, ?Integer remote_max_frame_size) -> untyped
|
49
|
+
|
50
|
+
def pack_error: (Integer | Symbol error, buffer: String) -> String
|
51
|
+
|
52
|
+
def unpack_error: (Integer) -> (Symbol | Integer)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module HTTP2
|
2
|
+
module Header
|
3
|
+
class Compressor
|
4
|
+
include PackingExtensions
|
5
|
+
|
6
|
+
@cc: EncodingContext
|
7
|
+
|
8
|
+
def table_size=: (Integer) -> void
|
9
|
+
|
10
|
+
def integer: (Integer, Integer, buffer: String, ?offset: Integer) -> String
|
11
|
+
|
12
|
+
def string: (String) -> String
|
13
|
+
|
14
|
+
def header: (header_command, ?String) -> String
|
15
|
+
|
16
|
+
def encode: (Enumerable[header_pair]) -> String
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def initialize: (?context_hash options) -> void
|
21
|
+
|
22
|
+
def huffman_string: (String str) -> String
|
23
|
+
|
24
|
+
def plain_string: (String str) -> String
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|