Skip to main content

ControlPlane

Struct ControlPlane 

Source
pub(crate) struct ControlPlane {
    client: Mutex<ClientLeg>,
    upstream_transport: Mutex<Option<TransportProfile>>,
    legs: LegSetup,
    shape: ShapeControl,
    stats: Arc<ProxyRecorder>,
    sessions: Mutex<HashMap<SessionId, SessionHandle>>,
    high_water: AtomicU64,
}
Expand description

The state a ProxyControl reads, owned by the proxy and shared with every handle it hands out.

One per TransparentProxy, never process-global: session ids are minted from a counter on the proxy and start again at 1 for each one, so two proxies in a process would collide on every id in a shared table.

Fields§

§client: Mutex<ClientLeg>

The client-facing leg: the listener once it exists, and the transport parameters a live request has installed on it.

One lock over both because the two have to move together. A request arriving while run() is between binding the endpoint and publishing it must not be dropped: it stores the parameters and finds no listener, and the publish then installs them. Split across two locks there is a window in which a request stores its parameters after the publish has read them and before the listener is visible, and the setting is accepted, reported as applied, and reaches nothing.

§upstream_transport: Mutex<Option<TransportProfile>>

The transport parameters a live request has set for the relay leg, or None while the proxy’s own template is what every session dials with.

§legs: LegSetup

The two legs’ fixed facts, from the configuration the proxy was built with.

§shape: ShapeControl

This proxy’s shaping profile and its pacing switch.

§stats: Arc<ProxyRecorder>

What every session this proxy accepts reports its shaping figures into, on top of its own.

Held here rather than on the [TransparentProxy] because this is what a session is already handed: attach_control is the one call that reaches every accepted session and no directly-driven one, which is exactly the set whose traffic belongs in a proxy-wide total.

Constructed with the plane and never replaced, so it outlives every session and a total taken from it never falls when one ends — unlike Self::sessions, whose entries are released by a Drop.

§sessions: Mutex<HashMap<SessionId, SessionHandle>>

Every session that is running right now.

§high_water: AtomicU64

The highest id ever registered here.

The only trace a finished session leaves, and it exists to separate ControlError::SessionEnded from ControlError::NoSuchSession. Ids are minted monotonically from a counter on the proxy, so an id at or below this one has run; anything above it has not. A set of retired ids would answer the same question and would grow for the life of the proxy.

0 before any session registers, and no session is ever SessionId(0).

Implementations§

Source§

impl ControlPlane

Source

pub(crate) fn new(legs: LegSetup) -> Arc<Self>

An empty control plane: nothing bound, no sessions.

Source

pub(crate) fn publish_listener( self: &Arc<Self>, listener: Arc<Listener>, ) -> BoundGuard

Publish listener as this proxy’s bound endpoint, and hand back the guard that un-publishes it.

A guard rather than a matching clear call because the accept loop leaves by three routes — cancellation, a fatal listener error propagated with ?, and the whole future being dropped by whoever spawned it — and only one of them is a place a call could be written.

Any transport parameters a request set before there was a listener are installed here, under the same lock the request took, which is what makes a request that arrives during the bind land on the endpoint rather than on nothing.

Source

fn bound(&self) -> Option<Arc<Listener>>

The bound listener, or None before there is one.

Source

fn unbind(&self)

Forget the bound listener.

Source

pub(crate) fn client_transport(&self) -> Option<Arc<TransportConfig>>

The transport parameters the client leg should bind with, or None when no request has set any and the proxy’s template stands.

Source

fn set_client_transport(&self, transport: Arc<TransportConfig>)

Install transport on the client leg, now if there is an endpoint and at bind time if there is not.

Source

pub(crate) fn upstream_transport(&self) -> Option<TransportProfile>

The profile every session this proxy accepts from now on dials the relay with, or None when the proxy’s template stands.

Source

pub(crate) fn shape(&self) -> &ShapeControl

This proxy’s shaping profile and pacing switch, for a session to build its scheduler from and to watch.

Source

pub(crate) fn stats_recorder(&self) -> Arc<ProxyRecorder>

The proxy-wide shaping counters, for a session to report into.

Handed out as an Arc clone rather than a borrow because the session keeps it: its recorder forwards into this for the session’s whole life, which outlives any borrow of the plane a call could hold.

Source

fn build_transport( &self, leg: Leg, profile: &TransportProfile, ) -> Result<Arc<TransportConfig>, ControlError>

Turn profile into the config leg would install, refusing exactly what a configured profile on that leg would be refused for.

Built through the leg’s own TransportInstaller when it has one, so a caller who supplied an installer to start with gets the same step here — a live request that quietly used the default installer instead would produce a connection built differently from every one the proxy made before it, with nothing saying so.

Source§

impl ControlPlane

Source

pub(crate) fn register( self: &Arc<Self>, id: SessionId, handle: SessionHandle, ) -> SessionGuard

Register id as live, and hand back the guard that ends it.

See this module’s own documentation for why the removal is a Drop and not a call on each of the session’s termination paths.

Source

fn end(&self, id: SessionId)

Retire id. Idempotent.

Source

fn live(&self) -> Vec<SessionId>

Every live id, ascending.

Source

fn session(&self, id: SessionId) -> Option<SessionHandle>

The handle for one live session, or None when it is not registered.

The only correct way to read the map: a caller that held the lock itself could still be holding it while it talked to the session.

Source

fn reach(&self, id: SessionId) -> Result<SessionHandle, ControlError>

The handle to act on id through, or the refusal that says why there is none. Three answers, and the third is the one worth stating: a session that is registered but whose cancellation token has already fired is refused as ended rather than acted on. It is going down and its tasks are unwinding, so a request accepted there would be taken and then never served — which is exactly the accepts a request and discards it outcome this module refuses to have.

Trait Implementations§

Source§

impl Debug for ControlPlane

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more