Skip to content

Commit

Permalink
Move to core::net, implement embedded-io-async and release as 0.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
diondokter committed Dec 6, 2024
1 parent 7fa055f commit 8b98ef6
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 76 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 0.6.0 (2024-12-06)

- Added TLS support (https://github.com/diondokter/nrf-modem/pull/26)
- Fixed small socket addres length bug (https://github.com/diondokter/nrf-modem/pull/28)
- Added opt-in non-blocking async DNS resolver (https://github.com/diondokter/nrf-modem/pull/27)
- Exposed as a cargo feature
- Moved to `core::net` instead of using `no-std-net`
- Move MSRV to 1.82 for the raw references and c strings
- Added embedded-io-async traits to Tcp stream types and Tls stream types

## 0.5.1 (2024-08-28)

- Fix documentation generation for docs.rs
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "nrf-modem"
version = "0.5.1"
version = "0.6.0"
edition = "2021"
rust-version = "1.64"
rust-version = "1.82"
license = "MIT OR Apache-2.0"
description = "Async modem api for the nRF91xx"
homepage = "https://github.com/diondokter/nrf-modem"
Expand All @@ -24,11 +24,11 @@ arrayvec = { version = "0.7", default-features = false }
nrf9160-pac = { version = "0.12.2", optional = true }
nrf9120-pac = { version = "0.12.2", optional = true }
at-commands = "0.5.2"
no-std-net = "0.6.0"
critical-section = "1.1"
embassy-sync = "0.6.0"
embassy-time = { version = "0.3.0", optional = true }
grounded = "0.2.0"
embedded-io-async = "0.6.1"

[features]
default = []
Expand All @@ -41,4 +41,4 @@ nrf9161 = ["nrf9120"]
nrf9120 = ["nrfxlib-sys/nrf9120", "dep:nrf9120-pac"]

[package.metadata.docs.rs]
features = ["nrf9160"]
features = ["nrf9160"]
10 changes: 5 additions & 5 deletions src/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub fn send_at_blocking<const CAP: usize>(command: &str) -> Result<ArrayString<C
nrfxlib_sys::nrf_modem_at_cmd(
buffer.as_mut_ptr() as _,
buffer.len(),
b"%.*s\0".as_ptr() as *const core::ffi::c_char,
c"%.*s".as_ptr() as *const core::ffi::c_char,
command.len(),
command.as_ptr(),
)
Expand All @@ -117,7 +117,7 @@ pub fn send_at_blocking<const CAP: usize>(command: &str) -> Result<ArrayString<C
} else {
unsafe {
nrfxlib_sys::nrf_modem_at_printf(
b"%.*s\0".as_ptr() as *const core::ffi::c_char,
c"%.*s".as_ptr() as *const core::ffi::c_char,
command.len(),
command.as_ptr(),
)
Expand All @@ -139,7 +139,7 @@ struct SendATFuture<'c, const CAP: usize> {
response: [u8; CAP],
}

impl<'c, const CAP: usize> Future for SendATFuture<'c, CAP> {
impl<const CAP: usize> Future for SendATFuture<'_, CAP> {
type Output = Result<ArrayString<CAP>, Error>;

fn poll(
Expand Down Expand Up @@ -175,7 +175,7 @@ impl<'c, const CAP: usize> Future for SendATFuture<'c, CAP> {
let result = unsafe {
nrfxlib_sys::nrf_modem_at_cmd_async(
Some(at_callback),
b"%.*s\0".as_ptr() as *const core::ffi::c_char,
c"%.*s".as_ptr() as *const core::ffi::c_char,
self.command.len(),
self.command.as_ptr(),
)
Expand Down Expand Up @@ -214,7 +214,7 @@ impl<'c, const CAP: usize> Future for SendATFuture<'c, CAP> {
}
}

impl<'c, const CAP: usize> Drop for SendATFuture<'c, CAP> {
impl<const CAP: usize> Drop for SendATFuture<'_, CAP> {
fn drop(&mut self) {
match self.state {
SendATState::WaitingOnAccess => {}
Expand Down
2 changes: 1 addition & 1 deletion src/dns/dns_blocking.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{ip::NrfSockAddr, lte_link::LteLink, CancellationToken, Error};
use arrayvec::ArrayString;
use core::net::{IpAddr, SocketAddr};
use core::str::FromStr;
use no_std_net::{IpAddr, SocketAddr};

/// Get the IP address that corresponds to the given hostname.
///
Expand Down
2 changes: 1 addition & 1 deletion src/dtls_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
CancellationToken, CipherSuite, PeerVerification,
};

use no_std_net::SocketAddr;
use core::net::SocketAddr;

pub struct DtlsSocket {
inner: Socket,
Expand Down
33 changes: 33 additions & 0 deletions src/embedded_io_macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
macro_rules! impl_error_trait {
($name:path, $error:path, <$($generics:lifetime),*>) => {
impl<$($generics),*> embedded_io_async::ErrorType for $name {
type Error = $error;
}
};
}

macro_rules! impl_write_trait {
($name:path, <$($generics:lifetime),*>) => {
impl<$($generics),*> embedded_io_async::Write for $name {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
Self::write(self, buf).await?;
Ok(buf.len())
}
}
};
}

macro_rules! impl_read_trait {
($name:path, <$($generics:lifetime),*>) => {
impl<$($generics),*> embedded_io_async::Read for $name {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let read = self.receive(buf).await?;
Ok(read.len())
}
}
};
}

pub(crate) use impl_error_trait;
pub(crate) use impl_read_trait;
pub(crate) use impl_write_trait;
32 changes: 32 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,38 @@ pub enum Error {
DnsParseFailed,
}

impl embedded_io_async::Error for Error {
fn kind(&self) -> embedded_io_async::ErrorKind {
match self {
Error::ModemNotInitialized => embedded_io_async::ErrorKind::Other,
Error::GnssAlreadyTaken => embedded_io_async::ErrorKind::Other,
Error::NrfError(_) => embedded_io_async::ErrorKind::Other,
Error::BufferTooSmall(_) => embedded_io_async::ErrorKind::OutOfMemory,
Error::OutOfMemory => embedded_io_async::ErrorKind::OutOfMemory,
Error::AtParseError(_) => embedded_io_async::ErrorKind::Other,
Error::InvalidSystemModeConfig => embedded_io_async::ErrorKind::Other,
Error::StringNotNulTerminated => embedded_io_async::ErrorKind::InvalidInput,
Error::Utf8Error => embedded_io_async::ErrorKind::InvalidInput,
Error::LteRegistrationDenied => embedded_io_async::ErrorKind::Other,
Error::SimFailure => embedded_io_async::ErrorKind::Other,
Error::UnexpectedAtResponse => embedded_io_async::ErrorKind::Other,
Error::HostnameNotAscii => embedded_io_async::ErrorKind::InvalidInput,
Error::HostnameTooLong => embedded_io_async::ErrorKind::InvalidInput,
Error::AddressNotFound => embedded_io_async::ErrorKind::Other,
Error::SocketOptionError(_) => embedded_io_async::ErrorKind::Other,
Error::OperationCancelled => embedded_io_async::ErrorKind::Other,
Error::SmsNumberNotAscii => embedded_io_async::ErrorKind::Other,
Error::Disconnected => embedded_io_async::ErrorKind::ConnectionReset,
Error::TooManyLteLinks => embedded_io_async::ErrorKind::Other,
Error::InternalRuntimeMutexLocked => embedded_io_async::ErrorKind::Other,
Error::BadMemoryLayout => embedded_io_async::ErrorKind::Other,
Error::ModemAlreadyInitialized => embedded_io_async::ErrorKind::Other,
Error::TlsPacketTooBig => embedded_io_async::ErrorKind::Other,
Error::NoSecurityTag => embedded_io_async::ErrorKind::Other,
}
}
}

pub trait ErrorSource {
fn into_result(self) -> Result<(), Error>;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ip.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::socket::SocketFamily;
// use core::mem::size_of;
use no_std_net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use core::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use nrfxlib_sys::{nrf_sockaddr, nrf_sockaddr_in, nrf_sockaddr_in6};

pub enum NrfSockAddr {
Expand Down
16 changes: 9 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod at_notifications;
mod cancellation;
mod dns;
mod dtls_socket;
pub(crate) mod embedded_io_macros;
mod error;
pub mod ffi;
mod gnss;
Expand All @@ -29,7 +30,6 @@ mod tls_stream;
mod udp_socket;
pub(crate) mod waker_node_list;

pub use no_std_net;
pub use nrfxlib_sys;

pub use at::*;
Expand Down Expand Up @@ -71,7 +71,7 @@ type WrappedHeap = Mutex<RefCell<Option<Heap>>>;
static LIBRARY_ALLOCATOR: WrappedHeap = Mutex::new(RefCell::new(None));

/// Our transmit heap.
///
/// We initalise this later using a special region of shared memory that can be
/// seen by the Cortex-M33 and the modem CPU.
static TX_ALLOCATOR: WrappedHeap = Mutex::new(RefCell::new(None));
Expand Down Expand Up @@ -119,12 +119,14 @@ pub async fn init_with_custom_layout(
}

unsafe {
const HEAP_SIZE: usize = 1024;
/// Allocate some space in global data to use as a heap.
static mut HEAP_MEMORY: [u32; 1024] = [0u32; 1024];
let heap_start = HEAP_MEMORY.as_ptr() as *mut u8;
let heap_size = HEAP_MEMORY.len() * core::mem::size_of::<u32>();
static mut HEAP_MEMORY: [u32; HEAP_SIZE] = [0u32; HEAP_SIZE];
let heap_start = &raw mut HEAP_MEMORY;
let heap_size = HEAP_SIZE * core::mem::size_of::<u32>();
critical_section::with(|cs| {
*LIBRARY_ALLOCATOR.borrow(cs).borrow_mut() = Some(Heap::new(heap_start, heap_size))
*LIBRARY_ALLOCATOR.borrow(cs).borrow_mut() =
Some(Heap::new(heap_start.cast::<u8>(), heap_size))
});
}

Expand Down Expand Up @@ -210,7 +212,7 @@ pub async fn init_with_custom_layout(
/// The full range needs to be in the lower 128k of ram.
/// This also contains the fixed [nrfxlib_sys::NRF_MODEM_SHMEM_CTRL_SIZE].
///
/// Nordic guide: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.1/nrfxlib/nrf_modem/doc/architecture.html#shared-memory-configuration
/// Nordic guide: <https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.1/nrfxlib/nrf_modem/doc/architecture.html#shared-memory-configuration>
pub struct MemoryLayout {
/// The start of the memory area
pub base_address: u32,
Expand Down
4 changes: 2 additions & 2 deletions src/socket.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::{
error::Error, ffi::get_last_error, ip::NrfSockAddr, lte_link::LteLink, CancellationToken,
};
use core::net::SocketAddr;
use core::{
cell::RefCell,
ops::{BitOr, BitOrAssign, Deref, Neg},
sync::atomic::{AtomicU8, Ordering},
task::{Poll, Waker},
};
use critical_section::Mutex;
use no_std_net::SocketAddr;
use num_enum::{IntoPrimitive, TryFromPrimitive};

// use 16 slots for wakers instead of 8, which is the max number of sockets allowed, so they
Expand Down Expand Up @@ -701,7 +701,7 @@ pub enum SocketOption<'a> {
TlsTagList(&'a [nrfxlib_sys::nrf_sec_tag_t]),
TlsCipherSuiteList(&'a [i32]),
}
impl<'a> SocketOption<'a> {
impl SocketOption<'_> {
pub(crate) fn get_name(&self) -> i32 {
match self {
SocketOption::TlsHostName(_) => nrfxlib_sys::NRF_SO_SEC_HOSTNAME as i32,
Expand Down
58 changes: 34 additions & 24 deletions src/tcp_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
socket::{Socket, SocketFamily, SocketProtocol, SocketType, SplitSocketHandle},
CancellationToken, LteLink,
};
use no_std_net::ToSocketAddrs;
use core::net::SocketAddr;

/// A TCP stream that is connected to another endpoint
pub struct TcpStream {
Expand Down Expand Up @@ -105,43 +105,37 @@ macro_rules! impl_write {

impl TcpStream {
/// Connect a TCP stream to the given address
pub async fn connect(addr: impl ToSocketAddrs) -> Result<Self, Error> {
pub async fn connect(addr: SocketAddr) -> Result<Self, Error> {
Self::connect_with_cancellation(addr, &Default::default()).await
}

/// Connect a TCP stream to the given address
pub async fn connect_with_cancellation(
addr: impl ToSocketAddrs,
addr: SocketAddr,
token: &CancellationToken,
) -> Result<Self, Error> {
let mut last_error = None;
let lte_link = LteLink::new().await?;
let addrs = addr.to_socket_addrs().unwrap();

for addr in addrs {
token.as_result()?;
token.as_result()?;

let family = match addr {
no_std_net::SocketAddr::V4(_) => SocketFamily::Ipv4,
no_std_net::SocketAddr::V6(_) => SocketFamily::Ipv6,
};
let family = match addr {
SocketAddr::V4(_) => SocketFamily::Ipv4,
SocketAddr::V6(_) => SocketFamily::Ipv6,
};

let socket = Socket::create(family, SocketType::Stream, SocketProtocol::Tcp).await?;
let socket = Socket::create(family, SocketType::Stream, SocketProtocol::Tcp).await?;

match unsafe { socket.connect(addr, token).await } {
Ok(_) => {
lte_link.deactivate().await?;
return Ok(TcpStream { inner: socket });
}
Err(e) => {
last_error = Some(e);
socket.deactivate().await?;
}
match unsafe { socket.connect(addr, token).await } {
Ok(_) => {
lte_link.deactivate().await?;
Ok(TcpStream { inner: socket })
}
Err(e) => {
lte_link.deactivate().await?;
socket.deactivate().await?;
Err(e)
}
}

lte_link.deactivate().await?;
Err(last_error.take().unwrap())
}

/// Get the raw underlying file descriptor for when you need to interact with the nrf libraries directly
Expand Down Expand Up @@ -184,6 +178,10 @@ impl TcpStream {
}
}

crate::embedded_io_macros::impl_error_trait!(TcpStream, Error, <>);
crate::embedded_io_macros::impl_read_trait!(TcpStream, <>);
crate::embedded_io_macros::impl_write_trait!(TcpStream, <>);

/// A borrowed read half of a TCP stream
pub struct TcpReadStream<'a> {
stream: &'a TcpStream,
Expand All @@ -197,6 +195,9 @@ impl<'a> TcpReadStream<'a> {
impl_receive!();
}

crate::embedded_io_macros::impl_error_trait!(TcpReadStream<'a>, Error, <'a>);
crate::embedded_io_macros::impl_read_trait!(TcpReadStream<'a>, <'a>);

/// A borrowed write half of a TCP stream
pub struct TcpWriteStream<'a> {
stream: &'a TcpStream,
Expand All @@ -210,6 +211,9 @@ impl<'a> TcpWriteStream<'a> {
impl_write!();
}

crate::embedded_io_macros::impl_error_trait!(TcpWriteStream<'a>, Error, <'a>);
crate::embedded_io_macros::impl_write_trait!(TcpWriteStream<'a>, <'a>);

/// An owned read half of a TCP stream
pub struct OwnedTcpReadStream {
stream: SplitSocketHandle,
Expand All @@ -230,6 +234,9 @@ impl OwnedTcpReadStream {
}
}

crate::embedded_io_macros::impl_error_trait!(OwnedTcpReadStream, Error, <>);
crate::embedded_io_macros::impl_read_trait!(OwnedTcpReadStream, <>);

/// An owned write half of a TCP stream
pub struct OwnedTcpWriteStream {
stream: SplitSocketHandle,
Expand All @@ -249,3 +256,6 @@ impl OwnedTcpWriteStream {
Ok(())
}
}

crate::embedded_io_macros::impl_error_trait!(OwnedTcpWriteStream, Error, <>);
crate::embedded_io_macros::impl_write_trait!(OwnedTcpWriteStream, <>);
Loading

0 comments on commit 8b98ef6

Please sign in to comment.