Skip to main content

snap_control/
pg_wap.rs

1// Copyright 2026 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! PathGuard WAP SNAP extension.
16//!
17//! The WAP control plane is assembled from four components:
18//!
19//! * [`grants::GrantManager`] - Manages which client IPs are authorized for which targets and
20//!   segments, and when those authorizations expire.
21//! * [`segments::SegmentManager`] -  Keeps public segments for the (src, dst) pairs in use fresh.
22//! * [`paths::PathManager`] -  Combines public and granted segments into the single best path, and
23//!   reports which segments it used.
24//! * [`uplinks::UplinkManager`] - Creates and manages one uplink per (path, WAG) pair, multiplexes
25//!   SNI streams over it, refreshes its path, cleans it when unused or closed.
26//!
27//! Clients reach the control plane over the Connect RPC API in [`crpc`], which is where the
28//! authorizations that [`grants::GrantManager`] hands out come from.
29//!
30//! ## Time
31//!
32//! Every operation that depends on the current time takes it as a `now: SystemTime` argument, so
33//! all the decisions taken while serving one connection can be made against a single timestamp
34//! instead of drifting apart as the clock moves under them.
35//!
36//! The `run` maintenance loops are the exception: they own their cadence, so they read the wall
37//! clock themselves.
38
39use crate::pg_wap::{
40    grants::GrantManager,
41    paths::PathManager,
42    segments::SegmentManager,
43    uplinks::{UplinkEstablisher, UplinkManager},
44};
45
46pub mod crpc;
47pub mod grants;
48pub mod paths;
49pub mod segments;
50pub mod sni;
51pub mod uplinks;
52
53#[cfg(test)]
54mod test_util;
55
56/// The WAP control plane
57pub struct WapControlPlane<EstablisherType: UplinkEstablisher> {
58    /// Decides which client IP may reach which target over which private segments.
59    pub grant: GrantManager,
60    /// Public segments for all (src, dst) pairs currently in use.
61    pub segments: SegmentManager,
62    /// Combines public and granted segments into paths.
63    pub paths: PathManager,
64    /// Uplinks towards the WAGs, keyed by the (path, WAG) pair they were established for.
65    pub uplinks: UplinkManager<EstablisherType>,
66}
67impl<T: UplinkEstablisher> WapControlPlane<T> {
68    /// Creates a new WAP control plane.
69    pub fn new(
70        grant: GrantManager,
71        segments: SegmentManager,
72        paths: PathManager,
73        uplinks: UplinkManager<T>,
74    ) -> Self {
75        Self {
76            grant,
77            segments,
78            paths,
79            uplinks,
80        }
81    }
82
83    /// Runs the maintenance loops of every component that has one.
84    ///
85    /// Never returns, unless one of the loops panics.
86    pub async fn run(&self) {
87        tokio::join!(self.grant.run(), self.segments.run(), self.uplinks.run());
88    }
89}
90
91impl<T: UplinkEstablisher> Clone for WapControlPlane<T> {
92    fn clone(&self) -> Self {
93        Self {
94            grant: self.grant.clone(),
95            segments: self.segments.clone(),
96            paths: self.paths.clone(),
97            uplinks: self.uplinks.clone(),
98        }
99    }
100}