Skip to content

Instantly share code, notes, and snippets.

@richardeoin
Created August 14, 2019 17:29
Show Gist options
  • Save richardeoin/b562e79d0d499e00a8bf4944f00594d9 to your computer and use it in GitHub Desktop.
Save richardeoin/b562e79d0d499e00a8bf4944f00594d9 to your computer and use it in GitHub Desktop.
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate getopts;
extern crate smoltcp;
mod utils;
use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache};
use smoltcp::phy::wait as phy_wait;
use smoltcp::socket::SocketSet;
use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
use std::fmt::Write;
use std::os::unix::io::AsRawFd;
use std::str;
fn main() {
utils::setup_logging("");
let (mut opts, mut free) = utils::create_options();
utils::add_tap_options(&mut opts, &mut free);
utils::add_middleware_options(&mut opts, &mut free);
let mut matches = utils::parse_options(&opts, free);
let device = utils::parse_tap_options(&mut matches);
let fd = device.as_raw_fd();
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
let mut neighbor_cache_storage = [None; 8];
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_storage[..]);
// UDP
let mut udp_rx_meta_storage = [UdpPacketMetadata::EMPTY; 1];
let mut udp_tx_meta_storage = [UdpPacketMetadata::EMPTY; 1];
let mut udp_rx_storage = [0; 64];
let mut udp_tx_storage = [0; 128];
let udp_rx_buffer = UdpSocketBuffer::new(&mut udp_rx_meta_storage[..], &mut udp_rx_storage[..]);
let udp_tx_buffer = UdpSocketBuffer::new(&mut udp_tx_meta_storage[..], &mut udp_tx_storage[..]);
let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
let mut tcp_rx_storage = [0; 64];
let mut tcp_tx_storage = [0; 128];
let tcp1_rx_buffer = TcpSocketBuffer::new(&mut tcp_rx_storage[..]);
let tcp1_tx_buffer = TcpSocketBuffer::new(&mut tcp_tx_storage[..]);
let tcp1_socket = TcpSocket::new(tcp1_rx_buffer, tcp1_tx_buffer);
let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
let ip_addrs = [
IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64),
IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64),
];
let mut iface = EthernetInterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.finalize();
let mut socket_set_entries: [_; 8] = Default::default();
let mut sockets = SocketSet::new(&mut socket_set_entries[..]);
let udp_handle = sockets.add(udp_socket);
let tcp1_handle = sockets.add(tcp1_socket);
loop {
let timestamp = Instant::now();
match iface.poll(&mut sockets, timestamp) {
Ok(_) => {}
Err(e) => {
debug!("poll error: {}", e);
}
}
// udp:6969: respond "hello"
{
let mut socket = sockets.get::<UdpSocket>(udp_handle);
if !socket.is_open() {
socket.bind(6969).unwrap()
}
let client = match socket.recv() {
Ok((data, endpoint)) => {
debug!(
"udp:6969 recv data: {:?} from {}",
str::from_utf8(data.as_ref()).unwrap(),
endpoint
);
Some(endpoint)
}
Err(_) => None,
};
if let Some(endpoint) = client {
let data = b"hello\n";
debug!(
"udp:6969 send data: {:?}",
str::from_utf8(data.as_ref()).unwrap()
);
socket.send_slice(data, endpoint).unwrap();
}
}
// tcp:6969: respond "hello"
{
let mut socket = sockets.get::<TcpSocket>(tcp1_handle);
if !socket.is_open() {
socket.listen(6969).unwrap();
}
if socket.can_send() {
debug!("tcp:6969 send greeting");
write!(socket, "hello\n").unwrap();
debug!("tcp:6969 close");
socket.close();
}
}
phy_wait(fd, iface.poll_delay(&sockets, timestamp)).expect("wait error");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment