use rawsock::{pcap, pfring, wpcap};
use rawsock::traits::{DynamicInterface, Library};

pub const ICMP_PACKET: [u8; 84] = [
    0x45, 0x00, 0x00, 0x54, 0xee, 0x96, 0x40, 0x00, 0x40, 0x01, 0x79, 0xf0, 0xc0, 0xa8, 0x01, 0x6a,
    0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x2f, 0x08, 0x66, 0xc2, 0x00, 0x12, 0x82, 0xaa, 0xcc, 0x5c,
    0x00, 0x00, 0x00, 0x00, 0x51, 0x49, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
    0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37];

pub fn open_library<T>() -> T where T: Library {
    let lib = T::open_default_paths().expect("Could not open library");
    println!("Library opened, version is {}", lib.version());
    lib
}

pub fn receive_packets<'a, T>(interf: &mut T) where T: DynamicInterface<'a> {
    println!("Receiving 5 packets:");
    for i in 1..6 {
        let packet = interf.receive().expect("Error while receiving packet");
        println!("Packet {} is {}", i, packet);
    }
}

pub fn send_packets<'a, T>(interf: &mut T) where T: DynamicInterface<'a> {
    println!("Data link: {}", interf.data_link());
    println!("Sending 5 ICMP ping packets:");
    for i in 1..6 {
        interf.send(&ICMP_PACKET).expect("Errow while sending packet");
        println!("Packet {} was sent", i);
    }
}

// from: https://github.com/szymonwieloch/rust-rawsock/tree/master/examples
fn main() {
    run_pcap();
    run_pfring();
    run_wpcap();
}

fn run_pcap() {
    let lib = open_library::<pcap::Library>();
    let ifname = lib.all_interfaces()
        .expect("Could not obtain interface list").first()
        .expect("There are no available interfaces").name.clone();
    let mut interf = lib.open_interface(&ifname).expect("Could not open pcap interface");
    send_packets(&mut interf);
    receive_packets(&mut interf);
}

fn run_wpcap() {
    let lib = open_library::<wpcap::Library>();
    let ifname = lib.all_interfaces()
        .expect("Could not obtain interface list").first()
        .expect("There are no available interfaces").name.clone();
    let mut interf = lib.open_interface(&ifname).expect("Could not open wpcap interface");
    send_packets(&mut interf);
    receive_packets(&mut interf);
}

fn run_pfring() {
    let lib = open_library::<pfring::Library>();
    let ifname = lib.all_interfaces()
        .expect("Could not obtain interface list").first()
        .expect("There are no available interfaces").name.clone();
    let mut interf = lib.open_interface(&ifname).expect("Could not open pfring interface");
    send_packets(&mut interf);
    receive_packets(&mut interf);
}