crafter 0.3.4

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

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

fn main() -> ExampleResult<()> {
    if print_help_if_requested(
        "usage: cargo run --example ssdp_notify --\n\nBuild, compile, decode, and inspect SSDP notification packets offline.",
    ) {
        return Ok(());
    }

    let device_uuid = "device-1";
    let location = SsdpLocation::new("http://192.0.2.10:8000/rootDesc.xml")?;
    let root = SsdpTarget::rootdevice();
    let usn = SsdpUsn::rootdevice(device_uuid);
    let packets = vec![
        (
            "alive",
            ssdp_ipv4_multicast_packet(
                local_ipv4(),
                Ssdp::notify_alive()
                    .notification_type(root.clone())
                    .unique_service_name(usn.clone())
                    .location(location.clone())
                    .max_age(1_800)
                    .server("ExampleOS/1.0 UPnP/2.0 libcrafter/0.3")
                    .boot_id(1)
                    .config_id(1),
            ),
        ),
        (
            "byebye",
            ssdp_ipv4_multicast_packet(
                local_ipv4(),
                Ssdp::notify_byebye()
                    .notification_type(root.clone())
                    .unique_service_name(usn.clone())
                    .boot_id(1)
                    .config_id(1),
            ),
        ),
        (
            "update",
            ssdp_ipv4_multicast_packet(
                local_ipv4(),
                Ssdp::notify_update()
                    .notification_type(root)
                    .unique_service_name(usn)
                    .location(location)
                    .max_age(1_800)
                    .boot_id(1)
                    .config_id(2)
                    .next_boot_id(2),
            ),
        ),
    ];

    println!("example: ssdp_notify");
    println!("mode: offline");
    for (label, packet) in packets {
        print_packet(label, &packet)?;
    }

    Ok(())
}

fn print_packet(label: &str, packet: &Packet) -> ExampleResult<()> {
    let compiled = packet.compile()?;
    let decoded = Packet::decode_from_l3(NetworkLayer::Ipv4, compiled.as_bytes())?;

    println!("{label} summary: {}", decoded.summary());
    println!("{label} show:\n{}", decoded.show());
    println!("{label} hexdump:\n{}", compiled.hexdump());

    Ok(())
}