Skip to content

Commit

Permalink
Implement TcpFullStack with server capabilities, and TcpListeners
Browse files Browse the repository at this point in the history
  • Loading branch information
MathiasKoch committed Sep 29, 2021
1 parent 037a122 commit d998dca
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 125 deletions.
3 changes: 2 additions & 1 deletion ublox-short-range/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ atat = { version = "0.13.1", features = ["derive", "defmt", "bytes"] }
heapless = { version = "^0.7", features = ["serde"] }
no-std-net = { version = "^0.5", features = ["serde"] }
serde = { version = "^1", default-features = false, features = ["derive"] }
ublox-sockets = { git = "https://github.com/BlackbirdHQ/ublox-sockets", rev = "097c2822" }
ublox-sockets = { path = "../../ublox-sockets" }
# ublox-sockets = { git = "https://github.com/BlackbirdHQ/ublox-sockets", rev = "097c2822" }
hash32 = "^0.2.1"
hash32-derive = "^0.1.0"

Expand Down
105 changes: 77 additions & 28 deletions ublox-short-range/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
command::{
data_mode::types::IPProtocol,
edm::{types::Protocol, urc::EdmEvent, EdmAtCmdWrapper, SwitchToEdmCommand},
ping::types::PingError,
system::{
Expand All @@ -16,11 +17,15 @@ use crate::{
},
};
use core::convert::TryInto;
use core::str::FromStr;
use embedded_hal::digital::OutputPin;
use embedded_nal::{nb, IpAddr, SocketAddr};
use embedded_nal::{nb, IpAddr, Ipv4Addr, SocketAddr};
use embedded_time::duration::{Generic, Milliseconds};
use embedded_time::Clock;
use ublox_sockets::{AnySocket, SocketSet, SocketType, TcpSocket, TcpState, UdpSocket, UdpState};
use ublox_sockets::{
tcp_listener::TcpListener, AnySocket, SocketSet, SocketType, TcpSocket, TcpState, UdpSocket,
UdpState,
};

#[derive(PartialEq, Copy, Clone)]
pub enum SerialMode {
Expand Down Expand Up @@ -61,6 +66,7 @@ where
pub(crate) timer: CLK,
pub(crate) reset_pin: Option<RST>,
pub(crate) edm_mapping: EdmMap,
pub(crate) tcp_listener: TcpListener<3, N>,
}

impl<C, CLK, RST, const N: usize, const L: usize> UbloxClient<C, CLK, RST, N, L>
Expand All @@ -84,6 +90,7 @@ where
timer,
reset_pin,
edm_mapping: EdmMap::new(),
tcp_listener: TcpListener::new(),
}
}

Expand Down Expand Up @@ -213,6 +220,7 @@ where
fn handle_urc(&mut self) -> Result<(), Error> {
if let Some(ref mut sockets) = self.sockets.as_deref_mut() {
let dns_state = &mut self.dns_state;
let tcp_listener = &mut self.tcp_listener;
let edm_mapping = &mut self.edm_mapping;
let wifi_connection = self.wifi_connection.as_mut();
let ts = self.timer.try_now().map_err(|_| Error::Timer)?;
Expand All @@ -224,18 +232,55 @@ where
let res = match edm_urc {
EdmEvent::ATEvent(urc) => {
match urc {
Urc::PeerConnected(_) => {
defmt::trace!("[URC] PeerConnected");

// TODO:
//
// We should probably move
// `tcp.set_state(TcpState::Connected(endpoint));`
// + `udp.set_state(UdpState::Established);` as
// well as `tcp.update_handle(*socket);` +
// `udp.update_handle(*socket);` here, to make
// sure that part also works without EDM mode
true
Urc::PeerConnected(event) => {
defmt::trace!(
"[URC] PeerConnected {:?}",
defmt::Debug2Format(&event)
);

let remote_ip = Ipv4Addr::from_str(
core::str::from_utf8(event.remote_address.as_slice()).unwrap(),
)
.unwrap();

let remote = SocketAddr::new(remote_ip.into(), event.remote_port);

if let Some(queue) = tcp_listener.incoming(event.local_port) {
queue.enqueue((event.handle, remote)).unwrap();
return true;
} else {
match event.protocol {
IPProtocol::TCP => {
if let Ok(mut tcp) =
sockets.get::<TcpSocket<CLK, L>>(event.handle)
{
defmt::debug!(
"Binding remote {=[u8]:a} to TCP socket {:?}",
event.remote_address.as_slice(),
event.handle
);
tcp.set_state(TcpState::Connected(remote));
return true;
}
}
IPProtocol::UDP => {
if let Ok(mut udp) =
sockets.get::<UdpSocket<CLK, L>>(event.handle)
{
defmt::debug!(
"Binding remote {=[u8]:a} to UDP socket {:?}",
event.remote_address.as_slice(),
event.handle
);
udp.bind(remote).unwrap();
udp.set_state(UdpState::Established);
return true;
}
}
}
}

false
}
Urc::PeerDisconnected(msg) => {
defmt::trace!("[URC] PeerDisconnected");
Expand All @@ -253,6 +298,7 @@ where
{
udp.close();
}
// FIXME: Is this correct?
sockets.remove(msg.handle).ok();
}
_ => {}
Expand Down Expand Up @@ -287,10 +333,16 @@ where
}
Urc::WifiAPUp(_) => {
defmt::trace!("[URC] WifiAPUp");
if let Some(con) = wifi_connection {
con.wifi_state = WiFiState::Connected;
}
true
}
Urc::WifiAPDown(_) => {
defmt::trace!("[URC] WifiAPDown");
if let Some(con) = wifi_connection {
con.wifi_state = WiFiState::NotConnected;
}
true
}
Urc::WifiAPStationConnected(client) => {
Expand Down Expand Up @@ -362,7 +414,7 @@ where
EdmEvent::IPv4ConnectEvent(event) => {
defmt::trace!(
"[EDM_URC] IPv4ConnectEvent! Channel_id: {:?}",
event.channel_id
defmt::Debug2Format(&event)
);

let endpoint = SocketAddr::new(event.remote_ip.into(), event.remote_port);
Expand All @@ -372,19 +424,17 @@ where
.find_map(|(h, s)| {
match event.protocol {
Protocol::TCP => {
let mut tcp = TcpSocket::downcast(s).ok()?;
let tcp = TcpSocket::downcast(s).ok()?;
if tcp.endpoint() == Some(endpoint) {
edm_mapping.insert(event.channel_id, h).unwrap();
tcp.set_state(TcpState::Connected(endpoint));
return Some(true);
return Some(());
}
}
Protocol::UDP => {
let mut udp = UdpSocket::downcast(s).ok()?;
let udp = UdpSocket::downcast(s).ok()?;
if udp.endpoint() == Some(endpoint) {
edm_mapping.insert(event.channel_id, h).unwrap();
udp.set_state(UdpState::Established);
return Some(true);
return Some(());
}
}
_ => {}
Expand All @@ -396,7 +446,7 @@ where
EdmEvent::IPv6ConnectEvent(event) => {
defmt::trace!(
"[EDM_URC] IPv6ConnectEvent! Channel_id: {:?}",
event.channel_id
defmt::Debug2Format(&event)
);

let endpoint = SocketAddr::new(event.remote_ip.into(), event.remote_port);
Expand All @@ -406,19 +456,18 @@ where
.find_map(|(h, s)| {
match event.protocol {
Protocol::TCP => {
let mut tcp = TcpSocket::downcast(s).ok()?;
let tcp = TcpSocket::downcast(s).ok()?;
if tcp.endpoint() == Some(endpoint) {
edm_mapping.insert(event.channel_id, h).unwrap();
tcp.set_state(TcpState::Connected(endpoint));
return Some(true);
return Some(());
}
}
Protocol::UDP => {
let mut udp = UdpSocket::downcast(s).ok()?;
let udp = UdpSocket::downcast(s).ok()?;
defmt::debug!("Found matching UDP socket");
if udp.endpoint() == Some(endpoint) {
edm_mapping.insert(event.channel_id, h).unwrap();
udp.set_state(UdpState::Established);
return Some(true);
return Some(());
}
}
_ => {}
Expand Down
46 changes: 24 additions & 22 deletions ublox-short-range/src/command/data_mode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use super::NoResponse;

/// 5.1 Enter data mode O
///
/// Requests the module to move to the new mode.
/// After executing the data mode command or the extended data mode command, a delay of 50 ms is
/// required before start of data transmission.
/// Requests the module to move to the new mode. After executing the data mode
/// command or the extended data mode command, a delay of 50 ms is required
/// before start of data transmission.
#[derive(Clone, AtatCmd)]
#[at_cmd("O", NoResponse, timeout_ms = 10000, value_sep = false)]
pub struct ChangeMode {
Expand All @@ -24,9 +24,9 @@ pub struct ChangeMode {

/// 5.2 Connect peer +UDCP
///
/// Connects to an enabled service on a remote device. When the host connects to a
/// service on a remote device, it implicitly registers to receive the "Connection Closed"
/// event.
/// Connects to an enabled service on a remote device. When the host connects to
/// a service on a remote device, it implicitly registers to receive the
/// "Connection Closed" event.
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDCP", ConnectPeerResponse, timeout_ms = 10000)]
pub struct ConnectPeer<'a> {
Expand All @@ -46,9 +46,10 @@ pub struct ClosePeerConnection {

/// 5.4 Default remote peer +UDDRP
///
/// The default remote peer command works for Bluetooth BR/EDR, Bluetooth low energy (SPS), TCP, and UDP.
/// The DCE will connect to a default remote peer when entering either the Data mode or Extended data mode
/// (either by command or at start up, if defined by the Module Start Mode +UMSM command).
/// The default remote peer command works for Bluetooth BR/EDR, Bluetooth low
/// energy (SPS), TCP, and UDP. The DCE will connect to a default remote peer
/// when entering either the Data mode or Extended data mode (either by command
/// or at start up, if defined by the Module Start Mode +UMSM command).
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDDRP", NoResponse, timeout_ms = 10000)]
pub struct SetDefaultRemotePeer<'a> {
Expand All @@ -74,7 +75,8 @@ pub struct PeerList;
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDSC", NoResponse, timeout_ms = 10000)]
pub struct ServerConfiguration {
/// 0-6, the server ID to configure. Disable an active server first before changing.
/// 0-6, the server ID to configure. Disable an active server first before
/// changing.
#[at_arg(position = 0)]
pub id: u8,
#[at_arg(position = 1)]
Expand All @@ -83,10 +85,11 @@ pub struct ServerConfiguration {

/// 5.7 Server flags +UDSF
///
/// Bit 0, remote configuration: When the remote configuration bit is set, the module will look for the escape
/// sequence over the air (see S2 command). When the escape sequence is detected, the channel will enter
/// command mode and parse AT commands. The command mode is exited by sending an ATO to the module (see
/// O command).
/// Bit 0, remote configuration: When the remote configuration bit is set, the
/// module will look for the escape sequence over the air (see S2 command). When
/// the escape sequence is detected, the channel will enter command mode and
/// parse AT commands. The command mode is exited by sending an ATO to the
/// module (see O command).
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDSF", NoResponse, timeout_ms = 10000)]
pub struct SetServerFlags {
Expand All @@ -100,8 +103,8 @@ pub struct SetServerFlags {

/// 5.8 Watchdog settings +UDWS
///
/// The data watchdog functionality is active only in the data or extended data mode. Additionally, the power
/// mode must also be set to online or sleep mode.
/// The data watchdog functionality is active only in the data or extended data
/// mode. Additionally, the power mode must also be set to online or sleep mode.
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDWS", NoResponse, timeout_ms = 10000)]
pub struct SetWatchdogSettings {
Expand All @@ -127,9 +130,8 @@ pub struct SetPeerConfiguration {

/// 5.12 Bind +UDBIND
///
/// Writes backspace character.
/// This setting changes the decimal value of the character recognized by the DCE as a
/// request to delete from the command line, the immediately preceding character.
/// Bind two streams together for transparent data transfer between physical
/// interfaces.
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDBIND", BindResponse, timeout_ms = 10000)]
pub struct SetBind {
Expand All @@ -141,9 +143,9 @@ pub struct SetBind {

/// 5.13 Bind to channel +UDBINDC
///
/// Binds Stream with Id <StreamId> to channel with Id <ChannelId>. Stream ids are
/// provided on response of a successful connection. Channel id is provided on response
/// of a successful bind command.
/// Binds Stream with Id <StreamId> to channel with Id <ChannelId>. Stream ids
/// are provided on response of a successful connection. Channel id is provided
/// on response of a successful bind command.
#[derive(Clone, AtatCmd)]
#[at_cmd("+UDBINDC", NoResponse, timeout_ms = 10000)]
pub struct SoftwareUpdate {
Expand Down
3 changes: 2 additions & 1 deletion ublox-short-range/src/command/data_mode/responses.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Responses for Data Mode
use atat::atat_derive::AtatResp;
use heapless::String;
use ublox_sockets::SocketHandle;

/// 5.2 Connect peer +UDCP
#[derive(Clone, AtatResp)]
pub struct ConnectPeerResponse {
#[at_arg(position = 0)]
pub peer_handle: u8,
pub peer_handle: SocketHandle,
}

/// 5.5 Peer list +UDLP
Expand Down
8 changes: 2 additions & 6 deletions ublox-short-range/src/command/data_mode/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,8 @@ pub enum ConnectScheme {
}
#[derive(Clone, PartialEq, AtatEnum)]
pub enum ServerConfig {
Type(ServerType),
Url(String<128>),
}
#[derive(Clone, PartialEq, AtatEnum)]
pub enum ServerType {
#[at_arg(value = 0)]
Dissabled,
Disabled,
#[at_arg(value = 1)]
TCP(u16, ImmediateFlush),
#[at_arg(value = 2)]
Expand All @@ -65,6 +60,7 @@ pub enum ServerType {
SPS,
#[at_arg(value = 8)]
ATP(Interface, Option<u16>),
Url(String<128>),
}

#[derive(Clone, PartialEq, AtatEnum)]
Expand Down
Loading

0 comments on commit d998dca

Please sign in to comment.