examples/std: update to new embassy-net trait.
This commit is contained in:
parent
5eae295c8a
commit
790e4e1594
@ -1,8 +1,10 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::task::Context;
|
||||||
|
|
||||||
use async_io::Async;
|
use async_io::Async;
|
||||||
|
use embassy_net::device::{self, Device, DeviceCapabilities, LinkState};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
|
pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
|
||||||
@ -125,54 +127,35 @@ impl io::Write for TunTap {
|
|||||||
|
|
||||||
pub struct TunTapDevice {
|
pub struct TunTapDevice {
|
||||||
device: Async<TunTap>,
|
device: Async<TunTap>,
|
||||||
waker: Option<Waker>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TunTapDevice {
|
impl TunTapDevice {
|
||||||
pub fn new(name: &str) -> io::Result<TunTapDevice> {
|
pub fn new(name: &str) -> io::Result<TunTapDevice> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
device: Async::new(TunTap::new(name)?)?,
|
device: Async::new(TunTap::new(name)?)?,
|
||||||
waker: None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use core::task::Waker;
|
|
||||||
use std::task::Context;
|
|
||||||
|
|
||||||
use embassy_net::{Device, DeviceCapabilities, LinkState, Packet, PacketBox, PacketBoxExt, PacketBuf};
|
|
||||||
|
|
||||||
impl Device for TunTapDevice {
|
impl Device for TunTapDevice {
|
||||||
fn is_transmit_ready(&mut self) -> bool {
|
type RxToken<'a> = RxToken where Self: 'a;
|
||||||
true
|
type TxToken<'a> = TxToken<'a> where Self: 'a;
|
||||||
}
|
|
||||||
|
|
||||||
fn transmit(&mut self, pkt: PacketBuf) {
|
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||||
// todo handle WouldBlock
|
let mut buf = vec![0; self.device.get_ref().mtu];
|
||||||
match self.device.get_mut().write(&pkt) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
|
||||||
info!("transmit WouldBlock");
|
|
||||||
}
|
|
||||||
Err(e) => panic!("transmit error: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn receive(&mut self) -> Option<PacketBuf> {
|
|
||||||
let mut pkt = PacketBox::new(Packet::new()).unwrap();
|
|
||||||
loop {
|
loop {
|
||||||
match self.device.get_mut().read(&mut pkt[..]) {
|
match self.device.get_mut().read(&mut buf) {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
return Some(pkt.slice(0..n));
|
buf.truncate(n);
|
||||||
|
return Some((
|
||||||
|
RxToken { buffer: buf },
|
||||||
|
TxToken {
|
||||||
|
device: &mut self.device,
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||||
let ready = if let Some(w) = self.waker.as_ref() {
|
if !self.device.poll_readable(cx).is_ready() {
|
||||||
let mut cx = Context::from_waker(w);
|
|
||||||
self.device.poll_readable(&mut cx).is_ready()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
if !ready {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,28 +164,10 @@ impl Device for TunTapDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_waker(&mut self, w: &Waker) {
|
fn transmit(&mut self, _cx: &mut Context) -> Option<Self::TxToken<'_>> {
|
||||||
match self.waker {
|
Some(TxToken {
|
||||||
// Optimization: If both the old and new Wakers wake the same task, we can simply
|
device: &mut self.device,
|
||||||
// keep the old waker, skipping the clone. (In most executor implementations,
|
})
|
||||||
// cloning a waker is somewhat expensive, comparable to cloning an Arc).
|
|
||||||
Some(ref w2) if (w2.will_wake(w)) => {}
|
|
||||||
_ => {
|
|
||||||
// clone the new waker and store it
|
|
||||||
if let Some(old_waker) = core::mem::replace(&mut self.waker, Some(w.clone())) {
|
|
||||||
// We had a waker registered for another task. Wake it, so the other task can
|
|
||||||
// reregister itself if it's still interested.
|
|
||||||
//
|
|
||||||
// If two tasks are waiting on the same thing concurrently, this will cause them
|
|
||||||
// to wake each other in a loop fighting over this WakerRegistration. This wastes
|
|
||||||
// CPU but things will still work.
|
|
||||||
//
|
|
||||||
// If the user wants to have two tasks waiting on the same thing they should use
|
|
||||||
// a more appropriate primitive that can store multiple wakers.
|
|
||||||
old_waker.wake()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capabilities(&self) -> DeviceCapabilities {
|
fn capabilities(&self) -> DeviceCapabilities {
|
||||||
@ -211,7 +176,7 @@ impl Device for TunTapDevice {
|
|||||||
caps
|
caps
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_state(&mut self) -> LinkState {
|
fn link_state(&mut self, _cx: &mut Context) -> LinkState {
|
||||||
LinkState::Up
|
LinkState::Up
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,3 +184,41 @@ impl Device for TunTapDevice {
|
|||||||
[0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
|
[0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct RxToken {
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl device::RxToken for RxToken {
|
||||||
|
fn consume<R, F>(mut self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
{
|
||||||
|
f(&mut self.buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct TxToken<'a> {
|
||||||
|
device: &'a mut Async<TunTap>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> device::TxToken for TxToken<'a> {
|
||||||
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
{
|
||||||
|
let mut buffer = vec![0; len];
|
||||||
|
let result = f(&mut buffer);
|
||||||
|
|
||||||
|
// todo handle WouldBlock with async
|
||||||
|
match self.device.get_mut().write(&buffer) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::WouldBlock => info!("transmit WouldBlock"),
|
||||||
|
Err(e) => panic!("transmit error: {:?}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user