A local process attempts to send packet to WireGuard IP address (e.g., 192.168.4.3). The packet is delivered to wg interface (for user-space implementation, this is a TUN interface). Boringtun reads packets from the tun interface, find a matching peer, encapsulate packet and emit packet via the Udp socket. Recall that unlike TCP (connection, STREAM, ...), a UDP socket can be reused to send packets to different destinations (See sendto() and recvfrom() usages).
When a packet arrives to the Udp socket, receive it (and records its source address). If rate_limiter.verify_packet(Some(addr.ip()), packet, &mut t.dst_buf) is Err(TunnResult::WriteToNetwork(cookie), then udp.sendto(cookie, addr).
In most cases, boringtun will decapsulate the data and send it through the tun interface (Check the source IP address).
Conceptually, Device is mapped to a Wireguard interface (iface: Arc<T>). udp4 or udp6 is the listening UDP socket.
The device maintains a mapping from public key to Peer used for crypto-key routing.
peers_by_ip is a trie of IP/cidr addresses.
pub struct Device<T: Tun, S: Sock> {
key_pair: Option<(Arc<X25519SecretKey>, Arc<X25519PublicKey>)>,
queue: Arc<EventPoll<Handler<T, S>>>,
listen_port: u16,
fwmark: Option<u32>,
iface: Arc<T>,
udp4: Option<Arc<S>>,
udp6: Option<Arc<S>>,
yield_notice: Option<EventRef>,
exit_notice: Option<EventRef>,
peers: HashMap<Arc<X25519PublicKey>, Arc<Peer<S>>>,
peers_by_ip: AllowedIps<Arc<Peer<S>>>,
peers_by_idx: HashMap<u32, Arc<Peer<S>>>,
next_index: u32,
config: DeviceConfig,
cleanup_paths: Vec<String>,
mtu: AtomicUsize,
rate_limiter: Option<Arc<RateLimiter>>,
}
impl<T: Tun, S: Sock> Device<T, S> {
// ...
#[allow(clippy::too_many_arguments)]
fn update_peer(
&mut self,
pub_key: X25519PublicKey,
remove: bool,
_replace_ips: bool,
endpoint: Option<SocketAddr>,
allowed_ips: Vec<AllowedIP>,
keepalive: Option<u16>,
preshared_key: Option<[u8; 32]>,
) {