Changelog
View Source[0.5.5] - 2026-01-06
Added
Custom Decoders for Flows API - Register custom decoders for protocol-specific payloads
- New
:decodersoption onPcapFileEx.Flows.analyze/2 - Decode UDP datagrams based on destination port
- Decode HTTP/1 and HTTP/2 bodies based on content-type
- Decode multipart parts based on content-type or content-id
- New modules:
PcapFileEx.Flows.Decoder- Behaviour and types for custom decodersPcapFileEx.Flows.DecoderMatcher- Matcher evaluation and decoder invocation
- Decoder types:
- Arity-1 functions:
(binary() -> term())for simple decoders - Arity-2 functions:
(match_context(), binary() -> decode_result())for context-aware decoders - Modules implementing
Decoderbehaviour withdecode/2callback
- Arity-1 functions:
- Match criteria: protocol, scope, port, content_type, content_id, method, path
- Result wrapping:
{:custom, term}for success,{:decode_error, reason}for failure - "Binary only" focus: Custom decoders do not override built-in JSON/text decoding
- Full context passed to decoders: protocol, direction, scope, headers, method, path, status
- New
Binary Preservation - New
keep_binary: trueoption for playback scenarios- Preserves original binary in
payload_binary(UDP) orbody_binary(multipart parts) - Only when custom decoder was invoked (success or error), not for
:skipor built-in decoders - Warning: Doubles memory for decoded content
- Preserves original binary in
Traffic Flows API - Unified API to analyze traffic flows by protocol
- New
PcapFileEx.Flowsmodule withanalyze/2function - Identifies and groups traffic by protocol: HTTP/1, HTTP/2, UDP
- Returns hierarchical
AnalysisResultwith protocol-specific flow containers - Unified timeline for playback with nanosecond-precision ordering
- O(1) flow lookups via
FlowKeystruct - Playback timing metadata:
response_delay_msfor HTTP,relative_offset_msfor UDP - New modules:
PcapFileEx.FlowKey- Stable identity for flow map lookupsPcapFileEx.Flow- Base flow identity with display and authoritative fieldsPcapFileEx.Flows.AnalysisResult- Result container with flows map, protocol lists, timelinePcapFileEx.Flows.TimelineEvent- Unified timeline event for playbackPcapFileEx.Flows.Stats- Flow statistics (packet/byte counts, timestamps, duration)PcapFileEx.Flows.ProtocolDetector- Protocol detection via content inspectionPcapFileEx.Flows.TCPExtractor- Shared TCP extraction logic (refactored from HTTP2)PcapFileEx.Flows.HTTP1.Analyzer- HTTP/1.x request/response reconstructionPcapFileEx.Flows.HTTP1.Exchange- HTTP/1 exchange with playback timingPcapFileEx.Flows.HTTP1.Flow- HTTP/1 flow containerPcapFileEx.Flows.HTTP2.Flow- HTTP/2 flow wrapper (streams + incomplete)PcapFileEx.Flows.HTTP2.Stream- HTTP/2 stream with seq_num and timingPcapFileEx.Flows.HTTP2.Adapter- Converts HTTP2.Exchange to Flows formatPcapFileEx.Flows.UDP.Collector- UDP datagram collectionPcapFileEx.Flows.UDP.Flow- UDP flow (grouped by server,from: :any)PcapFileEx.Flows.UDP.Datagram- UDP datagram with playback timing
- Protocol detection via content inspection:
- HTTP/2: Connection preface
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" - HTTP/1: Request methods (
GET,POST, etc.) orHTTP/response
- HTTP/2: Connection preface
- Full hosts_map support for endpoint resolution
- New
Hosts Mapping Feature - Map IP addresses to human-readable hostnames
- New
:hosts_mapoption on all entry points:stream/2,read_all/2,HTTP2.analyze/2, etc. PcapFileEx.Endpointenhancements:- New
hostfield for optional hostname new/3- Create endpoint with IP, port, and hostnamewith_hosts/2- Apply hosts mapping to existing endpointfrom_tuple/1,from_tuple/2- Create endpoint from IP tuple (used by HTTP/2 analyzer)- Updated
to_string/1- Prefers hostname over IP when displaying String.Charsprotocol implementation for string interpolation
- New
- Hosts map format:
%{String.t() => String.t()}(IP strings to hostname strings) - Uses
:inet.ntoa/1everywhere for consistent IP string formatting
- New
Breaking
UDP Datagram structure changed (for consistency with multipart parts)
decoded_payloadfield REMOVEDpayloadfield type changed frombinary()todecoded() | binary()wheredecoded() = {:custom, term()} | {:decode_error, term()}New
payload_binaryfield:binary() | nil(only set whenkeep_binary: trueAND decoder matched/errored):skipreturns are semantically equivalent to "no decoder" (raw payload, nopayload_binary)- Migration:
# Before case datagram.decoded_payload do {:custom, data} -> handle_decoded(data) nil -> handle_raw(datagram.payload) end # After (comprehensive pattern matching) case datagram.payload do {:custom, data} -> handle_decoded(data) # For playback: datagram.payload_binary (if keep_binary: true) {:decode_error, reason} -> Logger.warning("Decode failed: #{inspect(reason)}") # Recovery: datagram.payload_binary (if keep_binary: true) raw when is_binary(raw) -> handle_raw(raw) # Note: payload_binary is nil in this case end
HTTP/2 Exchange and IncompleteExchange struct changes
- Removed
tcp_flowfield (was{endpoint(), endpoint()}tuple) - Added four new endpoint fields:
client: Endpoint.t() | nil- Client endpoint (when identified via HTTP/2 preface)server: Endpoint.t() | nil- Server endpoint (when identified)endpoint_a: Endpoint.t() | nil- First endpoint (when client/server unknown)endpoint_b: Endpoint.t() | nil- Second endpoint (when client/server unknown)
- New helper functions:
endpoints/1,client_identified?/1 - Migration:
# Before {{{src_ip}, src_port}, {{dst_ip}, dst_port}} = exchange.tcp_flow # After (when client/server identified) %Endpoint{ip: client_ip, port: client_port} = exchange.client %Endpoint{ip: server_ip, port: server_port} = exchange.server # After (when unknown, use helper) {endpoint1, endpoint2} = Exchange.endpoints(exchange)
- Removed
[0.5.4] - 2025-12-23
Fixed
- HTTP/2 GOAWAY incorrectly marking complete exchanges as incomplete - Fixed a bug where streams that had fully completed (both request and response with END_STREAM flags) were incorrectly marked as
IncompleteExchangeif a GOAWAY frame was received afterward. Theprocess_goaway/2function now checks if a stream is already complete before terminating it. Per RFC 7540, GOAWAY indicates streams that won't be processed, but streams already complete should remain complete - the GOAWAY is informational about why the connection closed, not a retroactive failure of completed exchanges.
[0.5.3] - 2025-12-16
Fixed
- CRITICAL: HTTP/2 analysis with pkt-decoded packets - Fixed incorrect IP address extraction from
pktlibrary's IPv4/IPv6 record tuples. The code was readingelem(ip_header, 1)andelem(ip_header, 2)which returned IHL (4) and DSCP (5) header fields instead of actual IP addresses. This caused bidirectional TCP traffic to be split into two separate flows, resulting in all HTTP/2 exchanges being marked as incomplete (requests and responses tracked separately). Fixed to use correct tuple positions:elem(ip_header, 12)andelem(ip_header, 13)for IPv4,elem(ip_header, 6)andelem(ip_header, 7)for IPv6.
[0.5.2] - 2025-12-15
Added
- Automatic Content-Type based body decoding for HTTP/2 exchanges
- New
PcapFileEx.HTTP.Contentmodule for generic content decoding - Supports JSON, text (UTF-8/ISO-8859-1), multipart/*, binary fallback
- Request and response bodies automatically decoded based on Content-Type header
- New
decoded_bodyfield in HTTP/2 Exchange request/response structs - New
:decode_contentoption forHTTP2.analyze/2andanalyze_segments/2(default: true) - Multipart/related support with recursive part decoding
- Comprehensive test suite: 42 unit tests + 21 property tests
- New
- HTTP/2 Cleartext (h2c) Analysis - Reconstruct HTTP/2 request/response exchanges from PCAP files
- New
PcapFileEx.HTTP2module with public APIHTTP2.analyze/2- Analyze PCAP file for HTTP/2 exchanges (options::port,:decode_content)HTTP2.analyze_segments/2- Analyze pre-parsed TCP segments (options::decode_content)HTTP2.http2?/1- Detect HTTP/2 connection prefaceHTTP2.connection_preface/0- Get preface string
- New submodules for HTTP/2 protocol handling:
HTTP2.Frame- Frame parsing with padding and priority handlingHTTP2.FrameBuffer- Cross-packet frame reassemblyHTTP2.Headers- Pseudo/regular header separation with trailer supportHTTP2.StreamState- Per-stream state with CONTINUATION handlingHTTP2.Connection- Dual HPACK tables per direction with SETTINGSHTTP2.Analyzer- Main stream reconstruction algorithmHTTP2.Exchange- Complete request/response pair structHTTP2.IncompleteExchange- Partial exchange with reason tracking
- Returns complete and incomplete exchanges separately
- Supports mid-connection captures (with HPACK limitations)
- HPACK header decompression via
hpaxlibrary - TCP sequence number ordering and retransmission detection
- Handles RST_STREAM, GOAWAY, and truncated streams
- Limitations: Cleartext only (no TLS), prior-knowledge h2c only (no HTTP/1.1 Upgrade)
- Comprehensive test suite:
- Unit tests for Frame, FrameBuffer, Headers modules
- Property-based tests (22 properties) for frame parsing and headers
- Integration tests (16 tests) including real PCAP file analysis
- New dependency:
{:hpax, "~> 1.0"}for HPACK decompression - Documentation:
usage-rules/http2.mdguide with patterns and best practices
- New
Breaking
- Dropped Intel Mac (
x86_64-apple-darwin) precompiled binaries - Apple Silicon (aarch64-apple-darwin) remains supported. Intel Mac users can compile from source withPCAP_FILE_EX_BUILD=1or stay on v0.5.1.
Changed
- Updated dependencies:
- bandit 1.8.0 → 1.9.0
- ex_doc 0.39.1 → 0.39.3
- rustler_precompiled 0.8.3 → 0.8.4
- plug 1.18.1 → 1.19.1 (transitive)
- thousand_island 1.4.2 → 1.4.3 (transitive)
- castore 1.0.16 → 1.0.17 (transitive)
[0.5.1] - 2025-12-01
- dependencies updates
[0.5.0] - 2025-11-19
⚠️ BREAKING CHANGES - Decoder Registry API Enhanced with Context Passing
Added
- Context passing in decoder registry - Matchers can now return context to decoders
- New API: Matchers return
{:match, context}instead oftrue - New API: Decoders accept
(context, payload)instead of just(payload) - Eliminates need for
Process.putworkarounds (thread-safe, no race conditions) - More efficient: decode once in matcher, use cached result in decoder
- Pure data flow makes testing easier
- Backward compatible via runtime detection (old API still works with deprecation warnings)
- New API: Matchers return
Changed
- Decoder registration now accepts both old (arity-1) and new (arity-2) decoders
- HTTP decoder optimized to decode once instead of twice (no visible API change)
- Decodes payload in matcher, caches result as context
- Decoder uses cached result instead of re-decoding
- Performance improvement: 50% reduction in HTTP decode time for matched packets
Deprecated
- Legacy decoder API (arity-1 decoders) will be removed in v1.0.0
- Runtime deprecation warnings emitted when registering old-style decoders
- Migration guide: See "Migration Guide" section below
Migration Guide
Old API (still works with warnings):
DecoderRegistry.register(%{
matcher: fn layers, payload -> my_protocol?(layers) end, # Returns boolean
decoder: fn payload -> decode(payload) end, # Arity-1
})New API (recommended):
DecoderRegistry.register(%{
matcher: fn layers, payload ->
if my_protocol?(layers) do
{:match, extract_context(layers)} # Return context
else
false
end
end,
decoder: fn context, payload -> decode(payload, context) end, # Arity-2
})Benefits
- ✅ Thread-safe - No
Process.putor shared state - ✅ No race conditions - Explicit context passing
- ✅ More efficient - Decode once, not twice
- ✅ Easier to test - Pure functions with explicit dependencies
- ✅ Clearer intent - Context requirements are explicit in type signatures
Implementation Details
Updated modules:
lib/pcap_file_ex/decoder_registry.ex- New type definitions, backward compatibility wrapperslib/pcap_file_ex/packet.ex- Updated invocation logic to pass context through
Testing: (372 tests → 393 tests, +21 tests)
- New unit tests for context passing, backward compatibility, error handling
- New integration tests with real PCAP files
- New property-based tests for invariants
- All existing tests continue to pass
Documentation:
- Updated module documentation with new API examples
- Added deprecation warnings for old API usage
- CHANGELOG entry with migration guide
Technical Notes
- Based on spec
specs/20251119-decoder-registry-context-passing.md - Backward compatibility achieved via runtime arity detection and wrapper functions
- Deprecation timeline: v0.5.0 (warning) → v1.0.0 (removal)
[0.4.0] - 2025-11-09
MAJOR FEATURE - PCAP/PCAPNG Writer API (MVP)
Added
Writer API - Create PCAP and PCAPNG files from packets
- New
PcapFileEx.PcapWritermodule for PCAP file creationPcapWriter.open/2- Create new PCAP files with headerPcapWriter.write_packet/2- Write individual packetsPcapWriter.write_all/3- Convenience batch writerPcapWriter.close/1- Explicit close with flush
- New
PcapFileEx.PcapNgWritermodule for PCAPNG file creationPcapNgWriter.open/1- Create new PCAPNG filesPcapNgWriter.write_interface/2- Register interfacesPcapNgWriter.write_packet/2- Write packets with interface trackingPcapNgWriter.write_all/4- Batch write with auto-interface registrationPcapNgWriter.close/1- Explicit close with flush
- 64KB buffered writes for optimal throughput
- Full nanosecond timestamp precision preservation
- Thread-safe Rust NIF implementation with Mutex-protected resources
- New
High-Level Convenience API
PcapFileEx.write/4- Format auto-detection from file extensionPcapFileEx.write!/4- Bang variant that raises on errorsPcapFileEx.copy/3- Copy/convert PCAP files with format conversionPcapFileEx.export_filtered/4- Filter and export packets to new file:on_erroroption (:haltor:skip) for handling corrupt packets during copy/export- Automatic PCAP ↔ PCAPNG format conversion with interface preservation
Timestamp Utilities
- New
PcapFileEx.TimestampShiftmodule for timestamp manipulation TimestampShift.shift_all/2- Shift timestamps by nanosecond offsetTimestampShift.normalize_to_epoch/1- Normalize first packet to Unix epoch- Useful for anonymization and reproducible test files
- New
Data Structure Enhancements
Header.to_map/1- Convert header to NIF-compatible mapPacket.to_map/1- Convert packet to NIF-compatible mapInterface.to_map/1- Convert interface to NIF-compatible map- Bidirectional type conversions (Elixir ↔ Rust)
Limitations (MVP)
- Append mode not supported
- PCAP append: Not supported by upstream pcap-file crate (clear error returned)
- PCAPNG append: Not implemented in MVP (requires block scanning/truncation)
- Both formats return clear error messages explaining limitations
- Create new files or use format conversion as workaround
- Future versions will add PCAPNG append support
Implementation Details
Rust NIFs (native/pcap_file_ex/src/)
pcap_writer.rs- PCAP writer with 4 NIFs (open, write, close, append stub)pcapng_writer.rs- PCAPNG writer with 5 NIFs (open, write_interface, write, close, append stub)types.rs- Reverse type conversions (Elixir → Rust) for all data structures- Rustler Resources for thread-safe writer state management
- Interface tracking in Rust NIF layer for PCAPNG validation
Testing
- New
test/pcap_file_ex/writer_smoke_test.exswith 6 tests - Tests cover: PCAP write, PCAPNG write, copy, filter/export, append limitations
- All tests pass with round-trip validation (write → read → verify)
- New
Changed
- Module aliases in
PcapFileExto avoid naming conflicts withElixir.Stream - Updated
Nativemodule with 9 new NIF stubs for writer functions
Technical Notes
- Based on spec
specs/20251109-pcap-writer-api.md(v1.3) - Streaming architecture: O(1) memory for files of any size
Error propagation: Consistent
{:ok, result} | {:error, reason}pattern- Format detection: Auto-detect from file extension (.pcap vs .pcapng)
- Interface metadata: Derived from source headers during PCAP→PCAPNG conversion
[0.3.0] - 2025-11-09
MAJOR FEATURE - Multi-File PCAP Timeline Merge
Added
Multi-File Merge API - Chronologically merge multiple PCAP/PCAPNG files
- New
PcapFileEx.Mergemodule with comprehensive merge capabilities Merge.stream/2- Creates lazy chronologically-sorted packet stream from multiple filesMerge.stream!/2- Bang variant that raises on errorsMerge.count/1- Fast total packet count across multiple filesMerge.validate_clocks/1- Clock synchronization validation with drift detection- Supports mixed PCAP and PCAPNG files in single merge operation
- Memory-efficient: O(N files) memory usage via min-heap algorithm
- Performance: O(M log N) time complexity (M packets, N files)
- Comprehensive test coverage: 352 tests (including 8 new property tests)
- New
Nanosecond-Precision Chronological Ordering
- Uses
Timestamp.compare/2for accurate chronological merging - Preserves microsecond and nanosecond precision from source files
- Deterministic ordering for packets with identical timestamps
- Stable sort using file index and packet index as tiebreakers
- Uses
PCAPNG Interface ID Remapping (Critical for Multi-File PCAPNG Merges)
- Automatic global interface ID assignment prevents collisions
- Maintains invariant:
packet.interface_id == packet.interface.id - New
PcapFileEx.Merge.InterfaceMappermodule handles remapping logic - Clones
Interfacestruct to update nestedidfield correctly - Per-file interface scanning and global ID allocation
Source Annotation (
:annotate_sourceoption)- Track packet origins with rich metadata
- Metadata includes:
:source_file,:file_index,:packet_index - PCAPNG-specific metadata:
:original_interface_id,:remapped_interface_id - Enables packet provenance tracking and debugging
- Stream format:
{packet, metadata}tuples when enabled
Flexible Error Handling (
:on_erroroption):halt- Stop streaming on first error (default, safe behavior):skip- Skip corrupt packets, emit{:skipped_packet, meta}markers:collect- Wrap all items in result tuples:{:ok, packet}or{:error, meta}- Works seamlessly with annotation (nested tuples:
{:ok, {packet, meta}}) - Error metadata includes:
:reason,:source_file,:packet_index
Clock Validation and Drift Detection
validate_clocks/1checks timestamp alignment across files- Returns
:okwith stats or{:error, :excessive_drift, stats} - Drift threshold: 10 seconds (configurable)
- Per-file statistics: min/max timestamps, packet counts
- Helps identify unsynchronized capture clocks
Priority Queue Implementation
- New
PcapFileEx.Merge.Heapmodule for min-heap operations - Optimized for streaming merge with O(log N) push/pop
- Efficient chronological packet ordering
- Custom comparison using
Timestamp.compare/2
- New
Comprehensive Property-Based Tests
- 8 new property tests in
test/property_test/merge_property_test.exs - Properties tested:
- Chronological ordering invariant
- Total packet count preservation
- Source annotation completeness
- Deterministic ordering for identical timestamps
- Error mode behavior (
:collect,:skip,:halt) - PCAPNG interface ID invariant
- Interface ID annotation completeness
- Environment-aware: 100 iterations locally, 1000 in CI
- 8 new property tests in
Changed
Code Review Remediation - Two rounds of thorough review and fixes
- Round 1 (5 findings): Fixed 2 CRITICAL, 2 HIGH, 1 MEDIUM priority issues
- Fixed premature resource cleanup (CRITICAL)
- Added explicit file validation (CRITICAL)
- Fixed NIF error propagation (HIGH)
- Added comprehensive error metadata (HIGH)
- Enhanced property test coverage (MEDIUM)
- Round 2 (2 findings): Fixed remaining invariant and metadata issues
- Fixed PCAPNG interface invariant breach (CRITICAL)
- Added
remapped_interface_idto metadata (HIGH) - Added regression tests for both issues
- Round 1 (5 findings): Fixed 2 CRITICAL, 2 HIGH, 1 MEDIUM priority issues
Test Suite Enhancements
- Removed unused
@sample2_pcapngmodule attribute - Added "PCAPNG interface remapping maintains invariant" property test
- Added "PCAPNG annotation includes both interface IDs" property test
- Updated existing annotation test to assert both interface ID fields
- Removed unused
Fixed
Interface ID Remapping (CRITICAL, Code Review Round 2)
InterfaceMapper.remap_packet/3now updates both fields:- Updates
packet.interface_id(top-level field) - Clones and updates
packet.interface.id(nested struct field)
- Updates
- Maintains invariant:
packet.interface_id == packet.interface.id - Prevents packets from carrying original interface IDs in merged streams
Metadata Completeness (HIGH, Code Review Round 2)
- Annotation now includes both
:original_interface_idand:remapped_interface_id - API contract fully met for PCAPNG multi-file merges
- Users can track both original source interface and global merged interface
- Annotation now includes both
Documentation
- Complete feature specification:
specs/20251109-multi-file-pcap-timeline-merge.md(v1.4)- 85+ pages covering design, implementation, and code review
- Includes two rounds of code review findings and fixes
- Comprehensive examples and edge case documentation
- See README.md for usage examples and integration guide
- See
usage-rules/merging.mdfor detailed merge patterns and best practices
[0.2.1] - 2025-11-09
- improve CI pipeline - add dialyzer, credo, package audit
- optimize rust NIFs build process
[0.2.0] - 2025-11-09
⚠️ BREAKING CHANGES - Stream API now follows Elixir conventions
Added
- Safe Stream API - New tuple-returning functions following Elixir conventions
PcapFileEx.stream/1andstream/2now return{:ok, stream} | {:error, reason}instead of raisingPcapFileEx.Stream.packets/1now returns{:ok, stream} | {:error, reason}PcapFileEx.Stream.from_reader/1now returns{:ok, stream}for consistency- Added bang variants for convenience (old behavior):
stream!/1,stream!/2- raises on errorPcapFileEx.Stream.packets!/1- raises on errorPcapFileEx.Stream.from_reader!/1- raises on error
- Comprehensive migration guide in module documentation
- Unified Format Detection - New
PcapFileEx.Formatmodule- Single source of truth for PCAP/PCAPNG format detection
- Eliminates 70+ lines of duplicate code between
PcapFileExandPcapFileEx.Validator Format.detect/1function for file format detection
- CI Version Synchronization - Prevents version drift
- New CI job verifies
mix.exsandCargo.tomlversions match - Rejects
-devsuffix on release tags to prevent accidental dev releases - Ensures Elixir and Rust packages stay synchronized
- New CI job verifies
- CONTRIBUTING.md - Contributor onboarding guide
- Development setup instructions (Elixir, Rust, Git)
- Tidewave MCP integration guide for development
- Rust development workflow (linting, formatting, testing)
- Testing guidelines (example-based and property-based)
- Code quality standards and PR guidelines
- Tidewave MCP Integration for enhanced development experience
- Live code evaluation in project context via
mcp__tidewave__project_eval - Module/function documentation access via
mcp__tidewave__get_docs - Source location lookup via
mcp__tidewave__get_source_location - Application log inspection via
mcp__tidewave__get_logs - Dependency documentation search via
mcp__tidewave__search_package_docs - Configured in
.mcp.jsonfor seamless integration with AI coding assistants - Particularly useful with Claude Code for live introspection and testing
- Includes two Mix aliases for starting the MCP server:
mix tidewave- Background server (no IEx shell)iex -S mix tidewave-iex- Interactive IEx shell with MCP server
- Live code evaluation in project context via
- Nanosecond Timestamp Precision Support (v0.2.0)
- New
PcapFileEx.Timestampmodule for nanosecond-precision timestamps - All packets now include both
timestamp(DateTime, microsecond precision) andtimestamp_precise(Timestamp, nanosecond precision) - Zero breaking changes - existing code using
packet.timestampcontinues to work - Full API for timestamp operations:
new/2,to_unix_nanos/1,to_datetime/1,from_datetime/2,compare/2,diff/2 - Implements String.Chars and Inspect protocols for pretty printing
- Ideal for merging packets from multiple files chronologically with nanosecond accuracy
- Comprehensive test suite with 80+ test cases
- New
- Property-Based Testing with StreamData
- 94 new property tests covering timestamps, packets, filters, streams, and decoding
- Comprehensive generators for all core data types (timestamps, packets, filters, etc.)
- Environment-aware configuration: 100 test runs locally, 1000 in CI
- Tests edge cases automatically: boundary timestamps, truncated packets, filter compositions
- Validates invariants: timestamp ordering, packet consistency, filter count properties
- Zero performance impact: tests run in ~0.9 seconds (total suite: ~1.2s)
- In-memory testing for fast, deterministic results
- See
test/property_test/for 5 test files andtest/support/generators.exfor reusable generators
Changed
BREAKING:
PcapFileEx.stream/1andstream/2signature changed from returningEnumerable.t()to{:ok, Enumerable.t()} | {:error, String.t()}BREAKING:
PcapFileEx.Stream.packets/1now returns{:ok, stream} | {:error, reason}- BREAKING:
PcapFileEx.Stream.from_reader/1now returns{:ok, stream}instead of bare stream - Error Handling:
Pcap.read_all/1andPcapNg.read_all/1now return{:error, reason}on packet parsing errors instead of silently dropping errors- Prevents corrupted files or decoder regressions from appearing as "short captures"
- Properly closes file handles even on error
- CI Improvements:
- Fixed formatter condition to use
startsWith(matrix.elixir_version, '1.19')- formatter now actually runs! - Removed duplicate
rust-ci.ymlworkflow (Rust linting consolidated in main CI)
- Fixed formatter condition to use
- Documentation Updates:
- All README.md examples updated to v0.2.0 API (shows both safe and bang patterns)
- All usage-rules documentation updated (~90 code blocks across 6 files)
- Comprehensive migration guide in stream module documentation
- Roadmap Reorganized in README.md:
- Split into "Completed Features" and "Planned Features" sections
- Added 5 new planned features from CODEX review
- Improved documentation
- Updated
PcapFileEx.Packetstruct to includetimestamp_precisefield - Modified timestamp conversion to preserve nanosecond precision when possible
- Added
test/supportto elixirc_paths for test environment (supports property test generators) - Version bumped to 0.2.0 in both
mix.exsandnative/pcap_file_ex/Cargo.toml
Fixed
- Format Detection: Eliminated duplicate magic number detection logic
- Previously duplicated between
PcapFileExandPcapFileEx.Validator - Now uses single
PcapFileEx.Format.detect/1function
- Previously duplicated between
- CI Formatter: Formatter check was never running due to incorrect version match (
'1.19'vs'1.19.1') - Error Propagation: Packet parsing errors in
read_all/1are now properly surfaced instead of being silently dropped - Stats Module: Updated to use
stream!/1to maintain backward compatibility in internal calls
Removed
- Duplicate
.github/workflows/rust-ci.yml- Rust linting now handled exclusively in main CI workflow
[0.1.5] - 2025-11-08
Added
- Expanded platform support with CPU variants (inspired by elixir-explorer/explorer)
- Added FreeBSD support (
x86_64-unknown-freebsd) - Implemented CPU capability detection for automatic legacy artifact selection
- Added variant system for x86_64 platforms (Linux, Windows, FreeBSD)
- Now shipping 11 precompiled NIF artifacts (up from 6):
aarch64-apple-darwin(macOS ARM)aarch64-unknown-linux-gnu(Linux ARM)x86_64-apple-darwin(macOS Intel)x86_64-unknown-linux-gnu(Linux Intel/AMD)x86_64-unknown-linux-gnu--legacy_cpu(Linux Intel/AMD, legacy CPUs)x86_64-pc-windows-msvc(Windows MSVC)x86_64-pc-windows-msvc--legacy_cpu(Windows MSVC, legacy CPUs)x86_64-pc-windows-gnu(Windows GCC)x86_64-pc-windows-gnu--legacy_cpu(Windows GCC, legacy CPUs)x86_64-unknown-freebsd(FreeBSD)x86_64-unknown-freebsd--legacy_cpu(FreeBSD, legacy CPUs)
- Added FreeBSD support (
- Automatic CPU detection - Linux x86_64 systems automatically select the appropriate binary variant based on CPU capabilities (AVX, FMA, SSE4.2, etc.)
- Manual legacy override - Set
PCAP_FILE_EX_USE_LEGACY_ARTIFACTS=1to force legacy CPU variants on any platform - Compile-time CPU capability detection for automatic binary selection
Changed
- Updated NIF configuration to match elixir-explorer/explorer best practices
- Reorganized target list alphabetically for better maintainability
- Enhanced checksum file to include all platform variants
Fixed
- Legacy CPU support for systems without AVX/FMA instruction sets
- Checksum generation now covers all 11 artifacts instead of only 6
[0.1.4] - 2025-11-08
- Improve CI/CD pipeline
[0.1.3] - 2025-11-08
Fixed
- CRITICAL: Include checksum files in Hex package to enable precompiled NIF downloads
- Added
checksum-*.exsto package files list in mix.exs - Users can now install from Hex without requiring Rust compiler
- Previously, checksums were only on GitHub releases but not in Hex package
- This caused
RuntimeError: the precompiled NIF file does not exist in the checksum file - Follows elixir-explorer/explorer best practices for rustler_precompiled
- Added
[0.1.2] - 2025-11-08
Added
- LLM-friendly usage rules: Comprehensive documentation for AI coding assistants
- Main
usage-rules.mdwith decision trees and common patterns - Detailed sub-guides:
usage-rules/performance.md,filtering.md,http.md,formats.md,examples.md - Guidance on format auto-detection, resource management, and filtering strategies
- Performance optimization recommendations (PreFilter for 10-100x speedup)
- Common mistakes section with wrong vs correct patterns
- Complete working examples for real-world scenarios
- Main
- Usage rules integrated with HEX package for distribution to dependencies
- README section on AI-assisted development with integration instructions
Changed
- Package files list now includes
usage-rules.mdandusage-rules/directory for HEX distribution - Added "Usage Rules" link to package metadata
- Updated version requirements to Elixir 1.19.2 and Erlang/OTP 28.1.1
- Updated Rust toolchain to 1.91.0 in GitHub Actions
Fixed
- Major GitHub Actions workflow improvements (based on elixir-explorer/explorer best practices)
- CRITICAL: Switched from manual cargo builds to
rustler-precompiled-action@v1.1.4- Fixes artifact naming to match RustlerPrecompiled expectations:
pcap_file_ex-nif-2.15-{target}.tar.gz - Previously used incompatible naming:
libpcap_file_ex-{target}.so(raw files) - Ensures precompiled binary downloads work correctly
- Fixes artifact naming to match RustlerPrecompiled expectations:
- Compatibility: Changed Linux builds from Ubuntu 24.04 to 22.04
- Better glibc compatibility (2.35 vs 2.39)
- Precompiled binaries work on more Linux distributions
- Performance: Added Rust caching with
Swatinem/rust-cache@v2- Expected 5-10x faster builds on subsequent runs
- Target-specific cache keys for optimal reuse
- Security: Added build attestation with
actions/attest-build-provenance@v1- Cryptographic proof of build provenance
- Enhanced supply chain security
- Configuration: Added explicit NIF version ("2.15") in Native module
- Required for OTP 28 compatibility
- Enables RustlerPrecompiled to match artifacts to OTP versions
- Permissions: Added workflow permissions (contents, id-token, attestations)
- Updated runner images:
- Linux:
ubuntu-22.04(was ubuntu-24.04, ImageOS: ubuntu22) - Windows:
windows-2022(was windows-2019, ImageOS: win22) - macOS:
macos-13(Intel x86_64) andmacos-14(ARM aarch64)
- Linux:
- Upgraded actions to v4 (
checkout@v4,upload-artifact@v4,download-artifact@v4) - Updated Elixir to 1.19.2 and OTP to 28.1.1 in all jobs
- Pinned Rust version to 1.91.0 for reproducible builds
- CRITICAL: Switched from manual cargo builds to
[0.1.1] - 2025-11-08
Added
- HEX package publication support: Added comprehensive metadata for publishing to hex.pm
- MIT License file
- Package metadata (description, maintainers, links, files list)
- ExDoc configuration with README and CHANGELOG
- Rustler precompiled support with GitHub Actions workflow for cross-platform NIF builds
- Mix clean task that removes Rust build artifacts, priv/ directory, and generated test fixtures
- Comprehensive timestamp precision tests (
test/pcap_file_ex/timestamp_precision_test.exs) covering microsecond and nanosecond PCAP formats, PCAPNG compatibility, and cross-platform support (15 test cases).
Fixed
- PCAP nanosecond precision support: Fixed Linux PCAP file parsing failure. The Elixir validator was only checking for microsecond-precision magic numbers (0xD4C3B2A1, 0xA1B2C3D4) and rejecting nanosecond-precision files (0x4D3CB2A1, 0xA1B23C4D) before they reached the Rust NIF. Added support for all four PCAP magic number variants in both
PcapFileEx.ValidatorandPcapFileExmodules. The underlying pcap-file Rust crate already supported all formats. - Cross-platform compatibility: Linux dumpcap defaults to nanosecond precision while macOS uses microsecond precision. Both formats are now fully supported with automatic detection and no timestamp conversion.
Changed
- Updated .gitignore to exclude build artifacts (native/target/, priv/), generated test fixtures, and AI configuration files
- Synced version numbers across mix.exs and Cargo.toml
- Updated GitHub repository URLs from placeholder to actual repository
[69e8fdc] - 2025-11-03
Added
- Wireshark-style display filter engine (
PcapFileEx.DisplayFilter) with inlinefilter/2, reusablecompile/1+run/2, and parser support for boolean/relational operators. - Dynamic field integration with the decoder registry so decoded payloads expose filterable fields automatically.
%PcapFileEx.Endpoint{}usage throughout docs and helpers demonstrating endpoint pattern matching.- Display filter tests covering HTTP and transport-layer queries, plus documentation recipes.
Changed
- Packets now carry cached decoded payloads, layers, and endpoint structs while display filters reuse cached data.
- Decoder registry default HTTP decoder publishes request/response field descriptors.
[5a036d5] - 2025-11-03
Added
%PcapFileEx.Endpoint{ip, port}struct andPacket.endpoint_to_string/1helper to simplify matching/filtering on endpoints.- Updated tests and docs to reflect structured endpoints.
Changed
- Packet construction caches decoded layers/payload for reuse (
decode_registered/1,attach_decoded/1). - API usage streamlined with attach/decode helpers.
[7e47baa] - 2025-11-03
Added
- Decoder caching helpers (
decode_registered!/1,attach_decoded/1) and endpoint metadata improvements.
Changed
- Optimized packet metadata extraction and decoder integration; cleaned up docs to show updated API usage.
[2ec8193] - 2025-11-02
Added
- Decoder registry with default HTTP decoder, enabling protocol-aware payload decoding and caching.
- Documentation describing decoder registration workflow and storing decoded payloads on packets.
[31d7e85] - 2025-11-02
Added
- UDP fixtures/tests ensuring loopback handling, protocol metadata, and decoder integration behave correctly.
[11066d2] - 2025-11-02
Added
- HTTP decoding helpers tied to
pktlibrary and automatic loopback normalization. - Protocol-aware filtering (
Filter.by_protocol/2) and metadata enrichment (protocols,protocol).
Fixed
- Loopback interface handling; ensure
ipv4/ipv6classification and pseudo-header stripping.
[be90371] - 2025-11-02
Added
- Initial filtering DSL (size/time/content) with composable helpers.
[5c205f7] - 2025-11-02
Added
- Core PCAP and PCAPNG format support with automatic detection, streaming API, packet/header structs, and docs/tests for both formats.
[7152143] - 2025-11-02
Added
- Initial mix project skeleton.
[Unreleased]
Added
- BPF-style pre-filtering in Rust layer for high-performance packet filtering (10-100x speedup)
- Filter by IP address (exact match and CIDR ranges)
- Filter by port (exact match and ranges)
- Filter by protocol (TCP, UDP, ICMP, IPv4, IPv6)
- Filter by packet size (min/max/range)
- Filter by timestamp (Unix seconds)
- Logical operators (AND, OR, NOT)
PcapFileEx.PreFiltermodule with type-safe filter constructorsset_filter/2andclear_filter/1for both PCAP and PCAPNG readers
- Streaming statistics via
PcapFileEx.Stats.compute_streaming/1- Constant memory usage for huge files (no size limit)
- Can be combined with filtering and other stream operations
- Produces identical results to
compute/1but never loads all packets into memory - Accepts both file paths and streams
- PCAPNG interface metadata exposure (
PcapFileEx.PcapNg.interfaces/1) and per-packet fields (interface_id,interface,timestamp_resolution). - Test fixture script option
--interfaces ... --nanosecondfor generating multi-interface nanosecond captures; documentation on advanced capture workflows. - Comprehensive documentation:
docs/pre_filtering_feature_spec.md- Complete feature specificationdocs/benchmarks.md- Benchmark guidedocs/epcap_comparison.md- Comparison with epcap librarydocs/TROUBLESHOOTING.md- User troubleshooting guidedocs/SECURITY_ETF_FIX.md- ETF security fix documentation
Changed
PcapFileEx.Stream.from_reader/1now supports bothPcapandPcapNgreaders (previously only supported Pcap)PcapFileEx.Packetstruct docs/examples updated with interface metadata and resolution info.- Capture script defaults now auto-name multi-interface nanosecond captures (
sample_multi_nanosecond.pcapng). - Documented automatic decoder attachment and the
decode: falseopt-out in README and User Guide. - Updated benchmarks with pre-filtering vs post-filtering comparisons
Fixed
PcapFileEx.Stream.from_reader/1now correctly handles PcapNg readers (previously caused FunctionClauseError)- Security: ETF (Erlang Term Format) decoding now uses
:safeflag to prevent code execution from malicious PCAP files - Cross-platform: Test fixture generation scripts now work on both macOS and Linux
- Auto-detect loopback interface (
loon Linux,lo0on macOS) - Permission checking for dumpcap with platform-specific guidance
- Port checking uses
sson Linux (faster), falls back tolsofon macOS - Interface validation before capture starts
- Tests auto-generate missing fixtures on fresh clones
- Auto-detect loopback interface (
Added (Cross-Platform Support)
- Mix task
mix test.fixturesfor manual fixture generation - Automatic fixture generation in test setup (test/test_helper.exs)
- Comprehensive development setup documentation with platform-specific instructions:
- macOS: Homebrew installation and ChmodBPF setup
- Ubuntu/Debian: apt-get installation and wireshark group configuration
- Fedora/RHEL: dnf installation instructions
- Arch Linux: pacman installation instructions
- Troubleshooting guide covering:
- Interface detection errors ("No such device")
- Permission denied errors with platform-specific solutions
- dumpcap setup verification
- Fixture generation debugging
- Enhanced test/fixtures/README.md with platform compatibility matrix
- Smart interface detection and validation in capture scripts
- Platform detection (
uname -s) for Darwin (macOS) vs Linux
Improved
- Test fixture scripts work seamlessly on both macOS and Linux without modification
- Better error messages for missing tools or permission issues
- Graceful degradation when dumpcap is unavailable (tests skip with clear message)
- Documentation covers both Git dependency and future Hex publishing scenarios