Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tls options #1

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
// override the default setting (`cargo check --all-targets`) which produces the following error
// "can't find crate for `test`" when the default compilation target is a no_std target
// with these changes RA will call `cargo check --bins` on save
"rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.cargo.target": "thumbv7em-none-eabihf",
"rust-analyzer.diagnostics.disabled": [
"unresolved-import"
]
}
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ categories = ["embedded", "hardware-support", "no-std", "network-programming"]
nb = "1"
no-std-net = "0.4"
heapless = "^0.5"

[features]
default = ["tls"]

tls = []
110 changes: 110 additions & 0 deletions src/addr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
pub use no_std_net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};

use core::str::FromStr;
use heapless::{consts::U256, String};

use crate::Dns;

#[derive(Clone, Debug)]
pub struct HostAddr {
ip: IpAddr,
hostname: Option<String<U256>>,
}

impl HostAddr {
pub fn new(ip: IpAddr, hostname: Option<String<U256>>) -> Self {
HostAddr { ip, hostname }
}

pub fn ipv4(octets: [u8; 4]) -> HostAddr {
HostAddr {
ip: IpAddr::from(octets),
hostname: None,
}
}

pub fn ipv6(octets: [u8; 16]) -> HostAddr {
HostAddr {
ip: IpAddr::from(octets),
hostname: None,
}
}

pub fn ip(&self) -> IpAddr {
self.ip
}

pub fn try_from_hostname<D: Dns>(dns: &D, hostname: &str) -> Result<Self, D::Error> {
dns.get_host_by_name(hostname, crate::AddrType::Either)
}

pub fn hostname(&self) -> Option<&str> {
self.hostname.as_deref()
}
}

#[derive(Clone, Debug)]
pub struct AddrParseError;

impl FromStr for HostAddr {
type Err = AddrParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(HostAddr::new(
IpAddr::from_str(s).map_err(|_| AddrParseError)?,
Some(String::from_str(s).unwrap()),
))
}
}

impl From<IpAddr> for HostAddr {
fn from(ip: IpAddr) -> Self {
HostAddr { ip, hostname: None }
}
}

impl From<Ipv4Addr> for HostAddr {
fn from(ip: Ipv4Addr) -> Self {
HostAddr { ip: ip.into(), hostname: None }
}
}

impl From<Ipv6Addr> for HostAddr {
fn from(ip: Ipv6Addr) -> Self {
HostAddr { ip: ip.into(), hostname: None }
}
}

#[derive(Clone, Debug)]
pub struct HostSocketAddr {
addr: HostAddr,
port: u16,
}

impl From<SocketAddr> for HostSocketAddr {
fn from(s: SocketAddr) -> Self {
Self::new(HostAddr::new(s.ip(), None), s.port())
}
}

impl HostSocketAddr {
pub fn new(addr: HostAddr, port: u16) -> HostSocketAddr {
HostSocketAddr { addr, port }
}

pub fn from(addr: &str, port: u16) -> Result<HostSocketAddr, AddrParseError> {
Ok(Self::new(HostAddr::from_str(addr)?, port))
}

pub fn addr(&self) -> &HostAddr {
&self.addr
}

pub fn port(&self) -> u16 {
self.port
}

pub fn as_socket_addr(&self) -> SocketAddr {
SocketAddr::new(self.addr.ip, self.port)
}
}
6 changes: 3 additions & 3 deletions src/dns.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heapless::{consts, String};
use no_std_net::IpAddr;
use crate::addr::HostAddr;

/// This is the host address type to be returned by `gethostbyname`.
///
Expand Down Expand Up @@ -31,13 +31,13 @@ pub trait Dns {

/// Resolve the first ip address of a host, given its hostname and a desired
/// address record type to look for
fn get_host_by_name(&self, hostname: &str, addr_type: AddrType) -> Result<IpAddr, Self::Error>;
fn get_host_by_name(&self, hostname: &str, addr_type: AddrType) -> Result<HostAddr, Self::Error>;

/// Resolve the hostname of a host, given its ip address
///
/// **Note**: A fully qualified domain name (FQDN), has a maximum length of
/// 255 bytes [`rfc1035`]
///
/// [`rfc1035`]: https://tools.ietf.org/html/rfc1035
fn get_host_by_address(&self, addr: IpAddr) -> Result<String<consts::U256>, Self::Error>;
fn get_host_by_address(&self, addr: IpAddr) -> Result<HostAddr, Self::Error>;
}
21 changes: 13 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
//! # embedded-nal - A Network Abstraction Layer for Embedded Systems

//!
#![doc(html_root_url = "https://docs.rs/embedded-nal/0.2.0")]
#![no_std]
#![deny(missing_docs)]
// #![deny(missing_docs)]
#![deny(unsafe_code)]

pub use nb;
mod dns;
mod addr;

#[cfg(feature = "tls")]
pub mod tls;
pub use addr::{HostAddr, HostSocketAddr};
pub use nb;
pub use dns::{AddrType, Dns};

pub use no_std_net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
Expand Down Expand Up @@ -35,7 +40,7 @@ pub trait TcpClientStack {
fn connect(
&self,
socket: &mut Self::TcpSocket,
remote: SocketAddr,
remote: HostSocketAddr,
) -> nb::Result<(), Self::Error>;

/// Check if this socket is connected
Expand Down Expand Up @@ -85,7 +90,7 @@ pub trait TcpFullStack: TcpClientStack {
fn accept(
&self,
socket: &mut Self::TcpSocket,
) -> nb::Result<(Self::TcpSocket, SocketAddr), Self::Error>;
) -> nb::Result<(Self::TcpSocket, HostSocketAddr), Self::Error>;
}

/// This trait is implemented by UDP/IP stacks. You could, for example, have
Expand All @@ -105,7 +110,7 @@ pub trait UdpClientStack {
/// Connect a UDP socket with a peer using a dynamically selected port.
///
/// Selects a port number automatically and initializes for read/writing.
fn connect(&self, socket: &mut Self::UdpSocket, remote: SocketAddr) -> Result<(), Self::Error>;
fn connect(&self, socket: &mut Self::UdpSocket, remote: HostSocketAddr) -> Result<(), Self::Error>;

/// Send a datagram to the remote host.
///
Expand All @@ -123,7 +128,7 @@ pub trait UdpClientStack {
&self,
socket: &mut Self::UdpSocket,
buffer: &mut [u8],
) -> nb::Result<(usize, SocketAddr), Self::Error>;
) -> nb::Result<(usize, HostSocketAddr), Self::Error>;

/// Close an existing UDP socket.
fn close(&self, socket: Self::UdpSocket) -> Result<(), Self::Error>;
Expand All @@ -139,7 +144,7 @@ pub trait UdpFullStack: UdpClientStack {
fn send_to(
&self,
socket: &mut Self::UdpSocket,
remote: SocketAddr,
remote: HostSocketAddr,
buffer: &[u8],
) -> nb::Result<(), Self::Error>;
}
Loading