PcapFileEx.Flows.AnalysisResult (pcap_file_ex v0.5.5)
View SourceResult of analyzing a PCAP file for traffic flows.
Contains protocol-specific flow lists, a unified timeline for playback, and a lookup map for O(1) flow access by key.
Fields
flows- Map ofFlowKey.t() => flow_ref()for O(1) lookupshttp1- List of HTTP/1 flows (sorted by first exchange timestamp)http2- List of HTTP/2 flows (sorted by first stream timestamp)udp- List of UDP flows (sorted by first datagram timestamp)timeline- Unified timeline of all events (sorted by timestamp, then deterministically by flow and event)stats- Aggregate statistics across all flows
Flow Lookup
Use get_flow/2 for O(1) access to flows by key:
key = FlowKey.new(:http2, client_endpoint, server_endpoint)
flow = AnalysisResult.get_flow(result, key)Or extract a key from an existing flow:
key = Flow.key(some_flow)
flow = AnalysisResult.get_flow(result, key)Timeline Access
Use get_event/2 to retrieve actual event data from a timeline event:
Enum.each(result.timeline, fn event ->
case AnalysisResult.get_event(result, event) do
%HTTP1.Exchange{} = ex -> handle_http1(ex)
%HTTP2.Stream{} = stream -> handle_http2(stream)
%UDP.Datagram{} = dg -> handle_udp(dg)
end
end)Examples
{:ok, result} = PcapFileEx.Flows.analyze("capture.pcapng")
# Access by protocol
IO.puts("HTTP/1 flows: #{length(result.http1)}")
IO.puts("HTTP/2 flows: #{length(result.http2)}")
IO.puts("UDP flows: #{length(result.udp)}")
# Query specific flows
result.http2
|> Enum.filter(fn f -> f.flow.from == "web-client" end)
# Playback in timeline order
Enum.each(result.timeline, fn event ->
data = AnalysisResult.get_event(result, event)
playback(data)
end)
Summary
Functions
Builds an AnalysisResult from protocol-specific flow lists.
Retrieves the actual event data from a TimelineEvent.
Looks up a flow by its FlowKey.
Creates a new empty AnalysisResult.
Types
@type flow_ref() :: %{protocol: :http1 | :http2 | :udp, index: non_neg_integer()}
@type t() :: %PcapFileEx.Flows.AnalysisResult{ flows: %{required(PcapFileEx.FlowKey.t()) => flow_ref()}, http1: [PcapFileEx.Flows.HTTP1.Flow.t()], http2: [PcapFileEx.Flows.HTTP2.Flow.t()], stats: PcapFileEx.Flows.Stats.t(), timeline: [PcapFileEx.Flows.TimelineEvent.t()], udp: [PcapFileEx.Flows.UDP.Flow.t()] }
Functions
@spec build([PcapFileEx.Flows.HTTP1.Flow.t()], [PcapFileEx.Flows.HTTP2.Flow.t()], [ PcapFileEx.Flows.UDP.Flow.t() ]) :: t()
Builds an AnalysisResult from protocol-specific flow lists.
Constructs the flows map, timeline, and aggregate stats.
Parameters
http1_flows- List of HTTP/1 flowshttp2_flows- List of HTTP/2 flowsudp_flows- List of UDP flows
@spec get_event(t(), PcapFileEx.Flows.TimelineEvent.t()) :: PcapFileEx.Flows.HTTP1.Exchange.t() | PcapFileEx.Flows.HTTP2.Stream.t() | PcapFileEx.Flows.UDP.Datagram.t() | nil
Retrieves the actual event data from a TimelineEvent.
Returns the event struct (Exchange, Stream, or Datagram) or nil if not found.
Parameters
result- The AnalysisResultevent- The TimelineEvent
Examples
event = Enum.at(result.timeline, 5)
case AnalysisResult.get_event(result, event) do
%HTTP1.Exchange{} = ex ->
IO.puts("#{ex.request.method} #{ex.request.path}")
%HTTP2.Stream{exchange: ex} ->
IO.puts("#{ex.request.method} #{ex.request.path}")
%UDP.Datagram{} = dg ->
IO.puts("UDP: #{dg.size} bytes")
end
@spec get_flow(t(), PcapFileEx.FlowKey.t()) :: PcapFileEx.Flows.HTTP1.Flow.t() | PcapFileEx.Flows.HTTP2.Flow.t() | PcapFileEx.Flows.UDP.Flow.t() | nil
Looks up a flow by its FlowKey.
Returns the flow struct or nil if not found.
Parameters
result- The AnalysisResultkey- The FlowKey to look up
Examples
key = FlowKey.new(:http2, client_endpoint, server_endpoint)
case AnalysisResult.get_flow(result, key) do
%HTTP2.Flow{} = flow -> handle_flow(flow)
nil -> :not_found
end
@spec new() :: t()
Creates a new empty AnalysisResult.