Skip to content

Commit

Permalink
Make utils feature independent of embedded-svc feature
Browse files Browse the repository at this point in the history
  • Loading branch information
bjoernQ committed Sep 21, 2022
1 parent 7d306f7 commit ec39588
Show file tree
Hide file tree
Showing 4 changed files with 317 additions and 321 deletions.
2 changes: 1 addition & 1 deletion examples/coex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use ble_hci::{
att::Uuid,
Ble, HciConnector,
};
use esp_wifi::{ble::controller::BleConnector, current_millis, wifi::utils::Network};
use esp_wifi::{ble::controller::BleConnector, current_millis, wifi_interface::Network};

use embedded_io::blocking::*;
use embedded_svc::wifi::{
Expand Down
4 changes: 2 additions & 2 deletions examples/dhcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use embedded_svc::wifi::{
use esp_backtrace as _;
use esp_println::logger::init_logger;
use esp_println::{print, println};
use esp_wifi::wifi::utils::{create_network_interface, Network};
use esp_wifi::wifi_interface::{timestamp, WifiError};
use esp_wifi::wifi::utils::{create_network_interface};
use esp_wifi::wifi_interface::{timestamp, WifiError, Network};
use esp_wifi::{create_network_stack_storage, network_stack_storage};
use esp_wifi::{current_millis, initialize};
use hal::clock::{ClockControl, CpuClock};
Expand Down
315 changes: 0 additions & 315 deletions src/wifi/utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
use core::cell::RefCell;
use embedded_io::blocking::Read;
use embedded_io::blocking::Write;
use embedded_io::Io;
use smoltcp::iface::SocketHandle;
use smoltcp::time::Instant;
use smoltcp::wire::Ipv4Address;
use smoltcp::{
iface::{Interface, InterfaceBuilder, Neighbor, NeighborCache, Route, Routes, SocketStorage},
socket::{Dhcpv4Socket, TcpSocket, TcpSocketBuffer},
Expand Down Expand Up @@ -94,311 +87,3 @@ pub fn create_network_interface<'a>(

ethernet
}

// Following code is not well tested, yet.
// It's currently more or less just here for the DHCP example.
// Might get replaced or improved in future.

pub struct Network<'a> {
interface: RefCell<crate::wifi_interface::Wifi<'a>>,
current_millis_fn: fn() -> u64,
local_port: RefCell<u16>,
}

impl<'a> Network<'a> {
pub fn new(
interface: crate::wifi_interface::Wifi<'a>,
current_millis_fn: fn() -> u64,
) -> Network {
Self {
interface: RefCell::new(interface),
current_millis_fn,
local_port: RefCell::new(41000),
}
}

fn with_interface<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut crate::wifi_interface::Wifi<'a>) -> R,
{
let mut interface = self.interface.borrow_mut();
f(&mut interface)
}

pub fn get_socket<'s>(&'s mut self) -> Socket<'s, 'a>
where
'a: 's,
{
let socket_handle = self.with_interface(|interface| {
let (socket_handle, _) = interface.network_interface().sockets_mut().next().unwrap();
socket_handle
});

Socket {
socket_handle,
network: self,
}
}

pub fn work(&self) {
loop {
self.with_interface(|interface| interface.poll_dhcp().ok());
if let Ok(false) = self.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis((self.current_millis_fn)() as i64))
}) {
break;
}
}
}

fn next_local_port(&self) -> u16 {
let mut local_port = self.local_port.borrow_mut();
*local_port += 1;
if *local_port == 65535 {
*local_port = 41000;
}
*local_port
}
}

pub struct Socket<'s, 'n: 's> {
socket_handle: SocketHandle,
network: &'s Network<'n>,
}

impl<'s, 'n: 's> Socket<'s, 'n> {
pub fn open<'i>(&'i mut self, addr: Ipv4Address, port: u16) -> Result<(), IoError>
where
's: 'i,
{
{
self.network.with_interface(|interface| {
let (sock, cx) = interface
.network_interface()
.get_socket_and_context::<TcpSocket>(self.socket_handle);
let remote_endpoint = (addr, port);
sock.connect(cx, remote_endpoint, self.network.next_local_port())
.unwrap();
});
}

loop {
let can_send = self.network.with_interface(|interface| {
let sock = interface
.network_interface()
.get_socket::<TcpSocket>(self.socket_handle);
if sock.can_send() {
true
} else {
false
}
});

if can_send {
break;
}

self.work();
}

Ok(())
}

pub fn disconnect(&mut self) {
self.network.with_interface(|interface| {
interface
.network_interface()
.get_socket::<TcpSocket>(self.socket_handle)
.abort();
});

self.work();
}

pub fn work(&mut self) {
loop {
self.network
.with_interface(|interface| interface.poll_dhcp().ok());
if let Ok(false) = self.network.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis(
(self.network.current_millis_fn)() as i64
))
}) {
break;
}
}
}
}

#[derive(Debug)]
pub enum IoError {
Other(smoltcp::Error),
SocketClosed,
}

impl embedded_io::Error for IoError {
fn kind(&self) -> embedded_io::ErrorKind {
embedded_io::ErrorKind::Other
}
}

impl From<smoltcp::Error> for IoError {
fn from(e: smoltcp::Error) -> Self {
IoError::Other(e)
}
}

impl<'s, 'n: 's> Io for Socket<'s, 'n> {
type Error = IoError;
}

impl<'s, 'n: 's> Read for Socket<'s, 'n> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
loop {
self.network.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis(
(self.network.current_millis_fn)() as i64
))
.unwrap();
});

let (may_recv, is_open, can_recv) = self.network.with_interface(|interface| {
let socket = interface
.network_interface()
.get_socket::<TcpSocket>(self.socket_handle);

(socket.may_recv(), socket.is_open(), socket.can_recv())
});
if may_recv {
break;
}

if !is_open {
return Err(IoError::SocketClosed);
}

if !can_recv {
return Err(IoError::SocketClosed);
}
}

loop {
let res = self.network.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis(
(self.network.current_millis_fn)() as i64
))
});

if let Ok(false) = res {
break;
}
}

self.network.with_interface(|interface| {
let socket = interface
.network_interface()
.get_socket::<TcpSocket>(self.socket_handle);

socket.recv_slice(buf).map_err(|e| IoError::Other(e))
})
}
}

impl<'s, 'n: 's> Write for Socket<'s, 'n> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
loop {
self.network.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis(
(self.network.current_millis_fn)() as i64
))
.unwrap();
});

let (may_send, is_open, can_send) = self.network.with_interface(|interface| {
let socket = interface
.network_interface()
.get_socket::<TcpSocket>(self.socket_handle);

(socket.may_send(), socket.is_open(), socket.can_send())
});

if may_send {
break;
}

if !is_open {
return Err(IoError::SocketClosed);
}

if !can_send {
return Err(IoError::SocketClosed);
}
}

loop {
let res = self.network.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis(
(self.network.current_millis_fn)() as i64
))
});

if let Ok(false) = res {
break;
}
}

let res = self.network.with_interface(|interface| {
let socket = interface
.network_interface()
.get_socket::<TcpSocket>(self.socket_handle);

let mut written = 0;
loop {
match socket.send_slice(&buf[written..]) {
Ok(len) => {
written += len;

if written >= buf.len() {
break Ok(written);
}

log::info!("not fully written: {}", len);
}
Err(err) => break Err(IoError::Other(err)),
}
}
});

res
}

fn flush(&mut self) -> Result<(), Self::Error> {
loop {
let res = self.network.with_interface(|interface| {
interface
.network_interface()
.poll(Instant::from_millis(
(self.network.current_millis_fn)() as i64
))
});

if let Ok(false) = res {
break;
}
}

Ok(())
}
}
Loading

0 comments on commit ec39588

Please sign in to comment.