1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
use std::{ collections::BTreeMap, io, net::SocketAddr, sync::{ atomic::{AtomicU16, Ordering}, Arc, }, }; use device::FutureDevice; use futures::Future; use reactor::Reactor; use smoltcp::{ iface::{EthernetInterfaceBuilder, NeighborCache, Routes}, wire::{EthernetAddress, IpAddress, IpCidr}, }; pub use socket::{TcpListener, TcpSocket}; pub mod device; mod reactor; mod socket; mod socket_alloctor; pub mod util; pub struct NetConfig { pub ethernet_addr: EthernetAddress, pub ip_addr: IpCidr, pub gateway: IpAddress, } pub struct Net { reactor: Arc<Reactor>, ip_addr: IpCidr, from_port: AtomicU16, } impl Net { pub fn new<S: device::Interface + 'static>( device: FutureDevice<S>, config: NetConfig, ) -> (Net, impl Future<Output = ()> + Send) { let mut routes = Routes::new(BTreeMap::new()); match config.gateway { IpAddress::Ipv4(v4) => routes.add_default_ipv4_route(v4).unwrap(), _ => panic!("gateway should be set"), }; let neighbor_cache = NeighborCache::new(BTreeMap::new()); let interf = EthernetInterfaceBuilder::new(device) .ethernet_addr(config.ethernet_addr) .neighbor_cache(neighbor_cache) .ip_addrs(vec![config.ip_addr.clone()]) .routes(routes) .finalize(); let (reactor, fut) = Reactor::new(interf); ( Net { reactor: Arc::new(reactor), ip_addr: config.ip_addr, from_port: AtomicU16::new(10001), }, fut, ) } fn get_port(&self) -> u16 { self.from_port .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { Some(if x > 60000 { 10000 } else { x + 1 }) }) .unwrap() } pub async fn tcp_bind(&self, addr: SocketAddr) -> io::Result<TcpListener> { TcpListener::new(self.reactor.clone(), addr.into()).await } pub async fn tcp_connect(&self, addr: SocketAddr) -> io::Result<TcpSocket> { TcpSocket::connect( self.reactor.clone(), (self.ip_addr.address(), self.get_port()).into(), addr.into(), ) .await } }