PcapFileEx.DecoderRegistry (pcap_file_ex v0.5.5)

View Source

Registry of application-layer payload decoders.

New API (v0.5.0+)

Matchers can now return context to decoders for clean data flow:

DecoderRegistry.register(%{
  protocol: :my_protocol,
  matcher: fn layers, payload ->
    if my_protocol?(layers) do
      {:match, extract_context(layers)}  # Return context
    else
      false
    end
  end,
  decoder: fn context, payload ->  # Receive context
    decode(payload, context)
  end,
  fields: [...]
})

Benefits:

  • ✅ No Process.put workarounds (thread-safe, no race conditions)
  • ✅ More efficient (decode once in matcher, use cached result in decoder)
  • ✅ Pure data flow (easier to test)

Legacy API (deprecated, will be removed in v1.0.0)

The old API is still supported for backward compatibility:

DecoderRegistry.register(%{
  protocol: :my_protocol,
  matcher: fn layers, payload -> my_protocol?(layers) end,  # Returns boolean
  decoder: fn payload -> decode(payload) end,  # Arity-1
  fields: [...]
})

Note: Deprecation warnings will be emitted when using the old API.

Decoder Entry Format

Each decoder entry supplies:

  • :protocol — atom identifying the protocol (e.g., :http)
  • :matcher — function returning false | {:match, context} when the decoder applies

  • :decoder — function accepting (context, payload) and returning structured data
  • :fields — optional list of field descriptors for extraction

Matchers receive the list of protocol layers returned by :pkt.decode/2 and the raw payload binary from the previous layer. Decoders receive the context from the matcher (or nil for old API) and the payload. Decoders should return {:ok, value} on success; any other return is wrapped in {:ok, value} automatically.

Summary

Functions

Lists the registered decoder entries in registration order.

Registers a new decoder entry.

Unregisters a decoder by protocol atom. No-op if not present.

Types

decoder_fun()

@type decoder_fun() :: (term(), binary() -> {:ok, term()} | {:error, term()} | term())

entry()

@type entry() :: %{
  protocol: atom(),
  matcher: matcher_fun(),
  decoder: decoder_fun(),
  fields: [field_descriptor()]
}

field_descriptor()

@type field_descriptor() :: %{
  id: String.t(),
  type: :string | :integer | :list_integer,
  extractor: (term() -> term())
}

match_result()

@type match_result() :: false | {:match, context :: term()}

matcher_fun()

@type matcher_fun() :: (list(), binary() -> match_result())

Functions

list()

@spec list() :: [entry()]

Lists the registered decoder entries in registration order.

register(entry)

@spec register(entry()) :: :ok

Registers a new decoder entry.

If a decoder for entry.protocol already exists it is replaced.

Supports both new API (arity-2 decoder) and legacy API (arity-1 decoder).

unregister(protocol)

@spec unregister(atom()) :: :ok

Unregisters a decoder by protocol atom. No-op if not present.