protocol-http2 0.19.1 → 0.19.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/protocol/http2/connection.rb +6 -8
- data/lib/protocol/http2/flow_controlled.rb +0 -4
- data/lib/protocol/http2/stream.rb +2 -2
- data/lib/protocol/http2/version.rb +1 -1
- data/lib/protocol/http2/window.rb +117 -0
- data/lib/protocol/http2/window_update_frame.rb +1 -96
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fc681846886564561e01287c0c8ac5db0944222c6f94262894fe50ac1d0d2a5
|
4
|
+
data.tar.gz: 94106491f20c0b6f08fc637ecd46ccab6a38362207f90ddfefb12b02ba901aad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bb39e01cf605b16625a81ba6706b37ec9022c220e3200cea4e8136091842532f9a00b47c76980a36e726401f35eaf22522211e2c567322099512f6a1c472278
|
7
|
+
data.tar.gz: e2ca6677a9b488a0ec7d4e74ecf1bfb349e496d2e248c60928c27286cfa99c3a5e07a6edf2b957d797c6f374e2e23b2f2ac362b0458594064acf5d9de856c872
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -41,7 +41,7 @@ module Protocol
|
|
41
41
|
@decoder = HPACK::Context.new
|
42
42
|
@encoder = HPACK::Context.new
|
43
43
|
|
44
|
-
@local_window = LocalWindow.new
|
44
|
+
@local_window = LocalWindow.new
|
45
45
|
@remote_window = Window.new
|
46
46
|
end
|
47
47
|
|
@@ -215,20 +215,18 @@ module Protocol
|
|
215
215
|
def write_frame(frame)
|
216
216
|
synchronize do
|
217
217
|
@framer.write_frame(frame)
|
218
|
-
|
219
|
-
# I tried moving this outside the synchronize block but it caused a deadlock.
|
220
|
-
@framer.flush
|
221
218
|
end
|
219
|
+
|
220
|
+
@framer.flush
|
222
221
|
end
|
223
222
|
|
224
223
|
def write_frames
|
225
224
|
if @framer
|
226
225
|
synchronize do
|
227
226
|
yield @framer
|
228
|
-
|
229
|
-
# See note above.
|
230
|
-
@framer.flush
|
231
227
|
end
|
228
|
+
|
229
|
+
@framer.flush
|
232
230
|
else
|
233
231
|
raise EOFError, "Connection closed!"
|
234
232
|
end
|
@@ -476,7 +474,7 @@ module Protocol
|
|
476
474
|
# Return if there is no window to consume:
|
477
475
|
return unless size > 0
|
478
476
|
|
479
|
-
# Console.
|
477
|
+
# Console.info(self) do |buffer|
|
480
478
|
# @dependencies.each do |id, dependency|
|
481
479
|
# buffer.puts "- #{dependency}"
|
482
480
|
# end
|
@@ -70,15 +70,11 @@ module Protocol
|
|
70
70
|
def receive_window_update(frame)
|
71
71
|
amount = frame.unpack
|
72
72
|
|
73
|
-
# Async.logger.info(self) {"expanding remote_window=#{@remote_window} by #{amount}"}
|
74
|
-
|
75
73
|
if amount != 0
|
76
74
|
@remote_window.expand(amount)
|
77
75
|
else
|
78
76
|
raise ProtocolError, "Invalid window size increment: #{amount}!"
|
79
77
|
end
|
80
|
-
|
81
|
-
# puts "expanded remote_window=#{@remote_window} by #{amount}"
|
82
78
|
end
|
83
79
|
|
84
80
|
# The window has been expanded by the given amount.
|
@@ -275,7 +275,7 @@ module Protocol
|
|
275
275
|
end
|
276
276
|
|
277
277
|
protected def ignore_headers(frame)
|
278
|
-
#
|
278
|
+
# Console.warn(self) {"Received headers in state: #{@state}!"}
|
279
279
|
end
|
280
280
|
|
281
281
|
def receive_headers(frame)
|
@@ -316,7 +316,7 @@ module Protocol
|
|
316
316
|
end
|
317
317
|
|
318
318
|
def ignore_data(frame)
|
319
|
-
#
|
319
|
+
# Console.warn(self) {"Received headers in state: #{@state}!"}
|
320
320
|
end
|
321
321
|
|
322
322
|
# DATA frames are subject to flow control and can only be sent when a stream is in the "open" or "half-closed (remote)" state. The entire DATA frame payload is included in flow control, including the Pad Length and Padding fields if present. If a DATA frame is received whose stream is not in "open" or "half-closed (local)" state, the recipient MUST respond with a stream error of type STREAM_CLOSED.
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
module Protocol
|
7
|
+
module HTTP2
|
8
|
+
class Window
|
9
|
+
# When an HTTP/2 connection is first established, new streams are created with an initial flow-control window size of 65,535 octets. The connection flow-control window is also 65,535 octets.
|
10
|
+
DEFAULT_CAPACITY = 0xFFFF
|
11
|
+
|
12
|
+
# @param capacity [Integer] The initial window size, typically from the settings.
|
13
|
+
def initialize(capacity = DEFAULT_CAPACITY)
|
14
|
+
# This is the main field required:
|
15
|
+
@available = capacity
|
16
|
+
|
17
|
+
# These two fields are primarily used for efficiently sending window updates:
|
18
|
+
@used = 0
|
19
|
+
@capacity = capacity
|
20
|
+
end
|
21
|
+
|
22
|
+
# The window is completely full?
|
23
|
+
def full?
|
24
|
+
@available <= 0
|
25
|
+
end
|
26
|
+
|
27
|
+
attr :used
|
28
|
+
attr :capacity
|
29
|
+
|
30
|
+
# When the value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust the size of all stream flow-control windows that it maintains by the difference between the new value and the old value.
|
31
|
+
def capacity= value
|
32
|
+
difference = value - @capacity
|
33
|
+
|
34
|
+
# An endpoint MUST treat a change to SETTINGS_INITIAL_WINDOW_SIZE that causes any flow-control window to exceed the maximum size as a connection error of type FLOW_CONTROL_ERROR.
|
35
|
+
if (@available + difference) > MAXIMUM_ALLOWED_WINDOW_SIZE
|
36
|
+
raise FlowControlError, "Changing window size by #{difference} caused overflow: #{@available + difference} > #{MAXIMUM_ALLOWED_WINDOW_SIZE}!"
|
37
|
+
end
|
38
|
+
|
39
|
+
@available += difference
|
40
|
+
@capacity = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def consume(amount)
|
44
|
+
@available -= amount
|
45
|
+
@used += amount
|
46
|
+
end
|
47
|
+
|
48
|
+
attr :available
|
49
|
+
|
50
|
+
def available?
|
51
|
+
@available > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def expand(amount)
|
55
|
+
available = @available + amount
|
56
|
+
|
57
|
+
if available > MAXIMUM_ALLOWED_WINDOW_SIZE
|
58
|
+
raise FlowControlError, "Expanding window by #{amount} caused overflow: #{available} > #{MAXIMUM_ALLOWED_WINDOW_SIZE}!"
|
59
|
+
end
|
60
|
+
|
61
|
+
# puts "expand(#{amount}) @available=#{@available}"
|
62
|
+
@available += amount
|
63
|
+
@used -= amount
|
64
|
+
end
|
65
|
+
|
66
|
+
def wanted
|
67
|
+
@used
|
68
|
+
end
|
69
|
+
|
70
|
+
def limited?
|
71
|
+
@available < (@capacity / 2)
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
"\#<#{self.class} available=#{@available} used=#{@used} capacity=#{@capacity}#{limited? ? " limited" : nil}>"
|
76
|
+
end
|
77
|
+
|
78
|
+
alias to_s inspect
|
79
|
+
end
|
80
|
+
|
81
|
+
# This is a window which efficiently maintains a desired capacity.
|
82
|
+
class LocalWindow < Window
|
83
|
+
def initialize(capacity = DEFAULT_CAPACITY, desired: nil)
|
84
|
+
super(capacity)
|
85
|
+
|
86
|
+
# The desired capacity of the window, may be bigger than the initial capacity.
|
87
|
+
# If that is the case, we will likely send a window update to the remote end to increase the capacity.
|
88
|
+
@desired = desired
|
89
|
+
end
|
90
|
+
|
91
|
+
# The desired capacity of the window.
|
92
|
+
attr_accessor :desired
|
93
|
+
|
94
|
+
def wanted
|
95
|
+
if @desired
|
96
|
+
# We must send an update which allows at least @desired bytes to be sent.
|
97
|
+
(@desired - @capacity) + @used
|
98
|
+
else
|
99
|
+
super
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def limited?
|
104
|
+
if @desired
|
105
|
+
# Do not send window updates until we are less than half the desired capacity:
|
106
|
+
@available < (@desired / 2)
|
107
|
+
else
|
108
|
+
super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def inspect
|
113
|
+
"\#<#{self.class} available=#{@available} used=#{@used} capacity=#{@capacity} desired=#{@desired} #{limited? ? "limited" : nil}>"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -4,105 +4,10 @@
|
|
4
4
|
# Copyright, 2019-2024, by Samuel Williams.
|
5
5
|
|
6
6
|
require_relative "frame"
|
7
|
+
require_relative "window"
|
7
8
|
|
8
9
|
module Protocol
|
9
10
|
module HTTP2
|
10
|
-
class Window
|
11
|
-
# @param capacity [Integer] The initial window size, typically from the settings.
|
12
|
-
def initialize(capacity = 0xFFFF)
|
13
|
-
# This is the main field required:
|
14
|
-
@available = capacity
|
15
|
-
|
16
|
-
# These two fields are primarily used for efficiently sending window updates:
|
17
|
-
@used = 0
|
18
|
-
@capacity = capacity
|
19
|
-
end
|
20
|
-
|
21
|
-
# The window is completely full?
|
22
|
-
def full?
|
23
|
-
@available <= 0
|
24
|
-
end
|
25
|
-
|
26
|
-
attr :used
|
27
|
-
attr :capacity
|
28
|
-
|
29
|
-
# When the value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust the size of all stream flow-control windows that it maintains by the difference between the new value and the old value.
|
30
|
-
def capacity= value
|
31
|
-
difference = value - @capacity
|
32
|
-
|
33
|
-
# An endpoint MUST treat a change to SETTINGS_INITIAL_WINDOW_SIZE that causes any flow-control window to exceed the maximum size as a connection error of type FLOW_CONTROL_ERROR.
|
34
|
-
if (@available + difference) > MAXIMUM_ALLOWED_WINDOW_SIZE
|
35
|
-
raise FlowControlError, "Changing window size by #{difference} caused overflow: #{@available + difference} > #{MAXIMUM_ALLOWED_WINDOW_SIZE}!"
|
36
|
-
end
|
37
|
-
|
38
|
-
@available += difference
|
39
|
-
@capacity = value
|
40
|
-
end
|
41
|
-
|
42
|
-
def consume(amount)
|
43
|
-
@available -= amount
|
44
|
-
@used += amount
|
45
|
-
end
|
46
|
-
|
47
|
-
attr :available
|
48
|
-
|
49
|
-
def available?
|
50
|
-
@available > 0
|
51
|
-
end
|
52
|
-
|
53
|
-
def expand(amount)
|
54
|
-
available = @available + amount
|
55
|
-
|
56
|
-
if available > MAXIMUM_ALLOWED_WINDOW_SIZE
|
57
|
-
raise FlowControlError, "Expanding window by #{amount} caused overflow: #{available} > #{MAXIMUM_ALLOWED_WINDOW_SIZE}!"
|
58
|
-
end
|
59
|
-
|
60
|
-
# puts "expand(#{amount}) @available=#{@available}"
|
61
|
-
@available += amount
|
62
|
-
@used -= amount
|
63
|
-
end
|
64
|
-
|
65
|
-
def wanted
|
66
|
-
@used
|
67
|
-
end
|
68
|
-
|
69
|
-
def limited?
|
70
|
-
@available < (@capacity / 2)
|
71
|
-
end
|
72
|
-
|
73
|
-
def inspect
|
74
|
-
"\#<#{self.class} used=#{@used} available=#{@available} capacity=#{@capacity}>"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# This is a window which efficiently maintains a desired capacity.
|
79
|
-
class LocalWindow < Window
|
80
|
-
def initialize(capacity = 0xFFFF, desired: nil)
|
81
|
-
super(capacity)
|
82
|
-
|
83
|
-
@desired = desired
|
84
|
-
end
|
85
|
-
|
86
|
-
attr_accessor :desired
|
87
|
-
|
88
|
-
def wanted
|
89
|
-
if @desired
|
90
|
-
# We must send an update which allows at least @desired bytes to be sent.
|
91
|
-
(@desired - @capacity) + @used
|
92
|
-
else
|
93
|
-
@used
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def limited?
|
98
|
-
if @desired
|
99
|
-
@available < @desired
|
100
|
-
else
|
101
|
-
super
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
11
|
# The WINDOW_UPDATE frame is used to implement flow control.
|
107
12
|
#
|
108
13
|
# +-+-------------------------------------------------------------+
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-http2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.19.
|
4
|
+
version: 0.19.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -40,7 +40,7 @@ cert_chain:
|
|
40
40
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
41
41
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
42
42
|
-----END CERTIFICATE-----
|
43
|
-
date: 2024-
|
43
|
+
date: 2024-10-02 00:00:00.000000000 Z
|
44
44
|
dependencies:
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: protocol-hpack
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- lib/protocol/http2/settings_frame.rb
|
98
98
|
- lib/protocol/http2/stream.rb
|
99
99
|
- lib/protocol/http2/version.rb
|
100
|
+
- lib/protocol/http2/window.rb
|
100
101
|
- lib/protocol/http2/window_update_frame.rb
|
101
102
|
- license.md
|
102
103
|
- readme.md
|
metadata.gz.sig
CHANGED
Binary file
|