diff --git a/embassy-net-examples/Cargo.toml b/embassy-net-examples/Cargo.toml deleted file mode 100644 index 413428bf6..000000000 --- a/embassy-net-examples/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "embassy-net-examples" -version = "0.1.0" -authors = ["Dario Nieuwenhuis "] -edition = "2018" - -[dependencies] -heapless = { version = "0.5.6", default-features = false } -embassy = { version = "0.1.0", path = "../embassy", features=["std", "log"] } -embassy-std = { version = "0.1.0", path = "../embassy-std" } -embassy-net = { version = "0.1.0", path = "../embassy-net", features=["std", "log", "medium-ethernet", "tcp", "dhcpv4"] } -env_logger = "0.8.2" -log = "0.4.11" -futures = "0.3.8" -libc = "0.2.81" -async-io = "1.3.1" -smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev="ec59aba5e10cf91df0c9253d9c2aca4dd143d2ff", default-features = false } -clap = { version = "3.0.0-beta.2", features = ["derive"] } -rand_core = { version = "0.6.0", features = ["std"] } diff --git a/embassy-net-examples/src/main.rs b/embassy-net-examples/src/main.rs deleted file mode 100644 index d1c2658dd..000000000 --- a/embassy-net-examples/src/main.rs +++ /dev/null @@ -1,102 +0,0 @@ -#![feature(type_alias_impl_trait)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -use clap::{AppSettings, Clap}; -use embassy::executor::Spawner; -use embassy::io::AsyncWriteExt; -use embassy::util::Forever; -use embassy_net::*; -use embassy_std::Executor; -use heapless::Vec; -use log::*; - -mod tuntap; - -use crate::tuntap::TunTapDevice; - -static DEVICE: Forever = Forever::new(); -static CONFIG: Forever = Forever::new(); - -#[derive(Clap)] -#[clap(version = "1.0")] -#[clap(setting = AppSettings::ColoredHelp)] -struct Opts { - /// TAP device name - #[clap(long, default_value = "tap0")] - tap: String, -} - -#[embassy::task] -async fn net_task() { - embassy_net::run().await -} - -#[embassy::task] -async fn main_task(spawner: Spawner) { - let opts: Opts = Opts::parse(); - - // Init network device - let device = TunTapDevice::new(&opts.tap).unwrap(); - - // Static IP configuration - let config = StaticConfigurator::new(Config { - address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), - dns_servers: Vec::new(), - gateway: Some(Ipv4Address::new(192, 168, 69, 1)), - }); - - // DHCP configruation - let config = DhcpConfigurator::new(); - - // Init network stack - embassy_net::init(DEVICE.put(device), CONFIG.put(config)); - - // Launch network task - spawner.spawn(net_task()).unwrap(); - - // Then we can use it! - let mut rx_buffer = [0; 4096]; - let mut tx_buffer = [0; 4096]; - let mut socket = TcpSocket::new(&mut rx_buffer, &mut tx_buffer); - - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); - - let remote_endpoint = (Ipv4Address::new(192, 168, 69, 74), 8000); - info!("connecting to {:?}...", remote_endpoint); - let r = socket.connect(remote_endpoint).await; - if let Err(e) = r { - warn!("connect error: {:?}", e); - return; - } - info!("connected!"); - loop { - let r = socket.write_all(b"Hello!\n").await; - if let Err(e) = r { - warn!("write error: {:?}", e); - return; - } - } -} - -#[no_mangle] -fn _embassy_rand(buf: &mut [u8]) { - use rand_core::{OsRng, RngCore}; - OsRng.fill_bytes(buf); -} - -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(); - }); -} diff --git a/embassy-net-examples/src/tuntap.rs b/embassy-net-examples/src/tuntap.rs deleted file mode 100644 index dd453deb3..000000000 --- a/embassy-net-examples/src/tuntap.rs +++ /dev/null @@ -1,225 +0,0 @@ -use async_io::Async; -use libc; -use log::*; -use smoltcp::wire::EthernetFrame; -use std::io; -use std::io::{Read, Write}; -use std::os::unix::io::{AsRawFd, RawFd}; - -pub const SIOCGIFMTU: libc::c_ulong = 0x8921; -pub const SIOCGIFINDEX: libc::c_ulong = 0x8933; -pub const ETH_P_ALL: libc::c_short = 0x0003; -pub const TUNSETIFF: libc::c_ulong = 0x400454CA; -pub const IFF_TUN: libc::c_int = 0x0001; -pub const IFF_TAP: libc::c_int = 0x0002; -pub const IFF_NO_PI: libc::c_int = 0x1000; - -#[repr(C)] -#[derive(Debug)] -struct ifreq { - ifr_name: [libc::c_char; libc::IF_NAMESIZE], - ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ -} - -fn ifreq_for(name: &str) -> ifreq { - let mut ifreq = ifreq { - ifr_name: [0; libc::IF_NAMESIZE], - ifr_data: 0, - }; - for (i, byte) in name.as_bytes().iter().enumerate() { - ifreq.ifr_name[i] = *byte as libc::c_char - } - ifreq -} - -fn ifreq_ioctl( - lower: libc::c_int, - ifreq: &mut ifreq, - cmd: libc::c_ulong, -) -> io::Result { - unsafe { - let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq); - if res == -1 { - return Err(io::Error::last_os_error()); - } - } - - Ok(ifreq.ifr_data) -} - -#[derive(Debug)] -pub struct TunTap { - fd: libc::c_int, - ifreq: ifreq, - mtu: usize, -} - -impl AsRawFd for TunTap { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -impl TunTap { - pub fn new(name: &str) -> io::Result { - unsafe { - let fd = libc::open( - "/dev/net/tun\0".as_ptr() as *const libc::c_char, - libc::O_RDWR | libc::O_NONBLOCK, - ); - if fd == -1 { - return Err(io::Error::last_os_error()); - } - - let mut ifreq = ifreq_for(name); - ifreq.ifr_data = IFF_TAP | IFF_NO_PI; - ifreq_ioctl(fd, &mut ifreq, TUNSETIFF)?; - - let socket = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); - if socket == -1 { - return Err(io::Error::last_os_error()); - } - - let ip_mtu = ifreq_ioctl(socket, &mut ifreq, SIOCGIFMTU); - libc::close(socket); - let ip_mtu = ip_mtu? as usize; - - // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.) - // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it. - let mtu = ip_mtu + EthernetFrame::<&[u8]>::header_len(); - - Ok(TunTap { fd, mtu, ifreq }) - } - } -} - -impl Drop for TunTap { - fn drop(&mut self) { - unsafe { - libc::close(self.fd); - } - } -} - -impl io::Read for TunTap { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let len = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len()) }; - if len == -1 { - Err(io::Error::last_os_error()) - } else { - Ok(len as usize) - } - } -} - -impl io::Write for TunTap { - fn write(&mut self, buf: &[u8]) -> io::Result { - let len = unsafe { libc::write(self.fd, buf.as_ptr() as *mut libc::c_void, buf.len()) }; - if len == -1 { - Err(io::Error::last_os_error()) - } else { - Ok(len as usize) - } - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub struct TunTapDevice { - device: Async, - waker: Option, -} - -impl TunTapDevice { - pub fn new(name: &str) -> io::Result { - Ok(Self { - device: Async::new(TunTap::new(name)?)?, - waker: None, - }) - } -} - -use core::task::Waker; -use embassy_net::{DeviceCapabilities, LinkState, Packet, PacketBox, PacketBoxExt, PacketBuf}; -use std::task::Context; - -impl crate::Device for TunTapDevice { - fn is_transmit_ready(&mut self) -> bool { - true - } - - fn transmit(&mut self, pkt: PacketBuf) { - // todo handle WouldBlock - 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 { - let mut pkt = PacketBox::new(Packet::new()).unwrap(); - loop { - match self.device.get_mut().read(&mut pkt[..]) { - Ok(n) => { - return Some(pkt.slice(0..n)); - } - Err(e) if e.kind() == io::ErrorKind::WouldBlock => { - let ready = if let Some(w) = self.waker.as_ref() { - let mut cx = Context::from_waker(w); - let ready = self.device.poll_readable(&mut cx).is_ready(); - ready - } else { - false - }; - if !ready { - return None; - } - } - Err(e) => panic!("read error: {:?}", e), - } - } - } - - fn register_waker(&mut self, w: &Waker) { - match self.waker { - // Optimization: If both the old and new Wakers wake the same task, we can simply - // 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(&mut self) -> DeviceCapabilities { - let mut caps = DeviceCapabilities::default(); - caps.max_transmission_unit = self.device.get_ref().mtu; - caps - } - - fn link_state(&mut self) -> LinkState { - LinkState::Up - } - - fn ethernet_address(&mut self) -> [u8; 6] { - [0x02, 0x03, 0x04, 0x05, 0x06, 0x07] - } -} diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 30970c371..5d391698c 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -25,7 +25,7 @@ log = { version = "0.4.11", optional = true } embassy = { version = "0.1.0", path = "../embassy" } managed = { version = "0.8.0", default-features = false, features = [ "map" ]} -heapless = { version = "0.5.6", default-features = false } +heapless = { version = "0.7.1", default-features = false } as-slice = { version = "0.1.4" } generic-array = { version = "0.14.4", default-features = false } stable_deref_trait = { version = "1.2.0", default-features = false } diff --git a/embassy-net/src/config/mod.rs b/embassy-net/src/config/mod.rs index 16470f7e6..94725dba6 100644 --- a/embassy-net/src/config/mod.rs +++ b/embassy-net/src/config/mod.rs @@ -1,4 +1,3 @@ -use heapless::consts::*; use heapless::Vec; use smoltcp::time::Instant; use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; @@ -29,7 +28,7 @@ pub enum Event { pub struct Config { pub address: Ipv4Cidr, pub gateway: Option, - pub dns_servers: Vec, + pub dns_servers: Vec, } pub trait Configurator { diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 04e89269d..22ffc8937 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -18,4 +18,4 @@ nix = "0.21.0" libc = "0.2.81" clap = { version = "3.0.0-beta.2", features = ["derive"] } rand_core = { version = "0.6.0", features = ["std"] } -heapless = { version = "0.5.6", default-features = false } +heapless = { version = "0.7.1", default-features = false } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index c5c8d9ae6..2c16af5fb 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -32,4 +32,4 @@ embedded-hal = { version = "0.2.4" } panic-probe = { version = "0.2.0", features= ["print-defmt"] } futures = { version = "0.3.8", default-features = false, features = ["async-await"] } rtt-target = { version = "0.3", features = ["cortex-m"] } -heapless = "0.7" \ No newline at end of file +heapless = { version = "0.7.1", default-features = false } \ No newline at end of file