(fix): connections (again)

This commit is contained in:
Alois 2026-07-28 23:53:37 +02:00
commit c3a07b31ec
Signed by: alois
SSH key fingerprint: SHA256:GBzT2DXvAuGV9XIV5W3WrzVpjU54FThmxHXdbz95J24
8 changed files with 66 additions and 29 deletions

22
Cargo.lock generated
View file

@ -1581,7 +1581,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp" name = "mtp"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"mtp-client", "mtp-client",
"mtp-codec", "mtp-codec",
@ -1597,7 +1597,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-client" name = "mtp-client"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"mtp-codec", "mtp-codec",
"mtp-common", "mtp-common",
@ -1610,7 +1610,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-codec" name = "mtp-codec"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"byteorder", "byteorder",
@ -1623,7 +1623,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-common" name = "mtp-common"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"quinn", "quinn",
"rustls", "rustls",
@ -1634,7 +1634,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-crypto" name = "mtp-crypto"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"chacha20poly1305", "chacha20poly1305",
@ -1656,7 +1656,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-files" name = "mtp-files"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"mtp-crypto", "mtp-crypto",
"rand 0.10.2", "rand 0.10.2",
@ -1667,7 +1667,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-host" name = "mtp-host"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"mtp-codec", "mtp-codec",
"mtp-common", "mtp-common",
@ -1682,7 +1682,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-transport" name = "mtp-transport"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"mtp-codec", "mtp-codec",
@ -1700,7 +1700,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-type-map" name = "mtp-type-map"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"serde", "serde",
"serde_yaml", "serde_yaml",
@ -1709,7 +1709,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-webserver" name = "mtp-webserver"
version = "0.2.0" version = "0.2.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#590810ce59709efccd81ca04401c855be314b9c0" source = "git+https://git.methanium.net/Methanium/mtp.git#6f673ba7f2834b95ce724babe131241df8a119c6"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bytes", "bytes",
@ -3032,7 +3032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [ dependencies = [
"fastrand", "fastrand",
"getrandom 0.4.3", "getrandom 0.3.4",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.61.2", "windows-sys 0.61.2",

View file

@ -24,7 +24,6 @@ const RECONNECT_DELAY: Duration = Duration::from_secs(5);
const MAX_RECONNECT_DELAY: Duration = Duration::from_secs(300); const MAX_RECONNECT_DELAY: Duration = Duration::from_secs(300);
const CONNECTION_TIMEOUT: Duration = Duration::from_secs(10); const CONNECTION_TIMEOUT: Duration = Duration::from_secs(10);
const PING_INTERVAL: Duration = Duration::from_secs(5); const PING_INTERVAL: Duration = Duration::from_secs(5);
const MAX_MISSED_PINGS: usize = 3;
const TASK_CLEANUP_INTERVAL: Duration = Duration::from_secs(60); const TASK_CLEANUP_INTERVAL: Duration = Duration::from_secs(60);
const TASK_MAX_AGE: Duration = Duration::from_secs(60); const TASK_MAX_AGE: Duration = Duration::from_secs(60);
const MAX_CONCURRENT_REQUESTS: usize = 128; const MAX_CONCURRENT_REQUESTS: usize = 128;
@ -284,7 +283,7 @@ impl OmegaConnection {
.with_persistent_stream_retries(5, Duration::from_secs(5)), .with_persistent_stream_retries(5, Duration::from_secs(5)),
) )
.with_ping_interval(PING_INTERVAL) .with_ping_interval(PING_INTERVAL)
.with_max_missed_pings(MAX_MISSED_PINGS); .with_max_missed_pings(0);
let host_public_key = load_public_key_bundle("./omega.mpkb") let host_public_key = load_public_key_bundle("./omega.mpkb")
.map_err(|e| format!("Failed to load omega.mpkb: {}", e))?; .map_err(|e| format!("Failed to load omega.mpkb: {}", e))?;

View file

@ -75,6 +75,10 @@ impl ClientConnection {
self.rho_connection.read().await.clone() self.rho_connection.read().await.clone()
} }
pub async fn set_rho_connection(&self, rho_connection: Arc<RhoConnection>) {
*self.rho_connection.write().await = Some(rho_connection);
}
/// Send a CommunicationValue to the client /// Send a CommunicationValue to the client
pub async fn send_message(self: Arc<Self>, cv: &CommunicationValue) { pub async fn send_message(self: Arc<Self>, cv: &CommunicationValue) {
if !*self.is_open.read().await { if !*self.is_open.read().await {

View file

@ -234,6 +234,12 @@ impl GeneralConnection {
let iota = IotaConnection::from_general(self.clone(), id).await; let iota = IotaConnection::from_general(self.clone(), id).await;
let rho = Arc::new(RhoConnection::new(iota.clone(), Vec::new()).await); let rho = Arc::new(RhoConnection::new(iota.clone(), Vec::new()).await);
iota.set_rho_connection(rho.clone()).await; iota.set_rho_connection(rho.clone()).await;
if let Some(previous) = self.state.rho.get_by_iota(id as i64).await {
for client in previous.drain_client_connections() {
client.set_rho_connection(rho.clone()).await;
rho.add_client_connection(client).await;
}
}
self.state.rho.add(rho).await; self.state.rho.add(rho).await;
self.load_iota_users(&iota, id).await; self.load_iota_users(&iota, id).await;
iota.start(); iota.start();

View file

@ -66,7 +66,14 @@ impl IotaConnection {
iota_for_closure.handle_message(cv).await; iota_for_closure.handle_message(cv).await;
}); });
} }
Err(_) => { Err(error) => {
log_err!(
self_clone.iota_id as i64,
PrintType::Iota,
"Iota receive loop ended: {}; transport close reason: {:?}",
error,
self_clone.receiver.close_reason()
);
break; break;
} }
} }

View file

@ -63,6 +63,17 @@ impl RhoConnection {
.collect() .collect()
} }
pub fn drain_client_connections(&self) -> Vec<Arc<ClientConnection>> {
let keys: Vec<_> = self
.client_connections
.iter()
.map(|entry| *entry.key())
.collect();
keys.into_iter()
.filter_map(|key| self.client_connections.remove(&key).map(|(_, value)| value))
.collect()
}
/// Get client connections for a specific user /// Get client connections for a specific user
pub async fn get_client_connections_for_user( pub async fn get_client_connections_for_user(
&self, &self,
@ -198,25 +209,26 @@ impl RhoConnection {
/// Close the Iota connection and all associated client connections /// Close the Iota connection and all associated client connections
pub async fn close_iota_connection(&self) { pub async fn close_iota_connection(&self) {
let iota_id = self.get_iota_id().await as i64;
if self
.iota_connection
.state
.rho
.remove_if_current(iota_id, self)
.await
.is_none()
{
return;
}
// Close all client connections // Close all client connections
let connections = self.get_client_connections().await; let connections = self.get_client_connections().await;
for connection in connections { for connection in connections {
connection.close().await; connection.close().await;
} }
// Remove from manager
self.iota_connection
.state
.rho
.remove(self.get_iota_id().await as i64)
.await;
// Notify OmegaConnection // Notify OmegaConnection
self.iota_connection self.iota_connection.state.omega.close_iota(iota_id).await;
.state
.omega
.close_iota(self.get_iota_id().await as i64)
.await;
} }
/// Send message from Iota to specific client /// Send message from Iota to specific client

View file

@ -89,8 +89,17 @@ impl RhoManager {
} }
} }
pub async fn remove(&self, iota_id: i64) -> Option<Arc<RhoConnection>> { pub async fn remove_if_current(
let rho = self.connections.remove(&iota_id).map(|(_, rho)| rho); &self,
iota_id: i64,
expected: &RhoConnection,
) -> Option<Arc<RhoConnection>> {
let rho = self
.connections
.remove_if(&iota_id, |_, current| {
std::ptr::eq(current.as_ref(), expected)
})
.map(|(_, rho)| rho);
if let Some(rho) = rho.as_ref() { if let Some(rho) = rho.as_ref() {
self.users.retain(|_, mapped| !Arc::ptr_eq(mapped, rho)); self.users.retain(|_, mapped| !Arc::ptr_eq(mapped, rho));
} }

View file

@ -124,7 +124,7 @@ pub async fn start(state: Arc<AppState>) -> Result<(), Box<dyn std::error::Error
Duration::from_millis(30_000), Duration::from_millis(30_000),
) )
.with_keep_alive(Some(Duration::from_secs(6))) .with_keep_alive(Some(Duration::from_secs(6)))
.with_max_idle_timeout(Some(Duration::from_secs(30))) .with_max_idle_timeout(None)
.with_receiver_queue_capacity(1000) .with_receiver_queue_capacity(1000)
.with_max_concurrent_stream_tasks(10) .with_max_concurrent_stream_tasks(10)
.with_persistent_stream_retries(5, Duration::from_secs(5)), .with_persistent_stream_retries(5, Duration::from_secs(5)),