docs(connlib): add more inline docs to connlib's state (#5105)

This is a follow-up to #5035. I didn't end up renaming `Tunnel`,
`GatewayState` or `ClientState` but I've added some comments with my
understanding of what the state is we are tracking and tried to group
the fields together in a logical way.

---------

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
This commit is contained in:
Thomas Eizinger
2024-05-24 13:52:06 +10:00
committed by GitHub
parent 994b25bf71
commit bb8cc86b58
5 changed files with 69 additions and 23 deletions

View File

@@ -60,6 +60,7 @@ clippy.unused_async = "warn"
clippy.wildcard_enum_match_arm = "warn" # Ensures we match on all combinations of `Poll`, preventing erroneous suspensions.
clippy.redundant_else = "warn"
clippy.redundant_clone = "warn"
rustdoc.private-intra-doc-links = "allow" # We don't publish any of our docs but want to catch dead links.
[patch.crates-io]
boringtun = { git = "https://github.com/cloudflare/boringtun", branch = "master" }

View File

@@ -281,37 +281,61 @@ fn send_dns_answer(
}
}
/// A sans-IO implementation of a Client's functionality.
///
/// Internally, this composes a [`snownet::ClientNode`] with firezone's policy engine around resources.
/// Clients differ from gateways in that they also implement a DNS resolver for DNS resources.
/// They also initiate connections to Gateways based on packets sent to Resources. Gateways only accept incoming connections.
pub struct ClientState {
awaiting_connection: HashMap<ResourceId, AwaitingConnectionDetails>,
resources_gateways: HashMap<ResourceId, GatewayId>,
pub dns_resources_internal_ips: HashMap<DnsResource, HashSet<IpAddr>>,
dns_resources: HashMap<String, ResourceDescriptionDns>,
cidr_resources: IpNetworkTable<ResourceDescriptionCidr>,
pub resource_ids: HashMap<ResourceId, ResourceDescription>,
pub deferred_dns_queries: HashMap<(DnsResource, Rtype), IpPacket<'static>>,
peers: PeerStore<GatewayId, GatewayOnClient>,
/// Manages wireguard tunnels to gateways.
node: ClientNode<GatewayId, RelayId>,
/// All gateways we are connected to and the associated, connection-specific state.
peers: PeerStore<GatewayId, GatewayOnClient>,
/// Which Resources we are trying to connect to.
awaiting_connection: HashMap<ResourceId, AwaitingConnectionDetails>,
pub ip_provider: IpProvider,
/// Tracks which gateway to use for a particular Resource.
resources_gateways: HashMap<ResourceId, GatewayId>,
/// The site a gateway belongs to.
gateways_site: HashMap<GatewayId, SiteId>,
/// The online/offline status of a site.
sites_status: HashMap<SiteId, Status>,
dns_mapping: BiMap<IpAddr, DnsServer>,
/// All DNS resources we know about, indexed by their domain (could be wildcard domain like `*.mycompany.com`).
dns_resources: HashMap<String, ResourceDescriptionDns>,
/// All CIDR resources we know about, indexed by the IP range they cover (like `1.1.0.0/8`).
cidr_resources: IpNetworkTable<ResourceDescriptionCidr>,
/// All resources indexed by their ID.
resource_ids: HashMap<ResourceId, ResourceDescription>,
buffered_events: VecDeque<ClientEvent>,
interface_config: Option<InterfaceConfig>,
buffered_packets: VecDeque<IpPacket<'static>>,
/// The DNS resolvers configured on the system outside of connlib.
system_resolvers: Vec<IpAddr>,
/// DNS queries that we need to forward to the system resolver.
buffered_dns_queries: VecDeque<DnsQuery<'static>>,
/// The (internal) IPs we have assigned for a certain DNS resource.
///
/// We assign one internal IP per externally resolved IP.
dns_resources_internal_ips: HashMap<DnsResource, HashSet<IpAddr>>,
/// DNS queries we can only answer once we have connected to the resource.
///
/// See [`dns::ResolveStrategy`] for details.
deferred_dns_queries: HashMap<(DnsResource, Rtype), IpPacket<'static>>,
/// Hands out IPs for DNS resources.
ip_provider: IpProvider,
/// Maps from connlib-assigned IP of a DNS server back to the originally configured system DNS resolver.
dns_mapping: BiMap<IpAddr, DnsServer>,
/// When to next refresh DNS resources.
///
/// "Refreshing" DNS resources means triggering a new DNS lookup for this domain on the gateway.
next_dns_refresh: Option<Instant>,
system_resolvers: Vec<IpAddr>,
/// Configuration of the TUN device, when it is up.
interface_config: Option<InterfaceConfig>,
gateways_site: HashMap<GatewayId, SiteId>,
sites_status: HashMap<SiteId, Status>,
buffered_events: VecDeque<ClientEvent>,
buffered_packets: VecDeque<IpPacket<'static>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]

View File

@@ -125,10 +125,20 @@ where
}
}
/// A SANS-IO implementation of a gateway's functionality.
///
/// Internally, this composes a [`snownet::ServerNode`] with firezone's policy engine around resources.
pub struct GatewayState {
peers: PeerStore<ClientId, ClientOnGateway>,
/// The [`snownet::ClientNode`].
///
/// Manages wireguard tunnels to clients.
node: ServerNode<ClientId, RelayId>,
/// All clients we are connected to and the associated, connection-specific state.
peers: PeerStore<ClientId, ClientOnGateway>,
/// When to next check whether a resource-access policy has expired.
next_expiry_resources_check: Option<Instant>,
buffered_events: VecDeque<GatewayEvent>,
}

View File

@@ -24,10 +24,15 @@ use std::{
const DNS_QUERIES_QUEUE_SIZE: usize = 100;
/// Bundles together all side-effects that connlib needs to have access to.
pub struct Io {
/// The TUN device offered to the user.
///
/// This is the `tun-firezone` network interface that users see when they e.g. type `ip addr` on Linux.
device: Device,
timeout: Option<Pin<Box<tokio::time::Sleep>>>,
/// The UDP sockets used to send & receive packets from the network.
sockets: Sockets,
timeout: Option<Pin<Box<tokio::time::Sleep>>>,
upstream_dns_servers: HashMap<IpAddr, TokioAsyncResolver>,
forwarded_dns_queries: FuturesTupleSet<

View File

@@ -45,13 +45,19 @@ const FIREZONE_MARK: u32 = 0xfd002021;
pub type GatewayTunnel<CB> = Tunnel<CB, GatewayState>;
pub type ClientTunnel<CB> = Tunnel<CB, ClientState>;
/// Tunnel is a wireguard state machine that uses webrtc's ICE channels instead of UDP sockets to communicate between peers.
/// [`Tunnel`] glues together connlib's [`Io`] component and the respective (pure) state of a client or gateway.
///
/// Most of connlib's functionality is implemented as a pure state machine in [`ClientState`] and [`GatewayState`].
/// The only job of [`Tunnel`] is to take input from the TUN [`Device`](crate::device_channel::Device), [`Sockets`] or time and pass it to the respective state.
pub struct Tunnel<CB: Callbacks, TRoleState> {
pub callbacks: CB,
/// State that differs per role, i.e. clients vs gateways.
/// (pure) state that differs per role, either [`ClientState`] or [`GatewayState`].
role_state: TRoleState,
/// The I/O component of connlib.
///
/// Handles all side-effects.
io: Io,
write_buf: Box<[u8; MAX_UDP_SIZE]>,