Something went wrong. Try again.
Nothing to see here, move along meow
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227use core::sync::atomic::{AtomicBool, Ordering};use smoltcp::iface::{Config, Interface, SocketHandle, SocketSet, SocketStorage};use smoltcp::socket::{dhcpv4, dns, icmp, tcp, udp};use smoltcp::time::{Duration, Instant};use smoltcp::wire::{ EthernetAddress, HardwareAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address, Ipv6Cidr,};
use crate::device::PacketDevice;
static CREATED: AtomicBool = AtomicBool::new(false);pub static MDNS_JOIN_FAILED: AtomicBool = AtomicBool::new(false);
const TCP_RX_BUF_SIZE: usize = 8192;const TCP_TX_BUF_SIZE: usize = 8192;const SHELL_TCP_RX_SIZE: usize = 8192;const SHELL_TCP_TX_SIZE: usize = 8192;pub const MAX_SHELL_SOCKETS: usize = 4;pub const MAX_UDP_SOCKETS: usize = 4;const DNS_QUERY_SLOTS: usize = 2;const MAX_SOCKETS: usize = 2 + MAX_SHELL_SOCKETS + 2 + 1 + MAX_UDP_SOCKETS + 1;
static mut TCP_RX_DATA: [u8; TCP_RX_BUF_SIZE] = [0u8; TCP_RX_BUF_SIZE];static mut TCP_TX_DATA: [u8; TCP_TX_BUF_SIZE] = [0u8; TCP_TX_BUF_SIZE];static mut SHELL_TCP_RX_POOL: [[u8; SHELL_TCP_RX_SIZE]; MAX_SHELL_SOCKETS] = [[0u8; SHELL_TCP_RX_SIZE]; MAX_SHELL_SOCKETS];static mut SHELL_TCP_TX_POOL: [[u8; SHELL_TCP_TX_SIZE]; MAX_SHELL_SOCKETS] = [[0u8; SHELL_TCP_TX_SIZE]; MAX_SHELL_SOCKETS];static mut SOCKET_STORAGE: [SocketStorage<'static>; MAX_SOCKETS] = [SocketStorage::EMPTY; MAX_SOCKETS];static mut DNS_QUERIES: [Option<dns::DnsQuery>; DNS_QUERY_SLOTS] = [const { None }; DNS_QUERY_SLOTS];
const ICMP_META_SLOTS: usize = 4;const ICMP_PAYLOAD_SIZE: usize = 512;static mut ICMP_RX_META: [icmp::PacketMetadata; ICMP_META_SLOTS] = [icmp::PacketMetadata::EMPTY; ICMP_META_SLOTS];static mut ICMP_RX_DATA: [u8; ICMP_PAYLOAD_SIZE] = [0u8; ICMP_PAYLOAD_SIZE];static mut ICMP_TX_META: [icmp::PacketMetadata; ICMP_META_SLOTS] = [icmp::PacketMetadata::EMPTY; ICMP_META_SLOTS];static mut ICMP_TX_DATA: [u8; ICMP_PAYLOAD_SIZE] = [0u8; ICMP_PAYLOAD_SIZE];
const UDP_BUF_SIZE: usize = 2048;const UDP_META_SLOTS: usize = 4;static mut UDP_RX_META_POOL: [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] = [[udp::PacketMetadata::EMPTY; UDP_META_SLOTS]; MAX_UDP_SOCKETS];static mut UDP_RX_DATA_POOL: [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] = [[0u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS];static mut UDP_TX_META_POOL: [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] = [[udp::PacketMetadata::EMPTY; UDP_META_SLOTS]; MAX_UDP_SOCKETS];static mut UDP_TX_DATA_POOL: [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] = [[0u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS];
const MDNS_META_SLOTS: usize = 4;const MDNS_BUF_SIZE: usize = 1500;static mut MDNS_RX_META: [udp::PacketMetadata; MDNS_META_SLOTS] = [udp::PacketMetadata::EMPTY; MDNS_META_SLOTS];static mut MDNS_RX_DATA: [u8; MDNS_BUF_SIZE] = [0u8; MDNS_BUF_SIZE];static mut MDNS_TX_META: [udp::PacketMetadata; MDNS_META_SLOTS] = [udp::PacketMetadata::EMPTY; MDNS_META_SLOTS];static mut MDNS_TX_DATA: [u8; MDNS_BUF_SIZE] = [0u8; MDNS_BUF_SIZE];
pub struct NetStack { pub iface: Interface, pub sockets: SocketSet<'static>, pub tcp_handle: SocketHandle, pub shell_handles: [SocketHandle; MAX_SHELL_SOCKETS], pub dhcp_handle: SocketHandle, pub dns_handle: SocketHandle, pub icmp_handle: SocketHandle, pub udp_handles: [SocketHandle; MAX_UDP_SOCKETS], pub mdns_handle: SocketHandle,}
#[allow(clippy::deref_addrof)]pub fn create(device: &mut PacketDevice, mac: [u8; 6], now: Instant) -> NetStack { assert!( !CREATED.swap(true, Ordering::Relaxed), "stack::create() called twice" ); let hw_addr = HardwareAddress::Ethernet(EthernetAddress(mac)); let config = Config::new(hw_addr); let mut iface = Interface::new(config, device, now);
let socket_storage: &'static mut [SocketStorage<'static>; MAX_SOCKETS] = unsafe { &mut *(&raw mut SOCKET_STORAGE) }; let mut sockets = SocketSet::new(&mut socket_storage[..]);
let tcp_rx_data: &'static mut [u8] = unsafe { &mut *(&raw mut TCP_RX_DATA) }; let tcp_rx_buf = tcp::SocketBuffer::new(tcp_rx_data); let tcp_tx_data: &'static mut [u8] = unsafe { &mut *(&raw mut TCP_TX_DATA) }; let tcp_tx_buf = tcp::SocketBuffer::new(tcp_tx_data); let tcp_socket = tcp::Socket::new(tcp_rx_buf, tcp_tx_buf); let tcp_handle = sockets.add(tcp_socket);
let rx_pool: &'static mut [[u8; SHELL_TCP_RX_SIZE]; MAX_SHELL_SOCKETS] = unsafe { &mut *(&raw mut SHELL_TCP_RX_POOL) }; let tx_pool: &'static mut [[u8; SHELL_TCP_TX_SIZE]; MAX_SHELL_SOCKETS] = unsafe { &mut *(&raw mut SHELL_TCP_TX_POOL) };
let mut shell_handles_tmp: [Option<SocketHandle>; MAX_SHELL_SOCKETS] = [None; MAX_SHELL_SOCKETS]; rx_pool .iter_mut() .zip(tx_pool.iter_mut()) .zip(shell_handles_tmp.iter_mut()) .for_each(|((rx_data, tx_data), slot)| { let mut sock = tcp::Socket::new( tcp::SocketBuffer::new(&mut rx_data[..]), tcp::SocketBuffer::new(&mut tx_data[..]), ); sock.set_nagle_enabled(false); sock.set_ack_delay(None); sock.set_keep_alive(Some(Duration::from_secs(30))); *slot = Some(sockets.add(sock)); });
let shell_handles = shell_handles_tmp.map(|opt| opt.unwrap());
let dhcp_socket = dhcpv4::Socket::new(); let dhcp_handle = sockets.add(dhcp_socket);
let dns_queries: &'static mut [Option<dns::DnsQuery>; DNS_QUERY_SLOTS] = unsafe { &mut *(&raw mut DNS_QUERIES) }; let dns_socket = dns::Socket::new(&[] as &[IpAddress], &mut dns_queries[..]); let dns_handle = sockets.add(dns_socket);
let icmp_rx_meta: &'static mut [icmp::PacketMetadata; ICMP_META_SLOTS] = unsafe { &mut *(&raw mut ICMP_RX_META) }; let icmp_rx_data: &'static mut [u8; ICMP_PAYLOAD_SIZE] = unsafe { &mut *(&raw mut ICMP_RX_DATA) }; let icmp_tx_meta: &'static mut [icmp::PacketMetadata; ICMP_META_SLOTS] = unsafe { &mut *(&raw mut ICMP_TX_META) }; let icmp_tx_data: &'static mut [u8; ICMP_PAYLOAD_SIZE] = unsafe { &mut *(&raw mut ICMP_TX_DATA) }; let icmp_rx_buf = icmp::PacketBuffer::new(&mut icmp_rx_meta[..], &mut icmp_rx_data[..]); let icmp_tx_buf = icmp::PacketBuffer::new(&mut icmp_tx_meta[..], &mut icmp_tx_data[..]); let mut icmp_socket = icmp::Socket::new(icmp_rx_buf, icmp_tx_buf); icmp_socket.bind(icmp::Endpoint::Ident(0x4C41)).unwrap(); let icmp_handle = sockets.add(icmp_socket);
let udp_rx_meta_pool: &'static mut [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] = unsafe { &mut *(&raw mut UDP_RX_META_POOL) }; let udp_rx_data_pool: &'static mut [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] = unsafe { &mut *(&raw mut UDP_RX_DATA_POOL) }; let udp_tx_meta_pool: &'static mut [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] = unsafe { &mut *(&raw mut UDP_TX_META_POOL) }; let udp_tx_data_pool: &'static mut [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] = unsafe { &mut *(&raw mut UDP_TX_DATA_POOL) };
let mut udp_handles_tmp: [Option<SocketHandle>; MAX_UDP_SOCKETS] = [None; MAX_UDP_SOCKETS]; udp_rx_meta_pool .iter_mut() .zip(udp_rx_data_pool.iter_mut()) .zip(udp_tx_meta_pool.iter_mut()) .zip(udp_tx_data_pool.iter_mut()) .zip(udp_handles_tmp.iter_mut()) .for_each(|((((rx_meta, rx_data), tx_meta), tx_data), slot)| { let sock = udp::Socket::new( udp::PacketBuffer::new(&mut rx_meta[..], &mut rx_data[..]), udp::PacketBuffer::new(&mut tx_meta[..], &mut tx_data[..]), ); *slot = Some(sockets.add(sock)); });
let udp_handles = udp_handles_tmp.map(|opt| opt.unwrap());
let mdns_rx_meta: &'static mut [udp::PacketMetadata; MDNS_META_SLOTS] = unsafe { &mut *(&raw mut MDNS_RX_META) }; let mdns_rx_data: &'static mut [u8; MDNS_BUF_SIZE] = unsafe { &mut *(&raw mut MDNS_RX_DATA) }; let mdns_tx_meta: &'static mut [udp::PacketMetadata; MDNS_META_SLOTS] = unsafe { &mut *(&raw mut MDNS_TX_META) }; let mdns_tx_data: &'static mut [u8; MDNS_BUF_SIZE] = unsafe { &mut *(&raw mut MDNS_TX_DATA) }; let mdns_rx_buf = udp::PacketBuffer::new(&mut mdns_rx_meta[..], &mut mdns_rx_data[..]); let mdns_tx_buf = udp::PacketBuffer::new(&mut mdns_tx_meta[..], &mut mdns_tx_data[..]); let mut mdns_socket = udp::Socket::new(mdns_rx_buf, mdns_tx_buf); mdns_socket .bind(smoltcp::wire::IpListenEndpoint { addr: None, port: 5353, }) .unwrap(); let mdns_handle = sockets.add(mdns_socket);
let link_local = eui64_link_local(&mac); iface.update_ip_addrs(|addrs| { let _ = addrs.push(IpCidr::Ipv6(Ipv6Cidr::new(link_local, 64))); });
if iface .join_multicast_group(Ipv4Address::new(224, 0, 0, 251)) .is_err() { MDNS_JOIN_FAILED.store(true, Ordering::Relaxed); }
NetStack { iface, sockets, tcp_handle, shell_handles, dhcp_handle, dns_handle, icmp_handle, udp_handles, mdns_handle, }}
pub fn eui64_link_local_bytes(mac: &[u8; 6]) -> [u8; 16] { let addr = eui64_link_local(mac); addr.octets()}
fn eui64_link_local(mac: &[u8; 6]) -> Ipv6Address { Ipv6Address::new( 0xfe80, 0, 0, 0, ((mac[0] ^ 0x02) as u16) << 8 | mac[1] as u16, (mac[2] as u16) << 8 | 0x00ff, 0xfe00 | mac[3] as u16, (mac[4] as u16) << 8 | mac[5] as u16, )}