biryani 0.0.8 → 0.0.9
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/biryani.gemspec +5 -2
- data/lib/biryani/connection.rb +11 -7
- data/lib/biryani/hpack/field.rb +5 -9
- data/lib/biryani/state.rb +1 -1
- data/lib/biryani/streams_context.rb +15 -15
- data/lib/biryani/version.rb +1 -1
- metadata +2 -73
- data/.github/workflows/ci.yml +0 -30
- data/.github/workflows/conformance.yml +0 -46
- data/.gitignore +0 -18
- data/spec/connection/handle_connection_window_update_spec.rb +0 -16
- data/spec/connection/handle_data_spec.rb +0 -58
- data/spec/connection/handle_headers_spec.rb +0 -19
- data/spec/connection/handle_ping_spec.rb +0 -21
- data/spec/connection/handle_rst_stream_spec.rb +0 -16
- data/spec/connection/handle_settings_spec.rb +0 -37
- data/spec/connection/handle_stream_window_update_spec.rb +0 -20
- data/spec/connection/read_http2_magic_spec.rb +0 -26
- data/spec/connection/send_spec.rb +0 -104
- data/spec/connection/transition_stream_state_send_spec.rb +0 -39
- data/spec/data_buffer_spec.rb +0 -135
- data/spec/frame/continuation_spec.rb +0 -39
- data/spec/frame/data_spec.rb +0 -25
- data/spec/frame/goaway_spec.rb +0 -23
- data/spec/frame/headers_spec.rb +0 -52
- data/spec/frame/ping_spec.rb +0 -22
- data/spec/frame/priority_spec.rb +0 -22
- data/spec/frame/push_promise_spec.rb +0 -24
- data/spec/frame/read_spec.rb +0 -30
- data/spec/frame/rst_stream_spec.rb +0 -21
- data/spec/frame/settings_spec.rb +0 -23
- data/spec/frame/window_update_spec.rb +0 -21
- data/spec/hpack/decoder_spec.rb +0 -170
- data/spec/hpack/encoder_spec.rb +0 -48
- data/spec/hpack/field_spec.rb +0 -43
- data/spec/hpack/fields_spec.rb +0 -17
- data/spec/hpack/huffman_spec.rb +0 -20
- data/spec/hpack/integer_spec.rb +0 -27
- data/spec/hpack/string_spec.rb +0 -19
- data/spec/http_request_spec.rb +0 -62
- data/spec/http_response_spec.rb +0 -12
- data/spec/spec_helper.rb +0 -9
- data/spec/streams_context_spec.rb +0 -79
- data/spec/utils_spec.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 33f21fe89774fbe47cfaa0f36bb1eaaabc333701ffce568c410818aa86c6441d
|
|
4
|
+
data.tar.gz: 290247cccbfbf21eb1d6d4e93b1f39a4cfb5dbe26fcef278f9804f95221e7ec1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eed8eb6993bdc77026e12b52836a0970bc6ed6ba024f05bb278049e38ddf9528dadea31c8d42660f0d0c38da08295ac7343702436512d0de148f4f6d82205811
|
|
7
|
+
data.tar.gz: abffb2767adcddc3556a22367a7a67c78cbc636de1dfa794b65f421c5ac15c30a546e3641edf607bce8119c3c2420856700bbc19439883fc0a74b4fcb3623bc6
|
data/biryani.gemspec
CHANGED
|
@@ -13,8 +13,11 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
spec.license = 'MIT'
|
|
14
14
|
spec.required_ruby_version = '>=4.0'
|
|
15
15
|
|
|
16
|
-
spec.files
|
|
17
|
-
|
|
16
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
17
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
18
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
19
|
+
end
|
|
20
|
+
end
|
|
18
21
|
spec.require_paths = ['lib']
|
|
19
22
|
|
|
20
23
|
spec.add_development_dependency 'bundler'
|
data/lib/biryani/connection.rb
CHANGED
|
@@ -71,10 +71,9 @@ module Biryani
|
|
|
71
71
|
# rubocop: disable Metrics/PerceivedComplexity
|
|
72
72
|
def send_loop(io)
|
|
73
73
|
loop do
|
|
74
|
-
|
|
75
|
-
break if ports.empty? && @sock.closed?
|
|
74
|
+
break if @sock.closed? && @streams_ctx.empty?
|
|
76
75
|
|
|
77
|
-
port, obj = Ractor.select(@sock,
|
|
76
|
+
port, obj = Ractor.select(@sock, @streams_ctx.tx)
|
|
78
77
|
if port == @sock
|
|
79
78
|
if Biryani.err?(obj)
|
|
80
79
|
reply_frame = Biryani.unwrap(obj, @streams_ctx.last_stream_id)
|
|
@@ -104,7 +103,6 @@ module Biryani
|
|
|
104
103
|
self.class.send_data(io, stream_id, data, @send_window, max_frame_size, @streams_ctx, @data_buffer) unless data.empty?
|
|
105
104
|
end
|
|
106
105
|
|
|
107
|
-
@streams_ctx.remove_closed(@data_buffer)
|
|
108
106
|
break if closed?
|
|
109
107
|
end
|
|
110
108
|
end
|
|
@@ -182,7 +180,7 @@ module Biryani
|
|
|
182
180
|
max_streams = @peer_settings[SettingsID::SETTINGS_MAX_CONCURRENT_STREAMS]
|
|
183
181
|
send_initial_window_size = @peer_settings[SettingsID::SETTINGS_INITIAL_WINDOW_SIZE]
|
|
184
182
|
recv_initial_window_size = @settings[SettingsID::SETTINGS_INITIAL_WINDOW_SIZE]
|
|
185
|
-
obj = self.class.transition_stream_state_recv(frame, @streams_ctx, stream_id, max_streams, send_initial_window_size, recv_initial_window_size)
|
|
183
|
+
obj = self.class.transition_stream_state_recv(frame, @streams_ctx, @data_buffer, stream_id, max_streams, send_initial_window_size, recv_initial_window_size)
|
|
186
184
|
return [obj] if Biryani.err?(obj)
|
|
187
185
|
|
|
188
186
|
ctx = obj
|
|
@@ -237,6 +235,7 @@ module Biryani
|
|
|
237
235
|
# @param recv_frame [Object]
|
|
238
236
|
# @param streams_ctx [StreamsContext]
|
|
239
237
|
# @param stream_id [Integer]
|
|
238
|
+
# @param data_buffer [DataBuffer]
|
|
240
239
|
# @param max_streams [Integer]
|
|
241
240
|
# @param send_initial_window_size [Integer]
|
|
242
241
|
# @param recv_initial_window_size [Integer]
|
|
@@ -244,13 +243,18 @@ module Biryani
|
|
|
244
243
|
# @return [StreamContext, StreamError, ConnectionError]
|
|
245
244
|
# rubocop: disable Metrics/CyclomaticComplexity
|
|
246
245
|
# rubocop: disable Metrics/PerceivedComplexity
|
|
247
|
-
def self.transition_stream_state_recv(recv_frame, streams_ctx, stream_id, max_streams, send_initial_window_size, recv_initial_window_size)
|
|
246
|
+
def self.transition_stream_state_recv(recv_frame, streams_ctx, data_buffer, stream_id, max_streams, send_initial_window_size, recv_initial_window_size)
|
|
248
247
|
ctx = streams_ctx[stream_id]
|
|
249
248
|
return StreamError.new(ErrorCode::PROTOCOL_ERROR, stream_id, 'exceed max concurrent streams') if ctx.nil? && streams_ctx.count_active + 1 > max_streams
|
|
250
249
|
return ConnectionError.new(ErrorCode::PROTOCOL_ERROR, 'even-numbered stream identifier') if ctx.nil? && stream_id.even?
|
|
251
250
|
return ConnectionError.new(ErrorCode::PROTOCOL_ERROR, 'new stream identifier is less than the existing stream identifiers') if ctx.nil? && streams_ctx.last_stream_id > stream_id
|
|
252
251
|
|
|
253
|
-
|
|
252
|
+
if ctx.nil?
|
|
253
|
+
ctx = streams_ctx.new_context(stream_id, send_initial_window_size, recv_initial_window_size)
|
|
254
|
+
# An ideal implementation would wait the RTT before removing the stream.
|
|
255
|
+
streams_ctx.remove_closed(data_buffer)
|
|
256
|
+
end
|
|
257
|
+
|
|
254
258
|
obj = ctx.state_transition!(recv_frame, :recv)
|
|
255
259
|
return obj if Biryani.err?(obj)
|
|
256
260
|
|
data/lib/biryani/hpack/field.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Biryani
|
|
|
9
9
|
# @return [String]
|
|
10
10
|
def self.encode(name, value, dynamic_table)
|
|
11
11
|
case find(name, value, dynamic_table)
|
|
12
|
-
in Some(index,
|
|
12
|
+
in Some(index, nil)
|
|
13
13
|
res = encode_indexed(index)
|
|
14
14
|
in Some(index, v)
|
|
15
15
|
res = encode_literal_value(index, v)
|
|
@@ -145,8 +145,7 @@ module Biryani
|
|
|
145
145
|
# @return [Integer]
|
|
146
146
|
def self.decode_indexed(io, cursor, dynamic_table)
|
|
147
147
|
index, c = Integer.decode(io, 7, cursor)
|
|
148
|
-
raise Error::HPACKDecodeError if index.zero?
|
|
149
|
-
raise Error::HPACKDecodeError if index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
148
|
+
raise Error::HPACKDecodeError if index.zero? || index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
150
149
|
|
|
151
150
|
field = if index <= STATIC_TABLE_SIZE
|
|
152
151
|
STATIC_TABLE[index - 1]
|
|
@@ -203,8 +202,7 @@ module Biryani
|
|
|
203
202
|
# @return [Integer]
|
|
204
203
|
def self.decode_literal_value_incremental_indexing(io, cursor, dynamic_table)
|
|
205
204
|
index, c = Integer.decode(io, 6, cursor)
|
|
206
|
-
raise Error::HPACKDecodeError if index.zero?
|
|
207
|
-
raise Error::HPACKDecodeError if index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
205
|
+
raise Error::HPACKDecodeError if index.zero? || index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
208
206
|
|
|
209
207
|
name = if index <= STATIC_TABLE_SIZE
|
|
210
208
|
STATIC_TABLE[index - 1][0]
|
|
@@ -283,8 +281,7 @@ module Biryani
|
|
|
283
281
|
# @return [Integer]
|
|
284
282
|
def self.decode_literal_value_never_indexed(io, cursor, dynamic_table)
|
|
285
283
|
index, c = Integer.decode(io, 4, cursor)
|
|
286
|
-
raise Error::HPACKDecodeError if index.zero?
|
|
287
|
-
raise Error::HPACKDecodeError if index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
284
|
+
raise Error::HPACKDecodeError if index.zero? || index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
288
285
|
|
|
289
286
|
name = if index <= STATIC_TABLE_SIZE
|
|
290
287
|
STATIC_TABLE[index - 1][0]
|
|
@@ -339,8 +336,7 @@ module Biryani
|
|
|
339
336
|
# @return [Integer]
|
|
340
337
|
def self.decode_literal_value_without_indexing(io, cursor, dynamic_table)
|
|
341
338
|
index, c = Integer.decode(io, 4, cursor)
|
|
342
|
-
raise Error::HPACKDecodeError if index.zero?
|
|
343
|
-
raise Error::HPACKDecodeError if index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
339
|
+
raise Error::HPACKDecodeError if index.zero? || index > STATIC_TABLE_SIZE + dynamic_table.count_entries
|
|
344
340
|
|
|
345
341
|
name = if index <= STATIC_TABLE_SIZE
|
|
346
342
|
STATIC_TABLE[index - 1][0]
|
data/lib/biryani/state.rb
CHANGED
|
@@ -255,7 +255,7 @@ module Biryani
|
|
|
255
255
|
|
|
256
256
|
# @return [Boolean]
|
|
257
257
|
def receiving_continuation?
|
|
258
|
-
%i[receiving_continuation receiving_continuation_and_data].include?(@state)
|
|
258
|
+
%i[receiving_continuation receiving_continuation_and_data receiving_trailer_continuation].include?(@state)
|
|
259
259
|
end
|
|
260
260
|
end
|
|
261
261
|
end
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
module Biryani
|
|
2
2
|
class StreamsContext
|
|
3
|
+
attr_accessor :tx
|
|
4
|
+
|
|
3
5
|
def initialize(proc)
|
|
4
6
|
@h = {} # Hash<Integer, StreamContext>
|
|
5
7
|
@proc = proc
|
|
8
|
+
@tx = Ractor::Port.new
|
|
6
9
|
end
|
|
7
10
|
|
|
8
11
|
# @param stream_id [Integer]
|
|
@@ -11,7 +14,7 @@ module Biryani
|
|
|
11
14
|
#
|
|
12
15
|
# @return [StreamContext]
|
|
13
16
|
def new_context(stream_id, send_initial_window_size, recv_initial_window_size)
|
|
14
|
-
ctx = StreamContext.new(stream_id, send_initial_window_size, recv_initial_window_size, @proc)
|
|
17
|
+
ctx = StreamContext.new(stream_id, send_initial_window_size, recv_initial_window_size, @proc, @tx)
|
|
15
18
|
@h[stream_id] = ctx
|
|
16
19
|
ctx
|
|
17
20
|
end
|
|
@@ -33,13 +36,13 @@ module Biryani
|
|
|
33
36
|
@h.length
|
|
34
37
|
end
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
# @return [Boolean]
|
|
40
|
+
def empty?
|
|
41
|
+
@h.empty?
|
|
38
42
|
end
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@h.values.filter { |ctx| !ctx.closed? }.map(&:tx)
|
|
44
|
+
def each(&block)
|
|
45
|
+
@h.each_value(&block)
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
# @return [Integer]
|
|
@@ -88,28 +91,25 @@ module Biryani
|
|
|
88
91
|
def remove_closed(data_buffer)
|
|
89
92
|
closed_ids = closed_stream_ids.filter { |id| !data_buffer.has?(id) }
|
|
90
93
|
closed_ids.each do |id|
|
|
91
|
-
@h
|
|
94
|
+
@h.delete(id)
|
|
92
95
|
end
|
|
93
96
|
end
|
|
94
97
|
|
|
95
98
|
def close_all
|
|
96
|
-
each
|
|
97
|
-
ctx.tx.close
|
|
98
|
-
ctx.close
|
|
99
|
-
end
|
|
99
|
+
each(&:close)
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
class StreamContext
|
|
104
|
-
attr_accessor :
|
|
104
|
+
attr_accessor :send_window, :recv_window, :fragment, :content
|
|
105
105
|
|
|
106
106
|
# @param stream_id [Integer]
|
|
107
107
|
# @param send_initial_window_size [Integer]
|
|
108
108
|
# @param recv_initial_window_size [Integer]
|
|
109
109
|
# @param proc [Proc]
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@stream = Stream.new(
|
|
110
|
+
# @param tx [Ractor::Port]
|
|
111
|
+
def initialize(stream_id, send_initial_window_size, recv_initial_window_size, proc, tx)
|
|
112
|
+
@stream = Stream.new(tx, stream_id, proc)
|
|
113
113
|
@send_window = Window.new(send_initial_window_size)
|
|
114
114
|
@recv_window = Window.new(recv_initial_window_size)
|
|
115
115
|
@fragment = ''.b
|
data/lib/biryani/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: biryani
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thekuwayama
|
|
@@ -30,9 +30,6 @@ executables: []
|
|
|
30
30
|
extensions: []
|
|
31
31
|
extra_rdoc_files: []
|
|
32
32
|
files:
|
|
33
|
-
- ".github/workflows/ci.yml"
|
|
34
|
-
- ".github/workflows/conformance.yml"
|
|
35
|
-
- ".gitignore"
|
|
36
33
|
- ".rubocop.yml"
|
|
37
34
|
- ".ruby-version"
|
|
38
35
|
- Gemfile
|
|
@@ -83,40 +80,6 @@ files:
|
|
|
83
80
|
- lib/biryani/utils.rb
|
|
84
81
|
- lib/biryani/version.rb
|
|
85
82
|
- lib/biryani/window.rb
|
|
86
|
-
- spec/connection/handle_connection_window_update_spec.rb
|
|
87
|
-
- spec/connection/handle_data_spec.rb
|
|
88
|
-
- spec/connection/handle_headers_spec.rb
|
|
89
|
-
- spec/connection/handle_ping_spec.rb
|
|
90
|
-
- spec/connection/handle_rst_stream_spec.rb
|
|
91
|
-
- spec/connection/handle_settings_spec.rb
|
|
92
|
-
- spec/connection/handle_stream_window_update_spec.rb
|
|
93
|
-
- spec/connection/read_http2_magic_spec.rb
|
|
94
|
-
- spec/connection/send_spec.rb
|
|
95
|
-
- spec/connection/transition_stream_state_send_spec.rb
|
|
96
|
-
- spec/data_buffer_spec.rb
|
|
97
|
-
- spec/frame/continuation_spec.rb
|
|
98
|
-
- spec/frame/data_spec.rb
|
|
99
|
-
- spec/frame/goaway_spec.rb
|
|
100
|
-
- spec/frame/headers_spec.rb
|
|
101
|
-
- spec/frame/ping_spec.rb
|
|
102
|
-
- spec/frame/priority_spec.rb
|
|
103
|
-
- spec/frame/push_promise_spec.rb
|
|
104
|
-
- spec/frame/read_spec.rb
|
|
105
|
-
- spec/frame/rst_stream_spec.rb
|
|
106
|
-
- spec/frame/settings_spec.rb
|
|
107
|
-
- spec/frame/window_update_spec.rb
|
|
108
|
-
- spec/hpack/decoder_spec.rb
|
|
109
|
-
- spec/hpack/encoder_spec.rb
|
|
110
|
-
- spec/hpack/field_spec.rb
|
|
111
|
-
- spec/hpack/fields_spec.rb
|
|
112
|
-
- spec/hpack/huffman_spec.rb
|
|
113
|
-
- spec/hpack/integer_spec.rb
|
|
114
|
-
- spec/hpack/string_spec.rb
|
|
115
|
-
- spec/http_request_spec.rb
|
|
116
|
-
- spec/http_response_spec.rb
|
|
117
|
-
- spec/spec_helper.rb
|
|
118
|
-
- spec/streams_context_spec.rb
|
|
119
|
-
- spec/utils_spec.rb
|
|
120
83
|
homepage: https://github.com/thekuwayama/biryani
|
|
121
84
|
licenses:
|
|
122
85
|
- MIT
|
|
@@ -138,38 +101,4 @@ requirements: []
|
|
|
138
101
|
rubygems_version: 4.0.6
|
|
139
102
|
specification_version: 4
|
|
140
103
|
summary: An HTTP/2 server implemented using Ruby Ractor
|
|
141
|
-
test_files:
|
|
142
|
-
- spec/connection/handle_connection_window_update_spec.rb
|
|
143
|
-
- spec/connection/handle_data_spec.rb
|
|
144
|
-
- spec/connection/handle_headers_spec.rb
|
|
145
|
-
- spec/connection/handle_ping_spec.rb
|
|
146
|
-
- spec/connection/handle_rst_stream_spec.rb
|
|
147
|
-
- spec/connection/handle_settings_spec.rb
|
|
148
|
-
- spec/connection/handle_stream_window_update_spec.rb
|
|
149
|
-
- spec/connection/read_http2_magic_spec.rb
|
|
150
|
-
- spec/connection/send_spec.rb
|
|
151
|
-
- spec/connection/transition_stream_state_send_spec.rb
|
|
152
|
-
- spec/data_buffer_spec.rb
|
|
153
|
-
- spec/frame/continuation_spec.rb
|
|
154
|
-
- spec/frame/data_spec.rb
|
|
155
|
-
- spec/frame/goaway_spec.rb
|
|
156
|
-
- spec/frame/headers_spec.rb
|
|
157
|
-
- spec/frame/ping_spec.rb
|
|
158
|
-
- spec/frame/priority_spec.rb
|
|
159
|
-
- spec/frame/push_promise_spec.rb
|
|
160
|
-
- spec/frame/read_spec.rb
|
|
161
|
-
- spec/frame/rst_stream_spec.rb
|
|
162
|
-
- spec/frame/settings_spec.rb
|
|
163
|
-
- spec/frame/window_update_spec.rb
|
|
164
|
-
- spec/hpack/decoder_spec.rb
|
|
165
|
-
- spec/hpack/encoder_spec.rb
|
|
166
|
-
- spec/hpack/field_spec.rb
|
|
167
|
-
- spec/hpack/fields_spec.rb
|
|
168
|
-
- spec/hpack/huffman_spec.rb
|
|
169
|
-
- spec/hpack/integer_spec.rb
|
|
170
|
-
- spec/hpack/string_spec.rb
|
|
171
|
-
- spec/http_request_spec.rb
|
|
172
|
-
- spec/http_response_spec.rb
|
|
173
|
-
- spec/spec_helper.rb
|
|
174
|
-
- spec/streams_context_spec.rb
|
|
175
|
-
- spec/utils_spec.rb
|
|
104
|
+
test_files: []
|
data/.github/workflows/ci.yml
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
name: lint & test
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
pull_request:
|
|
8
|
-
branches:
|
|
9
|
-
- '*'
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
ci:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
strategy:
|
|
15
|
-
matrix:
|
|
16
|
-
ruby-version: ['4.0']
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
19
|
-
- name: Set up Ruby
|
|
20
|
-
uses: ruby/setup-ruby@ae195bbe749a7cef685ac729197124a48305c1cb # v1.276.0
|
|
21
|
-
with:
|
|
22
|
-
ruby-version: ${{ matrix.ruby-version }}
|
|
23
|
-
- name: Install dependencies
|
|
24
|
-
run: |
|
|
25
|
-
gem --version
|
|
26
|
-
gem install bundler
|
|
27
|
-
bundle --version
|
|
28
|
-
bundle install
|
|
29
|
-
- name: Run rubocop & rspec
|
|
30
|
-
run: bundle exec rake
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
name: h2spec
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
pull_request:
|
|
8
|
-
branches:
|
|
9
|
-
- '*'
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
conformance:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
permissions:
|
|
15
|
-
contents: read
|
|
16
|
-
checks: write
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
ruby-version: ['4.0']
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
22
|
-
- name: Set up Ruby
|
|
23
|
-
uses: ruby/setup-ruby@ae195bbe749a7cef685ac729197124a48305c1cb # v1.276.0
|
|
24
|
-
with:
|
|
25
|
-
ruby-version: ${{ matrix.ruby-version }}
|
|
26
|
-
- name: Install dependencies
|
|
27
|
-
run: |
|
|
28
|
-
gem --version
|
|
29
|
-
gem install bundler
|
|
30
|
-
bundle --version
|
|
31
|
-
bundle install
|
|
32
|
-
- name: Install h2spec
|
|
33
|
-
run: |
|
|
34
|
-
set -eu
|
|
35
|
-
curl -Ls https://github.com/summerwind/h2spec/releases/download/v2.6.0/h2spec_linux_amd64.tar.gz | tar xz
|
|
36
|
-
mkdir -p $GITHUB_WORKSPACE/bin
|
|
37
|
-
mv h2spec $GITHUB_WORKSPACE/bin/h2spec
|
|
38
|
-
chmod +x $GITHUB_WORKSPACE/bin/h2spec
|
|
39
|
-
echo $GITHUB_WORKSPACE/bin >> $GITHUB_PATH
|
|
40
|
-
- name: Run conformance test
|
|
41
|
-
run: bundle exec rake conformance
|
|
42
|
-
- uses: mikepenz/action-junit-report@a294a61c909bd8a4b563024a2faa28897fd53ebc # v6.1.0
|
|
43
|
-
if: success()
|
|
44
|
-
with:
|
|
45
|
-
report_paths: conformance/reports/h2spec.xml
|
|
46
|
-
detailed_summary: true
|
data/.gitignore
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_connection_window_update' do
|
|
5
|
-
let(:window_update) do
|
|
6
|
-
Frame::WindowUpdate.new(0, 1000)
|
|
7
|
-
end
|
|
8
|
-
let(:send_window) do
|
|
9
|
-
Window.new(65_535)
|
|
10
|
-
end
|
|
11
|
-
it 'should handle' do
|
|
12
|
-
expect { Connection.handle_connection_window_update(window_update, send_window) }.not_to raise_error
|
|
13
|
-
expect(send_window.length).to eq 2**16 - 1 + 1000
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_data' do
|
|
5
|
-
let(:decoder) do
|
|
6
|
-
HPACK::Decoder.new(4_096)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
let(:recv_window1) do
|
|
10
|
-
Window.new(65_535)
|
|
11
|
-
end
|
|
12
|
-
let(:streams_ctx1) do
|
|
13
|
-
streams_ctx = StreamsContext.new(do_nothing_proc)
|
|
14
|
-
streams_ctx.new_context(1, 65_535, 65_535)
|
|
15
|
-
streams_ctx.new_context(2, 65_535, 65_535)
|
|
16
|
-
streams_ctx
|
|
17
|
-
end
|
|
18
|
-
it 'should handle' do
|
|
19
|
-
expect(Connection.handle_data(2, 'Hello, world!', recv_window1, streams_ctx1, decoder)).to eq []
|
|
20
|
-
expect(streams_ctx1[2].content).to eq 'Hello, world!'
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
let(:recv_window2) do
|
|
24
|
-
recv_window = Window.new(65_535)
|
|
25
|
-
recv_window.consume!(65_535 / 2)
|
|
26
|
-
recv_window
|
|
27
|
-
end
|
|
28
|
-
let(:streams_ctx2) do
|
|
29
|
-
streams_ctx = StreamsContext.new(do_nothing_proc)
|
|
30
|
-
streams_ctx.new_context(1, 65_535, 65_535)
|
|
31
|
-
streams_ctx.new_context(2, 65_535, 65_535)
|
|
32
|
-
streams_ctx[2].recv_window.consume!(65_535 / 2)
|
|
33
|
-
streams_ctx
|
|
34
|
-
end
|
|
35
|
-
it 'should handle' do
|
|
36
|
-
frames = Connection.handle_data(2, 'Hello, world!', recv_window2, streams_ctx2, decoder)
|
|
37
|
-
expect(frames.map(&:f_type)).to eq [FrameType::WINDOW_UPDATE, FrameType::WINDOW_UPDATE]
|
|
38
|
-
expect(frames.map(&:stream_id)).to eq [0, 2]
|
|
39
|
-
expect(frames.map(&:window_size_increment)).to eq [65_535 / 2 + 13, 65_535 / 2 + 13]
|
|
40
|
-
expect(streams_ctx2[2].content).to eq 'Hello, world!'
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
let(:recv_window3) do
|
|
44
|
-
recv_window = Window.new(65_535)
|
|
45
|
-
recv_window.consume!(65_535)
|
|
46
|
-
recv_window
|
|
47
|
-
end
|
|
48
|
-
let(:streams_ctx3) do
|
|
49
|
-
streams_ctx = StreamsContext.new(do_nothing_proc)
|
|
50
|
-
streams_ctx.new_context(1, 65_535, 65_535)
|
|
51
|
-
streams_ctx.new_context(2, 65_535, 65_535)
|
|
52
|
-
streams_ctx
|
|
53
|
-
end
|
|
54
|
-
it 'should not handle' do
|
|
55
|
-
expect(Connection.handle_data(2, 'Hello, world!', recv_window3, streams_ctx3, decoder)).to be_kind_of ConnectionError
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_headers' do
|
|
5
|
-
let(:headers) do
|
|
6
|
-
Frame::Headers.new(true, false, 2, nil, nil, 'this is dummy', nil)
|
|
7
|
-
end
|
|
8
|
-
let(:ctx) do
|
|
9
|
-
StreamContext.new(2, 65_535, 65_535, do_nothing_proc)
|
|
10
|
-
end
|
|
11
|
-
let(:decoder) do
|
|
12
|
-
HPACK::Decoder.new(4_096)
|
|
13
|
-
end
|
|
14
|
-
it 'should handle' do
|
|
15
|
-
expect(Connection.handle_headers(headers, ctx, decoder)).to eq nil
|
|
16
|
-
expect(ctx.fragment).to eq 'this is dummy'
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_ping' do
|
|
5
|
-
let(:ping1) do
|
|
6
|
-
Frame::Ping.new(true, 0, "\x00" * 8)
|
|
7
|
-
end
|
|
8
|
-
it 'should handle' do
|
|
9
|
-
expect(Connection.handle_ping(ping1)).to eq nil
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
let(:ping2) do
|
|
13
|
-
Frame::Ping.new(false, 0, "\x00" * 8)
|
|
14
|
-
end
|
|
15
|
-
it 'should handle' do
|
|
16
|
-
expect(Connection.handle_ping(ping2)).to_not eq nil
|
|
17
|
-
expect(Connection.handle_ping(ping2).ack?).to eq true
|
|
18
|
-
expect(Connection.handle_ping(ping2).opaque).to eq "\x00" * 8
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_rst_stream' do
|
|
5
|
-
let(:rst_stream) do
|
|
6
|
-
Frame::RstStream.new(2, 0)
|
|
7
|
-
end
|
|
8
|
-
let(:ctx) do
|
|
9
|
-
StreamContext.new(2, 65_535, 65_535, do_nothing_proc)
|
|
10
|
-
end
|
|
11
|
-
it 'should handle' do
|
|
12
|
-
Connection.handle_rst_stream(rst_stream, ctx)
|
|
13
|
-
expect(ctx.closed?).to eq true
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_settings' do
|
|
5
|
-
let(:send_settings) do
|
|
6
|
-
Connection.default_settings
|
|
7
|
-
end
|
|
8
|
-
let(:decoder) do
|
|
9
|
-
HPACK::Decoder.new(4_096)
|
|
10
|
-
end
|
|
11
|
-
let(:streams_ctx) do
|
|
12
|
-
streams_ctx = StreamsContext.new(do_nothing_proc)
|
|
13
|
-
streams_ctx.new_context(1, 65_535, 65_535)
|
|
14
|
-
streams_ctx.new_context(2, 65_535, 65_535)
|
|
15
|
-
streams_ctx
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
let(:settings1) do
|
|
19
|
-
Frame::Settings.new(false, 0, { SettingsID::SETTINGS_HEADER_TABLE_SIZE => 8_192 })
|
|
20
|
-
end
|
|
21
|
-
it 'should handle' do
|
|
22
|
-
reply_settings = Connection.handle_settings(settings1, send_settings, decoder, streams_ctx)
|
|
23
|
-
expect(reply_settings.ack?).to eq true
|
|
24
|
-
expect(reply_settings.setting.empty?).to eq true
|
|
25
|
-
expect(send_settings[SettingsID::SETTINGS_MAX_CONCURRENT_STREAMS]).to eq 0xffffffff
|
|
26
|
-
expect(send_settings[SettingsID::SETTINGS_MAX_FRAME_SIZE]).to eq 16_384
|
|
27
|
-
expect(send_settings[SettingsID::SETTINGS_HEADER_TABLE_SIZE]).to eq 8_192
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
let(:settings2) do
|
|
31
|
-
Frame::Settings.new(true, 0, {})
|
|
32
|
-
end
|
|
33
|
-
it 'should handle' do
|
|
34
|
-
expect(Connection.handle_settings(settings2, send_settings, decoder, streams_ctx)).to eq nil
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'handle_stream_window_update' do
|
|
5
|
-
let(:window_update) do
|
|
6
|
-
Frame::WindowUpdate.new(1, 1000)
|
|
7
|
-
end
|
|
8
|
-
let(:streams_ctx) do
|
|
9
|
-
streams_ctx = StreamsContext.new(do_nothing_proc)
|
|
10
|
-
streams_ctx.new_context(1, 65_535, 65_535)
|
|
11
|
-
streams_ctx.new_context(2, 65_535, 65_535)
|
|
12
|
-
streams_ctx
|
|
13
|
-
end
|
|
14
|
-
it 'should handle' do
|
|
15
|
-
expect { Connection.handle_stream_window_update(window_update, streams_ctx) }.not_to raise_error
|
|
16
|
-
expect(streams_ctx[1].send_window.length).to eq 65_535 + 1000
|
|
17
|
-
expect(streams_ctx[2].send_window.length).to eq 65_535
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe Connection do
|
|
4
|
-
context 'read_http2_magic' do
|
|
5
|
-
let(:io1) do
|
|
6
|
-
StringIO.new("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
|
|
7
|
-
end
|
|
8
|
-
it 'should read' do
|
|
9
|
-
expect(Connection.read_http2_magic(io1)).to eq nil
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
let(:io2) do
|
|
13
|
-
StringIO.new("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n\x00xff")
|
|
14
|
-
end
|
|
15
|
-
it 'should read' do
|
|
16
|
-
expect(Connection.read_http2_magic(io2)).to eq nil
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
let(:io3) do
|
|
20
|
-
StringIO.new("\x00xffPRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
|
|
21
|
-
end
|
|
22
|
-
it 'should not read' do
|
|
23
|
-
expect(Connection.read_http2_magic(io3)).to be_kind_of ConnectionError
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|