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