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()
    }
}