Skip to main content

r_lanlib/packet/
wire.rs

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