http-2 0.12.0 → 1.0.2

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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Machine generated Huffman decoder state machine.
2
4
  # DO NOT EDIT THIS FILE.
3
5
 
@@ -266,7 +268,7 @@ module HTTP2
266
268
  [[28, 29], [28, 5], [29, 29], [29, 5], [30, 29], [30, 5], [31, 29], [31, 5], [127, 29], [127, 5], [220, 29], [220, 5], [249, 29], [249, 5], [nil, 254], [nil, 255]],
267
269
  [[10, 17], [10, 18], [10, 19], [10, 20], [10, 21], [10, 22], [10, 23], [10, 7], [13, 17], [13, 18], [13, 19], [13, 20], [13, 21], [13, 22], [13, 23], [13, 7]],
268
270
  [[22, 17], [22, 18], [22, 19], [22, 20], [22, 21], [22, 22], [22, 23], [22, 7], [256, 17], [256, 18], [256, 19], [256, 20], [256, 21], [256, 22], [256, 23], [256, 7]],
269
- ].each { |arr| arr.each { |subarr| subarr.each(&:freeze) }.freeze }.freeze
271
+ ].each { |arr| arr.each { |subarr| subarr.freeze }.freeze }.freeze
270
272
  end
271
273
  end
272
274
  end
@@ -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(**settings)
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 = HTTP2::Buffer.new Base64.urlsafe_decode64(settings.to_s)
78
- header = @framer.common_header(
79
- length: buf.bytesize,
80
- type: :settings,
81
- stream: 0,
82
- flags: []
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.merge!(flags: [:end_stream])
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 args [Array]
143
+ # @param parent [Stream]
144
+ # @param headers [Enumerable[String, String]]
145
+ # @param flags [Array[Symbol]]
120
146
  # @param callback [Proc]
121
- def promise(*args, &callback)
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
- callback.call(promise)
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, stream_dependency: dependency, exclusive: exclusive)
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 = connection.local_settings[:settings_initial_window_size]
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
- @send_buffer = []
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, 'must provide callback' unless block_given?
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, stream_dependency: dependency, exclusive: exclusive)
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
- emit(:active)
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
- emit(:active) unless @state == :open
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
- emit(:close, frame[:error])
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[:stream_dependency]
655
+ @dependency = frame[:dependency]
586
656
  emit(
587
657
  :priority,
588
658
  weight: frame[:weight],
589
- dependency: frame[:stream_dependency],
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
- return false unless frame[:flags]
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
- klass = error.to_s.split('_').map(&:capitalize).join
614
- raise Error.const_get(klass), msg
683
+ raise Error.types[error], msg
615
684
  end
616
685
  alias error stream_error
617
686
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP2
4
- VERSION = '0.12.0'
4
+ VERSION = "1.0.2"
5
5
  end
data/lib/http/2.rb CHANGED
@@ -1,15 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'http/2/version'
4
- require 'http/2/error'
5
- require 'http/2/emitter'
6
- require 'http/2/buffer'
7
- require 'http/2/flow_buffer'
8
- require 'http/2/huffman'
9
- require 'http/2/huffman_statemachine'
10
- require 'http/2/compressor'
11
- require 'http/2/framer'
12
- require 'http/2/connection'
13
- require 'http/2/client'
14
- require 'http/2/server'
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
@@ -0,0 +1,9 @@
1
+ module HTTP2
2
+ class Client < Connection
3
+ def upgrade: () -> Stream
4
+
5
+ def send_connection_preface: () -> void
6
+
7
+ def self.settings_header: (settings_enum) -> String
8
+ end
9
+ end
@@ -0,0 +1,94 @@
1
+ module HTTP2
2
+ class Connection
3
+ include FlowBuffer
4
+ include Emitter
5
+ include BufferUtils
6
+
7
+ REQUEST_MANDATORY_HEADERS: Array[String]
8
+ RESPONSE_MANDATORY_HEADERS: Array[String]
9
+
10
+ attr_reader state: Symbol
11
+
12
+ attr_reader local_window: Integer
13
+ attr_reader remote_window: Integer
14
+
15
+ alias window local_window
16
+
17
+ attr_reader remote_settings: settings_hash
18
+ attr_reader local_settings: settings_hash
19
+ attr_reader pending_settings: settings_ary
20
+
21
+ attr_accessor active_stream_count: Integer
22
+
23
+ @stream_id: Integer
24
+ @active_stream_count: Integer
25
+ @last_activated_stream: Integer
26
+ @last_stream_id: Integer
27
+
28
+ @streams: Hash[Integer, Stream]
29
+ @streams_recently_closed: Hash[Integer, Stream]
30
+
31
+ @framer: Framer
32
+
33
+ @local_window_limit: Integer
34
+ @remote_window_limit: Integer
35
+
36
+ @compressor: Header::Compressor
37
+ @decompressor: Header::Decompressor
38
+ @error: Symbol?
39
+
40
+ @recv_buffer: String
41
+ @continuation: Array[frame]
42
+
43
+ @closed_since: Float?
44
+ @received_frame: bool
45
+
46
+ def closed?: () -> bool
47
+
48
+ def new_stream: (**untyped) -> Stream
49
+
50
+ def ping: (String) -> void
51
+ | (String) { () -> void } -> void
52
+
53
+ def goaway: (?Symbol, ?String) -> void
54
+
55
+ def window_update: (Integer increment) -> void
56
+
57
+ def settings: (settings_enum) -> void
58
+
59
+ def receive: (string data) -> void
60
+ alias << receive
61
+
62
+ def initialize: (?settings_hash) -> void
63
+
64
+ private
65
+
66
+ def send: (frame) -> void
67
+
68
+ def encode: (frame) -> Array[String]
69
+
70
+ def connection_frame?: (frame) -> bool
71
+
72
+ def connection_management: (frame) -> void
73
+
74
+ def ping_management: (frame) -> void
75
+
76
+ def validate_settings: (:client | :server, settings_enum) -> void
77
+
78
+ def connection_settings: (frame) -> void
79
+
80
+ def decode_headers: (frame) -> void
81
+
82
+ def encode_headers: (frame) -> Array[frame]
83
+
84
+ def activate_stream: (id: Integer, **untyped) -> Stream
85
+
86
+ def verify_stream_order: (Integer id) -> void
87
+
88
+ def verify_pseudo_headers: (frame) -> void
89
+
90
+ def _verify_pseudo_headers: (frame, Array[String]) -> void
91
+
92
+ def connection_error: (?Symbol error, ?msg: String?, ?e: StandardError?) -> void
93
+ end
94
+ 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
@@ -0,0 +1,13 @@
1
+ module HTTP2
2
+ module BufferUtils
3
+ def read_str: (String str, Integer n) -> String
4
+
5
+ def read_uint32: (String str) -> Integer
6
+
7
+ def shift_byte: (String str) -> Integer
8
+ end
9
+
10
+ module PackingExtensions
11
+ def pack: (Array[Integer] array_to_pack, String template, buffer: String, ?offset: Integer) -> String
12
+ end
13
+ end
@@ -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
@@ -0,0 +1,13 @@
1
+ module HTTP2
2
+ class FrameBuffer
3
+ attr_reader bytesize: Integer
4
+
5
+ @buffer: Array[data_frame]
6
+
7
+ def <<: (data_frame) -> void
8
+
9
+ def empty?: () -> bool
10
+
11
+ def retrieve: (Integer) -> data_frame?
12
+ end
13
+ end
data/sig/framer.rbs ADDED
@@ -0,0 +1,55 @@
1
+ module HTTP2
2
+ class Framer
3
+ include PackingExtensions
4
+ include BufferUtils
5
+
6
+ DEFAULT_MAX_FRAME_SIZE: Integer
7
+
8
+ MAX_STREAM_ID: Integer
9
+
10
+ MAX_WINDOWINC: Integer
11
+
12
+ FRAME_TYPES: Hash[Symbol, Integer]
13
+
14
+ FRAME_TYPES_WITH_PADDING: Array[Symbol]
15
+
16
+ FRAME_FLAGS: Hash[Symbol, Hash[Symbol, Integer]]
17
+
18
+ DEFINED_SETTINGS: Hash[Symbol, Integer]
19
+
20
+ DEFINED_ERRORS: Hash[Symbol, Integer]
21
+
22
+ RBIT: Integer
23
+ RBYTE: Integer
24
+ EBIT: Integer
25
+ UINT32: String
26
+ UINT16: String
27
+ UINT8: String
28
+ HEADERPACK: String
29
+ FRAME_LENGTH_HISHIFT: Integer
30
+ FRAME_LENGTH_LOMASK: Integer
31
+
32
+ @local_max_frame_size: Integer
33
+ @remote_max_frame_size: Integer
34
+
35
+ attr_accessor local_max_frame_size: Integer
36
+
37
+ attr_accessor remote_max_frame_size: Integer
38
+
39
+ def common_header: (frame, buffer: String) -> String
40
+
41
+ def read_common_frame: (String) -> frame
42
+
43
+ def generate: (frame) -> String
44
+
45
+ def parse: (String) -> frame?
46
+
47
+ private
48
+
49
+ def initialize: (?Integer local_max_frame_size, ?Integer remote_max_frame_size) -> untyped
50
+
51
+ def pack_error: (Integer | Symbol error, buffer: String) -> String
52
+
53
+ def unpack_error: (Integer) -> (Symbol | Integer)
54
+ end
55
+ end