class Framer
Handles frame serialization and deserialization for HTTP/2 connections. This class manages the reading and writing of HTTP/2 frames to/from a stream.
Definitions
def initialize(stream, frames = FRAMES)
Initialize a new framer with a stream and frame definitions.
Signature
-
parameter
stream
IO
The underlying stream for frame I/O.
-
parameter
frames
Array
Frame type definitions to use.
Implementation
def initialize(stream, frames = FRAMES)
@stream = stream
@frames = frames
end
def flush
Flush the underlying stream.
Implementation
def flush
@stream.flush
end
def close
Close the underlying stream.
Implementation
def close
@stream.close
end
def closed?
Check if the underlying stream is closed.
Signature
-
returns
Boolean
True if the stream is closed.
Implementation
def closed?
@stream.closed?
end
def write_connection_preface
Write the HTTP/2 connection preface to the stream.
Implementation
def write_connection_preface
@stream.write(CONNECTION_PREFACE)
end
def read_connection_preface
Read and validate the HTTP/2 connection preface from the stream.
Signature
-
raises
HandshakeError
If the preface is invalid.
Implementation
def read_connection_preface
string = @stream.read(CONNECTION_PREFACE.bytesize)
unless string == CONNECTION_PREFACE
raise HandshakeError, "Invalid connection preface: #{string.inspect}"
end
return string
end
def read_frame(maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE)
Implementation
def read_frame(maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE)
# Read the header:
length, type, flags, stream_id = read_header
# Console.debug(self) {"read_frame: length=#{length} type=#{type} flags=#{flags} stream_id=#{stream_id} -> klass=#{@frames[type].inspect}"}
# Allocate the frame:
klass = @frames[type] || Frame
frame = klass.new(stream_id, flags, type, length)
# Read the payload:
frame.read(@stream, maximum_frame_size)
# Console.debug(self, name: "read") {frame.inspect}
return frame
end
def write_frame(frame)
Write a frame to the underlying IO. After writing one or more frames, you should call flush to ensure the frames are sent to the remote peer.
Signature
-
parameter
frame
Frame
the frame to write.
Implementation
def write_frame(frame)
# Console.debug(self, name: "write") {frame.inspect}
frame.write(@stream)
return frame
end
def read_header
Read a frame header from the stream.
Signature
-
returns
Array
Parsed frame header components: length, type, flags, stream_id.
-
raises
EOFError
If the header cannot be read completely.
Implementation
def read_header
if buffer = @stream.read(9)
if buffer.bytesize == 9
return Frame.parse_header(buffer)
end
end
raise EOFError, "Could not read frame header!"
end