H2_frameHTTP/2 Frame Layer.
This module implements HTTP/2 frame parsing and serialization as specified in RFC 9113 Section 4 and RFC 9113 Section 6.
All HTTP/2 frames share a common 9-octet header:
+-----------------------------------------------+ | Length (24) | +---------------+---------------+---------------+ | Type (8) | Flags (8) | +-+-------------+---------------+-------------------------------+ |R| Stream Identifier (31) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+
Per RFC 9113 Section 4.1:
Stream identifier. Per RFC 9113 Section 5.1.1:
val stream_id_is_client_initiated : stream_id -> boolstream_id_is_client_initiated id returns true for odd stream IDs.
val stream_id_is_server_initiated : stream_id -> boolstream_id_is_server_initiated id returns true for even non-zero stream IDs.
Per RFC 9113 Section 6.
type frame_type = | Data0x00 - RFC 9113 Section 6.1
*)| Headers0x01 - RFC 9113 Section 6.2
*)| Priority0x02 - RFC 9113 Section 6.3 (deprecated)
*)| Rst_stream0x03 - RFC 9113 Section 6.4
*)| Settings0x04 - RFC 9113 Section 6.5
*)| Push_promise0x05 - RFC 9113 Section 6.6
*)| Ping0x06 - RFC 9113 Section 6.7
*)| Goaway0x07 - RFC 9113 Section 6.8
*)| Window_update0x08 - RFC 9113 Section 6.9
*)| Continuation0x09 - RFC 9113 Section 6.10
*)| Unknown of intUnknown frame type - MUST be ignored per RFC 9113 Section 5.5
*)val frame_type_to_int : frame_type -> intConvert frame type to its numeric value.
val frame_type_of_int : int -> frame_typeConvert numeric value to frame type.
val pp_frame_type : Format.formatter -> frame_type -> unitPretty printer for frame types.
module Flags : sig ... endtype frame_header = {length : int;Payload length (24-bit unsigned). MUST NOT exceed SETTINGS_MAX_FRAME_SIZE.
*)frame_type : frame_type;Frame type (8-bit).
*)flags : Flags.t;Frame-specific flags (8-bit).
*)stream_id : stream_id;Stream identifier (31-bit). 0 for connection-level frames.
*)}val pp_frame_header : Format.formatter -> frame_header -> unitPretty printer for frame headers.
Per RFC 9113 Section 7.
type error_code = | No_error0x00 - Graceful shutdown
*)| Protocol_error0x01 - Protocol error detected
*)| Internal_error0x02 - Implementation fault
*)| Flow_control_error0x03 - Flow control limits exceeded
*)| Settings_timeout0x04 - Settings not acknowledged in time
*)| Stream_closed0x05 - Frame received for closed stream
*)| Frame_size_error0x06 - Frame size incorrect
*)| Refused_stream0x07 - Stream not processed
*)| Cancel0x08 - Stream cancelled
*)| Compression_error0x09 - Compression state not updated
*)| Connect_error0x0a - TCP connection error for CONNECT
*)| Enhance_your_calm0x0b - Processing capacity exceeded
*)| Inadequate_security0x0c - Negotiated TLS parameters not acceptable
*)| Http_1_1_required0x0d - Use HTTP/1.1 for this request
*)| Unknown_error of int32Unknown error code
*)val error_code_to_int32 : error_code -> int32Convert error code to its numeric value.
val error_code_of_int32 : int32 -> error_codeConvert numeric value to error code.
val error_code_to_string : error_code -> stringConvert error code to its string representation.
val pp_error_code : Format.formatter -> error_code -> unitPretty printer for error codes.
type setting = | Header_table_size of int0x01 - HPACK dynamic table size
*)| Enable_push of bool0x02 - Server push enabled
*)| Max_concurrent_streams of int320x03 - Maximum concurrent streams
*)| Initial_window_size of int320x04 - Initial flow control window
*)| Max_frame_size of int0x05 - Maximum frame payload size
*)| Max_header_list_size of int0x06 - Maximum header list size
*)| No_rfc7540_priorities of bool0x09 - RFC 9113: Deprecate RFC 7540 priorities
*)| Unknown_setting of int * int32Unknown setting (id, value)
*)val setting_to_pair : setting -> int * int32Convert setting to (identifier, value) pair.
val setting_of_pair : int -> int32 -> settingConvert (identifier, value) pair to setting.
val pp_setting : Format.formatter -> setting -> unitPretty printer for settings.
Per RFC 9113 Section 6.3.
Note: Stream prioritization is deprecated in RFC 9113 but MUST still be parsed.
type priority = {exclusive : bool;Exclusive dependency flag.
*)stream_dependency : stream_id;Stream this one depends on.
*)weight : int;Weight 1-256 (stored as 1-256, not 0-255).
*)}val default_priority : priorityDefault priority: non-exclusive, depends on 0, weight 16.
val pp_priority : Format.formatter -> priority -> unitPretty printer for priority.
type frame_payload = | Data_payload of {data : Cstruct.t;The actual data being transferred.
*)}| Headers_payload of {priority : priority option;Priority if PRIORITY flag set.
*)header_block : Cstruct.t;Encoded header block fragment (HPACK).
*)}| Priority_payload of priorityPriority specification (deprecated).
*)| Rst_stream_payload of error_codeError code for stream termination.
*)| Settings_payload of setting listList of settings. Empty list for ACK.
*)| Push_promise_payload of {promised_stream_id : stream_id;Stream ID being reserved.
*)header_block : Cstruct.t;Encoded header block fragment.
*)}| Ping_payload of Cstruct.t8 bytes of opaque data.
*)| Goaway_payload of {last_stream_id : stream_id;Highest processed stream ID.
*)error_code : error_code;Reason for closing connection.
*)debug_data : Cstruct.t;Optional diagnostic data.
*)}| Window_update_payload of int32Window size increment (1 to 2^31-1).
*)| Continuation_payload of {header_block : Cstruct.t;Continuation of header block.
*)}| Unknown_payload of Cstruct.tPayload for unknown frame types.
*)val pp_frame : Format.formatter -> frame -> unitPretty printer for frames.
Parse frames from Eio buffered input.
val pp_parse_error : Format.formatter -> parse_error -> unitPretty printer for parse errors.
val parse_frame_header : Cstruct.t -> (frame_header, parse_error) resultparse_frame_header buf parses a 9-byte frame header. Returns Error Incomplete if buffer is too small.
val parse_frame_payload :
frame_header ->
Cstruct.t ->
(frame_payload, parse_error) resultparse_frame_payload header buf parses frame payload based on type. The buffer should contain exactly header.length bytes.
val parse_frame :
Cstruct.t ->
max_frame_size:int ->
(frame * int, parse_error) resultparse_frame buf ~max_frame_size parses a complete frame. Returns the frame and number of bytes consumed. max_frame_size is the current SETTINGS_MAX_FRAME_SIZE value. Returns Error Frame_size_error if payload exceeds limit.
Serialize frames to Eio buffered output.
val serialize_frame_header : frame_header -> Cstruct.tserialize_frame_header header serializes a frame header to 9 bytes.
val write_frame : Eio.Buf_write.t -> frame -> unitwrite_frame writer frame writes a frame to the buffer.
make_data ~stream_id ?end_stream data creates a DATA frame.
val make_headers :
stream_id:stream_id ->
?end_stream:bool ->
?end_headers:bool ->
?priority:priority ->
Cstruct.t ->
framemake_headers ~stream_id ?end_stream ?end_headers ?priority block creates a HEADERS frame.
val make_rst_stream : stream_id:stream_id -> error_code -> framemake_rst_stream ~stream_id code creates a RST_STREAM frame.
make_settings ?ack settings creates a SETTINGS frame.
make_ping ?ack data creates a PING frame. data must be exactly 8 bytes.
val make_goaway :
last_stream_id:stream_id ->
error_code ->
?debug:string ->
unit ->
framemake_goaway ~last_stream_id code ?debug () creates a GOAWAY frame.
make_window_update ~stream_id increment creates a WINDOW_UPDATE frame.
make_continuation ~stream_id ?end_headers block creates a CONTINUATION frame.
HTTP/2 connection preface (magic string): "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"