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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use std::{ collections::BTreeMap, io, net::{Ipv4Addr, Ipv6Addr, 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, UdpSocket}; pub use socket_alloctor::BufferSize; use tokio::sync::Notify; 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 buffer_size: BufferSize, } pub struct Net { reactor: Arc<Reactor>, ip_addr: IpCidr, from_port: AtomicU16, stopper: Arc<Notify>, } 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 stopper = Arc::new(Notify::new()); let (reactor, fut) = Reactor::new(interf, config.buffer_size, stopper.clone()); ( Net { reactor: Arc::new(reactor), ip_addr: config.ip_addr, from_port: AtomicU16::new(10001), stopper, }, 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> { let addr = self.set_address(addr); 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 } pub async fn udp_bind(&self, addr: SocketAddr) -> io::Result<UdpSocket> { let addr = self.set_address(addr); UdpSocket::new(self.reactor.clone(), addr.into()).await } fn set_address(&self, mut addr: SocketAddr) -> SocketAddr { if addr.ip().is_unspecified() { addr.set_ip(match self.ip_addr.address() { IpAddress::Ipv4(ip) => Ipv4Addr::from(ip).into(), IpAddress::Ipv6(ip) => Ipv6Addr::from(ip).into(), _ => panic!("address must not be unspecified"), }); } if addr.port() == 0 { addr.set_port(self.get_port()); } addr } } impl Drop for Net { fn drop(&mut self) { self.stopper.notify_waiters() } }