class Protocol::HTTP2::Frame
def self.parse_header(buffer)
-
buffer
(String
) --
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 # puts "parse_header: length=#{length} type=#{type} flags=#{flags} stream_id=#{stream_id}" return length, type, flags, stream_id end
def <=> other
def <=> other to_ary <=> other.to_ary end
def apply(connection)
def apply(connection) connection.receive_frame(self) end
def clear_flags(mask)
def clear_flags(mask) @flags &= ~mask end
def connection?
-
(Boolean)
-
def connection? @stream_id.zero? end
def flag_set?(mask)
def flag_set?(mask) @flags & mask != 0 end
def header
-
(String)
-
def header unless VALID_LENGTH.include? @length raise ProtocolError, "Invalid frame length: #{@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
def initialize(stream_id = 0, flags = 0, type = self.class::TYPE, length = nil, payload = nil)
-
length
(Integer
) -- the length of the payload, or nil if the header has not been read yet.
def initialize(stream_id = 0, flags = 0, type = self.class::TYPE, length = nil, payload = nil) @stream_id = stream_id @flags = flags @type = type @length = length @payload = payload end
def inspect
def inspect "\#<#{self.class} stream_id=#{@stream_id} flags=#{@flags} payload=#{self.unpack}>" end
def pack(payload, maximum_size: nil)
def pack(payload, maximum_size: nil) @payload = payload @length = payload.bytesize if maximum_size and @length > maximum_size raise ProtocolError, "Frame length bigger than maximum allowed: #{@length} > #{maximum_size}" end end
def read(stream, maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE)
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
def read_header(stream)
def read_header(stream) if buffer = stream.read(9) and buffer.bytesize == 9 @length, @type, @flags, @stream_id = Frame.parse_header(buffer) # puts "read_header: #{@length} #{@type} #{@flags} #{@stream_id}" else raise EOFError, "Could not read frame header!" end end
def read_payload(stream)
def read_payload(stream) if payload = stream.read(@length) and payload.bytesize == @length @payload = payload else raise EOFError, "Could not read frame payload!" end end
def set_flags(mask)
def set_flags(mask) @flags |= mask end
def to_ary
def to_ary [@length, @type, @flags, @stream_id, @payload] end
def unpack
def unpack @payload end
def valid_type?
def valid_type? @type == self.class::TYPE end
def write(stream)
def write(stream) # Validate the payload size: if @payload.nil? if @length != 0 raise ProtocolError, "Invalid frame length: #{@length} != 0" end else if @length != @payload.bytesize raise ProtocolError, "Invalid payload size: #{@length} != #{@payload.bytesize}" end end self.write_header(stream) self.write_payload(stream) end
def write_header(stream)
def write_header(stream) stream.write self.header end
def write_payload(stream)
def write_payload(stream) stream.write(@payload) if @payload end