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