Skip to main content

ConnectionResolver

Struct ConnectionResolver 

Source
pub struct ConnectionResolver { /* private fields */ }
Expand description

What one connection may ask the resolver to do at once.

Two tiers, because a single shared pool answers only one of the two questions worth asking:

  • One reserved slot, held by this connection alone and by nothing else. No number of hostile connections can take it away, so a connection is never starved outright – at worst its lookups run one at a time. This is the guarantee; the shared allowance is only ever an optimisation on top of it.
  • BURST_LOOKUPS from the shared allowance, so ordinary use – a client opening thirty tunnels at once – still resolves them in parallel, while one connection can never hold more than its share of the pool.

The waiting itself is inside the caller’s connect_timeout, so a lookup that cannot get a slot in time is refused exactly as a resolver that did not answer in time is, with the same 504 and the same Proxy-Status (D90). One of these per connection, made by ResolverBudget::per_connection and held for the connection’s whole life by its crate::tunnel::Context. Deliberately not Clone: the bound is the connection’s, so a second handle counting separately would be no bound at all. That is also why the three semaphores are held inline rather than behind an Arc: with one owner and no clone, the allocation bought nothing. Each semaphore keeps its own, because acquire_owned needs an Arc<Semaphore> and one of them is the server-wide allowance every connection really does share.

Implementations§

Source§

impl ConnectionResolver

Source

pub async fn lookup(&self, host: &str, port: u16) -> Result<Vec<SocketAddr>>

resolve, with a slot in the blocking pool taken for the length of it.

An IP literal never reaches the resolver and so never occupies a thread: it is answered without taking a slot at all, which keeps the budget spent on the only thing that can block.

Trait Implementations§

Source§

impl Debug for ConnectionResolver

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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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