crafter 0.3.2

Packet-level network interaction for Rust tools and agents.
Documentation
mod common;

use common::{local_ipv4, print_help_if_requested, remote_ipv4, ExampleResult};
use crafter::prelude::*;

fn main() -> ExampleResult<()> {
    if print_help_if_requested(
        "usage: cargo run --example custom_registry --\n\nDecode generated bytes with a local ProtocolRegistry binding.",
    ) {
        return Ok(());
    }

    let packet = Ipv4::new()
        .src(local_ipv4())
        .dst(remote_ipv4())
        .ipv4_protocol(Ipv4Protocol::Udp)
        / Udp::new().sport(53000).dport(DNS_PORT)
        / Dns::a_query("example.com.").id(0x4242);
    let bytes = packet.compile()?;

    let default_decoded = Packet::decode_from_l3(NetworkLayer::Ipv4, bytes.as_bytes())?;

    let mut registry = ProtocolRegistry::new();
    registry.bind_udp_port(DNS_PORT, |packet, payload| {
        Ok(packet.push(Raw::from_bytes(payload)))
    });
    let custom_decoded =
        Packet::decode_from_l3_with_registry(&registry, NetworkLayer::Ipv4, bytes.as_bytes())?;
    let raw = custom_decoded
        .layer::<Raw>()
        .expect("custom DNS port binding should preserve payload as Raw");

    assert!(default_decoded.layer::<Dns>().is_some());
    assert!(custom_decoded.layer::<Dns>().is_none());

    println!("mode: offline");
    println!("default registry summary: {}", default_decoded.summary());
    println!("custom registry summary: {}", custom_decoded.summary());
    println!("custom raw bytes: {}", raw.len());
    println!("hexdump:\n{}", bytes.hexdump());

    Ok(())
}