Skip to content

Commit

Permalink
Update esp-hal to 0.20.1. Decompose RX, TX buffer sizes. Fix exampl…
Browse files Browse the repository at this point in the history
…es. (#45)

* refactor: Decompose BUFFER_SIZE into RX_SIZE and TX_SIZE

- The RX and TX buffers can now be set to use independent sizes.
- Re-order rx, tx according to discussed API guidelines.
- Fix async server examples who called `make_static!()` more than once.

* chore: Update esp-hal to `0.20.1`

- Update esp-hal to `0.20.1`.
- Fix `edge_server.rs` example by using a buffer pool like in `edge_nal_embassy`.
  • Loading branch information
AnthonyGrondin authored Sep 2, 2024
1 parent e8a33f2 commit 7de5d0a
Show file tree
Hide file tree
Showing 17 changed files with 383 additions and 291 deletions.
18 changes: 9 additions & 9 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ xtask = "run --manifest-path ./xtask/Cargo.toml --"
# Alias' for quickly building for different chips or running examples
# By default we enable
# - `default` HAL features to set up basic chip specific settings
esp32 = "run --features esp32 --target xtensa-esp32-none-elf --features esp-hal/default"
esp32s2 = "run --features esp32s2 --target xtensa-esp32s2-none-elf --features esp-hal/default"
esp32s3 = "run --features esp32s3 --target xtensa-esp32s3-none-elf --features esp-hal/default"
esp32c3 = "run --features esp32c3 --target riscv32imc-unknown-none-elf --features esp-hal/default"

besp32 = "build --features esp32 --target xtensa-esp32-none-elf --features esp-hal/default"
besp32s2 = "build --features esp32s2 --target xtensa-esp32s2-none-elf --features esp-hal/default"
besp32s3 = "build --features esp32s3 --target xtensa-esp32s3-none-elf --features esp-hal/default"
besp32c3 = "build --features esp32c3 --target riscv32imc-unknown-none-elf --features esp-hal/default"
esp32 = "run --release --features esp32 --target xtensa-esp32-none-elf --features esp-hal/default"
esp32s2 = "run --release --features esp32s2 --target xtensa-esp32s2-none-elf --features esp-hal/default"
esp32s3 = "run --release --features esp32s3 --target xtensa-esp32s3-none-elf --features esp-hal/default"
esp32c3 = "run --release --features esp32c3 --target riscv32imc-unknown-none-elf --features esp-hal/default"

besp32 = "build --release --features esp32 --target xtensa-esp32-none-elf --features esp-hal/default"
besp32s2 = "build --release --features esp32s2 --target xtensa-esp32s2-none-elf --features esp-hal/default"
besp32s3 = "build --release --features esp32s3 --target xtensa-esp32s3-none-elf --features esp-hal/default"
besp32c3 = "build --release --features esp32c3 --target riscv32imc-unknown-none-elf --features esp-hal/default"
13 changes: 7 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ lto = false
opt-level = 3

[dependencies]
esp-hal = { version = "0.19.0" }
esp-backtrace = { version = "0.13.0", features = [
esp-hal = { version = "0.20.1" }
esp-backtrace = { version = "0.14.0", features = [
"panic-handler",
"println",
"exception-handler",
] }
esp-println = { version = "0.10.0", features = ["log"] }
esp-hal-embassy = { version = "0.2.0", optional = true }
esp-println = { version = "0.11.0", features = ["log"] }
esp-hal-embassy = { version = "0.3.0", optional = true }

embassy-time = { version = "0.3.0", optional = true }
embassy-executor = { version = "0.5.0", package = "embassy-executor", features = [
embassy-executor = { version = "0.6.0", package = "embassy-executor", features = [
"nightly",
"integrated-timers",
], optional = true }
Expand All @@ -42,7 +42,7 @@ embassy-net = { version = "0.4.0", features = [
], optional = true }


esp-wifi = { version = "0.7.1", features = [
esp-wifi = { version = "0.8.0", features = [
"phy-enable-usb",
"embedded-svc",
"wifi-default",
Expand All @@ -69,6 +69,7 @@ esp-mbedtls = { path = "./esp-mbedtls" }

edge-http = { package = "edge-http", git = "https://github.com/ivmarkov/edge-net/", optional = true }
edge-nal-embassy = { package = "edge-nal-embassy", git = "https://github.com/ivmarkov/edge-net/", optional = true }
cfg-if = "1.0.0"

[[example]]
name = "crypto_self_test"
Expand Down
2 changes: 1 addition & 1 deletion esp-mbedtls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ log = "0.4.17"
embedded-io = { version = "0.6.1" }
embedded-io-async = { version = "0.6.0", optional = true }
crypto-bigint = { version = "0.5.3", default-features = false, features = ["extra-sizes"] }
esp-hal = { version = "0.19.0" }
esp-hal = { version = "0.20.1" }
cfg-if = "1.0.0"
edge-nal = { package = "edge-nal", git = "https://github.com/ivmarkov/edge-net/", optional = true }
edge-nal-embassy = { package = "edge-nal-embassy", git = "https://github.com/ivmarkov/edge-net/", optional = true }
Expand Down
190 changes: 190 additions & 0 deletions esp-mbedtls/src/compat/edge_nal_compat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use crate::asynch::{AsyncConnectedSession, Session};
use crate::{Certificates, Mode, Peripheral, Rsa, TlsError, TlsVersion, RSA, RSA_REF};
use core::{
cell::{Cell, RefCell, UnsafeCell},
mem::MaybeUninit,
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
ptr::NonNull,
};

use edge_nal::TcpBind;
use edge_nal_embassy::{Tcp, TcpAccept, TcpSocket};

pub struct TlsAcceptor<
'd,
D: embassy_net::driver::Driver,
const N: usize,
const RX_SZ: usize,
const TX_SZ: usize,
> {
acceptor: TcpAccept<'d, D, N, TX_SZ, RX_SZ>,
version: TlsVersion,
certificates: Certificates<'d>,
owns_rsa: bool,
tls_buffers: &'d TlsBuffers<RX_SZ, TX_SZ>,
tls_buffers_ptr: RefCell<NonNull<([u8; RX_SZ], [u8; TX_SZ])>>,
}

impl<'d, D, const N: usize, const RX_SZ: usize, const TX_SZ: usize> Drop
for TlsAcceptor<'d, D, N, RX_SZ, TX_SZ>
where
D: embassy_net::driver::Driver,
{
fn drop(&mut self) {
unsafe {
// If the struct that owns the RSA reference is dropped
// we remove RSA in static for safety
if self.owns_rsa {
log::debug!("Freeing RSA from acceptor");
RSA_REF = core::mem::transmute(None::<RSA>);
}

self.tls_buffers.pool.free(*self.tls_buffers_ptr.get_mut());
}
}
}

impl<'d, D, const N: usize, const RX_SZ: usize, const TX_SZ: usize>
TlsAcceptor<'d, D, N, RX_SZ, TX_SZ>
where
D: embassy_net::driver::Driver,
{
pub async fn new(
tcp: &'d Tcp<'d, D, N, TX_SZ, RX_SZ>,
tls_buffers: &'d TlsBuffers<RX_SZ, TX_SZ>,
port: u16,
version: TlsVersion,
certificates: Certificates<'d>,
) -> Self {
let acceptor = tcp
.bind(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(0, 0, 0, 0),
port,
)))
.await
.unwrap();

let socket_buffers = tls_buffers.pool.alloc().unwrap();

Self {
acceptor,
version,
certificates,
owns_rsa: false,
tls_buffers,
tls_buffers_ptr: RefCell::new(socket_buffers),
}
}

/// Enable the use of the hardware accelerated RSA peripheral for the lifetime of
/// [TlsAcceptor].
///
/// # Arguments
///
/// * `rsa` - The RSA peripheral from the HAL
pub fn with_hardware_rsa(mut self, rsa: impl Peripheral<P = RSA>) -> Self {
unsafe { RSA_REF = core::mem::transmute(Some(Rsa::new(rsa))) }
self.owns_rsa = true;
self
}
}

impl<'a, T, const RX_SIZE: usize, const TX_SIZE: usize> edge_nal::Readable
for AsyncConnectedSession<'a, T, RX_SIZE, TX_SIZE>
where
T: embedded_io_async::Read + embedded_io_async::Write,
{
async fn readable(&mut self) -> Result<(), Self::Error> {
unimplemented!();
}
}

impl<'d, D, const N: usize, const RX_SZ: usize, const TX_SZ: usize> edge_nal::TcpAccept
for TlsAcceptor<'d, D, N, RX_SZ, TX_SZ>
where
D: embassy_net::driver::Driver,
{
type Error = TlsError;
type Socket<'a> = AsyncConnectedSession<'a, TcpSocket<'a, N, TX_SZ, RX_SZ>, RX_SZ, TX_SZ> where Self: 'a;

async fn accept(
&self,
) -> Result<(SocketAddr, Self::Socket<'_>), <Self as edge_nal::TcpAccept>::Error> {
let (addr, socket) = self
.acceptor
.accept()
.await
.map_err(|e| TlsError::TcpError(e))?;
log::debug!("Accepted new connection on socket");

let (rx, tx) = unsafe { self.tls_buffers_ptr.borrow_mut().as_mut() };

let session: Session<_, RX_SZ, TX_SZ> = Session::new(
socket,
"",
Mode::Server,
self.version,
self.certificates,
rx,
tx,
)?;

log::debug!("Establishing SSL connection");
let connected_session = session.connect().await?;

Ok((addr, connected_session))
}
}

/// A struct that holds a pool of TLS buffers
pub struct TlsBuffers<const RX_SZ: usize, const TX_SZ: usize> {
pool: Pool<([u8; RX_SZ], [u8; TX_SZ]), 1>,
}

impl<const RX_SZ: usize, const TX_SZ: usize> TlsBuffers<RX_SZ, TX_SZ> {
/// Create a new `TlsBuffers` instance
pub const fn new() -> Self {
Self { pool: Pool::new() }
}
}

pub(crate) struct Pool<T, const N: usize> {
used: [Cell<bool>; N],
data: [UnsafeCell<MaybeUninit<T>>; N],
}

impl<T, const N: usize> Pool<T, N> {
#[allow(clippy::declare_interior_mutable_const)]
const VALUE: Cell<bool> = Cell::new(false);
const UNINIT: UnsafeCell<MaybeUninit<T>> = UnsafeCell::new(MaybeUninit::uninit());

const fn new() -> Self {
Self {
used: [Self::VALUE; N],
data: [Self::UNINIT; N],
}
}
}

impl<T, const N: usize> Pool<T, N> {
fn alloc(&self) -> Option<NonNull<T>> {
for n in 0..N {
// this can't race because Pool is not Sync.
if !self.used[n].get() {
self.used[n].set(true);
let p = self.data[n].get() as *mut T;
return Some(unsafe { NonNull::new_unchecked(p) });
}
}
None
}

/// safety: p must be a pointer obtained from self.alloc that hasn't been freed yet.
unsafe fn free(&self, p: NonNull<T>) {
let origin = self.data.as_ptr() as *mut T;
let n = p.as_ptr().offset_from(origin);
assert!(n >= 0);
assert!((n as usize) < N);
self.used[n as usize].set(false);
}
}
4 changes: 4 additions & 0 deletions esp-mbedtls/src/compat.rs → esp-mbedtls/src/compat/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use core::ffi::VaListImpl;
use core::fmt::Write;

/// Implements edge-nal traits
#[cfg(feature = "edge-nal")]
pub mod edge_nal_compat;

#[no_mangle]
pub unsafe extern "C" fn snprintf(dst: *mut u8, n: u32, format: *const u8, args: ...) -> i32 {
vsnprintf(dst, n, format, args)
Expand Down
Loading

0 comments on commit 7de5d0a

Please sign in to comment.