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.io/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(io) ⇒ Object
- #read_header(io) ⇒ Object
- #read_payload(io) ⇒ Object
- #set_flags(mask) ⇒ Object
- #to_ary ⇒ Object
- #unpack ⇒ Object
- #write(io) ⇒ Object
- #write_header(io) ⇒ Object
- #write_payload(io) ⇒ 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.
47 48 49 50 51 52 53 |
# File 'lib/http/protocol/http2/frame.rb', line 47 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.
77 78 79 |
# File 'lib/http/protocol/http2/frame.rb', line 77 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…) … ---------------------------------------------------------------
75 76 77 |
# File 'lib/http/protocol/http2/frame.rb', line 75 def length @length end |
#payload ⇒ Object
Returns the value of attribute payload.
79 80 81 |
# File 'lib/http/protocol/http2/frame.rb', line 79 def payload @payload end |
#stream_id ⇒ Object
Returns the value of attribute stream_id.
78 79 80 |
# File 'lib/http/protocol/http2/frame.rb', line 78 def stream_id @stream_id end |
#type ⇒ Object
Returns the value of attribute type.
76 77 78 |
# File 'lib/http/protocol/http2/frame.rb', line 76 def type @type end |
Class Method Details
.parse_header(buffer) ⇒ Object
Decodes common 9-byte header.
143 144 145 146 147 148 149 |
# File 'lib/http/protocol/http2/frame.rb', line 143 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
55 56 57 |
# File 'lib/http/protocol/http2/frame.rb', line 55 def <=> other to_ary <=> other.to_ary end |
#apply(connection) ⇒ Object
181 182 183 |
# File 'lib/http/protocol/http2/frame.rb', line 181 def apply(connection) connection.receive_frame(self) end |
#clear_flags(mask) ⇒ Object
98 99 100 |
# File 'lib/http/protocol/http2/frame.rb', line 98 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.
110 111 112 |
# File 'lib/http/protocol/http2/frame.rb', line 110 def connection? @stream_id.zero? end |
#flag_set?(mask) ⇒ Boolean
102 103 104 |
# File 'lib/http/protocol/http2/frame.rb', line 102 def flag_set?(mask) @flags & mask != 0 end |
#header ⇒ String
Generates common 9-byte frame header.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/http/protocol/http2/frame.rb', line 121 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
85 86 87 88 89 90 91 92 |
# File 'lib/http/protocol/http2/frame.rb', line 85 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(io) ⇒ Object
159 160 161 162 |
# File 'lib/http/protocol/http2/frame.rb', line 159 def read(io) read_header(io) unless @length read_payload(io) end |
#read_header(io) ⇒ Object
151 152 153 |
# File 'lib/http/protocol/http2/frame.rb', line 151 def read_header(io) @length, @type, @flags, @stream_id = Frame.parse_header(io.read(9)) end |
#read_payload(io) ⇒ Object
155 156 157 |
# File 'lib/http/protocol/http2/frame.rb', line 155 def read_payload(io) @payload = io.read(@length) end |
#set_flags(mask) ⇒ Object
94 95 96 |
# File 'lib/http/protocol/http2/frame.rb', line 94 def set_flags(mask) @flags |= mask end |
#to_ary ⇒ Object
59 60 61 |
# File 'lib/http/protocol/http2/frame.rb', line 59 def to_ary [@length, @type, @flags, @stream_id, @payload] end |
#unpack ⇒ Object
81 82 83 |
# File 'lib/http/protocol/http2/frame.rb', line 81 def unpack @payload end |
#write(io) ⇒ Object
172 173 174 175 176 177 178 179 |
# File 'lib/http/protocol/http2/frame.rb', line 172 def write(io) if @payload and @length != @payload.bytesize raise ProtocolError, "Invalid payload size: #{@length} != #{@payload.bytesize}" end self.write_header(io) self.write_payload(io) end |
#write_header(io) ⇒ Object
164 165 166 |
# File 'lib/http/protocol/http2/frame.rb', line 164 def write_header(io) io.write self.header end |
#write_payload(io) ⇒ Object
168 169 170 |
# File 'lib/http/protocol/http2/frame.rb', line 168 def write_payload(io) io.write(@payload) if @payload end |