use core::net::{IpAddr, Ipv6Addr, SocketAddr};
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(not(feature = "std"))]
use alloc::sync::Arc;
use crate::{
device::Device,
io::{IoImpl, KnownFunctionName, TcpListenerImpl, TcpStreamImpl, TlsStreamImpl, UdpSocketImpl},
packet::{NetworkPacket, NetworkPacketBody},
};
pub async fn setup_tcp<
Io: IoImpl<UdpSocket, TcpStream, TcpListener, TlsStream> + Unpin + 'static,
UdpSocket: UdpSocketImpl + Unpin + 'static,
TcpStream: TcpStreamImpl + Unpin + 'static,
TcpListener: TcpListenerImpl<TcpStream> + Unpin + 'static,
TlsStream: TlsStreamImpl + Unpin + 'static,
>(
device: Arc<Device<Io, UdpSocket, TcpStream, TcpListener, TlsStream>>,
) {
#[allow(unused_mut)]
let (mut tcp_listener, tcp_port) = {
let mut port = crate::config::MIN_TCP_PORT;
loop {
if port > crate::config::MAX_TCP_PORT {
log::error!(
"No port available in {}..{}",
crate::config::MIN_TCP_PORT,
crate::config::MAX_TCP_PORT
);
return;
}
if let Ok(tcp_listener) = device
.io_impl
.listen_tcp(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port))
.await
{
break (tcp_listener, port);
}
port += 1;
}
};
let _ = device.my_tcp_port.set(tcp_port).await;
super::start_discovering(Arc::clone(&device));
loop {
let Ok(socket) = tcp_listener.accept().await else {
#[cfg(feature = "embedded")]
device.io_impl.sleep(core::time::Duration::from_millis(500)).await;
continue;
};
Arc::clone(&device)
.io_impl
.spawn(KnownFunctionName::PerTcpStream(socket), Arc::clone(&device));
#[cfg(feature = "embedded")]
{
tcp_listener = device
.io_impl
.listen_tcp(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), tcp_port))
.await
.unwrap();
}
}
}
pub async fn per_tcp_stream<
Io: IoImpl<UdpSocket, TcpStream, TcpListener, TlsStream> + Unpin + 'static,
UdpSocket: UdpSocketImpl + Unpin + 'static,
TcpStream: TcpStreamImpl + Unpin + 'static,
TcpListener: TcpListenerImpl<TcpStream> + Unpin + 'static,
TlsStream: TlsStreamImpl + Unpin + 'static,
>(
mut socket: TcpStream,
device: Arc<Device<Io, UdpSocket, TcpStream, TcpListener, TlsStream>>,
) {
let mut i = 0;
let mut buf = [0; crate::config::TCP_BUFFER_SIZE];
loop {
let Ok(bytes_read) = socket.read(&mut buf[i..]).await else {
log::warn!(
"TCP packet is too large, consider reading the documentation of config::TCP_BUFFER_SIZE"
);
i = 0;
continue;
};
i += bytes_read;
if let Ok(NetworkPacket {
body: NetworkPacketBody::Identity(packet),
..
}) = NetworkPacket::try_read_from(&buf[..i])
{
if device.links.lock().await.contains_key(&packet.device_id) {
log::debug!(
"Device {} has already established connection, ignore the MDNS request",
packet.device_id
);
continue;
}
log::debug!("TCP Identity packet received, upgrading connection");
super::tls::upgrade_tcp_connection(packet, socket, device, true).await;
break;
}
if bytes_read == 0 {
log::warn!("tcp: Failed to parse the received JSON");
break;
}
}
}