// A packet capture in a browser: what is in a file, each packet in one line, a filter, the top
// talkers, and a pcapng with two byte orders, read without libpcap. The samples are made by
// standins/pcap_sample.mjs from documentation addresses: no real traffic.
//
//   quillo run pcap.qwe      then open http://localhost:8080/info, /packets and /summary
//
// To read your own: PCAP_FILE=/path/to/capture.pcap. Captures can hold passwords: mind who sees.

use "pcap.qwer"

let FILE = env("PCAP_FILE", "pcap_sample.pcap")
let NG = "pcap_sample.pcapng"

route GET /info = pcap_info(FILE)?

route GET /packets = pcap_packets(FILE, { limit: 100 })? | map((p) => p.info)

route GET /layers {
    let all = pcap_packets(FILE, {})?
    {
        arp: all[0].layers,
        vlan: [all[2].layers, all[2].vlans],
        qinq: [all[11].layers, all[11].vlans],
        v6_extension: [all[9].layers, all[9].extensions, all[9].src],
        fragment: [all[12].fragment, all[12].protocol, all[12].src_port],
        truncated: [all[13].truncated, all[13].length, all[13].captured, all[13].payload],
        icmp: [all[8].icmp, all[8].ttl],
        time: all[0].time,
    }
}

route GET /filter = {
    tcp: len(pcap_packets(FILE, { filter: { protocol: "tcp" } })?),
    port_53: pcap_packets(FILE, { filter: { port: 53 } })? | map((p) => p.index),
    vlan_200: pcap_packets(FILE, { filter: { vlan: 200 } })? | map((p) => p.index),
    host: len(pcap_packets(FILE, { filter: { host: "198.51.100.20", protocol: "udp" } })?),
    page: pcap_packets(FILE, { offset: 2, limit: 2 })? | map((p) => p.index),
}

route GET /summary = pcap_summary(FILE, 3)?

route GET /one {
    let p = pcap_packet(FILE, 7)?
    { info: p.info, seq: p.seq, ack: p.ack, window: p.window, payload: p.payload, text: slice(p.hex, 108, 116), missing: pcap_packet(FILE, 99).error }
}

route GET /pcapng {
    let i = pcap_info(NG)?
    { format: i.format, version: i.version, order: i.byte_order, sections: i.sections, packets: i.packets, names: i.names, interfaces: i.interfaces | map((x) => [x.name, x.link, x.ticks_per_second]) }
}

route GET /pcapng-packets = pcap_packets(NG, {})? | map((p) => [p.time, p.info])

route GET /decode = {
    frame: pcap_decode("ffffffffffff 02000000000a 0806 0001080006040001 02000000000a c000020a 000000000000 c6336414", 1)?.info,
    raw_ip: pcap_decode("4500001c00010000400100000a0000010a000002 0800000000010001", 101)?.info,
    short: pcap_decode("0200", 1)?,
}

route GET /damaged = {
    not_capture: pcap_info("pcap.qwe").error,
    no_file: pcap_info("nothing-here.pcap").error,
}

// An extract written, and read back.
route GET /write {
    let path = env("PCAP_OUT", "/tmp/quillo-pcap-extract.pcap")
    let n = pcap_write(path, [{ hex: "4500001c00010000400100000a0000010a0000020800000000010001", time_ms: 1793318400500 }], 101)?
    let i = pcap_info(path)?
    { wrote: n, format: i.format, link: i.interfaces[0].link, first: i.first, back: pcap_packets(path, {})?[0].info, bad: pcap_write(path, [{ time_ms: 1 }], 1).error }
}
