From 7785d085cfe57b4a5473e089ff75af6ba1d54075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 5 Mar 2025 15:17:51 +0100 Subject: [PATCH] Handle disconnect in IPR (#5547) * Implement disconnect in the IPR * Remove unused async --- .../ip-packet-router/src/clients/client_id.rs | 2 +- .../src/clients/connected_clients.rs | 36 ++++++----- .../ip-packet-router/src/mixnet_listener.rs | 59 +++++++++++++++---- .../ip-packet-router/src/tun_listener.rs | 2 +- 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/service-providers/ip-packet-router/src/clients/client_id.rs b/service-providers/ip-packet-router/src/clients/client_id.rs index 5add99a724..2842f261d3 100644 --- a/service-providers/ip-packet-router/src/clients/client_id.rs +++ b/service-providers/ip-packet-router/src/clients/client_id.rs @@ -7,7 +7,7 @@ use nym_sdk::mixnet::{AnonymousSenderTag, Recipient}; use crate::error::{IpPacketRouterError, Result}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum ConnectedClientId { AnonymousSenderTag(AnonymousSenderTag), NymAddress(Box), diff --git a/service-providers/ip-packet-router/src/clients/connected_clients.rs b/service-providers/ip-packet-router/src/clients/connected_clients.rs index 853c83f884..7100048dd8 100644 --- a/service-providers/ip-packet-router/src/clients/connected_clients.rs +++ b/service-providers/ip-packet-router/src/clients/connected_clients.rs @@ -59,6 +59,24 @@ impl ConnectedClients { .any(|client| client.client_id == *client_id) } + pub(crate) fn disconnect_client(&mut self, client_id: &ConnectedClientId) { + if let Some(ips) = self.lookup_ip_from_client_id(client_id) { + log::debug!("Disconnect client that requested to do so: {ips}"); + self.disconnect_client_handle(ips); + } + } + + fn disconnect_client_handle(&mut self, ips: IpPair) { + self.clients_ipv4_mapping.remove(&ips.ipv4); + self.clients_ipv6_mapping.remove(&ips.ipv6); + self.tun_listener_connected_client_tx + .send(ConnectedClientEvent::Disconnect(DisconnectEvent(ips))) + .inspect_err(|err| { + log::error!("Failed to send disconnect event: {err}"); + }) + .ok(); + } + pub(crate) fn lookup_ip_from_client_id(&self, client_id: &ConnectedClientId) -> Option { self.clients_ipv4_mapping .iter() @@ -164,14 +182,7 @@ impl ConnectedClients { ) { for (ips, _) in &stopped_clients { log::info!("Disconnect stopped client: {ips}"); - self.clients_ipv4_mapping.remove(&ips.ipv4); - self.clients_ipv6_mapping.remove(&ips.ipv6); - self.tun_listener_connected_client_tx - .send(ConnectedClientEvent::Disconnect(DisconnectEvent(*ips))) - .inspect_err(|err| { - log::error!("Failed to send disconnect event: {err}"); - }) - .ok(); + self.disconnect_client_handle(*ips); } } @@ -181,14 +192,7 @@ impl ConnectedClients { ) { for (ips, _) in &inactive_clients { log::info!("Disconnect inactive client: {ips}"); - self.clients_ipv4_mapping.remove(&ips.ipv4); - self.clients_ipv6_mapping.remove(&ips.ipv6); - self.tun_listener_connected_client_tx - .send(ConnectedClientEvent::Disconnect(DisconnectEvent(*ips))) - .inspect_err(|err| { - log::error!("Failed to send disconnect event: {err}"); - }) - .ok(); + self.disconnect_client_handle(*ips); } } diff --git a/service-providers/ip-packet-router/src/mixnet_listener.rs b/service-providers/ip-packet-router/src/mixnet_listener.rs index 31d4b2e5fe..b0957236ac 100644 --- a/service-providers/ip-packet-router/src/mixnet_listener.rs +++ b/service-providers/ip-packet-router/src/mixnet_listener.rs @@ -22,9 +22,9 @@ use crate::{ IpPacketRequest, PingRequest, StaticConnectRequest, }, response::{ - DynamicConnectFailureReason, DynamicConnectSuccess, HealthResponse, InfoLevel, - InfoResponse, InfoResponseReply, Response, StaticConnectFailureReason, - StaticConnectResponse, VersionedResponse, + DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason, + DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponse, InfoResponseReply, + Response, StaticConnectFailureReason, StaticConnectResponse, VersionedResponse, }, ClientVersion, }, @@ -225,7 +225,7 @@ impl MixnetListener { })) } - async fn on_dynamic_connect_request( + fn on_dynamic_connect_request( &mut self, connect_request: DynamicConnectRequest, ) -> PacketHandleResult { @@ -293,12 +293,47 @@ impl MixnetListener { })) } - fn on_disconnect_request(&self, _disconnect_request: DisconnectRequest) -> PacketHandleResult { - log::info!("Received disconnect request: not implemented, dropping"); - Ok(None) + fn on_disconnect_request( + &mut self, + disconnect_request: DisconnectRequest, + ) -> PacketHandleResult { + log::info!( + "Received disconnect request from {}", + disconnect_request.sent_by + ); + + let version = disconnect_request.version; + let request_id = disconnect_request.request_id; + let client_id = disconnect_request.sent_by; + + // Check if the client is connected + if !self.connected_clients.is_client_connected(&client_id) { + log::info!("Client {} is not connected, cannot disconnect", client_id); + return Ok(Some(VersionedResponse { + version, + reply_to: client_id, + response: Response::Disconnect { + request_id, + reply: DisconnectResponse::Failure(DisconnectFailureReason::ClientNotConnected), + }, + })); + } + + // Disconnect the client + log::info!("Disconnecting client {}", client_id); + self.connected_clients.disconnect_client(&client_id); + + Ok(Some(VersionedResponse { + version, + reply_to: client_id, + response: Response::Disconnect { + request_id, + reply: DisconnectResponse::Success, + }, + })) } - async fn on_ping_request(&self, ping_request: PingRequest) -> PacketHandleResult { + fn on_ping_request(&self, ping_request: PingRequest) -> PacketHandleResult { Ok(Some(VersionedResponse { version: ping_request.version, reply_to: ping_request.sent_by, @@ -308,7 +343,7 @@ impl MixnetListener { })) } - async fn on_health_request(&self, health_request: HealthRequest) -> PacketHandleResult { + fn on_health_request(&self, health_request: HealthRequest) -> PacketHandleResult { Ok(Some(VersionedResponse { version: health_request.version, reply_to: health_request.sent_by, @@ -325,10 +360,10 @@ impl MixnetListener { async fn on_control_request(&mut self, control_request: ControlRequest) -> PacketHandleResult { match control_request { ControlRequest::StaticConnect(r) => self.on_static_connect_request(r).await, - ControlRequest::DynamicConnect(r) => self.on_dynamic_connect_request(r).await, + ControlRequest::DynamicConnect(r) => self.on_dynamic_connect_request(r), ControlRequest::Disconnect(r) => self.on_disconnect_request(r), - ControlRequest::Ping(r) => self.on_ping_request(r).await, - ControlRequest::Health(r) => self.on_health_request(r).await, + ControlRequest::Ping(r) => self.on_ping_request(r), + ControlRequest::Health(r) => self.on_health_request(r), } } diff --git a/service-providers/ip-packet-router/src/tun_listener.rs b/service-providers/ip-packet-router/src/tun_listener.rs index 0d4a99e3b9..072ade7ab0 100644 --- a/service-providers/ip-packet-router/src/tun_listener.rs +++ b/service-providers/ip-packet-router/src/tun_listener.rs @@ -103,7 +103,7 @@ impl TunListener { .update(ConnectedClientEvent::Disconnect(DisconnectEvent(*ips))); } } else { - log::info!( + log::debug!( "dropping packet from network: no registered client for destination: {dst_addr}" ); }