smoltcp/phy/
raw_socket.rs1use std::cell::RefCell;
2use std::io;
3use std::os::unix::io::{AsRawFd, RawFd};
4use std::rc::Rc;
5use std::vec::Vec;
6
7use crate::phy::{self, Device, DeviceCapabilities, Medium, sys};
8use crate::time::Instant;
9
10#[derive(Debug)]
12pub struct RawSocket {
13 medium: Medium,
14 lower: Rc<RefCell<sys::RawSocketDesc>>,
15 mtu: usize,
16}
17
18impl AsRawFd for RawSocket {
19 fn as_raw_fd(&self) -> RawFd {
20 self.lower.borrow().as_raw_fd()
21 }
22}
23
24impl RawSocket {
25 pub fn new(name: &str, medium: Medium) -> io::Result<RawSocket> {
30 let mut lower = sys::RawSocketDesc::new(name, medium)?;
31 lower.bind_interface()?;
32
33 let mut mtu = lower.interface_mtu()?;
34
35 #[cfg(feature = "medium-ieee802154")]
36 if medium == Medium::Ieee802154 {
37 mtu += 2;
44 }
45
46 #[cfg(feature = "medium-ethernet")]
47 if medium == Medium::Ethernet {
48 mtu += crate::wire::EthernetFrame::<&[u8]>::header_len()
51 }
52
53 Ok(RawSocket {
54 medium,
55 lower: Rc::new(RefCell::new(lower)),
56 mtu,
57 })
58 }
59}
60
61impl Device for RawSocket {
62 type RxToken<'a>
63 = RxToken
64 where
65 Self: 'a;
66 type TxToken<'a>
67 = TxToken
68 where
69 Self: 'a;
70
71 fn capabilities(&self) -> DeviceCapabilities {
72 DeviceCapabilities {
73 max_transmission_unit: self.mtu,
74 medium: self.medium,
75 ..DeviceCapabilities::default()
76 }
77 }
78
79 fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
80 let mut lower = self.lower.borrow_mut();
81 let mut buffer = vec![0; self.mtu];
82 match lower.recv(&mut buffer[..]) {
83 Ok(size) => {
84 buffer.resize(size, 0);
85 let rx = RxToken { buffer };
86 let tx = TxToken {
87 lower: self.lower.clone(),
88 };
89 Some((rx, tx))
90 }
91 Err(err) if err.kind() == io::ErrorKind::WouldBlock => None,
92 Err(err) => panic!("{}", err),
93 }
94 }
95
96 fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
97 Some(TxToken {
98 lower: self.lower.clone(),
99 })
100 }
101}
102
103#[doc(hidden)]
104pub struct RxToken {
105 buffer: Vec<u8>,
106}
107
108impl phy::RxToken for RxToken {
109 fn consume<R, F>(self, f: F) -> R
110 where
111 F: FnOnce(&[u8]) -> R,
112 {
113 f(&self.buffer[..])
114 }
115}
116
117#[doc(hidden)]
118pub struct TxToken {
119 lower: Rc<RefCell<sys::RawSocketDesc>>,
120}
121
122impl phy::TxToken for TxToken {
123 fn consume<R, F>(self, len: usize, f: F) -> R
124 where
125 F: FnOnce(&mut [u8]) -> R,
126 {
127 let mut lower = self.lower.borrow_mut();
128 let mut buffer = vec![0; len];
129 let result = f(&mut buffer);
130 match lower.send(&buffer[..]) {
131 Ok(_) => {}
132 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
133 net_debug!("phy: tx failed due to WouldBlock")
134 }
135 Err(err) => panic!("{}", err),
136 }
137 result
138 }
139}