Protocol::HTTP2SourceProtocolHTTP2Framer

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