ts_netstack_smoltcp_socket (netsock)
Ergonomic sockets API layer built around [ts_netstack_smoltcp_core].
The idea is to take the command [Channel][ts_netstack_smoltcp_core::Channel] and use
it to expose an API that looks something like std::net or tokio::net, i.e. with
UdpSocket, TcpStream, TcpListener, etc. This is implemented here by internalizing
the Channel into each socket type so that they can all send commands on their own
behalf.
Socket creation is implemented by [CreateSocket] as a set of extension methods on
T where T: [HasChannel][ts_netstack_smoltcp_core::HasChannel].
Example
Compare the example in [ts_netstack_smoltcp_core]:
use core::net::SocketAddr;
use bytes::Bytes;
use netcore::smoltcp::time::Instant;
use netcore::smoltcp::phy::Medium;
use netcore::{Response, udp, HasChannel};
use netsock::CreateSocket;
extern crate ts_netstack_smoltcp_core as netcore;
extern crate ts_netstack_smoltcp_socket as netsock;
fn main() {
let mut stack = netcore::Netstack::new(netcore::Config::default(), Instant::ZERO);
let channel = stack.command_channel();
let thread = std::thread::spawn(move || {
for i in 0..2 {
let cmd = stack.wait_for_cmd_blocking(None).unwrap();
stack.process_one_cmd(cmd);
}
stack
});
let sock = channel.udp_bind_blocking(([127, 0, 0, 1], 1000).into()).unwrap();
println!("bound udp socket: {sock:?}");
sock.send_to_blocking(([1, 2, 3, 4], 80).into(), b"hello");
println!("sent udp packet");
let mut stack = thread.join().unwrap();
let (end1, end2) = netcore::Pipe::unbounded();
stack.poll_device_io(Instant::ZERO, &mut netcore::PipeDev {
pipe: end1,
medium: Medium::Ip,
mtu: 1500,
});
let packet = end2.rx.recv().unwrap();
println!("packet: {packet:?}");
assert_eq!(
packet.len(),
netcore::smoltcp::wire::IPV4_HEADER_LEN + netcore::smoltcp::wire::UDP_HEADER_LEN + b"hello".len(),
);
assert_eq!(packet[0] >> 4, 4); assert!(packet.ends_with(b"hello"));
}