PcapFileEx.HTTP2.StreamState (pcap_file_ex v0.5.5)

View Source

Per-stream state for HTTP/2 stream reconstruction.

Tracks request and response data including headers, body, and trailers. Handles CONTINUATION frame buffering for split header blocks.

Stream Lifecycle

  1. Created when first frame for stream ID is seen
  2. Receives HEADERS (possibly with CONTINUATION frames)
  3. May receive DATA frames
  4. May receive trailing HEADERS (trailers)
  5. Completes when both request and response have END_STREAM
  6. May be terminated early by RST_STREAM/GOAWAY

CONTINUATION Handling

When a HEADERS frame has END_HEADERS=false, subsequent CONTINUATION frames are buffered until END_HEADERS=true. During this time:

  • awaiting_continuation is true
  • pending_header_block accumulates the header block fragments
  • pending_end_stream tracks if the initial HEADERS had END_STREAM
  • pending_direction tracks who sent the initial HEADERS

Timestamps

  • created_at: When first frame for this stream was seen
  • completed_at: When BOTH request_complete AND response_complete became true

Summary

Functions

Append a CONTINUATION frame's payload to the pending header block.

Check if stream is complete (both request and response finished).

Complete the header block and clear continuation state.

Create a new stream state.

Get the complete request body as a binary.

Get the complete response body as a binary.

Record an error on the stream.

Set request headers (from initial HEADERS frame with :method).

Set request trailers (HEADERS with no pseudo-headers, from client).

Set response headers (from HEADERS frame with :status).

Set response trailers (HEADERS with no pseudo-headers, from server).

Start buffering a header block that spans multiple frames.

Mark stream as terminated with a reason.

Types

t()

@type t() :: %PcapFileEx.HTTP2.StreamState{
  awaiting_continuation: boolean(),
  completed_at: DateTime.t() | nil,
  created_at: DateTime.t(),
  error: term() | nil,
  informational_responses: [PcapFileEx.HTTP2.Headers.t()],
  pending_direction: boolean() | nil,
  pending_end_stream: boolean(),
  pending_header_block: binary(),
  request_body: iodata(),
  request_complete: boolean(),
  request_headers: PcapFileEx.HTTP2.Headers.t() | nil,
  request_trailers: PcapFileEx.HTTP2.Headers.t() | nil,
  response_body: iodata(),
  response_complete: boolean(),
  response_headers: PcapFileEx.HTTP2.Headers.t() | nil,
  response_trailers: PcapFileEx.HTTP2.Headers.t() | nil,
  stream_id: non_neg_integer(),
  terminated: boolean(),
  termination_reason: termination_reason() | nil
}

termination_reason()

@type termination_reason() ::
  {:rst_stream, non_neg_integer()}
  | {:goaway, non_neg_integer()}
  | :truncated_no_response
  | :truncated_incomplete_response
  | :truncated_incomplete_headers
  | :tcp_fin_without_end_stream
  | {:hpack_error, term()}
  | {:frame_error, term()}

Functions

append_continuation(stream, payload)

@spec append_continuation(t(), binary()) :: t()

Append a CONTINUATION frame's payload to the pending header block.

append_request_data(stream, data, end_stream, timestamp)

@spec append_request_data(t(), binary(), boolean(), DateTime.t()) :: t()

Append data to request body.

append_response_data(stream, data, end_stream, timestamp)

@spec append_response_data(t(), binary(), boolean(), DateTime.t()) :: t()

Append data to response body.

complete?(stream_state)

@spec complete?(t()) :: boolean()

Check if stream is complete (both request and response finished).

complete_continuation(stream)

@spec complete_continuation(t()) :: {binary(), boolean(), boolean() | nil, t()}

Complete the header block and clear continuation state.

Returns the complete header block and updated stream.

new(stream_id, timestamp)

@spec new(non_neg_integer(), DateTime.t()) :: t()

Create a new stream state.

request_body_binary(stream_state)

@spec request_body_binary(t()) :: binary()

Get the complete request body as a binary.

response_body_binary(stream_state)

@spec response_body_binary(t()) :: binary()

Get the complete response body as a binary.

set_error(stream, error)

@spec set_error(t(), term()) :: t()

Record an error on the stream.

set_request_headers(stream, headers, end_stream, timestamp)

@spec set_request_headers(t(), PcapFileEx.HTTP2.Headers.t(), boolean(), DateTime.t()) ::
  t()

Set request headers (from initial HEADERS frame with :method).

set_request_trailers(stream, headers, timestamp)

@spec set_request_trailers(t(), PcapFileEx.HTTP2.Headers.t(), DateTime.t()) :: t()

Set request trailers (HEADERS with no pseudo-headers, from client).

set_response_headers(stream, headers, end_stream, timestamp)

@spec set_response_headers(t(), PcapFileEx.HTTP2.Headers.t(), boolean(), DateTime.t()) ::
  t()

Set response headers (from HEADERS frame with :status).

Handles both informational (1xx) and final responses.

set_response_trailers(stream, headers, timestamp)

@spec set_response_trailers(t(), PcapFileEx.HTTP2.Headers.t(), DateTime.t()) :: t()

Set response trailers (HEADERS with no pseudo-headers, from server).

start_continuation(stream, header_block, end_stream, is_from_client)

@spec start_continuation(t(), binary(), boolean(), boolean()) :: t()

Start buffering a header block that spans multiple frames.

Called when HEADERS frame has END_HEADERS=false.

terminate(stream, reason)

@spec terminate(t(), termination_reason()) :: t()

Mark stream as terminated with a reason.