r_lanlib/packet/
wire.rs

1//! Implements a default Wire using pnet
2
3use pnet::datalink;
4use std::{
5    error::Error,
6    sync::{Arc, Mutex},
7};
8
9use crate::{
10    network::NetworkInterface,
11    packet::{Reader, Sender},
12};
13
14/// Represents a packet Reader and packet Sender tuple
15pub type Wire = (Arc<Mutex<dyn Reader>>, Arc<Mutex<dyn Sender>>);
16
17/// A PNetReader implementation of packet Reader
18pub struct PNetReader {
19    receiver: Box<dyn datalink::DataLinkReceiver>,
20}
21
22// Implements the Reader trait for our PNet implementation
23impl Reader for PNetReader {
24    fn next_packet(&mut self) -> Result<&[u8], Box<dyn Error>> {
25        self.receiver.next().map_err(Box::from)
26    }
27}
28
29unsafe impl Sync for PNetReader {}
30
31/// A PNetSender implementation of packet Sender
32pub struct PNetSender {
33    sender: Box<dyn datalink::DataLinkSender>,
34}
35
36// Implements the Sender trait for our PNet implementation
37impl Sender for PNetSender {
38    fn send(&mut self, packet: &[u8]) -> Result<(), Box<dyn Error>> {
39        let opt = self.sender.send_to(packet, None);
40        match opt {
41            Some(res) => Ok(res?),
42            None => Err(Box::from("failed to send packet")),
43        }
44    }
45}
46
47unsafe impl Sync for PNetSender {}
48
49/// Returns the default wire for current host
50///
51/// Example
52/// ```no_run
53/// # use std::io;
54/// # use r_lanlib::network;
55/// # use r_lanlib::packet::wire;
56/// let interface = network::get_default_interface().unwrap();
57/// let packet_wire = wire::default(&interface).unwrap();
58/// ```
59pub fn default(interface: &NetworkInterface) -> Result<Wire, Box<dyn Error>> {
60    let cfg = pnet::datalink::Config::default();
61
62    let channel = match pnet::datalink::channel(&interface.into(), cfg) {
63        Ok(pnet::datalink::Channel::Ethernet(tx, rx)) => Ok((tx, rx)),
64        Ok(_) => {
65            let e: Box<dyn Error> = Box::from("failed to create packet reader");
66            Err(e)
67        }
68        Err(e) => Err(Box::from(e.to_string())),
69    }?;
70
71    Ok((
72        Arc::new(Mutex::new(PNetReader {
73            receiver: channel.1,
74        })),
75        Arc::new(Mutex::new(PNetSender { sender: channel.0 })),
76    ))
77}
78
79#[cfg(test)]
80#[path = "./wire_tests.rs"]
81mod tests;