http-2-next 0.3.0 → 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/lib/http/2/next.rb +0 -1
- data/lib/http/2/next/connection.rb +15 -12
- data/lib/http/2/next/extensions.rb +17 -2
- data/lib/http/2/next/flow_buffer.rb +6 -3
- data/lib/http/2/next/framer.rb +13 -7
- data/lib/http/2/next/header/compressor.rb +2 -2
- data/lib/http/2/next/header/decompressor.rb +6 -5
- data/lib/http/2/next/server.rb +2 -1
- data/lib/http/2/next/stream.rb +1 -1
- data/lib/http/2/next/version.rb +1 -1
- data/sig/connection.rbs +1 -1
- data/sig/emitter.rbs +3 -3
- data/sig/framer.rbs +3 -3
- data/sig/header/compressor.rbs +3 -3
- data/sig/header/decompressor.rbs +5 -5
- data/sig/header/huffman.rbs +1 -1
- data/sig/next.rbs +41 -2
- metadata +3 -5
- data/lib/http/2/next/buffer.rb +0 -86
- data/sig/buffer.rbs +0 -21
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/lib/http/2/next.rb
CHANGED
@@ -51,6 +51,8 @@ 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
|
|
@@ -98,7 +100,7 @@ module HTTP2Next
|
|
98
100
|
@remote_window_limit = @remote_settings[:settings_initial_window_size]
|
99
101
|
@remote_window = @remote_window_limit
|
100
102
|
|
101
|
-
@recv_buffer =
|
103
|
+
@recv_buffer = "".b
|
102
104
|
@continuation = []
|
103
105
|
@error = nil
|
104
106
|
|
@@ -159,7 +161,7 @@ module HTTP2Next
|
|
159
161
|
send(type: :goaway, last_stream: last_stream,
|
160
162
|
error: error, payload: payload)
|
161
163
|
@state = :closed
|
162
|
-
@closed_since =
|
164
|
+
@closed_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
163
165
|
end
|
164
166
|
|
165
167
|
# Sends a WINDOW_UPDATE frame to the peer.
|
@@ -245,7 +247,7 @@ module HTTP2Next
|
|
245
247
|
@continuation.clear
|
246
248
|
|
247
249
|
frame.delete(:length)
|
248
|
-
frame[:payload] =
|
250
|
+
frame[:payload] = payload
|
249
251
|
frame[:flags] << :end_headers
|
250
252
|
end
|
251
253
|
|
@@ -478,7 +480,7 @@ module HTTP2Next
|
|
478
480
|
# the connection, although a new connection can be established
|
479
481
|
# for new streams.
|
480
482
|
@state = :closed
|
481
|
-
@closed_since =
|
483
|
+
@closed_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
482
484
|
emit(:goaway, frame[:last_stream], frame[:error], frame[:payload])
|
483
485
|
when :altsvc
|
484
486
|
# 4. The ALTSVC HTTP/2 Frame
|
@@ -503,7 +505,7 @@ module HTTP2Next
|
|
503
505
|
when :ping
|
504
506
|
ping_management(frame)
|
505
507
|
else
|
506
|
-
connection_error if (
|
508
|
+
connection_error if (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @closed_since) > 15
|
507
509
|
end
|
508
510
|
else
|
509
511
|
connection_error
|
@@ -671,7 +673,7 @@ module HTTP2Next
|
|
671
673
|
#
|
672
674
|
# @param frame [Hash]
|
673
675
|
def decode_headers(frame)
|
674
|
-
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)
|
675
677
|
rescue CompressionError => e
|
676
678
|
connection_error(:compression_error, e: e)
|
677
679
|
rescue ProtocolError => e
|
@@ -686,15 +688,16 @@ module HTTP2Next
|
|
686
688
|
# @return [Array of Frame]
|
687
689
|
def encode_headers(frame)
|
688
690
|
payload = frame[:payload]
|
689
|
-
payload = @compressor.encode(payload) unless payload.is_a?
|
691
|
+
payload = @compressor.encode(payload) unless payload.is_a?(String)
|
690
692
|
|
691
693
|
frames = []
|
692
694
|
|
693
|
-
while payload.bytesize > 0
|
695
|
+
while payload && payload.bytesize > 0
|
694
696
|
cont = frame.dup
|
695
697
|
cont[:type] = :continuation
|
696
698
|
cont[:flags] = []
|
697
|
-
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)
|
698
701
|
frames << cont
|
699
702
|
end
|
700
703
|
if frames.empty?
|
@@ -735,11 +738,11 @@ module HTTP2Next
|
|
735
738
|
# References to such streams will be purged whenever another stream
|
736
739
|
# is closed, with a minimum of 15s RTT time window.
|
737
740
|
@streams_recently_closed.reject! do |stream_id, v|
|
738
|
-
to_delete = (
|
741
|
+
to_delete = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - v) > 15
|
739
742
|
@streams.delete stream_id if to_delete
|
740
743
|
to_delete
|
741
744
|
end
|
742
|
-
@streams_recently_closed[id] =
|
745
|
+
@streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
743
746
|
end
|
744
747
|
|
745
748
|
stream.on(:promise, &method(:promise)) if is_a? Server
|
@@ -757,7 +760,7 @@ module HTTP2Next
|
|
757
760
|
|
758
761
|
def verify_pseudo_headers(frame, mandatory_headers)
|
759
762
|
headers = frame[:payload]
|
760
|
-
return if headers.is_a?(
|
763
|
+
return if headers.is_a?(String)
|
761
764
|
|
762
765
|
pseudo_headers = headers.take_while do |field, value|
|
763
766
|
# use this loop to validate pseudo-headers
|
@@ -12,8 +12,23 @@ module HTTP2Next
|
|
12
12
|
end
|
13
13
|
|
14
14
|
module StringExtensions
|
15
|
-
|
16
|
-
|
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)
|
17
32
|
def unpack1(format)
|
18
33
|
unpack(format).first
|
19
34
|
end
|
@@ -138,10 +138,13 @@ module HTTP2Next
|
|
138
138
|
|
139
139
|
# Split frame so that it fits in the window
|
140
140
|
# TODO: consider padding!
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
144
146
|
chunk[:payload] = payload
|
147
|
+
chunk[:length] = payload.bytesize
|
145
148
|
|
146
149
|
# if no longer last frame in sequence...
|
147
150
|
frame[:flags] -= [:end_stream] if end_stream
|
data/lib/http/2/next/framer.rb
CHANGED
@@ -159,7 +159,7 @@ module HTTP2Next
|
|
159
159
|
# @return [Hash] the corresponding frame
|
160
160
|
def read_common_header(buf)
|
161
161
|
frame = {}
|
162
|
-
len_hi, len_lo, type, flags, stream = buf.
|
162
|
+
len_hi, len_lo, type, flags, stream = buf.byteslice(0, 9).unpack(HEADERPACK)
|
163
163
|
|
164
164
|
frame[:length] = (len_hi << FRAME_LENGTH_HISHIFT) | len_lo
|
165
165
|
frame[:type], = FRAME_TYPES.find { |_t, pos| type == pos }
|
@@ -178,7 +178,7 @@ module HTTP2Next
|
|
178
178
|
#
|
179
179
|
# @param frame [Hash]
|
180
180
|
def generate(frame)
|
181
|
-
bytes =
|
181
|
+
bytes = "".b
|
182
182
|
length = 0
|
183
183
|
|
184
184
|
frame[:flags] ||= []
|
@@ -360,7 +360,7 @@ module HTTP2Next
|
|
360
360
|
frame[:padding] = padlen + 1
|
361
361
|
raise ProtocolError, "padding too long" if padlen > payload.bytesize
|
362
362
|
|
363
|
-
payload.
|
363
|
+
payload = payload.byteslice(0, payload.bytesize - padlen) if padlen > 0
|
364
364
|
frame[:length] -= frame[:padding]
|
365
365
|
frame[:flags].delete(:padded)
|
366
366
|
end
|
@@ -374,7 +374,9 @@ module HTTP2Next
|
|
374
374
|
e_sd = payload.read_uint32
|
375
375
|
frame[:dependency] = e_sd & RBIT
|
376
376
|
frame[:exclusive] = (e_sd & EBIT) != 0
|
377
|
-
|
377
|
+
weight = payload.byteslice(0, 1).ord + 1
|
378
|
+
frame[:weight] = weight
|
379
|
+
payload = payload.byteslice(1..-1)
|
378
380
|
end
|
379
381
|
frame[:payload] = payload.read(frame[:length])
|
380
382
|
when :priority
|
@@ -383,7 +385,9 @@ module HTTP2Next
|
|
383
385
|
e_sd = payload.read_uint32
|
384
386
|
frame[:dependency] = e_sd & RBIT
|
385
387
|
frame[:exclusive] = (e_sd & EBIT) != 0
|
386
|
-
|
388
|
+
weight = payload.byteslice(0, 1).ord + 1
|
389
|
+
frame[:weight] = weight
|
390
|
+
payload = payload.byteslice(1..-1)
|
387
391
|
when :rst_stream
|
388
392
|
raise FrameSizeError, "Invalid length for RST_STREAM (#{frame[:length]} != 4)" if frame[:length] != 4
|
389
393
|
|
@@ -428,10 +432,12 @@ module HTTP2Next
|
|
428
432
|
when :altsvc
|
429
433
|
frame[:max_age], frame[:port] = payload.read(6).unpack(UINT32 + UINT16)
|
430
434
|
|
431
|
-
len = payload.
|
435
|
+
len = payload.byteslice(0, 1).ord
|
436
|
+
payload = payload.byteslice(1..-1)
|
432
437
|
frame[:proto] = payload.read(len) if len > 0
|
433
438
|
|
434
|
-
len = payload.
|
439
|
+
len = payload.byteslice(0, 1).ord
|
440
|
+
payload = payload.byteslice(1..-1)
|
435
441
|
frame[:host] = payload.read(len) if len > 0
|
436
442
|
|
437
443
|
frame[:origin] = payload.read(payload.size) unless payload.empty?
|
@@ -91,7 +91,7 @@ module HTTP2Next
|
|
91
91
|
# @param h [Hash] header command
|
92
92
|
# @param buffer [String]
|
93
93
|
# @return [Buffer]
|
94
|
-
def header(h, buffer =
|
94
|
+
def header(h, buffer = "".b)
|
95
95
|
rep = HEADREP[h[:type]]
|
96
96
|
|
97
97
|
case h[:type]
|
@@ -122,7 +122,7 @@ module HTTP2Next
|
|
122
122
|
# @param headers [Array] +[[name, value], ...]+
|
123
123
|
# @return [Buffer]
|
124
124
|
def encode(headers)
|
125
|
-
buffer =
|
125
|
+
buffer = "".b
|
126
126
|
pseudo_headers, regular_headers = headers.partition { |f, _| f.start_with? ":" }
|
127
127
|
headers = [*pseudo_headers, *regular_headers]
|
128
128
|
commands = @cc.encode(headers)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module HTTP2Next
|
4
4
|
module Header
|
5
|
+
using StringExtensions
|
5
6
|
# Responsible for decoding received headers and maintaining compression
|
6
7
|
# context of the opposing peer. Decompressor must be initialized with
|
7
8
|
# appropriate starting context based on local role: client or server.
|
@@ -30,11 +31,11 @@ module HTTP2Next
|
|
30
31
|
# @return [Integer]
|
31
32
|
def integer(buf, n)
|
32
33
|
limit = 2**n - 1
|
33
|
-
i = !n.zero? ? (buf.
|
34
|
+
i = !n.zero? ? (buf.shift_byte & limit) : 0
|
34
35
|
|
35
36
|
m = 0
|
36
37
|
if i == limit
|
37
|
-
while (byte = buf.
|
38
|
+
while (byte = buf.shift_byte)
|
38
39
|
i += ((byte & 127) << m)
|
39
40
|
m += 7
|
40
41
|
|
@@ -53,12 +54,12 @@ module HTTP2Next
|
|
53
54
|
def string(buf)
|
54
55
|
raise CompressionError, "invalid header block fragment" if buf.empty?
|
55
56
|
|
56
|
-
huffman = (buf.
|
57
|
+
huffman = (buf.getbyte(0) & 0x80) == 0x80
|
57
58
|
len = integer(buf, 7)
|
58
59
|
str = buf.read(len)
|
59
60
|
raise CompressionError, "string too short" unless str.bytesize == len
|
60
61
|
|
61
|
-
str = Huffman.new.decode(
|
62
|
+
str = Huffman.new.decode(str) if huffman
|
62
63
|
str.force_encoding(Encoding::UTF_8)
|
63
64
|
end
|
64
65
|
|
@@ -67,7 +68,7 @@ module HTTP2Next
|
|
67
68
|
# @param buf [Buffer]
|
68
69
|
# @return [Hash] command
|
69
70
|
def header(buf)
|
70
|
-
peek = buf.
|
71
|
+
peek = buf.getbyte(0)
|
71
72
|
|
72
73
|
header = {}
|
73
74
|
header[:type], type = HEADREP.find do |_t, desc|
|
data/lib/http/2/next/server.rb
CHANGED
@@ -79,7 +79,8 @@ module HTTP2Next
|
|
79
79
|
receive(CONNECTION_PREFACE_MAGIC)
|
80
80
|
|
81
81
|
# Process received HTTP2-Settings payload
|
82
|
-
buf =
|
82
|
+
buf = "".b
|
83
|
+
buf << Base64.urlsafe_decode64(settings.to_s)
|
83
84
|
header = @framer.common_header(
|
84
85
|
length: buf.bytesize,
|
85
86
|
type: :settings,
|
data/lib/http/2/next/stream.rb
CHANGED
data/lib/http/2/next/version.rb
CHANGED
data/sig/connection.rbs
CHANGED
data/sig/emitter.rbs
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module HTTP2Next
|
2
2
|
module Emitter
|
3
|
-
|
3
|
+
def on: (Symbol event) { (*untyped) -> void } -> void
|
4
4
|
|
5
|
-
|
5
|
+
def once: (Symbol event) { (*untyped) -> void } -> void
|
6
6
|
|
7
|
-
|
7
|
+
def emit: (Symbol event, *untyped args) ?{ (*untyped) -> void } -> void
|
8
8
|
|
9
9
|
private
|
10
10
|
|
data/sig/framer.rbs
CHANGED
@@ -6,11 +6,11 @@ module HTTP2Next
|
|
6
6
|
|
7
7
|
def common_header: (frame) -> String
|
8
8
|
|
9
|
-
def read_common_frame: (
|
9
|
+
def read_common_frame: (String) -> frame
|
10
10
|
|
11
|
-
def generate: (frame) ->
|
11
|
+
def generate: (frame) -> String
|
12
12
|
|
13
|
-
def parse: (
|
13
|
+
def parse: (String) -> frame?
|
14
14
|
|
15
15
|
private
|
16
16
|
|
data/sig/header/compressor.rbs
CHANGED
@@ -9,10 +9,10 @@ module HTTP2Next
|
|
9
9
|
|
10
10
|
def string: (String) -> String
|
11
11
|
|
12
|
-
def header: (header_command,
|
13
|
-
| (header_command) ->
|
12
|
+
def header: (header_command, String) -> String
|
13
|
+
| (header_command) -> String
|
14
14
|
|
15
|
-
def encode: (Enumerable[header_pair]) ->
|
15
|
+
def encode: (Enumerable[header_pair]) -> String
|
16
16
|
|
17
17
|
private
|
18
18
|
|
data/sig/header/decompressor.rbs
CHANGED
@@ -5,14 +5,14 @@ module HTTP2Next
|
|
5
5
|
|
6
6
|
def table_size=: (Integer) -> void
|
7
7
|
|
8
|
-
def integer: (
|
8
|
+
def integer: (String, Integer) -> Integer
|
9
9
|
|
10
|
-
def string: (
|
10
|
+
def string: (String) -> String
|
11
11
|
|
12
|
-
def header: (
|
12
|
+
def header: (String) -> header_command
|
13
13
|
|
14
|
-
def decode: (
|
15
|
-
| (
|
14
|
+
def decode: (String, frame?) -> Array[header_pair]
|
15
|
+
| (String) -> Array[header_pair]
|
16
16
|
private
|
17
17
|
|
18
18
|
def initialize: (context_hash options) -> untyped
|
data/sig/header/huffman.rbs
CHANGED
data/sig/next.rbs
CHANGED
@@ -23,6 +23,46 @@ module HTTP2Next
|
|
23
23
|
|
24
24
|
type header_pair = [String, String]
|
25
25
|
|
26
|
+
# # FRAMES
|
27
|
+
# type frame_control_flags = Array[:end_headers | :end_stream]
|
28
|
+
|
29
|
+
# # HEADERS
|
30
|
+
# type headers_frame = {
|
31
|
+
# type: :headers, flags: frame_control_flags, stream: Integer, payload: Enumerable[header_pair],
|
32
|
+
# ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, ?padding: Integer
|
33
|
+
# }
|
34
|
+
|
35
|
+
# # DATA
|
36
|
+
# type data_frame = { type: :data, flags: frame_control_flags, stream: Integer, length: Integer, payload: String, ?padding: Integer }
|
37
|
+
|
38
|
+
# # PUSH_PROMISE
|
39
|
+
# type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, stream: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
|
40
|
+
|
41
|
+
# # SETTINGS
|
42
|
+
# type settings_frame = { type: :settings, stream: 0, payload: Array[[Symbol | Integer, Integer]] }
|
43
|
+
|
44
|
+
# # WINDOW_UPDATE
|
45
|
+
# type window_update_frame = { type: :window_update, stream: Integer, increment: Integer }
|
46
|
+
|
47
|
+
# # PRIORITY
|
48
|
+
# type priority_frame = { type: :priority, stream: Integer, dependency: Integer, exclusive: bool, weight: Integer }
|
49
|
+
|
50
|
+
# # ALTSVC
|
51
|
+
# type altsvc_frame = { type: :altsvc, stream: 0, max_age: Integer, port: Integer, proto: "String", host: String }
|
52
|
+
|
53
|
+
# # ORIGIN
|
54
|
+
# type origin_frame = { type: :origin, stream: 0, origin: Array[String] }
|
55
|
+
|
56
|
+
# # PING
|
57
|
+
# type ping_frame = { type: :ping, payload: String, length: Integer }
|
58
|
+
|
59
|
+
# # GOAWAY
|
60
|
+
# type goaway_frame = { type: :goaway, stream: 0, last_stream: Integer, error: Symbol? }
|
61
|
+
|
62
|
+
# type frame = headers_frame | data_frame | push_promise_frame |
|
63
|
+
# settings_frame | window_update_frame | priority_frame | altsvc_frame |
|
64
|
+
# origin_frame | ping_frame | goaway_frame
|
65
|
+
|
26
66
|
type frame_key = :type | :flags | :stream | :padding | :ignore |
|
27
67
|
# headers
|
28
68
|
:method | :trailer | :content_length |
|
@@ -44,10 +84,9 @@ module HTTP2Next
|
|
44
84
|
type frame_value = Integer |
|
45
85
|
Symbol | # type (:data, :headers)
|
46
86
|
Array[Symbol] |
|
47
|
-
String |
|
87
|
+
String |
|
48
88
|
bool |
|
49
89
|
Array[String] |
|
50
|
-
Array[Buffer] |
|
51
90
|
Array[[Symbol | Integer, Integer]] |
|
52
91
|
Enumerable[header_pair] |
|
53
92
|
nil
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http-2-next
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-02-21 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: Pure-ruby HTTP 2.0 protocol implementation
|
16
16
|
email:
|
@@ -21,7 +21,6 @@ extra_rdoc_files: []
|
|
21
21
|
files:
|
22
22
|
- README.md
|
23
23
|
- lib/http/2/next.rb
|
24
|
-
- lib/http/2/next/buffer.rb
|
25
24
|
- lib/http/2/next/client.rb
|
26
25
|
- lib/http/2/next/connection.rb
|
27
26
|
- lib/http/2/next/emitter.rb
|
@@ -39,7 +38,6 @@ files:
|
|
39
38
|
- lib/http/2/next/stream.rb
|
40
39
|
- lib/http/2/next/version.rb
|
41
40
|
- lib/tasks/generate_huffman_table.rb
|
42
|
-
- sig/buffer.rbs
|
43
41
|
- sig/client.rbs
|
44
42
|
- sig/connection.rbs
|
45
43
|
- sig/emitter.rbs
|
@@ -73,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
71
|
- !ruby/object:Gem::Version
|
74
72
|
version: '0'
|
75
73
|
requirements: []
|
76
|
-
rubygems_version: 3.
|
74
|
+
rubygems_version: 3.2.3
|
77
75
|
signing_key:
|
78
76
|
specification_version: 4
|
79
77
|
summary: Pure-ruby HTTP 2.0 protocol implementation
|
data/lib/http/2/next/buffer.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
|
5
|
-
module HTTP2Next
|
6
|
-
# Binary buffer wraps String.
|
7
|
-
#
|
8
|
-
class Buffer
|
9
|
-
extend Forwardable
|
10
|
-
|
11
|
-
using StringExtensions
|
12
|
-
|
13
|
-
def_delegators :@buffer, :ord, :encoding, :setbyte, :unpack,
|
14
|
-
:size, :each_byte, :to_str, :to_s, :length, :inspect,
|
15
|
-
:[], :[]=, :empty?, :bytesize, :include?
|
16
|
-
|
17
|
-
UINT32 = "N"
|
18
|
-
private_constant :UINT32
|
19
|
-
|
20
|
-
# Forces binary encoding on the string
|
21
|
-
def initialize(str = "".b)
|
22
|
-
str = str.dup if str.frozen?
|
23
|
-
@buffer = str.force_encoding(Encoding::BINARY)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Emulate StringIO#read: slice first n bytes from the buffer.
|
27
|
-
#
|
28
|
-
# @param n [Integer] number of bytes to slice from the buffer
|
29
|
-
def read(n)
|
30
|
-
Buffer.new(@buffer.slice!(0, n))
|
31
|
-
end
|
32
|
-
|
33
|
-
def unpack1(*arg)
|
34
|
-
@buffer.unpack1(*arg)
|
35
|
-
end
|
36
|
-
|
37
|
-
# Emulate StringIO#getbyte: slice first byte from buffer.
|
38
|
-
def getbyte
|
39
|
-
read(1).ord
|
40
|
-
end
|
41
|
-
|
42
|
-
def slice!(*args)
|
43
|
-
Buffer.new(@buffer.slice!(*args))
|
44
|
-
end
|
45
|
-
|
46
|
-
def slice(*args)
|
47
|
-
Buffer.new(@buffer.slice(*args))
|
48
|
-
end
|
49
|
-
|
50
|
-
def force_encoding(*args)
|
51
|
-
@buffer = @buffer.force_encoding(*args)
|
52
|
-
end
|
53
|
-
|
54
|
-
def ==(other)
|
55
|
-
@buffer == other
|
56
|
-
end
|
57
|
-
|
58
|
-
def +(other)
|
59
|
-
@buffer += other
|
60
|
-
end
|
61
|
-
|
62
|
-
# Emulate String#getbyte: return nth byte from buffer.
|
63
|
-
def readbyte(n)
|
64
|
-
@buffer[n].ord
|
65
|
-
end
|
66
|
-
|
67
|
-
# Slice unsigned 32-bit integer from buffer.
|
68
|
-
# @return [Integer]
|
69
|
-
def read_uint32
|
70
|
-
read(4).unpack1(UINT32)
|
71
|
-
end
|
72
|
-
|
73
|
-
# Ensures that data that is added is binary encoded as well,
|
74
|
-
# otherwise this could lead to the Buffer instance changing its encoding.
|
75
|
-
%i[<< prepend].each do |mutating_method|
|
76
|
-
class_eval(<<-METH, __FILE__, __LINE__ + 1)
|
77
|
-
def #{mutating_method}(string)
|
78
|
-
string = string.dup if string.frozen?
|
79
|
-
@buffer.send __method__, string.force_encoding(Encoding::BINARY)
|
80
|
-
|
81
|
-
self
|
82
|
-
end
|
83
|
-
METH
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/sig/buffer.rbs
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module HTTP2Next
|
2
|
-
class Buffer
|
3
|
-
|
4
|
-
def read: (Integer) -> Buffer
|
5
|
-
|
6
|
-
def getbyte: () -> Integer
|
7
|
-
|
8
|
-
def readbyte: (Integer) -> Integer
|
9
|
-
|
10
|
-
def read_uint32: () -> Integer
|
11
|
-
|
12
|
-
def <<: (string) -> void
|
13
|
-
|
14
|
-
def prepend: (string) -> void
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def initialize: () -> untyped
|
19
|
-
| (string) -> untyped
|
20
|
-
end
|
21
|
-
end
|