From 865a91976c5b6b5c45b37e0286e7c328e8404dde Mon Sep 17 00:00:00 2001 From: Artur Kowalski Date: Wed, 10 Aug 2022 19:38:34 +0200 Subject: Add UDP example app --- examples/std/src/bin/net_udp.rs | 109 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 examples/std/src/bin/net_udp.rs (limited to 'examples/std/src') diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs new file mode 100644 index 000000000..7fe36e233 --- /dev/null +++ b/examples/std/src/bin/net_udp.rs @@ -0,0 +1,109 @@ +#![feature(type_alias_impl_trait)] + +use clap::Parser; +use embassy_executor::executor::{Executor, Spawner}; +use embassy_net::udp::UdpSocket; +use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, PacketMetadata, Stack, StackResources}; +use embassy_util::Forever; +use heapless::Vec; +use log::*; +use rand_core::{OsRng, RngCore}; + +#[path = "../tuntap.rs"] +mod tuntap; + +use crate::tuntap::TunTapDevice; + +macro_rules! forever { + ($val:expr) => {{ + type T = impl Sized; + static FOREVER: Forever = Forever::new(); + FOREVER.put_with(move || $val) + }}; +} + +#[derive(Parser)] +#[clap(version = "1.0")] +struct Opts { + /// TAP device name + #[clap(long, default_value = "tap0")] + tap: String, + /// use a static IP instead of DHCP + #[clap(long)] + static_ip: bool, +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack) -> ! { + stack.run().await +} + +#[embassy_executor::task] +async fn main_task(spawner: Spawner) { + let opts: Opts = Opts::parse(); + + // Init network device + let device = TunTapDevice::new(&opts.tap).unwrap(); + + // Choose between dhcp or static ip + let config = if opts.static_ip { + ConfigStrategy::Static(embassy_net::Config { + address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), + dns_servers: Vec::new(), + gateway: Some(Ipv4Address::new(192, 168, 69, 1)), + }) + } else { + ConfigStrategy::Dhcp + }; + + // Generate random seed + let mut seed = [0; 8]; + OsRng.fill_bytes(&mut seed); + let seed = u64::from_le_bytes(seed); + + // Init network stack + let stack = &*forever!(Stack::new( + device, + config, + forever!(StackResources::<1, 2, 8>::new()), + seed + )); + + // Launch network task + spawner.spawn(net_task(stack)).unwrap(); + + // Then we can use it! + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut rx_buffer = [0; 4096]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + + let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); + socket.bind(9400).unwrap(); + + loop { + let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); + if let Ok(s) = core::str::from_utf8(&buf[..n]) { + info!("ECHO (to {}): {}", ep, s); + } else { + info!("ECHO (to {}): bytearray len {}", ep, n); + } + socket.send_to(&buf[..n], ep).await.unwrap(); + } +} + +static EXECUTOR: Forever = Forever::new(); + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Debug) + .filter_module("async_io", log::LevelFilter::Info) + .format_timestamp_nanos() + .init(); + + let executor = EXECUTOR.put(Executor::new()); + executor.run(|spawner| { + spawner.spawn(main_task(spawner)).unwrap(); + }); +} -- cgit