Expand description
A TCP implementation with a somewhat-BSD-like socket API. It is written as a “sans-I/O” library meaning it doesn’t do any networking I/O itself, it just accepts bytes and provides bytes. A dependencies object must be be provided to support setting timers and getting the current time. The TCP state object should probably be used with a reference-counting wrapper so that a reference to the state object can be stored in the timer callbacks.
use std::cell::RefCell;
use std::rc::{Rc, Weak};
#[derive(Debug)]
struct TcpDependencies {
    // a reference to the tcp state
    state: Weak<RefCell<tcp::TcpState<Self>>>,
}
impl tcp::Dependencies for TcpDependencies {
    type Instant = std::time::Instant;
    type Duration = std::time::Duration;
    fn register_timer(
        &self,
        time: Self::Instant,
        f: impl FnOnce(&mut tcp::TcpState<Self>, tcp::TimerRegisteredBy) + Send + Sync + 'static,
    ) {
        let tcp_state = self.state.upgrade().unwrap();
        // TODO: To register timers, you would likely want to involve an async
        // runtime. A simple example would create a new task for each timer. The
        // task would sleep for some duration and then run the callback.
    }
    fn current_time(&self) -> Self::Instant {
        std::time::Instant::now()
    }
    fn fork(&self) -> Self {
        // TODO: the implementation here would depend on the implementation
        // of `register_timer`
        todo!();
    }
}
// create the TCP state object
let tcp_state = Rc::new_cyclic(|weak| {
    let dependencies = TcpDependencies {
        state: weak.clone(),
    };
    RefCell::new(tcp::TcpState::new(dependencies, tcp::TcpConfig::default()))
});
let mut tcp_state = tcp_state.borrow_mut();
// connect to port 80
let dst_addr = "127.0.0.1:80".parse().unwrap();
tcp_state.connect(dst_addr, || {
    // here we would ask the network interface for an unused port (implicit bind),
    // or where we would use the port assigned to a raw IP socket
    let bind_addr = "127.0.0.1:2532".parse().unwrap();
    Ok::<_, ()>((bind_addr, ()))
}).unwrap();
// get the SYN packet from the connect
let (header, _payload) = tcp_state.pop_packet().unwrap();
assert!(header.flags.contains(tcp::TcpFlags::SYN));
assert_eq!(header.dst(), dst_addr);Modules§
Structs§
- Accepted
TcpState  - An accept()ed TCP state. This is used to ensure that the caller uses
finalizeto update the state’sDependenciessince the state is no longer owned by the listening socket. - Ipv4
Header  - Payload
 - A packet payload containing a list of byte chunks.
 - Poll
State  - TcpConfig
 - TcpFlags
 - TcpHeader
 - TcpState
 
Enums§
- Accept
Error  - Close
Error  - Connect
Error  - Listen
Error  - PopPacket
Error  - Push
Packet Error  - Recv
Error  - Send
Error  - Shutdown
 - Shutdown
Error  - TcpError
 - Timer
Registered By  - Specifies whether the callback is meant to run on the parent state or a child state.
 
Traits§
- Dependencies
 - A collection of methods that allow the TCP state to interact with the external system.