Class: Protocol::HTTP2::Frame
- Inherits:
-
Object
- Object
- Protocol::HTTP2::Frame
- Includes:
- Comparable
- Defined in:
- lib/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.
49 50 51 52 53 54 55 |
# File 'lib/protocol/http2/frame.rb', line 49 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.
79 80 81 |
# File 'lib/protocol/http2/frame.rb', line 79 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…) … ---------------------------------------------------------------
77 78 79 |
# File 'lib/protocol/http2/frame.rb', line 77 def length @length end |
#payload ⇒ Object
Returns the value of attribute payload.
81 82 83 |
# File 'lib/protocol/http2/frame.rb', line 81 def payload @payload end |
#stream_id ⇒ Object
Returns the value of attribute stream_id.
80 81 82 |
# File 'lib/protocol/http2/frame.rb', line 80 def stream_id @stream_id end |
#type ⇒ Object
Returns the value of attribute type.
78 79 80 |
# File 'lib/protocol/http2/frame.rb', line 78 def type @type end |
Class Method Details
.parse_header(buffer) ⇒ Object
Decodes common 9-byte header.
145 146 147 148 149 150 151 |
# File 'lib/protocol/http2/frame.rb', line 145 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
57 58 59 |
# File 'lib/protocol/http2/frame.rb', line 57 def <=> other to_ary <=> other.to_ary end |
#apply(connection) ⇒ Object
188 189 190 |
# File 'lib/protocol/http2/frame.rb', line 188 def apply(connection) connection.receive_frame(self) end |
#clear_flags(mask) ⇒ Object
100 101 102 |
# File 'lib/protocol/http2/frame.rb', line 100 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.
112 113 114 |
# File 'lib/protocol/http2/frame.rb', line 112 def connection? @stream_id.zero? end |
#flag_set?(mask) ⇒ Boolean
104 105 106 |
# File 'lib/protocol/http2/frame.rb', line 104 def flag_set?(mask) @flags & mask != 0 end |
#header ⇒ String
Generates common 9-byte frame header.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/protocol/http2/frame.rb', line 123 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
87 88 89 90 91 92 93 94 |
# File 'lib/protocol/http2/frame.rb', line 87 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
161 162 163 164 165 166 167 168 169 |
# File 'lib/protocol/http2/frame.rb', line 161 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
153 154 155 |
# File 'lib/protocol/http2/frame.rb', line 153 def read_header(stream) @length, @type, @flags, @stream_id = Frame.parse_header(stream.read(9)) end |
#read_payload(stream) ⇒ Object
157 158 159 |
# File 'lib/protocol/http2/frame.rb', line 157 def read_payload(stream) @payload = stream.read(@length) end |
#set_flags(mask) ⇒ Object
96 97 98 |
# File 'lib/protocol/http2/frame.rb', line 96 def set_flags(mask) @flags |= mask end |
#to_ary ⇒ Object
61 62 63 |
# File 'lib/protocol/http2/frame.rb', line 61 def to_ary [@length, @type, @flags, @stream_id, @payload] end |
#unpack ⇒ Object
83 84 85 |
# File 'lib/protocol/http2/frame.rb', line 83 def unpack @payload end |
#write(stream) ⇒ Object
179 180 181 182 183 184 185 186 |
# File 'lib/protocol/http2/frame.rb', line 179 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
171 172 173 |
# File 'lib/protocol/http2/frame.rb', line 171 def write_header(stream) stream.write self.header end |
#write_payload(stream) ⇒ Object
175 176 177 |
# File 'lib/protocol/http2/frame.rb', line 175 def write_payload(stream) stream.write(@payload) if @payload end |