Skip to main content

SnapTunNgServer

Struct SnapTunNgServer 

Source
pub struct SnapTunNgServer<T> { /* private fields */ }
Expand description

The SnapTunNgServer manages one Tunn per remote socket address.

The main structural difference between WireGuard (R) and snaptun-ng is that there is a one-to-one relation between a remote socket address (of the initiator) and a tunnel. The SnapTunNgServer manages that relation.

§Scaling

The main methods SnapTunNgServer::handle_incoming_packet, SnapTunNgServer::handle_outgoing_packet, and SnapTunNgServer::update_timers all require an exclusive reference to the internal state. The reason is that processing both, incoming and outgoing packets requires access to the session state.

One simple way to achieve load distribution across different cores/threads is to shard over multiple SnapTunNgServer-instances based on a hash of the remote socket address.

§Future improvements

  • Separate incoming and outgoing code paths and optimistically lock the session state.

§How to use

The SnapTunNgServer is i/o-free; i.e. it only manages state. The following is a pseudo-code like description of the simplest i/o-layer integration:

let mut server = SnapTunNgServer::new(/*...*/);
let mut send_to_network = VecDequeue::new();
let mut current_sockaddr = ;
loop {
  switch {
    (network_packet, sockaddr) = network_socket => {
      server.handle_incoming_packet(/*...*/);
      /* dispatch packets to tunnel if necessary */
    }
    tunnel_packet = tunnel_socket => {
      server.handle_outgoing_packet(/*...*/);
    }
    timer = tick(250ms) => {
      server.update_timers();
    }
  }
  // dispatch packets to network
  for p in send_to_network {
    network_socket.send(sockaddr, p);
  }
}

Implementations§

Source§

impl<T: SnapTunAuthorization> SnapTunNgServer<T>

Source

pub fn new( static_private: StaticSecret, rate_limiter: Arc<RateLimiter>, authz: Arc<T>, ) -> Self

Creates a new SnapTunNgServer instance.

Source

pub fn handle_incoming_packet( &mut self, packet: Packet, from: SocketAddr, send_to_network: &mut VecDeque<WgKind>, ) -> TunnResult

Handle incoming packet for a tunnel assocated with remote socket address from.

This method never returns TunnResult::WriteToNetwork. Instead, it codifies the expected protocol behavior which is that, upon receiving a packet from the remote, the queue of outgoing packets is completely drained.

If the rate limiter signals that the server is under load, at most one packet is added to the queue.

Source

pub fn handle_outgoing_packet( &mut self, packet: Packet, to: SocketAddr, ) -> Option<WgKind>

Handles an outgoing packet sent through the tunnel identified by the remote socket address to.

Source

pub fn update_timers(&mut self) -> Vec<WgKind>

Update timers of all tunnels. Generate corresponding keepalive or session handshake initializations.

As a result of this call, all expired tunnels are removed. Note that this is not the same as unauthorized tunnels.

Auto Trait Implementations§

§

impl<T> Freeze for SnapTunNgServer<T>

§

impl<T> !RefUnwindSafe for SnapTunNgServer<T>

§

impl<T> Send for SnapTunNgServer<T>
where T: Sync + Send,

§

impl<T> Sync for SnapTunNgServer<T>
where T: Sync + Send,

§

impl<T> Unpin for SnapTunNgServer<T>

§

impl<T> !UnwindSafe for SnapTunNgServer<T>

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.

Source§

impl<T> Instrument for T

Source§

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

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

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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