pub struct SnapTunServer<T> { /* private fields */ }Expand description
The SnapTunServer 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 SnapTunServer manages that relation.
§Scaling
The main methods SnapTunServer::handle_incoming_packet, SnapTunServer::handle_outgoing_packet, and SnapTunServer::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 SnapTunServer-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 SnapTunServer 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 = SnapTunServer::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> SnapTunServer<T>
impl<T: SnapTunAuthorization> SnapTunServer<T>
Sourcepub fn new(
static_private: StaticSecret,
rate_limiter: Arc<RateLimiter>,
authz: Arc<T>,
) -> Self
pub fn new( static_private: StaticSecret, rate_limiter: Arc<RateLimiter>, authz: Arc<T>, ) -> Self
Creates a new SnapTunServer instance.
Sourcepub fn handle_incoming_packet(
&mut self,
packet: Packet,
from: SocketAddr,
send_to_network: &mut VecDeque<WgKind>,
) -> TunnResult
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.
Sourcepub fn handle_outgoing_packet(
&mut self,
packet: Packet,
to: SocketAddr,
) -> Option<WgKind>
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.
Sourcepub fn update_timers(&mut self) -> Vec<(SocketAddr, WgKind)>
pub fn update_timers(&mut self) -> Vec<(SocketAddr, 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 SnapTunServer<T>
impl<T> !RefUnwindSafe for SnapTunServer<T>
impl<T> Send for SnapTunServer<T>
impl<T> Sync for SnapTunServer<T>
impl<T> Unpin for SnapTunServer<T>
impl<T> UnsafeUnpin for SnapTunServer<T>
impl<T> !UnwindSafe for SnapTunServer<T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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