use core::{ cell::RefCell, task::Waker, }; use alloc::vec::Vec; use smoltcp::{ iface::EthernetInterface, phy::Device, socket::SocketSet, time::Instant, }; use crate::task; mod tcp_stream; pub use tcp_stream::TcpStream; static mut SOCKETS: Option = None; pub struct Sockets { sockets: RefCell>, wakers: RefCell>, } impl Sockets { pub fn init(max_sockets: usize) { let mut sockets_storage = Vec::with_capacity(max_sockets); for _ in 0..max_sockets { sockets_storage.push(None); } let sockets = RefCell::new(SocketSet::new(sockets_storage)); let wakers = RefCell::new(Vec::new()); let instance = Sockets { sockets, wakers, }; unsafe { SOCKETS = Some(instance); } } /// Block and run executor indefinitely while polling the smoltcp /// iface pub fn run<'b, 'c, 'e, D: for<'d> Device<'d>>(iface: &mut EthernetInterface<'b, 'c, 'e, D>) { task::block_on(async { loop { Self::instance().poll(iface); task::r#yield().await; } }); } pub(crate) fn instance() -> &'static Self { unsafe { SOCKETS.as_ref().expect("Sockets") } } fn poll<'b, 'c, 'e, D: for<'d> Device<'d>>(&self, iface: &mut EthernetInterface<'b, 'c, 'e, D>) { // TODO: let instant = Instant::from_millis(0); let processed = { let mut sockets = self.sockets.borrow_mut(); match iface.poll(&mut sockets, instant) { Ok(processed) => processed, Err(_) => true, } }; if processed { let mut wakers = self.wakers.borrow_mut(); for waker in wakers.drain(..) { waker.wake(); } } } /// TODO: this was called through eg. TcpStream, another poll() /// might want to send packets before sleeping for an interrupt. pub(crate) fn register_waker(waker: Waker) { Self::instance().wakers.borrow_mut() .push(waker); } }