Class: HTTP::Protocol::HTTP2::Frame
- Inherits:
-
Object
- Object
- HTTP::Protocol::HTTP2::Frame
- Includes:
- Comparable
- Defined in:
- lib/http/protocol/http2/frame.rb
Direct Known Subclasses
ContinuationFrame, DataFrame, GoawayFrame, HeadersFrame, PingFrame, PriorityFrame, PushPromiseFrame, ResetStreamFrame, SettingsFrame, WindowUpdateFrame
Constant Summary collapse
- VALID_STREAM_ID =
Stream Identifier cannot be bigger than this: http2.github.stream/http2-spec/#rfc.section.4.1
0..0x7fffffff
- VALID_LENGTH =
The absolute maximum bounds for the length field:
0..0xffffff
- LENGTH_HISHIFT =
Used for generating 24-bit frame length:
16
- LENGTH_LOMASK =
0xFFFF
- HEADER_FORMAT =
'CnCCN'.freeze
- STREAM_ID_MASK =
0x7fffffff
Instance Attribute Summary collapse
-
#flags ⇒ Object
Returns the value of attribute flags.
-
#length ⇒ Object
The generic frame header uses the following binary representation:.
-
#payload ⇒ Object
Returns the value of attribute payload.
-
#stream_id ⇒ Object
Returns the value of attribute stream_id.
-
#type ⇒ Object
Returns the value of attribute type.
Class Method Summary collapse
-
.parse_header(buffer) ⇒ Object
Decodes common 9-byte header.
Instance Method Summary collapse
- #<=>(other) ⇒ Object
- #apply(connection) ⇒ Object
- #clear_flags(mask) ⇒ Object
-
#connection? ⇒ Boolean
Check if frame is a connection frame: SETTINGS, PING, GOAWAY, and any frame addressed to stream ID = 0.
- #flag_set?(mask) ⇒ Boolean
-
#header ⇒ String
Generates common 9-byte frame header.
-
#initialize(stream_id = 0, flags = 0, type = self.class.const_get(:TYPE), length = nil, payload = nil) ⇒ Frame
constructor
A new instance of Frame.
- #pack(payload, maximum_size: nil) ⇒ Object
- #read(stream, maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE) ⇒ Object
- #read_header(stream) ⇒ Object
- #read_payload(stream) ⇒ Object
- #set_flags(mask) ⇒ Object
- #to_ary ⇒ Object
- #unpack ⇒ Object
- #write(stream) ⇒ Object
- #write_header(stream) ⇒ Object
- #write_payload(stream) ⇒ Object
Constructor Details
#initialize(stream_id = 0, flags = 0, type = self.class.const_get(:TYPE), length = nil, payload = nil) ⇒ Frame
Returns a new instance of Frame.
50 51 52 53 54 55 56 |
# File 'lib/http/protocol/http2/frame.rb', line 50 def initialize(stream_id = 0, flags = 0, type = self.class.const_get(:TYPE), length = nil, payload = nil) @length = length @type = type @flags = flags @stream_id = stream_id @payload = payload end |
Instance Attribute Details
#flags ⇒ Object
Returns the value of attribute flags.
80 81 82 |
# File 'lib/http/protocol/http2/frame.rb', line 80 def flags @flags end |
#length ⇒ Object
The generic frame header uses the following binary representation:
-----------------------------------------------
| Length (24) | ---------------
—————---------------
| Type (8) | Flags (8) | -
————----------------
——————————-+ |R| Stream Identifier (31) | ==============================================================+ | Frame Payload (0…) … ---------------------------------------------------------------
78 79 80 |
# File 'lib/http/protocol/http2/frame.rb', line 78 def length @length end |
#payload ⇒ Object
Returns the value of attribute payload.
82 83 84 |
# File 'lib/http/protocol/http2/frame.rb', line 82 def payload @payload end |
#stream_id ⇒ Object
Returns the value of attribute stream_id.
81 82 83 |
# File 'lib/http/protocol/http2/frame.rb', line 81 def stream_id @stream_id end |
#type ⇒ Object
Returns the value of attribute type.
79 80 81 |
# File 'lib/http/protocol/http2/frame.rb', line 79 def type @type end |
Class Method Details
.parse_header(buffer) ⇒ Object
Decodes common 9-byte header.
146 147 148 149 150 151 152 |
# File 'lib/http/protocol/http2/frame.rb', line 146 def self.parse_header(buffer) length_hi, length_lo, type, flags, stream_id = buffer.unpack(HEADER_FORMAT) length = (length_hi << LENGTH_HISHIFT) | length_lo stream_id = stream_id & STREAM_ID_MASK return length, type, flags, stream_id end |
Instance Method Details
#<=>(other) ⇒ Object
58 59 60 |
# File 'lib/http/protocol/http2/frame.rb', line 58 def <=> other to_ary <=> other.to_ary end |
#apply(connection) ⇒ Object
189 190 191 |
# File 'lib/http/protocol/http2/frame.rb', line 189 def apply(connection) connection.receive_frame(self) end |
#clear_flags(mask) ⇒ Object
101 102 103 |
# File 'lib/http/protocol/http2/frame.rb', line 101 def clear_flags(mask) @flags &= ~mask end |
#connection? ⇒ Boolean
Check if frame is a connection frame: SETTINGS, PING, GOAWAY, and any frame addressed to stream ID = 0.
113 114 115 |
# File 'lib/http/protocol/http2/frame.rb', line 113 def connection? @stream_id.zero? end |
#flag_set?(mask) ⇒ Boolean
105 106 107 |
# File 'lib/http/protocol/http2/frame.rb', line 105 def flag_set?(mask) @flags & mask != 0 end |
#header ⇒ String
Generates common 9-byte frame header.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/http/protocol/http2/frame.rb', line 124 def header unless VALID_LENGTH.include? @length raise ProtocolError, "Invalid frame size: #{@length.inspect}" end unless VALID_STREAM_ID.include? @stream_id raise ProtocolError, "Invalid stream identifier: #{@stream_id.inspect}" end [ # These are guaranteed correct due to the length check above. @length >> LENGTH_HISHIFT, @length & LENGTH_LOMASK, @type, @flags, @stream_id ].pack(HEADER_FORMAT) end |
#pack(payload, maximum_size: nil) ⇒ Object
88 89 90 91 92 93 94 95 |
# File 'lib/http/protocol/http2/frame.rb', line 88 def pack(payload, maximum_size: nil) @payload = payload @length = payload.bytesize if maximum_size and @length > maximum_size raise ProtocolError, "Frame length #{@length} bigger than maximum allowed: #{maximum_size}" end end |
#read(stream, maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE) ⇒ Object
162 163 164 165 166 167 168 169 170 |
# File 'lib/http/protocol/http2/frame.rb', line 162 def read(stream, maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE) read_header(stream) unless @length if @length > maximum_frame_size raise FrameSizeError, "#{self.class} (type=#{@type}) frame length #{@length} exceeds maximum frame size #{maximum_frame_size}!" end read_payload(stream) end |
#read_header(stream) ⇒ Object
154 155 156 |
# File 'lib/http/protocol/http2/frame.rb', line 154 def read_header(stream) @length, @type, @flags, @stream_id = Frame.parse_header(stream.read(9)) end |
#read_payload(stream) ⇒ Object
158 159 160 |
# File 'lib/http/protocol/http2/frame.rb', line 158 def read_payload(stream) @payload = stream.read(@length) end |
#set_flags(mask) ⇒ Object
97 98 99 |
# File 'lib/http/protocol/http2/frame.rb', line 97 def set_flags(mask) @flags |= mask end |
#to_ary ⇒ Object
62 63 64 |
# File 'lib/http/protocol/http2/frame.rb', line 62 def to_ary [@length, @type, @flags, @stream_id, @payload] end |
#unpack ⇒ Object
84 85 86 |
# File 'lib/http/protocol/http2/frame.rb', line 84 def unpack @payload end |
#write(stream) ⇒ Object
180 181 182 183 184 185 186 187 |
# File 'lib/http/protocol/http2/frame.rb', line 180 def write(stream) if @payload and @length != @payload.bytesize raise ProtocolError, "Invalid payload size: #{@length} != #{@payload.bytesize}" end self.write_header(stream) self.write_payload(stream) end |
#write_header(stream) ⇒ Object
172 173 174 |
# File 'lib/http/protocol/http2/frame.rb', line 172 def write_header(stream) stream.write self.header end |
#write_payload(stream) ⇒ Object
176 177 178 |
# File 'lib/http/protocol/http2/frame.rb', line 176 def write_payload(stream) stream.write(@payload) if @payload end |