http-2-next 0.5.1 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7c15b998344b09aee75566b64f5ef94abb9b388fdc3d2f06704e8263a586789
4
- data.tar.gz: 935a6225e964eb46b6f26e57ccf3080fd231570f3710bf6e78e3f05f589a294f
3
+ metadata.gz: 772dfd651b9130358e1de248ead9c68729e482dfdd518973a2d4b61d787d7807
4
+ data.tar.gz: 59dca4e2a1319dc7363b00e3d52ee7889354f0b0bb114fe49bfc7cd47cbcb1e4
5
5
  SHA512:
6
- metadata.gz: 5d768219d315950da7cc798981c6d081e23f2ffab97f354149ebae1398a25cf3db304bdd81429f8e3f257cb0100cc1a28374a1459cef4dc551d317d9bb1cade0
7
- data.tar.gz: 758a733387749553121d3117d9a86ae6109fc28fcbae12cce2852c9d291a30ad133c16060a5374c6c13aadc16af02996fba41a239998d32a194d0516fa75c71f
6
+ metadata.gz: fb2dce4d9d3f663929771b3141b616030de65f1004e28acee1e01a7d4aa306daba51a839fb9c2e68337d056311369bfb6f1b3bb7dae3cf755a9510839185bef8
7
+ data.tar.gz: 5c3e377005030768e6056e9cab0076a5e1165ef0aa4433c4920db2cbd29fed171867da9f4b6da5e2c7b64da340bc24f65e01397c90cc7f160ae520f563dbc132
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ if RUBY_VERSION < "3.3.0"
4
+ require "base64"
5
+ elsif !defined?(Base64)
6
+ module HTTP2Next
7
+ # require "base64" will not be a default gem after ruby 3.4.0
8
+ module Base64
9
+ module_function
10
+
11
+ def encode64(bin)
12
+ [bin].pack("m")
13
+ end
14
+
15
+ def decode64(str)
16
+ str.unpack1("m")
17
+ end
18
+
19
+ def urlsafe_encode64(bin, padding: true)
20
+ str = strict_encode64(bin)
21
+ str.chomp!("==") or str.chomp!("=") unless padding
22
+ str.tr!("+/", "-_")
23
+ str
24
+ end
25
+ end
26
+
27
+ def urlsafe_decode64(str)
28
+ if !str.end_with?("=") && str.length % 4 != 0
29
+ str = str.ljust((str.length + 3) & ~3, "=")
30
+ str.tr!("-_", "+/")
31
+ else
32
+ str = str.tr("-_", "+/")
33
+ end
34
+ strict_decode64(str)
35
+ end
36
+ end
37
+ end
@@ -71,10 +71,7 @@ module HTTP2Next
71
71
 
72
72
  # Number of active streams between client and server (reserved streams
73
73
  # are not counted towards the stream limit).
74
- attr_reader :active_stream_count
75
-
76
- # Max number of streams that can be in-transit in this connection.
77
- attr_writer :max_streams
74
+ attr_accessor :active_stream_count
78
75
 
79
76
  # Initializes new connection object.
80
77
  #
@@ -86,7 +83,6 @@ module HTTP2Next
86
83
  @decompressor = Header::Decompressor.new(settings)
87
84
 
88
85
  @active_stream_count = 0
89
- @max_streams = nil
90
86
  @last_activated_stream = 0
91
87
  @last_stream_id = 0
92
88
  @streams = {}
@@ -120,8 +116,7 @@ module HTTP2Next
120
116
  # @param parent [Stream]
121
117
  def new_stream(**args)
122
118
  raise ConnectionClosed if @state == :closed
123
-
124
- raise StreamLimitExceeded if @active_stream_count >= (@max_streams || @remote_settings[:settings_max_concurrent_streams])
119
+ raise StreamLimitExceeded if @active_stream_count >= @remote_settings[:settings_max_concurrent_streams]
125
120
 
126
121
  connection_error(:protocol_error, msg: "id is smaller than previous") if @stream_id < @last_activated_stream
127
122
 
@@ -727,14 +722,10 @@ module HTTP2Next
727
722
  def activate_stream(id:, **args)
728
723
  connection_error(msg: "Stream ID already exists") if @streams.key?(id)
729
724
 
730
- raise StreamLimitExceeded if @active_stream_count >= (@max_streams || @local_settings[:settings_max_concurrent_streams])
725
+ raise StreamLimitExceeded if @active_stream_count >= @local_settings[:settings_max_concurrent_streams]
731
726
 
732
727
  stream = Stream.new(connection: self, id: id, **args)
733
728
 
734
- # Streams that are in the "open" state, or either of the "half closed"
735
- # states count toward the maximum number of streams that an endpoint is
736
- # permitted to open.
737
- stream.once(:active) { @active_stream_count += 1 }
738
729
  stream.once(:close) do
739
730
  # Store a reference to the closed stream, such that we can respond
740
731
  # to any in-flight frames while close is registered on both sides.
@@ -3,7 +3,7 @@
3
3
  module HTTP2Next
4
4
  # Stream, connection, and compressor exceptions.
5
5
  module Error
6
- @types = {} # rubocop:disable ThreadSafety/MutableClassInstanceVariable
6
+ @types = {}
7
7
 
8
8
  class << self
9
9
  attr_reader :types
@@ -1,16 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2Next
4
- module RegexpExtensions
5
- unless Regexp.method_defined?(:match?)
6
- refine Regexp do
7
- def match?(*args)
8
- !match(*args).nil?
9
- end
10
- end
11
- end
12
- end
13
-
14
4
  module StringExtensions
15
5
  refine String do
16
6
  def read(n)
@@ -29,12 +19,6 @@ module HTTP2Next
29
19
  def shift_byte
30
20
  read(1).ord
31
21
  end
32
-
33
- unless String.method_defined?(:unpack1)
34
- def unpack1(format)
35
- unpack(format).first
36
- end
37
- end
38
22
  end
39
23
  end
40
24
  end
@@ -8,8 +8,6 @@ module HTTP2Next
8
8
  class EncodingContext
9
9
  include Error
10
10
 
11
- using RegexpExtensions
12
-
13
11
  UPPER = /[[:upper:]]/.freeze
14
12
 
15
13
  # @private
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "base64"
4
3
  module HTTP2Next
5
4
  # HTTP 2.0 server connection class that implements appropriate header
6
5
  # compression / decompression algorithms and stream management logic.
@@ -91,6 +91,7 @@ module HTTP2Next
91
91
  @_method = @_content_length = @_status_code = nil
92
92
  @_waiting_on_trailers = false
93
93
  @received_data = false
94
+ @activated = false
94
95
 
95
96
  on(:window) { |v| @remote_window = v }
96
97
  on(:local_window) { |v| @local_window_max_size = @local_window = v }
@@ -605,7 +606,7 @@ module HTTP2Next
605
606
  case newstate
606
607
  when :open
607
608
  @state = newstate
608
- emit(:active)
609
+ activate_stream_in_conn
609
610
 
610
611
  when :reserved_local, :reserved_remote
611
612
  @state = newstate
@@ -613,7 +614,7 @@ module HTTP2Next
613
614
 
614
615
  when :half_closed_local, :half_closed_remote
615
616
  @closed = newstate
616
- emit(:active) unless @state == :open
617
+ activate_stream_in_conn unless @state == :open
617
618
  @state = :half_closing
618
619
 
619
620
  when :local_closed, :remote_closed, :local_rst, :remote_rst
@@ -624,11 +625,25 @@ module HTTP2Next
624
625
  @state
625
626
  end
626
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
+
627
642
  def complete_transition(frame)
628
643
  case @state
629
644
  when :closing
630
645
  @state = :closed
631
- emit(:close, frame[:error])
646
+ close_stream_in_conn(frame[:error])
632
647
  when :half_closing
633
648
  @state = @closed
634
649
  emit(:half_close)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2Next
4
- VERSION = "0.5.1"
4
+ VERSION = "1.0.1"
5
5
  end
data/lib/http/2/next.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "http/2/next/version"
4
4
  require "http/2/next/extensions"
5
+ require "http/2/next/base64"
5
6
  require "http/2/next/error"
6
7
  require "http/2/next/emitter"
7
8
  require "http/2/next/flow_buffer"
data/sig/connection.rbs CHANGED
@@ -17,9 +17,30 @@ module HTTP2Next
17
17
  attr_reader local_settings: settings_hash
18
18
  attr_reader pending_settings: settings_ary
19
19
 
20
- attr_reader active_stream_count: Integer
20
+ attr_accessor active_stream_count: Integer
21
21
 
22
- attr_writer max_streams: Integer?
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
23
44
 
24
45
  def closed?: () -> bool
25
46
 
@@ -37,9 +58,9 @@ module HTTP2Next
37
58
  def receive: (string data) -> void
38
59
  alias << receive
39
60
 
40
- private
61
+ def initialize: (?settings_hash) -> void
41
62
 
42
- def initialize: (?settings_hash) -> untyped
63
+ private
43
64
 
44
65
  def send: (frame) -> void
45
66
 
@@ -67,6 +88,6 @@ module HTTP2Next
67
88
 
68
89
  def _verify_pseudo_headers: (frame, Array[String]) -> void
69
90
 
70
- def connection_error: (?Symbol error, ?msg: String, ?e: StandardError) -> void
91
+ def connection_error: (?Symbol error, ?msg: String?, ?e: StandardError?) -> void
71
92
  end
72
93
  end
data/sig/error.rbs CHANGED
@@ -1,2 +1,35 @@
1
1
  module HTTP2Next
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
2
35
  end
data/sig/stream.rbs CHANGED
@@ -12,6 +12,16 @@ module HTTP2Next
12
12
  attr_reader local_window: Integer
13
13
  attr_reader closed: Symbol?
14
14
 
15
+ @connection: Connection
16
+ @local_window_max_size: Integer
17
+ @error: bool
18
+ @_method: String?
19
+ @_content_length: Integer?
20
+ @_status_code: Integer?
21
+ @_waiting_on_trailers: bool
22
+ @received_data: bool
23
+ @activated: bool
24
+
15
25
  alias window local_window
16
26
 
17
27
  def closed?: () -> bool
@@ -61,6 +71,10 @@ module HTTP2Next
61
71
 
62
72
  def event: (Symbol newstate) -> void
63
73
 
74
+ def activate_stream_in_conn: () -> void
75
+
76
+ def close_stream_in_conn: (*untyped) -> void
77
+
64
78
  def complete_transition: (frame) -> void
65
79
 
66
80
  def process_priority: ({weight: Integer, dependency: Integer, exclusive: bool}) -> void
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.5.1
4
+ version: 1.0.1
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: 2022-11-10 00:00:00.000000000 Z
13
+ date: 2023-10-13 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Pure-ruby HTTP 2.0 protocol implementation
16
16
  email:
@@ -21,6 +21,7 @@ extra_rdoc_files: []
21
21
  files:
22
22
  - README.md
23
23
  - lib/http/2/next.rb
24
+ - lib/http/2/next/base64.rb
24
25
  - lib/http/2/next/client.rb
25
26
  - lib/http/2/next/connection.rb
26
27
  - lib/http/2/next/emitter.rb
@@ -70,14 +71,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
71
  requirements:
71
72
  - - ">="
72
73
  - !ruby/object:Gem::Version
73
- version: 2.1.0
74
+ version: 2.7.0
74
75
  required_rubygems_version: !ruby/object:Gem::Requirement
75
76
  requirements:
76
77
  - - ">="
77
78
  - !ruby/object:Gem::Version
78
79
  version: '0'
79
80
  requirements: []
80
- rubygems_version: 3.3.7
81
+ rubygems_version: 3.4.10
81
82
  signing_key:
82
83
  specification_version: 4
83
84
  summary: Pure-ruby HTTP 2.0 protocol implementation