Lp/bugfix/share ip allocation (#6395)
* feat: use shared PeerManager between Authenticator and LpHandlerState * feat: share IpPool * clippy and test fixes * PR suggestions
This commit is contained in:
committed by
GitHub
parent
9d661e7a7b
commit
dccdde108c
Generated
+1
-1
@@ -8375,12 +8375,12 @@ dependencies = [
|
||||
"futures",
|
||||
"ip_network",
|
||||
"ipnetwork",
|
||||
"nym-authenticator-requests",
|
||||
"nym-credential-verification",
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-gateway-requests",
|
||||
"nym-gateway-storage",
|
||||
"nym-ip-packet-requests",
|
||||
"nym-metrics",
|
||||
"nym-network-defaults",
|
||||
"nym-node-metrics",
|
||||
|
||||
@@ -20,13 +20,12 @@ use nym_crypto::asymmetric::x25519::{PrivateKey, PublicKey};
|
||||
use sha2::Sha256;
|
||||
|
||||
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
|
||||
pub type PrivateIPs = HashMap<IpPair, Taken>;
|
||||
pub type PrivateIPs = HashMap<IpPair, SystemTime>;
|
||||
|
||||
#[cfg(feature = "verify")]
|
||||
pub type HmacSha256 = Hmac<Sha256>;
|
||||
|
||||
pub type Nonce = u64;
|
||||
pub type Taken = Option<SystemTime>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct IpPair {
|
||||
|
||||
@@ -26,7 +26,7 @@ impl From<&PeerControlRequest> for PeerControlRequestTypeV2 {
|
||||
fn from(req: &PeerControlRequest) -> Self {
|
||||
match req {
|
||||
PeerControlRequest::AddPeer { .. } => PeerControlRequestTypeV2::AddPeer,
|
||||
PeerControlRequest::RegisterPeer { .. } => PeerControlRequestTypeV2::AddPeer,
|
||||
PeerControlRequest::AllocatePeerIpPair { .. } => PeerControlRequestTypeV2::AddPeer,
|
||||
PeerControlRequest::RemovePeer { .. } => PeerControlRequestTypeV2::RemovePeer,
|
||||
PeerControlRequest::QueryPeer { .. } => PeerControlRequestTypeV2::QueryPeer,
|
||||
PeerControlRequest::GetClientBandwidthByKey { .. } => {
|
||||
@@ -41,6 +41,7 @@ impl From<&PeerControlRequest> for PeerControlRequestTypeV2 {
|
||||
PeerControlRequest::GetVerifierByIp { ip, .. } => {
|
||||
PeerControlRequestTypeV2::GetVerifierByIp { ip: *ip }
|
||||
}
|
||||
PeerControlRequest::ReleaseIpPair { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +114,7 @@ impl MockPeerControllerV2 {
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
PeerControlRequest::RegisterPeer { response_tx, .. } => {
|
||||
PeerControlRequest::AllocatePeerIpPair { response_tx, .. } => {
|
||||
response_tx
|
||||
.send(
|
||||
*response
|
||||
@@ -176,6 +177,15 @@ impl MockPeerControllerV2 {
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
PeerControlRequest::ReleaseIpPair { response_tx, .. } => {
|
||||
response_tx
|
||||
.send(
|
||||
*response
|
||||
.downcast()
|
||||
.expect("registered response has mismatched type"),
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ nym-credential-verification = { workspace = true }
|
||||
nym-crypto = { workspace = true, features = ["asymmetric"] }
|
||||
nym-gateway-storage = { workspace = true }
|
||||
nym-gateway-requests = { workspace = true }
|
||||
nym-ip-packet-requests = { workspace = true }
|
||||
nym-authenticator-requests = { workspace = true }
|
||||
nym-metrics = { workspace = true }
|
||||
nym-network-defaults = { workspace = true }
|
||||
nym-task = { workspace = true }
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::ip_pool::IpPair;
|
||||
|
||||
impl From<IpPair> for nym_authenticator_requests::v6::registration::IpPair {
|
||||
fn from(ip_pair: IpPair) -> Self {
|
||||
nym_authenticator_requests::v6::registration::IpPair {
|
||||
ipv4: ip_pair.ipv4,
|
||||
ipv6: ip_pair.ipv6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpPair> for nym_authenticator_requests::v5::registration::IpPair {
|
||||
fn from(ip_pair: IpPair) -> Self {
|
||||
nym_authenticator_requests::v5::registration::IpPair {
|
||||
ipv4: ip_pair.ipv4,
|
||||
ipv6: ip_pair.ipv6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpPair> for nym_authenticator_requests::v4::registration::IpPair {
|
||||
fn from(ip_pair: IpPair) -> Self {
|
||||
nym_authenticator_requests::v4::registration::IpPair {
|
||||
ipv4: ip_pair.ipv4,
|
||||
ipv6: ip_pair.ipv6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
impl From<nym_authenticator_requests::v6::registration::IpPair> for IpPair {
|
||||
fn from(ip_pair: nym_authenticator_requests::v6::registration::IpPair) -> Self {
|
||||
IpPair {
|
||||
ipv4: ip_pair.ipv4,
|
||||
ipv6: ip_pair.ipv6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nym_authenticator_requests::v5::registration::IpPair> for IpPair {
|
||||
fn from(ip_pair: nym_authenticator_requests::v5::registration::IpPair) -> Self {
|
||||
IpPair {
|
||||
ipv4: ip_pair.ipv4,
|
||||
ipv6: ip_pair.ipv6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nym_authenticator_requests::v4::registration::IpPair> for IpPair {
|
||||
fn from(ip_pair: nym_authenticator_requests::v4::registration::IpPair) -> Self {
|
||||
IpPair {
|
||||
ipv4: ip_pair.ipv4,
|
||||
ipv6: ip_pair.ipv6,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,56 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
mod compat;
|
||||
|
||||
use defguard_wireguard_rs::host::Peer;
|
||||
use ipnetwork::IpNetwork;
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use rand::seq::IteratorRandom;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::sync::Arc;
|
||||
use std::time::SystemTime;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::time::Instant;
|
||||
use tracing::{trace, warn};
|
||||
|
||||
// helper to convert peer's allocation into an `IpPair`
|
||||
pub fn allocated_ip_pair(peer: &Peer) -> Option<IpPair> {
|
||||
for allowed_ip in &peer.allowed_ips {
|
||||
// Extract IPv4 and IPv6 from peer's allowed_ips
|
||||
if let IpAddr::V4(ipv4) = allowed_ip.address {
|
||||
// Find corresponding IPv6
|
||||
if let Some(ipv6_mask) = peer
|
||||
.allowed_ips
|
||||
.iter()
|
||||
.find(|ip| matches!(ip.address, IpAddr::V6(_)))
|
||||
&& let IpAddr::V6(ipv6) = ipv6_mask.address
|
||||
{
|
||||
return Some(IpPair::new(ipv4, ipv6));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Hash)]
|
||||
pub struct IpPair {
|
||||
pub ipv4: Ipv4Addr,
|
||||
pub ipv6: Ipv6Addr,
|
||||
}
|
||||
|
||||
impl IpPair {
|
||||
pub fn new(ipv4: Ipv4Addr, ipv6: Ipv6Addr) -> Self {
|
||||
IpPair { ipv4, ipv6 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IpPair {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "IPv4: {}, IPv6: {}", self.ipv4, self.ipv6)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the state of an IP allocation
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -83,12 +125,8 @@ impl IpPool {
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"Initialized IP pool with {} address pairs from {}/{} and {}/{}",
|
||||
"Initialized IP pool with {} address pairs from {ipv4_network}/{ipv4_prefix} and {ipv6_network}/{ipv6_prefix}",
|
||||
allocations.len(),
|
||||
ipv4_network,
|
||||
ipv4_prefix,
|
||||
ipv6_network,
|
||||
ipv6_prefix
|
||||
);
|
||||
|
||||
Ok(IpPool {
|
||||
@@ -98,24 +136,28 @@ impl IpPool {
|
||||
|
||||
/// Allocate a free IP pair from the pool
|
||||
///
|
||||
/// Randomly selects an available IP pair and marks it as allocated.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns `IpPoolError::NoFreeIp` if no IPs are available
|
||||
pub async fn allocate(&self) -> Result<IpPair, IpPoolError> {
|
||||
let mut pool = self.allocations.write().await;
|
||||
|
||||
// Find a free IP and allocate it
|
||||
let assignment_start = Instant::now();
|
||||
let free_ip = pool
|
||||
.iter_mut()
|
||||
.filter(|(_, state)| matches!(state, AllocationState::Free))
|
||||
.choose(&mut rand::thread_rng())
|
||||
.ok_or(IpPoolError::NoFreeIp)?;
|
||||
let taken = assignment_start.elapsed();
|
||||
trace!("assigning free ip pair took {taken:?}");
|
||||
if taken > Duration::from_millis(500) {
|
||||
warn!("assigning free ip pair took {taken:?}");
|
||||
}
|
||||
|
||||
let ip_pair = *free_ip.0;
|
||||
*free_ip.1 = AllocationState::Allocated(SystemTime::now());
|
||||
|
||||
tracing::debug!("Allocated IP pair: {}", ip_pair);
|
||||
tracing::debug!("Allocated IP pair: {ip_pair}");
|
||||
Ok(ip_pair)
|
||||
}
|
||||
|
||||
@@ -126,7 +168,7 @@ impl IpPool {
|
||||
let mut pool = self.allocations.write().await;
|
||||
if let Some(state) = pool.get_mut(&ip_pair) {
|
||||
*state = AllocationState::Free;
|
||||
tracing::debug!("Released IP pair: {}", ip_pair);
|
||||
tracing::debug!("Released IP pair: {ip_pair}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,9 +179,9 @@ impl IpPool {
|
||||
let mut pool = self.allocations.write().await;
|
||||
if let Some(state) = pool.get_mut(&ip_pair) {
|
||||
*state = AllocationState::Allocated(SystemTime::now());
|
||||
tracing::debug!("Marked IP pair as used: {}", ip_pair);
|
||||
tracing::debug!("Marked IP pair as used: {ip_pair}");
|
||||
} else {
|
||||
tracing::warn!("Attempted to mark unknown IP pair as used: {}", ip_pair);
|
||||
tracing::warn!("Attempted to mark unknown IP pair as used: {ip_pair}");
|
||||
}
|
||||
}
|
||||
|
||||
+17
-34
@@ -2,9 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
|
||||
// #![warn(clippy::pedantic)]
|
||||
// #![warn(clippy::expect_used)]
|
||||
// #![warn(clippy::unwrap_used)]
|
||||
|
||||
use defguard_wireguard_rs::{
|
||||
WGApi, WireguardInterfaceApi, error::WireguardInterfaceError, host::Peer, key::Key,
|
||||
@@ -16,9 +13,6 @@ use std::sync::Arc;
|
||||
use tokio::sync::mpsc::{self, Receiver, Sender};
|
||||
use tracing::error;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use nym_network_defaults::constants::WG_TUN_BASE_NAME;
|
||||
|
||||
@@ -288,6 +282,22 @@ pub async fn start_wireguard(
|
||||
peer_bandwidth_managers.insert(peer.public_key.clone(), (bandwidth_manager, peer.clone()));
|
||||
}
|
||||
|
||||
// Initialize IP pool from configuration
|
||||
info!("Initializing IP pool for WireGuard peer allocation");
|
||||
let ip_pool = IpPool::new(
|
||||
wireguard_data.inner.config().private_ipv4,
|
||||
wireguard_data.inner.config().private_network_prefix_v4,
|
||||
wireguard_data.inner.config().private_ipv6,
|
||||
wireguard_data.inner.config().private_network_prefix_v6,
|
||||
)?;
|
||||
|
||||
// Mark existing peer IPs as used in the pool
|
||||
for peer in &peers {
|
||||
if let Some(ip_pair) = crate::ip_pool::allocated_ip_pair(peer) {
|
||||
ip_pool.mark_used(ip_pair).await;
|
||||
}
|
||||
}
|
||||
|
||||
wg_api.create_interface()?;
|
||||
let interface_config = InterfaceConfiguration {
|
||||
name: ifname.clone(),
|
||||
@@ -296,7 +306,7 @@ pub async fn start_wireguard(
|
||||
wireguard_data.inner.config().private_ipv4,
|
||||
))],
|
||||
port: wireguard_data.inner.config().announced_tunnel_port,
|
||||
peers: peers.clone(), // Clone since we need to use peers later to mark IPs as used
|
||||
peers,
|
||||
mtu: None,
|
||||
};
|
||||
info!(
|
||||
@@ -350,33 +360,6 @@ pub async fn start_wireguard(
|
||||
|
||||
let host = wg_api.read_interface_data()?;
|
||||
|
||||
// Initialize IP pool from configuration
|
||||
info!("Initializing IP pool for WireGuard peer allocation");
|
||||
let ip_pool = IpPool::new(
|
||||
wireguard_data.inner.config().private_ipv4,
|
||||
wireguard_data.inner.config().private_network_prefix_v4,
|
||||
wireguard_data.inner.config().private_ipv6,
|
||||
wireguard_data.inner.config().private_network_prefix_v6,
|
||||
)?;
|
||||
|
||||
// Mark existing peer IPs as used in the pool
|
||||
for peer in &peers {
|
||||
for allowed_ip in &peer.allowed_ips {
|
||||
// Extract IPv4 and IPv6 from peer's allowed_ips
|
||||
if let IpAddr::V4(ipv4) = allowed_ip.address {
|
||||
// Find corresponding IPv6
|
||||
if let Some(ipv6_mask) = peer
|
||||
.allowed_ips
|
||||
.iter()
|
||||
.find(|ip| matches!(ip.address, IpAddr::V6(_)))
|
||||
&& let IpAddr::V6(ipv6) = ipv6_mask.address
|
||||
{
|
||||
ip_pool.mark_used(IpPair::new(ipv4, ipv6)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let wg_api = std::sync::Arc::new(wg_api);
|
||||
let mut controller = PeerController::new(
|
||||
ecash_manager,
|
||||
|
||||
@@ -19,6 +19,7 @@ use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
|
||||
use crate::ip_pool::IpPair;
|
||||
pub use defguard_wireguard_rs::key::Key;
|
||||
|
||||
pub fn mock_peer_controller(
|
||||
@@ -70,7 +71,8 @@ impl From<&Key> for KeyWrapper {
|
||||
#[derive(Hash, PartialOrd, PartialEq, Clone, Debug, Eq)]
|
||||
pub enum PeerControlRequestType {
|
||||
AddPeer { public_key: KeyWrapper },
|
||||
RegisterPeer { public_key: KeyWrapper },
|
||||
AllocatePeerIpPair {},
|
||||
ReleaseIpPair { ip_pair: IpPair },
|
||||
RemovePeer { key: KeyWrapper },
|
||||
QueryPeer { key: KeyWrapper },
|
||||
GetClientBandwidthByKey { key: KeyWrapper },
|
||||
@@ -83,7 +85,8 @@ impl PeerControlRequestType {
|
||||
pub fn peer_key(&self) -> Option<KeyWrapper> {
|
||||
match self {
|
||||
PeerControlRequestType::AddPeer { public_key } => Some(public_key.clone()),
|
||||
PeerControlRequestType::RegisterPeer { public_key } => Some(public_key.clone()),
|
||||
PeerControlRequestType::AllocatePeerIpPair {} => None,
|
||||
PeerControlRequestType::ReleaseIpPair { .. } => None,
|
||||
PeerControlRequestType::RemovePeer { key } => Some(key.clone()),
|
||||
PeerControlRequestType::QueryPeer { key } => Some(key.clone()),
|
||||
PeerControlRequestType::GetClientBandwidthByKey { key } => Some(key.clone()),
|
||||
@@ -104,11 +107,12 @@ impl From<&PeerControlRequest> for PeerControlRequestType {
|
||||
PeerControlRequest::AddPeer { peer, .. } => PeerControlRequestType::AddPeer {
|
||||
public_key: (&peer.public_key).into(),
|
||||
},
|
||||
PeerControlRequest::RegisterPeer {
|
||||
registration_data, ..
|
||||
} => PeerControlRequestType::RegisterPeer {
|
||||
public_key: (®istration_data.public_key).into(),
|
||||
},
|
||||
PeerControlRequest::AllocatePeerIpPair { .. } => {
|
||||
PeerControlRequestType::AllocatePeerIpPair {}
|
||||
}
|
||||
PeerControlRequest::ReleaseIpPair { ip_pair, .. } => {
|
||||
PeerControlRequestType::ReleaseIpPair { ip_pair: *ip_pair }
|
||||
}
|
||||
PeerControlRequest::RemovePeer { key, .. } => {
|
||||
PeerControlRequestType::RemovePeer { key: key.into() }
|
||||
}
|
||||
@@ -166,9 +170,6 @@ pub struct MockPeerControllerState {
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct PeerState {
|
||||
/// Has IpPair been allocated to the peer?
|
||||
pub register_success: bool,
|
||||
|
||||
// in the future maybe we could extend it with `ClientBandwidth` information
|
||||
/// Has the client handle been spawned
|
||||
pub add_success: bool,
|
||||
@@ -265,14 +266,13 @@ impl MockPeerController {
|
||||
}
|
||||
response_tx.send_downcasted(response.content)
|
||||
}
|
||||
PeerControlRequest::RegisterPeer { response_tx, .. } => {
|
||||
let key = typ.peer_key_unchecked();
|
||||
let peer = peers_guard.peers.entry(key).or_default();
|
||||
if response.success {
|
||||
peer.register_success = true;
|
||||
}
|
||||
PeerControlRequest::AllocatePeerIpPair { response_tx, .. } => {
|
||||
response_tx.send_downcasted(response.content)
|
||||
}
|
||||
PeerControlRequest::ReleaseIpPair {
|
||||
response_tx,
|
||||
ip_pair: _,
|
||||
} => response_tx.send_downcasted(response.content),
|
||||
PeerControlRequest::RemovePeer { response_tx, .. } => {
|
||||
let key = typ.peer_key_unchecked();
|
||||
if response.success {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::ip_pool::allocated_ip_pair;
|
||||
use crate::{
|
||||
IpPool,
|
||||
error::{Error, Result},
|
||||
@@ -32,9 +33,9 @@ use std::{
|
||||
};
|
||||
use tokio::sync::{RwLock, mpsc};
|
||||
use tokio_stream::{StreamExt, wrappers::IntervalStream};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
pub use nym_ip_packet_requests::IpPair;
|
||||
pub use crate::ip_pool::IpPair;
|
||||
|
||||
#[cfg(feature = "mock")]
|
||||
pub mod mock;
|
||||
@@ -75,10 +76,14 @@ pub enum PeerControlRequest {
|
||||
peer: Peer,
|
||||
response_tx: oneshot::Sender<AddPeerControlResponse>,
|
||||
},
|
||||
/// Register a new peer and allocate IPs from the pool
|
||||
RegisterPeer {
|
||||
registration_data: PeerRegistrationData,
|
||||
response_tx: oneshot::Sender<RegisterPeerControlResponse>,
|
||||
/// Attempt to allocate an IP pair from the pool
|
||||
AllocatePeerIpPair {
|
||||
response_tx: oneshot::Sender<AllocatePeerControlResponse>,
|
||||
},
|
||||
/// Attempt to return an IP pair back to the pool
|
||||
ReleaseIpPair {
|
||||
response_tx: oneshot::Sender<ReleaseIpPairControlResponse>,
|
||||
ip_pair: IpPair,
|
||||
},
|
||||
RemovePeer {
|
||||
key: Key,
|
||||
@@ -109,7 +114,8 @@ pub enum PeerControlRequest {
|
||||
}
|
||||
|
||||
pub type AddPeerControlResponse = Result<()>;
|
||||
pub type RegisterPeerControlResponse = Result<IpPair>;
|
||||
pub type AllocatePeerControlResponse = Result<IpPair>;
|
||||
pub type ReleaseIpPairControlResponse = Result<()>;
|
||||
pub type RemovePeerControlResponse = Result<()>;
|
||||
pub type QueryPeerControlResponse = Result<Option<Peer>>;
|
||||
pub type GetClientBandwidthControlResponse = Result<ClientBandwidth>;
|
||||
@@ -207,9 +213,11 @@ impl PeerController {
|
||||
.await?;
|
||||
self.bw_storage_managers.remove(key);
|
||||
|
||||
warn!("MISSING CALL TO IP POOL RELEASE");
|
||||
// need to figure out what addresses to release
|
||||
// self.ip_pool.release()
|
||||
if let Ok(Some(peer)) = self.handle_query_peer_by_key(key).await
|
||||
&& let Some(ip_pair) = allocated_ip_pair(&peer)
|
||||
{
|
||||
self.ip_pool.release(ip_pair).await
|
||||
}
|
||||
|
||||
let ret = self.wg_api.remove_peer(key);
|
||||
if ret.is_err() {
|
||||
@@ -294,10 +302,7 @@ impl PeerController {
|
||||
///
|
||||
/// This only allocates IPs - the caller must handle database storage and
|
||||
/// then call AddPeer with a complete Peer struct.
|
||||
async fn handle_register_request(
|
||||
&mut self,
|
||||
_registration_data: PeerRegistrationData,
|
||||
) -> Result<IpPair> {
|
||||
async fn handle_ip_allocation_request(&mut self) -> Result<IpPair> {
|
||||
nym_metrics::inc!("wg_ip_allocation_attempts");
|
||||
|
||||
// Allocate IP pair from pool
|
||||
@@ -313,6 +318,11 @@ impl PeerController {
|
||||
Ok(ip_pair)
|
||||
}
|
||||
|
||||
/// Return IP pair back to the pool
|
||||
async fn handle_ip_release(&mut self, ip_pair: IpPair) {
|
||||
self.ip_pool.release(ip_pair).await
|
||||
}
|
||||
|
||||
async fn ip_to_key(&self, ip: IpAddr) -> Result<Option<Key>> {
|
||||
Ok(self
|
||||
.bw_storage_managers
|
||||
@@ -477,6 +487,62 @@ impl PeerController {
|
||||
);
|
||||
}
|
||||
|
||||
async fn handle_peer_control_request(&mut self, msg: PeerControlRequest) {
|
||||
match msg {
|
||||
PeerControlRequest::AddPeer { peer, response_tx } => {
|
||||
response_tx.send(self.handle_add_request(&peer).await).ok();
|
||||
}
|
||||
PeerControlRequest::AllocatePeerIpPair { response_tx } => {
|
||||
response_tx
|
||||
.send(self.handle_ip_allocation_request().await)
|
||||
.ok();
|
||||
}
|
||||
PeerControlRequest::ReleaseIpPair {
|
||||
response_tx,
|
||||
ip_pair,
|
||||
} => {
|
||||
self.handle_ip_release(ip_pair).await;
|
||||
response_tx.send(Ok(())).ok();
|
||||
}
|
||||
PeerControlRequest::RemovePeer { key, response_tx } => {
|
||||
response_tx.send(self.remove_peer(&key).await).ok();
|
||||
}
|
||||
PeerControlRequest::QueryPeer { key, response_tx } => {
|
||||
response_tx
|
||||
.send(self.handle_query_peer_by_key(&key).await)
|
||||
.ok();
|
||||
}
|
||||
PeerControlRequest::GetClientBandwidthByKey { key, response_tx } => {
|
||||
response_tx
|
||||
.send(self.handle_get_client_bandwidth_by_key(&key).await)
|
||||
.ok();
|
||||
}
|
||||
PeerControlRequest::GetClientBandwidthByIp { ip, response_tx } => {
|
||||
response_tx
|
||||
.send(self.handle_get_client_bandwidth_by_ip(ip).await)
|
||||
.ok();
|
||||
}
|
||||
PeerControlRequest::GetVerifierByKey {
|
||||
key,
|
||||
credential,
|
||||
response_tx,
|
||||
} => {
|
||||
response_tx
|
||||
.send(self.handle_query_verifier_by_key(&key, *credential).await)
|
||||
.ok();
|
||||
}
|
||||
PeerControlRequest::GetVerifierByIp {
|
||||
ip,
|
||||
credential,
|
||||
response_tx,
|
||||
} => {
|
||||
response_tx
|
||||
.send(self.handle_query_verifier_by_ip(ip, *credential).await)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) {
|
||||
info!("started wireguard peer controller");
|
||||
loop {
|
||||
@@ -504,30 +570,7 @@ impl PeerController {
|
||||
}
|
||||
msg = self.request_rx.recv() => {
|
||||
match msg {
|
||||
Some(PeerControlRequest::AddPeer { peer, response_tx }) => {
|
||||
response_tx.send(self.handle_add_request(&peer).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::RegisterPeer { registration_data, response_tx }) => {
|
||||
response_tx.send(self.handle_register_request(registration_data).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::RemovePeer { key, response_tx }) => {
|
||||
response_tx.send(self.remove_peer(&key).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::QueryPeer { key, response_tx }) => {
|
||||
response_tx.send(self.handle_query_peer_by_key(&key).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::GetClientBandwidthByKey { key, response_tx }) => {
|
||||
response_tx.send(self.handle_get_client_bandwidth_by_key(&key).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::GetClientBandwidthByIp { ip, response_tx }) => {
|
||||
response_tx.send(self.handle_get_client_bandwidth_by_ip(ip).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::GetVerifierByKey { key, credential, response_tx }) => {
|
||||
response_tx.send(self.handle_query_verifier_by_key(&key, *credential).await).ok();
|
||||
}
|
||||
Some(PeerControlRequest::GetVerifierByIp { ip, credential, response_tx }) => {
|
||||
response_tx.send(self.handle_query_verifier_by_ip(ip, *credential).await).ok();
|
||||
}
|
||||
Some(request) => self.handle_peer_control_request(request).await,
|
||||
None => {
|
||||
trace!("PeerController [main loop]: stopping since channel closed");
|
||||
break;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
pub use crate::node::client_handling::websocket::connection_handler::authenticated::RequestHandlingError;
|
||||
use crate::node::internal_service_providers::authenticator::error::AuthenticatorError;
|
||||
use crate::node::wireguard::GatewayWireguardError;
|
||||
use nym_credential_verification::upgrade_mode::UpgradeModeEnableError;
|
||||
use nym_gateway_stats_storage::error::StatsStorageError;
|
||||
use nym_gateway_storage::error::GatewayStorageError;
|
||||
@@ -158,6 +159,9 @@ pub enum GatewayError {
|
||||
|
||||
#[error(transparent)]
|
||||
UpgradeModeEnable(#[from] UpgradeModeEnableError),
|
||||
|
||||
#[error(transparent)]
|
||||
WireguardFailure(#[from] GatewayWireguardError),
|
||||
}
|
||||
|
||||
impl From<ClientCoreError> for GatewayError {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::wireguard::GatewayWireguardError;
|
||||
use ipnetwork::IpNetworkError;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_credential_verification::upgrade_mode::UpgradeModeEnableError;
|
||||
@@ -82,9 +83,6 @@ pub enum AuthenticatorError {
|
||||
#[error("internal data corruption: {0}")]
|
||||
InternalDataCorruption(String),
|
||||
|
||||
#[error("peers can't be interacted with anymore")]
|
||||
PeerInteractionStopped,
|
||||
|
||||
#[error("unknown version number")]
|
||||
UnknownVersion,
|
||||
|
||||
@@ -108,6 +106,9 @@ pub enum AuthenticatorError {
|
||||
|
||||
#[error(transparent)]
|
||||
UpgradeModeEnable(#[from] UpgradeModeEnableError),
|
||||
|
||||
#[error(transparent)]
|
||||
WireguardFailure(#[from] GatewayWireguardError),
|
||||
}
|
||||
|
||||
impl AuthenticatorError {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::internal_service_providers::authenticator::{
|
||||
config::Config, error::AuthenticatorError, peer_manager::PeerManager,
|
||||
seen_credential_cache::SeenCredentialCache,
|
||||
config::Config, error::AuthenticatorError, seen_credential_cache::SeenCredentialCache,
|
||||
};
|
||||
use crate::node::wireguard::PeerManager;
|
||||
use defguard_wireguard_rs::net::IpAddrMask;
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key};
|
||||
use futures::StreamExt;
|
||||
@@ -35,7 +35,6 @@ use nym_sphinx::receiver::ReconstructedMessage;
|
||||
use nym_task::ShutdownToken;
|
||||
use nym_wireguard::WireguardGatewayData;
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use rand::{prelude::IteratorRandom, thread_rng};
|
||||
use std::cmp::max;
|
||||
use std::{
|
||||
net::IpAddr,
|
||||
@@ -54,14 +53,14 @@ const DEFAULT_WG_CLIENT_BANDWIDTH_THRESHOLD: i64 = 1024 * 1024 * 1024;
|
||||
|
||||
pub(crate) struct RegisteredAndFree {
|
||||
registration_in_progress: PendingRegistrations,
|
||||
free_private_network_ips: PrivateIPs,
|
||||
taken_private_network_ips: PrivateIPs,
|
||||
}
|
||||
|
||||
impl RegisteredAndFree {
|
||||
pub(crate) fn new(free_private_network_ips: PrivateIPs) -> Self {
|
||||
pub(crate) fn new() -> Self {
|
||||
RegisteredAndFree {
|
||||
registration_in_progress: Default::default(),
|
||||
free_private_network_ips,
|
||||
taken_private_network_ips: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +89,6 @@ pub(crate) struct MixnetListener {
|
||||
impl MixnetListener {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
free_private_network_ips: PrivateIPs,
|
||||
wireguard_gateway_data: WireguardGatewayData,
|
||||
mixnet_client: nym_sdk::mixnet::MixnetClient,
|
||||
upgrade_mode: UpgradeModeDetails,
|
||||
@@ -101,7 +99,7 @@ impl MixnetListener {
|
||||
MixnetListener {
|
||||
config,
|
||||
mixnet_client,
|
||||
registered_and_free: RwLock::new(RegisteredAndFree::new(free_private_network_ips)),
|
||||
registered_and_free: RwLock::new(RegisteredAndFree::new()),
|
||||
peer_manager: PeerManager::new(wireguard_gateway_data),
|
||||
upgrade_mode,
|
||||
ecash_verifier,
|
||||
@@ -139,34 +137,30 @@ impl MixnetListener {
|
||||
.cloned()
|
||||
.collect();
|
||||
for reg in registered_values {
|
||||
let ip = registered_and_free
|
||||
.free_private_network_ips
|
||||
let timestamp = registered_and_free
|
||||
.taken_private_network_ips
|
||||
.get_mut(®.gateway_data.private_ips)
|
||||
.ok_or(AuthenticatorError::InternalDataCorruption(format!(
|
||||
"IPs {} should be present",
|
||||
reg.gateway_data.private_ips
|
||||
)))?;
|
||||
|
||||
let Some(timestamp) = ip else {
|
||||
registered_and_free
|
||||
.registration_in_progress
|
||||
.remove(®.gateway_data.pub_key());
|
||||
tracing::debug!(
|
||||
"Removed stale registration of {}",
|
||||
reg.gateway_data.pub_key()
|
||||
);
|
||||
continue;
|
||||
};
|
||||
let duration = SystemTime::now().duration_since(*timestamp).map_err(|_| {
|
||||
AuthenticatorError::InternalDataCorruption(
|
||||
"set timestamp shouldn't have been set in the future".to_string(),
|
||||
)
|
||||
})?;
|
||||
if duration > DEFAULT_REGISTRATION_TIMEOUT_CHECK {
|
||||
*ip = None;
|
||||
registered_and_free
|
||||
.registration_in_progress
|
||||
.remove(®.gateway_data.pub_key());
|
||||
registered_and_free
|
||||
.taken_private_network_ips
|
||||
.remove(®.gateway_data.private_ips);
|
||||
self.peer_manager
|
||||
.release_ip_pair(reg.gateway_data.private_ips.into())
|
||||
.await?;
|
||||
|
||||
tracing::debug!(
|
||||
"Removed stale registration of {}",
|
||||
reg.gateway_data.pub_key()
|
||||
@@ -383,19 +377,18 @@ impl MixnetListener {
|
||||
return Ok((bytes, reply_to));
|
||||
}
|
||||
|
||||
let private_ip_ref = registered_and_free
|
||||
.free_private_network_ips
|
||||
.iter_mut()
|
||||
.filter(|r| r.1.is_none())
|
||||
.choose(&mut thread_rng())
|
||||
.ok_or(AuthenticatorError::NoFreeIp)?;
|
||||
let private_ips = *private_ip_ref.0;
|
||||
// mark it as used, even though it's not final
|
||||
*private_ip_ref.1 = Some(SystemTime::now());
|
||||
let ip_allocation = self.peer_manager.allocate_peer_ip_pair().await?;
|
||||
self.registered_and_free
|
||||
.write()
|
||||
.await
|
||||
.taken_private_network_ips
|
||||
.insert(ip_allocation.into(), SystemTime::now());
|
||||
|
||||
let gateway_data = GatewayClient::new(
|
||||
self.keypair().private_key(),
|
||||
remote_public.inner(),
|
||||
*private_ip_ref.0,
|
||||
ip_allocation.into(),
|
||||
nonce,
|
||||
);
|
||||
let registration_data = latest::registration::RegistrationData {
|
||||
@@ -414,7 +407,7 @@ impl MixnetListener {
|
||||
gateway_data: v1::registration::GatewayClient::new(
|
||||
self.keypair().private_key(),
|
||||
remote_public.inner(),
|
||||
private_ips.ipv4.into(),
|
||||
ip_allocation.ipv4.into(),
|
||||
nonce,
|
||||
),
|
||||
wg_port: registration_data.wg_port,
|
||||
@@ -432,7 +425,7 @@ impl MixnetListener {
|
||||
gateway_data: v2::registration::GatewayClient::new(
|
||||
self.keypair().private_key(),
|
||||
remote_public.inner(),
|
||||
private_ips.ipv4.into(),
|
||||
ip_allocation.ipv4.into(),
|
||||
nonce,
|
||||
),
|
||||
wg_port: registration_data.wg_port,
|
||||
@@ -450,7 +443,7 @@ impl MixnetListener {
|
||||
gateway_data: v3::registration::GatewayClient::new(
|
||||
self.keypair().private_key(),
|
||||
remote_public.inner(),
|
||||
private_ips.ipv4.into(),
|
||||
ip_allocation.ipv4.into(),
|
||||
nonce,
|
||||
),
|
||||
wg_port: registration_data.wg_port,
|
||||
@@ -592,7 +585,7 @@ impl MixnetListener {
|
||||
.storage()
|
||||
.remove_wireguard_peer(&public_key)
|
||||
.await?;
|
||||
return Err(e);
|
||||
return Err(e.into());
|
||||
}
|
||||
|
||||
registered_and_free
|
||||
|
||||
@@ -3,21 +3,19 @@
|
||||
|
||||
use crate::node::internal_service_providers::authenticator::error::AuthenticatorError;
|
||||
use futures::channel::oneshot;
|
||||
use ipnetwork::IpNetwork;
|
||||
use nym_client_core::{HardcodedTopologyProvider, TopologyProvider};
|
||||
use nym_credential_verification::upgrade_mode::UpgradeModeDetails;
|
||||
use nym_sdk::{mixnet::Recipient, GatewayTransceiver};
|
||||
use nym_task::ShutdownTracker;
|
||||
use nym_wireguard::WireguardGatewayData;
|
||||
use std::{net::IpAddr, path::Path, sync::Arc, time::SystemTime};
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
pub use config::Config;
|
||||
use nym_credential_verification::upgrade_mode::UpgradeModeDetails;
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod mixnet_client;
|
||||
pub mod mixnet_listener;
|
||||
mod peer_manager;
|
||||
mod seen_credential_cache;
|
||||
|
||||
pub struct OnStartData {
|
||||
@@ -40,7 +38,6 @@ pub struct Authenticator {
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send + Sync>>,
|
||||
wireguard_gateway_data: WireguardGatewayData,
|
||||
ecash_verifier: Arc<dyn nym_credential_verification::ecash::traits::EcashManager + Send + Sync>,
|
||||
used_private_network_ips: Vec<IpAddr>,
|
||||
shutdown: ShutdownTracker,
|
||||
on_start: Option<oneshot::Sender<OnStartData>>,
|
||||
}
|
||||
@@ -50,7 +47,6 @@ impl Authenticator {
|
||||
config: Config,
|
||||
upgrade_mode_state: UpgradeModeDetails,
|
||||
wireguard_gateway_data: WireguardGatewayData,
|
||||
used_private_network_ips: Vec<IpAddr>,
|
||||
ecash_verifier: Arc<
|
||||
dyn nym_credential_verification::ecash::traits::EcashManager + Send + Sync,
|
||||
>,
|
||||
@@ -64,7 +60,6 @@ impl Authenticator {
|
||||
custom_gateway_transceiver: None,
|
||||
ecash_verifier,
|
||||
wireguard_gateway_data,
|
||||
used_private_network_ips,
|
||||
shutdown,
|
||||
on_start: None,
|
||||
}
|
||||
@@ -135,26 +130,8 @@ impl Authenticator {
|
||||
|
||||
let self_address = *mixnet_client.nym_address();
|
||||
|
||||
let used_private_network_ips =
|
||||
std::collections::BTreeSet::from_iter(self.used_private_network_ips.iter());
|
||||
let private_ip_network = IpNetwork::new(
|
||||
self.config.authenticator.private_ipv4.into(),
|
||||
self.config.authenticator.private_network_prefix_v4,
|
||||
)?;
|
||||
let now = SystemTime::now();
|
||||
let free_private_network_ips = private_ip_network
|
||||
.iter()
|
||||
.map(|ip: IpAddr| {
|
||||
if used_private_network_ips.contains(&ip) {
|
||||
(ip.into(), Some(now))
|
||||
} else {
|
||||
(ip.into(), None)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let mixnet_listener = mixnet_listener::MixnetListener::new(
|
||||
self.config,
|
||||
free_private_network_ips,
|
||||
self.wireguard_gateway_data,
|
||||
mixnet_client,
|
||||
self.upgrade_mode_state,
|
||||
|
||||
@@ -1228,8 +1228,8 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::node::lp_listener::peer_manager::PeerManager;
|
||||
use crate::node::lp_listener::{LpConfig, LpDebug};
|
||||
use crate::node::wireguard::PeerManager;
|
||||
use crate::node::ActiveClientsStore;
|
||||
use bytes::BytesMut;
|
||||
use nym_credential_verification::upgrade_mode::{
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
// They can be exported via Prometheus format using the metrics endpoint.
|
||||
|
||||
use crate::error::GatewayError;
|
||||
use crate::node::lp_listener::peer_manager::PeerManager;
|
||||
use crate::node::lp_listener::registration::RegistrationsInProgress;
|
||||
use crate::node::ActiveClientsStore;
|
||||
use dashmap::DashMap;
|
||||
@@ -86,6 +85,7 @@ use tokio::net::TcpListener;
|
||||
use tokio::sync::Semaphore;
|
||||
use tracing::*;
|
||||
|
||||
use crate::node::wireguard::PeerManager;
|
||||
pub use nym_lp::peer::LpLocalPeer;
|
||||
pub use nym_mixnet_client::forwarder::{
|
||||
mix_forwarding_channels, MixForwardingReceiver, MixForwardingSender,
|
||||
@@ -94,7 +94,6 @@ pub use nym_wireguard::{PeerControlRequest, WireguardGatewayData};
|
||||
|
||||
mod data_handler;
|
||||
pub mod handler;
|
||||
pub mod peer_manager;
|
||||
mod registration;
|
||||
|
||||
pub type ReceiverIndex = u32;
|
||||
@@ -578,6 +577,7 @@ impl LpListener {
|
||||
///
|
||||
/// The task automatically stops when the shutdown signal is received.
|
||||
fn spawn_state_cleanup_task(&self) -> tokio::task::JoinHandle<()> {
|
||||
let peer_manager = Arc::clone(&self.handler_state.peer_manager);
|
||||
let handshake_states = Arc::clone(&self.handler_state.handshake_states);
|
||||
let session_states = Arc::clone(&self.handler_state.session_states);
|
||||
let pending_registrations = self.handler_state.registrations_in_progress.clone();
|
||||
@@ -598,6 +598,7 @@ impl LpListener {
|
||||
|
||||
self.shutdown.try_spawn_named(
|
||||
cleanup_task::cleanup_loop(
|
||||
peer_manager,
|
||||
handshake_states,
|
||||
session_states,
|
||||
pending_registrations,
|
||||
@@ -620,15 +621,17 @@ impl LpListener {
|
||||
pub(crate) mod cleanup_task {
|
||||
use crate::node::lp_listener::registration::RegistrationsInProgress;
|
||||
use crate::node::lp_listener::{LpDebug, TimestampedState};
|
||||
use crate::node::wireguard::PeerManager;
|
||||
use dashmap::DashMap;
|
||||
use nym_lp::state_machine::LpStateBare;
|
||||
use nym_lp::LpStateMachine;
|
||||
use nym_metrics::inc_by;
|
||||
use nym_node_metrics::NymNodeMetrics;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, info};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
async fn perform_cleanup(
|
||||
peer_manager: &PeerManager,
|
||||
handshake_states: &Arc<DashMap<u32, TimestampedState<LpStateMachine>>>,
|
||||
session_states: &Arc<DashMap<u32, TimestampedState<LpStateMachine>>>,
|
||||
registrations_in_progress: &RegistrationsInProgress,
|
||||
@@ -678,17 +681,27 @@ pub(crate) mod cleanup_task {
|
||||
});
|
||||
|
||||
// Remove stale registrations (based on time since last activity)
|
||||
registrations_in_progress
|
||||
.lock()
|
||||
.await
|
||||
.retain(|_, timestamped| {
|
||||
if timestamped.age() > pending_registration_ttl {
|
||||
pending_reg_removed += 1;
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
let mut reg_guard = registrations_in_progress.lock().await;
|
||||
let mut stale_registrations = Vec::new();
|
||||
for (k, timestamped) in reg_guard.iter() {
|
||||
if timestamped.age() > pending_registration_ttl {
|
||||
stale_registrations.push(*k)
|
||||
}
|
||||
}
|
||||
|
||||
for to_remove in stale_registrations {
|
||||
pending_reg_removed += 1;
|
||||
|
||||
// SAFETY: we never dropped the guard and the entry existed
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let entry = reg_guard.remove(&to_remove).unwrap();
|
||||
if let Err(err) = peer_manager
|
||||
.release_ip_pair(entry.state.allocated_ip_pair())
|
||||
.await
|
||||
{
|
||||
error!("failed to release allocated ip pair: {err}")
|
||||
}
|
||||
}
|
||||
|
||||
if hs_removed > 0 || ss_removed > 0 || demoted_removed > 0 || pending_reg_removed > 0 {
|
||||
let duration = start.elapsed();
|
||||
@@ -724,6 +737,7 @@ pub(crate) mod cleanup_task {
|
||||
/// Demoted sessions (ReadOnlyTransport) use shorter TTL since they
|
||||
/// only need to drain in-flight packets after subsession promotion.
|
||||
pub(crate) async fn cleanup_loop(
|
||||
peer_manager: Arc<PeerManager>,
|
||||
handshake_states: Arc<DashMap<u32, TimestampedState<LpStateMachine>>>,
|
||||
session_states: Arc<DashMap<u32, TimestampedState<LpStateMachine>>>,
|
||||
registrations_in_progress: RegistrationsInProgress,
|
||||
@@ -743,7 +757,7 @@ pub(crate) mod cleanup_task {
|
||||
break;
|
||||
}
|
||||
_ = cleanup_interval.tick() => {
|
||||
perform_cleanup(&handshake_states, &session_states, ®istrations_in_progress, cfg).await;
|
||||
perform_cleanup(&peer_manager, &handshake_states, &session_states, ®istrations_in_progress, cfg).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::GatewayError;
|
||||
use defguard_wireguard_rs::host::Peer;
|
||||
use defguard_wireguard_rs::key::Key;
|
||||
use futures::channel::oneshot;
|
||||
use nym_credential_verification::ClientBandwidth;
|
||||
use nym_wireguard::peer_controller::IpPair;
|
||||
use nym_wireguard::{PeerControlRequest, PeerRegistrationData, WireguardGatewayData};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use tracing::error;
|
||||
|
||||
/// attempts to replicate [`crate::node::internal_service_providers::authenticator::peer_manager::PeerManager`]
|
||||
// TODO: put those in the shared crate
|
||||
pub struct PeerManager {
|
||||
pub(crate) wireguard_gateway_data: WireguardGatewayData,
|
||||
}
|
||||
|
||||
impl PeerManager {
|
||||
pub fn new(wireguard_gateway_data: WireguardGatewayData) -> Self {
|
||||
PeerManager {
|
||||
wireguard_gateway_data,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn register_peer(
|
||||
&self,
|
||||
registration_data: PeerRegistrationData,
|
||||
) -> Result<IpPair, GatewayError> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::RegisterPeer {
|
||||
registration_data,
|
||||
response_tx,
|
||||
};
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
GatewayError::InternalError(format!("Failed to send IP allocation request: {e}"))
|
||||
})?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|e| {
|
||||
GatewayError::InternalError(format!("Failed to receive IP allocation: {e}"))
|
||||
})?
|
||||
.map_err(|e| {
|
||||
error!("Failed to allocate IPs from pool: {e}");
|
||||
GatewayError::InternalError(format!("Failed to allocate IPs: {e}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn add_peer(&self, peer: Peer) -> Result<(), GatewayError> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::AddPeer { peer, response_tx };
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
GatewayError::InternalError(format!("Failed to send peer request: {e}"))
|
||||
})?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| GatewayError::InternalError("no response for add peer".to_string()))?
|
||||
.map_err(|err| {
|
||||
GatewayError::InternalError(format!("adding peer could not be performed: {err:?}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn query_peer(
|
||||
&self,
|
||||
public_key: PeerPublicKey,
|
||||
) -> Result<Option<Peer>, GatewayError> {
|
||||
let key = Key::new(public_key.to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::QueryPeer { key, response_tx };
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| {
|
||||
GatewayError::InternalError("Failed to send peer query request".to_string())
|
||||
})?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| GatewayError::InternalError("no response for query peer".to_string()))?
|
||||
.map_err(|err| {
|
||||
GatewayError::InternalError(format!(
|
||||
"querying peer could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn query_client_bandwidth(
|
||||
&self,
|
||||
key: PeerPublicKey,
|
||||
) -> Result<ClientBandwidth, GatewayError> {
|
||||
let key = Key::new(key.to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::GetClientBandwidthByKey { key, response_tx };
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| {
|
||||
GatewayError::InternalError(
|
||||
"Failed to send peer bandwidth query request".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| {
|
||||
GatewayError::InternalError("no response for query peer bandwidth".to_string())
|
||||
})?
|
||||
.map_err(|err| {
|
||||
GatewayError::InternalError(format!(
|
||||
"querying client bandwidth could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ use nym_registration_common::{
|
||||
LpRegistrationRequest, LpRegistrationRequestData, LpRegistrationResponse, RegistrationMode,
|
||||
RegistrationStatus, WireguardConfiguration,
|
||||
};
|
||||
use nym_wireguard::peer_controller::IpPair;
|
||||
use nym_wireguard::WireguardConfig;
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use std::collections::HashMap;
|
||||
@@ -71,6 +72,15 @@ pub struct PendingRegistrationState {
|
||||
wireguard_config: WireguardConfiguration,
|
||||
}
|
||||
|
||||
impl PendingRegistrationState {
|
||||
pub(crate) fn allocated_ip_pair(&self) -> IpPair {
|
||||
IpPair::new(
|
||||
self.wireguard_config.private_ipv4,
|
||||
self.wireguard_config.private_ipv6,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct RegistrationsInProgress {
|
||||
/// Wrapped in TimestampedState for TTL-based cleanup of stale data.
|
||||
@@ -416,12 +426,8 @@ impl LpHandlerState {
|
||||
// Allocate IPs from centralized pool managed by PeerController
|
||||
let defguard_key = Key::new(peer_key.to_bytes());
|
||||
|
||||
let registration_data = nym_wireguard::PeerRegistrationData::new(defguard_key.clone(), psk);
|
||||
|
||||
let psk = registration_data.preshared_key.clone();
|
||||
|
||||
// Request IP allocation from PeerController
|
||||
let ip_pair = self.peer_manager.register_peer(registration_data).await?;
|
||||
let ip_pair = self.peer_manager.allocate_peer_ip_pair().await?;
|
||||
|
||||
let client_ipv4 = ip_pair.ipv4;
|
||||
let client_ipv6 = ip_pair.ipv6;
|
||||
|
||||
+3
-16
@@ -18,6 +18,7 @@ use nym_credential_verification::upgrade_mode::{
|
||||
};
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_ip_packet_router::IpPacketRouter;
|
||||
use nym_lp::peer::LpLocalPeer;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_network_requester::NRServiceProviderBuilder;
|
||||
@@ -36,8 +37,8 @@ use tokio::sync::Semaphore;
|
||||
use tracing::*;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::node::lp_listener::peer_manager::PeerManager;
|
||||
pub use crate::node::upgrade_mode::watcher::UpgradeModeWatcher;
|
||||
use crate::node::wireguard::PeerManager;
|
||||
pub use client_handling::active_clients::ActiveClientsStore;
|
||||
pub use lp_listener::LpConfig;
|
||||
pub use nym_credential_verification::upgrade_mode::UpgradeModeCheckRequestSender;
|
||||
@@ -47,7 +48,6 @@ pub use nym_gateway_storage::{
|
||||
traits::{BandwidthGatewayStorage, InboxGatewayStorage},
|
||||
GatewayStorage,
|
||||
};
|
||||
use nym_lp::peer::LpLocalPeer;
|
||||
pub use nym_sdk::{NymApiTopologyProvider, NymApiTopologyProviderConfig, UserAgent};
|
||||
|
||||
pub(crate) mod client_handling;
|
||||
@@ -55,6 +55,7 @@ pub(crate) mod internal_service_providers;
|
||||
pub mod lp_listener;
|
||||
mod stale_data_cleaner;
|
||||
pub mod upgrade_mode;
|
||||
pub mod wireguard;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalNetworkRequesterOpts {
|
||||
@@ -492,25 +493,12 @@ impl GatewayTasksBuilder {
|
||||
Ok(peers)
|
||||
}
|
||||
|
||||
async fn get_wireguard_networks(&mut self) -> Result<Vec<IpAddr>, GatewayError> {
|
||||
if let Some(cached) = self.wireguard_networks.take() {
|
||||
return Ok(cached);
|
||||
}
|
||||
|
||||
let (peers, used_private_network_ips) = self.build_wireguard_peers_and_networks().await?;
|
||||
// cache peers for the other task
|
||||
|
||||
self.wireguard_peers = Some(peers);
|
||||
Ok(used_private_network_ips)
|
||||
}
|
||||
|
||||
pub async fn build_wireguard_authenticator(
|
||||
&mut self,
|
||||
upgrade_mode_common: UpgradeModeDetails,
|
||||
topology_provider: Box<dyn TopologyProvider + Send + Sync>,
|
||||
) -> Result<ServiceProviderBeingBuilt<Authenticator>, GatewayError> {
|
||||
let ecash_manager = self.ecash_manager().await?;
|
||||
let used_private_network_ips = self.get_wireguard_networks().await?;
|
||||
|
||||
let Some(opts) = &self.authenticator_opts else {
|
||||
return Err(GatewayError::UnspecifiedAuthenticatorConfig);
|
||||
@@ -533,7 +521,6 @@ impl GatewayTasksBuilder {
|
||||
opts.config.clone(),
|
||||
upgrade_mode_common,
|
||||
wireguard_data.inner.clone(),
|
||||
used_private_network_ips,
|
||||
ecash_manager,
|
||||
self.shutdown_tracker.clone(),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GatewayWireguardError {
|
||||
#[error("internal error: {0}")]
|
||||
InternalError(String),
|
||||
|
||||
#[error("peers can't be interacted with anymore")]
|
||||
PeerInteractionStopped,
|
||||
}
|
||||
|
||||
impl GatewayWireguardError {
|
||||
pub fn internal(message: impl Into<String>) -> Self {
|
||||
GatewayWireguardError::InternalError(message.into())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod error;
|
||||
pub mod peer_manager;
|
||||
|
||||
pub use error::GatewayWireguardError;
|
||||
pub use peer_manager::PeerManager;
|
||||
+73
-31
@@ -1,14 +1,17 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::internal_service_providers::authenticator::error::AuthenticatorError;
|
||||
use crate::node::wireguard::GatewayWireguardError;
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key};
|
||||
use futures::channel::oneshot;
|
||||
use nym_credential_verification::{ClientBandwidth, TicketVerifier};
|
||||
use nym_credentials_interface::CredentialSpendingData;
|
||||
use nym_wireguard::peer_controller::IpPair;
|
||||
use nym_wireguard::{peer_controller::PeerControlRequest, WireguardGatewayData};
|
||||
use nym_wireguard_types::PeerPublicKey;
|
||||
use tracing::error;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PeerManager {
|
||||
pub(crate) wireguard_gateway_data: WireguardGatewayData,
|
||||
}
|
||||
@@ -19,26 +22,73 @@ impl PeerManager {
|
||||
wireguard_gateway_data,
|
||||
}
|
||||
}
|
||||
pub async fn add_peer(&self, peer: Peer) -> Result<(), AuthenticatorError> {
|
||||
|
||||
pub async fn allocate_peer_ip_pair(&self) -> Result<IpPair, GatewayWireguardError> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::AllocatePeerIpPair { response_tx };
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|e| {
|
||||
GatewayWireguardError::InternalError(format!(
|
||||
"Failed to receive IP allocation: {e}"
|
||||
))
|
||||
})?
|
||||
.map_err(|e| {
|
||||
error!("Failed to allocate IPs from pool: {e}");
|
||||
GatewayWireguardError::InternalError(format!("Failed to allocate IPs: {e}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn release_ip_pair(&self, ip_pair: IpPair) -> Result<(), GatewayWireguardError> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::ReleaseIpPair {
|
||||
response_tx,
|
||||
ip_pair,
|
||||
};
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| GatewayWireguardError::internal("no response for release ip allocation"))?
|
||||
.map_err(|err| {
|
||||
GatewayWireguardError::InternalError(format!(
|
||||
"releasing ip pair not be performed: {err:?}"
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn add_peer(&self, peer: Peer) -> Result<(), GatewayWireguardError> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::AddPeer { peer, response_tx };
|
||||
self.wireguard_gateway_data
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::PeerInteractionStopped)?;
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::InternalError("no response for add peer".to_string()))?
|
||||
.map_err(|_| GatewayWireguardError::internal("no response for add peer".to_string()))?
|
||||
.map_err(|err| {
|
||||
AuthenticatorError::InternalError(format!(
|
||||
GatewayWireguardError::internal(format!(
|
||||
"adding peer could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn _remove_peer(&self, pub_key: PeerPublicKey) -> Result<(), AuthenticatorError> {
|
||||
pub async fn _remove_peer(&self, pub_key: PeerPublicKey) -> Result<(), GatewayWireguardError> {
|
||||
let key = Key::new(pub_key.to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::RemovePeer { key, response_tx };
|
||||
@@ -46,15 +96,13 @@ impl PeerManager {
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::PeerInteractionStopped)?;
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| {
|
||||
AuthenticatorError::InternalError("no response for remove peer".to_string())
|
||||
})?
|
||||
.map_err(|_| GatewayWireguardError::internal("no response for remove peer"))?
|
||||
.map_err(|err| {
|
||||
AuthenticatorError::InternalError(format!(
|
||||
GatewayWireguardError::InternalError(format!(
|
||||
"removing peer could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
@@ -63,7 +111,7 @@ impl PeerManager {
|
||||
pub async fn query_peer(
|
||||
&self,
|
||||
public_key: PeerPublicKey,
|
||||
) -> Result<Option<Peer>, AuthenticatorError> {
|
||||
) -> Result<Option<Peer>, GatewayWireguardError> {
|
||||
let key = Key::new(public_key.to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::QueryPeer { key, response_tx };
|
||||
@@ -71,15 +119,13 @@ impl PeerManager {
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::PeerInteractionStopped)?;
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| {
|
||||
AuthenticatorError::InternalError("no response for query peer".to_string())
|
||||
})?
|
||||
.map_err(|_| GatewayWireguardError::internal("no response for query peer".to_string()))?
|
||||
.map_err(|err| {
|
||||
AuthenticatorError::InternalError(format!(
|
||||
GatewayWireguardError::internal(format!(
|
||||
"querying peer could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
@@ -88,7 +134,7 @@ impl PeerManager {
|
||||
pub async fn query_bandwidth(
|
||||
&self,
|
||||
public_key: PeerPublicKey,
|
||||
) -> Result<i64, AuthenticatorError> {
|
||||
) -> Result<i64, GatewayWireguardError> {
|
||||
let client_bandwidth = self.query_client_bandwidth(public_key).await?;
|
||||
Ok(client_bandwidth.available().await)
|
||||
}
|
||||
@@ -96,7 +142,7 @@ impl PeerManager {
|
||||
pub async fn query_client_bandwidth(
|
||||
&self,
|
||||
key: PeerPublicKey,
|
||||
) -> Result<ClientBandwidth, AuthenticatorError> {
|
||||
) -> Result<ClientBandwidth, GatewayWireguardError> {
|
||||
let key = Key::new(key.to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::GetClientBandwidthByKey { key, response_tx };
|
||||
@@ -104,17 +150,13 @@ impl PeerManager {
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::PeerInteractionStopped)?;
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| {
|
||||
AuthenticatorError::InternalError(
|
||||
"no response for query client bandwidth".to_string(),
|
||||
)
|
||||
})?
|
||||
.map_err(|_| GatewayWireguardError::internal("no response for query client bandwidth"))?
|
||||
.map_err(|err| {
|
||||
AuthenticatorError::InternalError(format!(
|
||||
GatewayWireguardError::internal(format!(
|
||||
"querying client bandwidth could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
@@ -124,7 +166,7 @@ impl PeerManager {
|
||||
&self,
|
||||
key: PeerPublicKey,
|
||||
credential: CredentialSpendingData,
|
||||
) -> Result<Box<dyn TicketVerifier + Send + Sync>, AuthenticatorError> {
|
||||
) -> Result<Box<dyn TicketVerifier + Send + Sync>, GatewayWireguardError> {
|
||||
let key = Key::new(key.to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::GetVerifierByKey {
|
||||
@@ -136,15 +178,15 @@ impl PeerManager {
|
||||
.peer_tx()
|
||||
.send(msg)
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::PeerInteractionStopped)?;
|
||||
.map_err(|_| GatewayWireguardError::PeerInteractionStopped)?;
|
||||
|
||||
response_rx
|
||||
.await
|
||||
.map_err(|_| {
|
||||
AuthenticatorError::InternalError("no response for query verifier".to_string())
|
||||
GatewayWireguardError::internal("no response for query verifier".to_string())
|
||||
})?
|
||||
.map_err(|err| {
|
||||
AuthenticatorError::InternalError(format!(
|
||||
GatewayWireguardError::internal(format!(
|
||||
"querying verifier could not be performed: {err:?}"
|
||||
))
|
||||
})
|
||||
@@ -14,11 +14,11 @@ mod tests {
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_gateway::GatewayError;
|
||||
use nym_gateway::node::lp_listener::handler::LpConnectionHandler;
|
||||
use nym_gateway::node::lp_listener::peer_manager::PeerManager;
|
||||
use nym_gateway::node::lp_listener::{
|
||||
LpDebug, LpHandlerState, LpLocalPeer, MixForwardingReceiver, PeerControlRequest,
|
||||
WireguardGatewayData, mix_forwarding_channels,
|
||||
};
|
||||
use nym_gateway::node::wireguard::PeerManager;
|
||||
use nym_gateway::node::{ActiveClientsStore, GatewayStorage, LpConfig};
|
||||
use nym_registration_client::{LpClientError, LpRegistrationClient};
|
||||
use nym_test_utils::helpers::{CryptoRng, RngCore, u64_seeded_rng};
|
||||
@@ -443,11 +443,10 @@ mod tests {
|
||||
// 1) peer registration - ip pair allocation
|
||||
let ip_pair = entry.allocate_ip_pair().await;
|
||||
let reg_res = Ok::<_, nym_wireguard::Error>(ip_pair);
|
||||
let public_key = client_key.to_wg_key();
|
||||
|
||||
entry
|
||||
.register_peer_controller_response(
|
||||
PeerControlRequestType::RegisterPeer { public_key },
|
||||
PeerControlRequestType::AllocatePeerIpPair {},
|
||||
reg_res,
|
||||
)
|
||||
.await;
|
||||
@@ -497,7 +496,6 @@ mod tests {
|
||||
let peers_guard = entry.mock_peer_controller_state.peers.read().await;
|
||||
let peer = peers_guard.get_by_x25519_key(&client_key).unwrap().clone();
|
||||
drop(peers_guard);
|
||||
assert!(peer.register_success);
|
||||
assert!(peer.add_success);
|
||||
|
||||
assert_eq!(registration_result.private_ipv4, ip_pair.ipv4);
|
||||
@@ -616,11 +614,10 @@ mod tests {
|
||||
// 1) peer registration - ip pair allocation
|
||||
let entry_ip_pair = entry.allocate_ip_pair().await;
|
||||
let reg_res = Ok::<_, nym_wireguard::Error>(entry_ip_pair);
|
||||
let public_key = client_key.to_wg_key();
|
||||
|
||||
entry
|
||||
.register_peer_controller_response(
|
||||
PeerControlRequestType::RegisterPeer { public_key },
|
||||
PeerControlRequestType::AllocatePeerIpPair {},
|
||||
reg_res,
|
||||
)
|
||||
.await;
|
||||
@@ -668,10 +665,9 @@ mod tests {
|
||||
// 1) peer registration - ip pair allocation
|
||||
let exit_ip_pair = exit.allocate_ip_pair().await;
|
||||
let reg_res = Ok::<_, nym_wireguard::Error>(exit_ip_pair);
|
||||
let public_key = client_key.to_wg_key();
|
||||
|
||||
exit.register_peer_controller_response(
|
||||
PeerControlRequestType::RegisterPeer { public_key },
|
||||
PeerControlRequestType::AllocatePeerIpPair {},
|
||||
reg_res,
|
||||
)
|
||||
.await;
|
||||
@@ -738,13 +734,11 @@ mod tests {
|
||||
let peers_guard = entry.mock_peer_controller_state.peers.read().await;
|
||||
let entry_peer = peers_guard.get_by_x25519_key(&client_key).unwrap().clone();
|
||||
drop(peers_guard);
|
||||
assert!(entry_peer.register_success);
|
||||
assert!(entry_peer.add_success);
|
||||
|
||||
let peers_guard = exit.mock_peer_controller_state.peers.read().await;
|
||||
let exit_peer = peers_guard.get_by_x25519_key(&client_key).unwrap().clone();
|
||||
drop(peers_guard);
|
||||
assert!(exit_peer.register_success);
|
||||
assert!(exit_peer.add_success);
|
||||
|
||||
assert_eq!(entry_registration_result.private_ipv4, entry_ip_pair.ipv4);
|
||||
|
||||
Reference in New Issue
Block a user