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, sys, Device, DeviceCapabilities, Medium};
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> = RxToken
63 where
64 Self: 'a;
65 type TxToken<'a> = TxToken
66 where
67 Self: 'a;
68
69 fn capabilities(&self) -> DeviceCapabilities {
70 DeviceCapabilities {
71 max_transmission_unit: self.mtu,
72 medium: self.medium,
73 ..DeviceCapabilities::default()
74 }
75 }
76
77 fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
78 let mut lower = self.lower.borrow_mut();
79 let mut buffer = vec![0; self.mtu];
80 match lower.recv(&mut buffer[..]) {
81 Ok(size) => {
82 buffer.resize(size, 0);
83 let rx = RxToken { buffer };
84 let tx = TxToken {
85 lower: self.lower.clone(),
86 };
87 Some((rx, tx))
88 }
89 Err(err) if err.kind() == io::ErrorKind::WouldBlock => None,
90 Err(err) => panic!("{}", err),
91 }
92 }
93
94 fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
95 Some(TxToken {
96 lower: self.lower.clone(),
97 })
98 }
99}
100
101#[doc(hidden)]
102pub struct RxToken {
103 buffer: Vec<u8>,
104}
105
106impl phy::RxToken for RxToken {
107 fn consume<R, F>(self, f: F) -> R
108 where
109 F: FnOnce(&[u8]) -> R,
110 {
111 f(&self.buffer[..])
112 }
113}
114
115#[doc(hidden)]
116pub struct TxToken {
117 lower: Rc<RefCell<sys::RawSocketDesc>>,
118}
119
120impl phy::TxToken for TxToken {
121 fn consume<R, F>(self, len: usize, f: F) -> R
122 where
123 F: FnOnce(&mut [u8]) -> R,
124 {
125 let mut lower = self.lower.borrow_mut();
126 let mut buffer = vec![0; len];
127 let result = f(&mut buffer);
128 match lower.send(&buffer[..]) {
129 Ok(_) => {}
130 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
131 net_debug!("phy: tx failed due to WouldBlock")
132 }
133 Err(err) => panic!("{}", err),
134 }
135 result
136 }
137}