aboutsummaryrefslogtreecommitdiff
path: root/examples/std
diff options
context:
space:
mode:
Diffstat (limited to 'examples/std')
-rw-r--r--examples/std/Cargo.toml16
-rw-r--r--examples/std/README.md23
-rw-r--r--examples/std/src/bin/net.rs26
-rw-r--r--examples/std/src/bin/net_dns.rs94
-rw-r--r--examples/std/src/bin/net_udp.rs23
-rw-r--r--examples/std/src/bin/tcp_accept.rs129
-rw-r--r--examples/std/src/tuntap.rs119
7 files changed, 333 insertions, 97 deletions
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index c7cec6b19..92933ab50 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -2,22 +2,24 @@
2edition = "2021" 2edition = "2021"
3name = "embassy-std-examples" 3name = "embassy-std-examples"
4version = "0.1.0" 4version = "0.1.0"
5license = "MIT OR Apache-2.0"
5 6
6[dependencies] 7[dependencies]
7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] } 8embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] } 10embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "std", "nightly"] }
10embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "tcp", "udp", "dhcpv4", "pool-16"] } 11embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] }
11embedded-io = { version = "0.3.0", features = ["async", "std", "futures"] } 12embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" }
13embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] }
12critical-section = { version = "1.1", features = ["std"] } 14critical-section = { version = "1.1", features = ["std"] }
13 15
14async-io = "1.6.0" 16async-io = "1.6.0"
15env_logger = "0.9.0" 17env_logger = "0.9.0"
16futures = { version = "0.3.17" } 18futures = { version = "0.3.17" }
17log = "0.4.14" 19log = "0.4.14"
18nix = "0.22.1" 20nix = "0.26.2"
19libc = "0.2.101" 21libc = "0.2.101"
20clap = { version = "3.0.0-beta.5", features = ["derive"] } 22clap = { version = "3.0.0-beta.5", features = ["derive"] }
21rand_core = { version = "0.6.3", features = ["std"] } 23rand_core = { version = "0.6.3", features = ["std"] }
22heapless = { version = "0.7.5", default-features = false } 24heapless = { version = "0.7.5", default-features = false }
23static_cell = "1.0" 25static_cell = { version = "1.1", features = ["nightly"]}
diff --git a/examples/std/README.md b/examples/std/README.md
new file mode 100644
index 000000000..adc795928
--- /dev/null
+++ b/examples/std/README.md
@@ -0,0 +1,23 @@
1
2## Running the `embassy-net` examples
3
4First, create the tap0 interface. You only need to do this once.
5
6```sh
7sudo ip tuntap add name tap0 mode tap user $USER
8sudo ip link set tap0 up
9sudo ip addr add 192.168.69.100/24 dev tap0
10sudo ip -6 addr add fe80::100/64 dev tap0
11sudo ip -6 addr add fdaa::100/64 dev tap0
12sudo ip -6 route add fe80::/64 dev tap0
13sudo ip -6 route add fdaa::/64 dev tap0
14```
15
16Second, have something listening there. For example `nc -l 8000`
17
18Then run the example located in the `examples` folder:
19
20```sh
21cd $EMBASSY_ROOT/examples/std/
22cargo run --bin net -- --static-ip
23``` \ No newline at end of file
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs
index 9b1450b72..3aadb029d 100644
--- a/examples/std/src/bin/net.rs
+++ b/examples/std/src/bin/net.rs
@@ -1,28 +1,22 @@
1#![feature(type_alias_impl_trait)] 1#![feature(type_alias_impl_trait)]
2 2
3use std::default::Default;
4
3use clap::Parser; 5use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 6use embassy_executor::{Executor, Spawner};
5use embassy_net::tcp::TcpSocket; 7use embassy_net::tcp::TcpSocket;
6use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, Stack, StackResources}; 8use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
9use embassy_time::Duration;
7use embedded_io::asynch::Write; 10use embedded_io::asynch::Write;
8use heapless::Vec; 11use heapless::Vec;
9use log::*; 12use log::*;
10use rand_core::{OsRng, RngCore}; 13use rand_core::{OsRng, RngCore};
11use static_cell::StaticCell; 14use static_cell::{make_static, StaticCell};
12 15
13#[path = "../tuntap.rs"] 16#[path = "../tuntap.rs"]
14mod tuntap; 17mod tuntap;
15 18
16use crate::tuntap::TunTapDevice; 19use crate::tuntap::TunTapDevice;
17
18macro_rules! singleton {
19 ($val:expr) => {{
20 type T = impl Sized;
21 static STATIC_CELL: StaticCell<T> = StaticCell::new();
22 STATIC_CELL.init_with(move || $val)
23 }};
24}
25
26#[derive(Parser)] 20#[derive(Parser)]
27#[clap(version = "1.0")] 21#[clap(version = "1.0")]
28struct Opts { 22struct Opts {
@@ -48,13 +42,13 @@ async fn main_task(spawner: Spawner) {
48 42
49 // Choose between dhcp or static ip 43 // Choose between dhcp or static ip
50 let config = if opts.static_ip { 44 let config = if opts.static_ip {
51 ConfigStrategy::Static(embassy_net::Config { 45 Config::ipv4_static(embassy_net::StaticConfigV4 {
52 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), 46 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
53 dns_servers: Vec::new(), 47 dns_servers: Vec::new(),
54 gateway: Some(Ipv4Address::new(192, 168, 69, 1)), 48 gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
55 }) 49 })
56 } else { 50 } else {
57 ConfigStrategy::Dhcp 51 Config::dhcpv4(Default::default())
58 }; 52 };
59 53
60 // Generate random seed 54 // Generate random seed
@@ -63,10 +57,10 @@ async fn main_task(spawner: Spawner) {
63 let seed = u64::from_le_bytes(seed); 57 let seed = u64::from_le_bytes(seed);
64 58
65 // Init network stack 59 // Init network stack
66 let stack = &*singleton!(Stack::new( 60 let stack = &*make_static!(Stack::new(
67 device, 61 device,
68 config, 62 config,
69 singleton!(StackResources::<1, 2, 8>::new()), 63 make_static!(StackResources::<3>::new()),
70 seed 64 seed
71 )); 65 ));
72 66
@@ -78,7 +72,7 @@ async fn main_task(spawner: Spawner) {
78 let mut tx_buffer = [0; 4096]; 72 let mut tx_buffer = [0; 4096];
79 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); 73 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
80 74
81 socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); 75 socket.set_timeout(Some(Duration::from_secs(10)));
82 76
83 let remote_endpoint = (Ipv4Address::new(192, 168, 69, 100), 8000); 77 let remote_endpoint = (Ipv4Address::new(192, 168, 69, 100), 8000);
84 info!("connecting to {:?}...", remote_endpoint); 78 info!("connecting to {:?}...", remote_endpoint);
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs
new file mode 100644
index 000000000..65b5a2cd9
--- /dev/null
+++ b/examples/std/src/bin/net_dns.rs
@@ -0,0 +1,94 @@
1#![feature(type_alias_impl_trait)]
2
3use std::default::Default;
4
5use clap::Parser;
6use embassy_executor::{Executor, Spawner};
7use embassy_net::dns::DnsQueryType;
8use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
9use heapless::Vec;
10use log::*;
11use rand_core::{OsRng, RngCore};
12use static_cell::{make_static, StaticCell};
13
14#[path = "../tuntap.rs"]
15mod tuntap;
16
17use crate::tuntap::TunTapDevice;
18#[derive(Parser)]
19#[clap(version = "1.0")]
20struct Opts {
21 /// TAP device name
22 #[clap(long, default_value = "tap0")]
23 tap: String,
24 /// use a static IP instead of DHCP
25 #[clap(long)]
26 static_ip: bool,
27}
28
29#[embassy_executor::task]
30async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! {
31 stack.run().await
32}
33
34#[embassy_executor::task]
35async fn main_task(spawner: Spawner) {
36 let opts: Opts = Opts::parse();
37
38 // Init network device
39 let device = TunTapDevice::new(&opts.tap).unwrap();
40
41 // Choose between dhcp or static ip
42 let config = if opts.static_ip {
43 Config::ipv4_static(embassy_net::StaticConfigV4 {
44 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 1), 24),
45 dns_servers: Vec::from_slice(&[Ipv4Address::new(8, 8, 4, 4).into(), Ipv4Address::new(8, 8, 8, 8).into()])
46 .unwrap(),
47 gateway: Some(Ipv4Address::new(192, 168, 69, 100)),
48 })
49 } else {
50 Config::dhcpv4(Default::default())
51 };
52
53 // Generate random seed
54 let mut seed = [0; 8];
55 OsRng.fill_bytes(&mut seed);
56 let seed = u64::from_le_bytes(seed);
57
58 // Init network stack
59 let stack: &Stack<_> = &*make_static!(Stack::new(
60 device,
61 config,
62 make_static!(StackResources::<3>::new()),
63 seed
64 ));
65
66 // Launch network task
67 spawner.spawn(net_task(stack)).unwrap();
68
69 let host = "example.com";
70 info!("querying host {:?}...", host);
71 match stack.dns_query(host, DnsQueryType::A).await {
72 Ok(r) => {
73 info!("query response: {:?}", r);
74 }
75 Err(e) => {
76 warn!("query error: {:?}", e);
77 }
78 };
79}
80
81static EXECUTOR: StaticCell<Executor> = StaticCell::new();
82
83fn main() {
84 env_logger::builder()
85 .filter_level(log::LevelFilter::Debug)
86 .filter_module("async_io", log::LevelFilter::Info)
87 .format_timestamp_nanos()
88 .init();
89
90 let executor = EXECUTOR.init(Executor::new());
91 executor.run(|spawner| {
92 spawner.spawn(main_task(spawner)).unwrap();
93 });
94}
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs
index 392a97f0d..3fc46156c 100644
--- a/examples/std/src/bin/net_udp.rs
+++ b/examples/std/src/bin/net_udp.rs
@@ -2,26 +2,17 @@
2 2
3use clap::Parser; 3use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 4use embassy_executor::{Executor, Spawner};
5use embassy_net::udp::UdpSocket; 5use embassy_net::udp::{PacketMetadata, UdpSocket};
6use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, PacketMetadata, Stack, StackResources}; 6use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
7use heapless::Vec; 7use heapless::Vec;
8use log::*; 8use log::*;
9use rand_core::{OsRng, RngCore}; 9use rand_core::{OsRng, RngCore};
10use static_cell::StaticCell; 10use static_cell::{make_static, StaticCell};
11 11
12#[path = "../tuntap.rs"] 12#[path = "../tuntap.rs"]
13mod tuntap; 13mod tuntap;
14 14
15use crate::tuntap::TunTapDevice; 15use crate::tuntap::TunTapDevice;
16
17macro_rules! singleton {
18 ($val:expr) => {{
19 type T = impl Sized;
20 static STATIC_CELL: StaticCell<T> = StaticCell::new();
21 STATIC_CELL.init_with(move || $val)
22 }};
23}
24
25#[derive(Parser)] 16#[derive(Parser)]
26#[clap(version = "1.0")] 17#[clap(version = "1.0")]
27struct Opts { 18struct Opts {
@@ -47,13 +38,13 @@ async fn main_task(spawner: Spawner) {
47 38
48 // Choose between dhcp or static ip 39 // Choose between dhcp or static ip
49 let config = if opts.static_ip { 40 let config = if opts.static_ip {
50 ConfigStrategy::Static(embassy_net::Config { 41 Config::ipv4_static(embassy_net::StaticConfigV4 {
51 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), 42 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
52 dns_servers: Vec::new(), 43 dns_servers: Vec::new(),
53 gateway: Some(Ipv4Address::new(192, 168, 69, 1)), 44 gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
54 }) 45 })
55 } else { 46 } else {
56 ConfigStrategy::Dhcp 47 Config::dhcpv4(Default::default())
57 }; 48 };
58 49
59 // Generate random seed 50 // Generate random seed
@@ -62,10 +53,10 @@ async fn main_task(spawner: Spawner) {
62 let seed = u64::from_le_bytes(seed); 53 let seed = u64::from_le_bytes(seed);
63 54
64 // Init network stack 55 // Init network stack
65 let stack = &*singleton!(Stack::new( 56 let stack = &*make_static!(Stack::new(
66 device, 57 device,
67 config, 58 config,
68 singleton!(StackResources::<1, 2, 8>::new()), 59 make_static!(StackResources::<3>::new()),
69 seed 60 seed
70 )); 61 ));
71 62
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs
new file mode 100644
index 000000000..df09986ac
--- /dev/null
+++ b/examples/std/src/bin/tcp_accept.rs
@@ -0,0 +1,129 @@
1#![feature(type_alias_impl_trait)]
2
3use core::fmt::Write as _;
4use std::default::Default;
5
6use clap::Parser;
7use embassy_executor::{Executor, Spawner};
8use embassy_net::tcp::TcpSocket;
9use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
10use embassy_time::{Duration, Timer};
11use embedded_io::asynch::Write as _;
12use heapless::Vec;
13use log::*;
14use rand_core::{OsRng, RngCore};
15use static_cell::{make_static, StaticCell};
16
17#[path = "../tuntap.rs"]
18mod tuntap;
19
20use crate::tuntap::TunTapDevice;
21#[derive(Parser)]
22#[clap(version = "1.0")]
23struct Opts {
24 /// TAP device name
25 #[clap(long, default_value = "tap0")]
26 tap: String,
27 /// use a static IP instead of DHCP
28 #[clap(long)]
29 static_ip: bool,
30}
31
32#[embassy_executor::task]
33async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! {
34 stack.run().await
35}
36
37#[derive(Default)]
38struct StrWrite(pub heapless::Vec<u8, 30>);
39
40impl core::fmt::Write for StrWrite {
41 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
42 self.0.extend_from_slice(s.as_bytes()).unwrap();
43 Ok(())
44 }
45}
46
47#[embassy_executor::task]
48async fn main_task(spawner: Spawner) {
49 let opts: Opts = Opts::parse();
50
51 // Init network device
52 let device = TunTapDevice::new(&opts.tap).unwrap();
53
54 // Choose between dhcp or static ip
55 let config = if opts.static_ip {
56 Config::ipv4_static(embassy_net::StaticConfigV4 {
57 address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
58 dns_servers: Vec::new(),
59 gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
60 })
61 } else {
62 Config::dhcpv4(Default::default())
63 };
64
65 // Generate random seed
66 let mut seed = [0; 8];
67 OsRng.fill_bytes(&mut seed);
68 let seed = u64::from_le_bytes(seed);
69
70 // Init network stack
71 let stack = &*make_static!(Stack::new(
72 device,
73 config,
74 make_static!(StackResources::<3>::new()),
75 seed
76 ));
77
78 // Launch network task
79 spawner.spawn(net_task(stack)).unwrap();
80
81 // Then we can use it!
82 let mut rx_buffer = [0; 4096];
83 let mut tx_buffer = [0; 4096];
84
85 loop {
86 let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
87 socket.set_timeout(Some(Duration::from_secs(10)));
88 info!("Listening on TCP:9999...");
89 if let Err(_) = socket.accept(9999).await {
90 warn!("accept error");
91 continue;
92 }
93
94 info!("Accepted a connection");
95
96 // Write some quick output
97 for i in 1..=5 {
98 let mut w = StrWrite::default();
99 write!(w, "{}! ", i).unwrap();
100 let r = socket.write_all(&w.0).await;
101 if let Err(e) = r {
102 warn!("write error: {:?}", e);
103 return;
104 }
105
106 Timer::after(Duration::from_millis(500)).await;
107 }
108 info!("Closing the connection");
109 socket.abort();
110 info!("Flushing the RST out...");
111 _ = socket.flush().await;
112 info!("Finished with the socket");
113 }
114}
115
116static EXECUTOR: StaticCell<Executor> = StaticCell::new();
117
118fn main() {
119 env_logger::builder()
120 .filter_level(log::LevelFilter::Debug)
121 .filter_module("async_io", log::LevelFilter::Info)
122 .format_timestamp_nanos()
123 .init();
124
125 let executor = EXECUTOR.init(Executor::new());
126 executor.run(|spawner| {
127 spawner.spawn(main_task(spawner)).unwrap();
128 });
129}
diff --git a/examples/std/src/tuntap.rs b/examples/std/src/tuntap.rs
index a0cace7f7..d918a2e62 100644
--- a/examples/std/src/tuntap.rs
+++ b/examples/std/src/tuntap.rs
@@ -1,8 +1,10 @@
1use std::io; 1use std::io;
2use std::io::{Read, Write}; 2use std::io::{Read, Write};
3use std::os::unix::io::{AsRawFd, RawFd}; 3use std::os::unix::io::{AsRawFd, RawFd};
4use std::task::Context;
4 5
5use async_io::Async; 6use async_io::Async;
7use embassy_net_driver::{self, Capabilities, Driver, LinkState};
6use log::*; 8use log::*;
7 9
8pub const SIOCGIFMTU: libc::c_ulong = 0x8921; 10pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
@@ -125,54 +127,35 @@ impl io::Write for TunTap {
125 127
126pub struct TunTapDevice { 128pub struct TunTapDevice {
127 device: Async<TunTap>, 129 device: Async<TunTap>,
128 waker: Option<Waker>,
129} 130}
130 131
131impl TunTapDevice { 132impl TunTapDevice {
132 pub fn new(name: &str) -> io::Result<TunTapDevice> { 133 pub fn new(name: &str) -> io::Result<TunTapDevice> {
133 Ok(Self { 134 Ok(Self {
134 device: Async::new(TunTap::new(name)?)?, 135 device: Async::new(TunTap::new(name)?)?,
135 waker: None,
136 }) 136 })
137 } 137 }
138} 138}
139 139
140use core::task::Waker; 140impl Driver for TunTapDevice {
141use std::task::Context; 141 type RxToken<'a> = RxToken where Self: 'a;
142 142 type TxToken<'a> = TxToken<'a> where Self: 'a;
143use embassy_net::{Device, DeviceCapabilities, LinkState, Packet, PacketBox, PacketBoxExt, PacketBuf};
144
145impl Device for TunTapDevice {
146 fn is_transmit_ready(&mut self) -> bool {
147 true
148 }
149 143
150 fn transmit(&mut self, pkt: PacketBuf) { 144 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
151 // todo handle WouldBlock 145 let mut buf = vec![0; self.device.get_ref().mtu];
152 match self.device.get_mut().write(&pkt) {
153 Ok(_) => {}
154 Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
155 info!("transmit WouldBlock");
156 }
157 Err(e) => panic!("transmit error: {:?}", e),
158 }
159 }
160
161 fn receive(&mut self) -> Option<PacketBuf> {
162 let mut pkt = PacketBox::new(Packet::new()).unwrap();
163 loop { 146 loop {
164 match self.device.get_mut().read(&mut pkt[..]) { 147 match self.device.get_mut().read(&mut buf) {
165 Ok(n) => { 148 Ok(n) => {
166 return Some(pkt.slice(0..n)); 149 buf.truncate(n);
150 return Some((
151 RxToken { buffer: buf },
152 TxToken {
153 device: &mut self.device,
154 },
155 ));
167 } 156 }
168 Err(e) if e.kind() == io::ErrorKind::WouldBlock => { 157 Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
169 let ready = if let Some(w) = self.waker.as_ref() { 158 if !self.device.poll_readable(cx).is_ready() {
170 let mut cx = Context::from_waker(w);
171 self.device.poll_readable(&mut cx).is_ready()
172 } else {
173 false
174 };
175 if !ready {
176 return None; 159 return None;
177 } 160 }
178 } 161 }
@@ -181,37 +164,19 @@ impl Device for TunTapDevice {
181 } 164 }
182 } 165 }
183 166
184 fn register_waker(&mut self, w: &Waker) { 167 fn transmit(&mut self, _cx: &mut Context) -> Option<Self::TxToken<'_>> {
185 match self.waker { 168 Some(TxToken {
186 // Optimization: If both the old and new Wakers wake the same task, we can simply 169 device: &mut self.device,
187 // keep the old waker, skipping the clone. (In most executor implementations, 170 })
188 // cloning a waker is somewhat expensive, comparable to cloning an Arc).
189 Some(ref w2) if (w2.will_wake(w)) => {}
190 _ => {
191 // clone the new waker and store it
192 if let Some(old_waker) = core::mem::replace(&mut self.waker, Some(w.clone())) {
193 // We had a waker registered for another task. Wake it, so the other task can
194 // reregister itself if it's still interested.
195 //
196 // If two tasks are waiting on the same thing concurrently, this will cause them
197 // to wake each other in a loop fighting over this WakerRegistration. This wastes
198 // CPU but things will still work.
199 //
200 // If the user wants to have two tasks waiting on the same thing they should use
201 // a more appropriate primitive that can store multiple wakers.
202 old_waker.wake()
203 }
204 }
205 }
206 } 171 }
207 172
208 fn capabilities(&self) -> DeviceCapabilities { 173 fn capabilities(&self) -> Capabilities {
209 let mut caps = DeviceCapabilities::default(); 174 let mut caps = Capabilities::default();
210 caps.max_transmission_unit = self.device.get_ref().mtu; 175 caps.max_transmission_unit = self.device.get_ref().mtu;
211 caps 176 caps
212 } 177 }
213 178
214 fn link_state(&mut self) -> LinkState { 179 fn link_state(&mut self, _cx: &mut Context) -> LinkState {
215 LinkState::Up 180 LinkState::Up
216 } 181 }
217 182
@@ -219,3 +184,41 @@ impl Device for TunTapDevice {
219 [0x02, 0x03, 0x04, 0x05, 0x06, 0x07] 184 [0x02, 0x03, 0x04, 0x05, 0x06, 0x07]
220 } 185 }
221} 186}
187
188#[doc(hidden)]
189pub struct RxToken {
190 buffer: Vec<u8>,
191}
192
193impl embassy_net_driver::RxToken for RxToken {
194 fn consume<R, F>(mut self, f: F) -> R
195 where
196 F: FnOnce(&mut [u8]) -> R,
197 {
198 f(&mut self.buffer)
199 }
200}
201
202#[doc(hidden)]
203pub struct TxToken<'a> {
204 device: &'a mut Async<TunTap>,
205}
206
207impl<'a> embassy_net_driver::TxToken for TxToken<'a> {
208 fn consume<R, F>(self, len: usize, f: F) -> R
209 where
210 F: FnOnce(&mut [u8]) -> R,
211 {
212 let mut buffer = vec![0; len];
213 let result = f(&mut buffer);
214
215 // todo handle WouldBlock with async
216 match self.device.get_mut().write(&buffer) {
217 Ok(_) => {}
218 Err(e) if e.kind() == io::ErrorKind::WouldBlock => info!("transmit WouldBlock"),
219 Err(e) => panic!("transmit error: {:?}", e),
220 }
221
222 result
223 }
224}