PcapFileEx.HTTP2.Exchange (pcap_file_ex v0.5.5)

View Source

Represents a complete HTTP/2 request/response exchange.

An exchange is complete when both the request and response have received their END_STREAM flag, indicating no more data will be sent.

Structure

  • stream_id - HTTP/2 stream identifier
  • client - Client endpoint (set when client/server identified via HTTP/2 preface or stream semantics)
  • server - Server endpoint (set when client/server identified)
  • endpoint_a - First endpoint (set when client/server cannot be identified, uses flow_key order)
  • endpoint_b - Second endpoint (set when client/server cannot be identified)
  • request - Request data including headers, body, and method
  • response - Response data including headers, body, and status
  • start_timestamp - When first frame of this stream was seen
  • end_timestamp - When final END_STREAM frame was received

Endpoint Semantics

Exactly one pair of endpoint fields will be set:

  • When client/server roles are identified: client and server are set, endpoint_a and endpoint_b are nil
  • When identification fails: endpoint_a and endpoint_b are set, client and server are nil

Use client_identified?/1 to check which pair is set, and endpoints/1 to get the pair of endpoints regardless of which fields are populated.

Summary

Types

Tuple of {ip_tuple, port} for backwards compatibility

t()

Functions

Build just the request portion from a stream state.

Build just the response portion from a stream state.

Returns true if client/server roles were identified for this exchange.

Returns the pair of endpoints, regardless of whether client/server was identified.

Build a complete exchange from a finished stream state.

Get a friendly string representation of the exchange.

Types

legacy_endpoint()

@type legacy_endpoint() :: {tuple(), non_neg_integer()}

Tuple of {ip_tuple, port} for backwards compatibility

request()

@type request() :: %{
  headers: PcapFileEx.HTTP2.Headers.t(),
  trailers: PcapFileEx.HTTP2.Headers.t() | nil,
  body: binary(),
  decoded_body: PcapFileEx.HTTP.Content.decoded() | nil,
  method: String.t(),
  path: String.t(),
  authority: String.t() | nil
}

response()

@type response() :: %{
  headers: PcapFileEx.HTTP2.Headers.t(),
  trailers: PcapFileEx.HTTP2.Headers.t() | nil,
  body: binary(),
  decoded_body: PcapFileEx.HTTP.Content.decoded() | nil,
  status: integer(),
  informational: [PcapFileEx.HTTP2.Headers.t()]
}

t()

@type t() :: %PcapFileEx.HTTP2.Exchange{
  client: PcapFileEx.Endpoint.t() | nil,
  end_timestamp: DateTime.t(),
  endpoint_a: PcapFileEx.Endpoint.t() | nil,
  endpoint_b: PcapFileEx.Endpoint.t() | nil,
  request: request(),
  response: response(),
  server: PcapFileEx.Endpoint.t() | nil,
  start_timestamp: DateTime.t(),
  stream_id: non_neg_integer()
}

Functions

build_request(stream)

@spec build_request(PcapFileEx.HTTP2.StreamState.t()) :: request() | nil

Build just the request portion from a stream state.

Returns nil if no request headers are present.

build_response(stream)

@spec build_response(PcapFileEx.HTTP2.StreamState.t()) :: response() | nil

Build just the response portion from a stream state.

Returns nil if no response headers are present.

client_identified?(exchange)

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

Returns true if client/server roles were identified for this exchange.

Examples

if Exchange.client_identified?(exchange) do
  IO.puts("Client: #{exchange.client}")
else
  IO.puts("Endpoints: #{exchange.endpoint_a} <-> #{exchange.endpoint_b}")
end

endpoints(exchange)

@spec endpoints(t()) :: {PcapFileEx.Endpoint.t(), PcapFileEx.Endpoint.t()}

Returns the pair of endpoints, regardless of whether client/server was identified.

When client/server identified, returns {client, server}. When not identified, returns {endpoint_a, endpoint_b}.

Examples

{client, server} = Exchange.endpoints(exchange)

from_stream(stream, tcp_flow)

@spec from_stream(
  PcapFileEx.HTTP2.StreamState.t(),
  {legacy_endpoint(), legacy_endpoint()}
) :: t() | nil

Build a complete exchange from a finished stream state.

Returns nil if the stream is not complete.

Parameters

  • stream - The completed stream state
  • tcp_flow - Tuple of {{ip_tuple, port}, {ip_tuple, port}} (legacy format)
  • opts - Options:
    • :hosts_map - Map of IP strings to hostnames
    • :client_identified - Whether client/server roles were identified (default: true)

from_stream(stream, arg, opts)

@spec from_stream(
  PcapFileEx.HTTP2.StreamState.t(),
  {legacy_endpoint(), legacy_endpoint()},
  keyword()
) ::
  t() | nil

to_string(exchange)

@spec to_string(t()) :: String.t()

Get a friendly string representation of the exchange.