mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 17:36:29 +03:00
fix: don't init Iroh on channel leave (#7210)
Some Delta Chat clients (Desktop, for example) do `leave_webxdc_realtime` regardless of whether we've ever joined a realtime channel in the first place. Such as when closing a WebXDC window. This might result in unexpected and suspicious firewall warnings. Co-authored-by: iequidoo <dgreshilov@gmail.com>
This commit is contained in:
@@ -2001,6 +2001,11 @@ impl CommandApi {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Leaves the gossip of the webxdc with the given message id.
|
||||||
|
///
|
||||||
|
/// NB: When this is called before closing a webxdc app in UIs, it must be guaranteed that
|
||||||
|
/// `send_webxdc_realtime_*()` functions aren't called for the given `instance_message_id`
|
||||||
|
/// anymore until the app is open again.
|
||||||
async fn leave_webxdc_realtime(&self, account_id: u32, instance_message_id: u32) -> Result<()> {
|
async fn leave_webxdc_realtime(&self, account_id: u32, instance_message_id: u32) -> Result<()> {
|
||||||
let ctx = self.get_context(account_id).await?;
|
let ctx = self.get_context(account_id).await?;
|
||||||
leave_webxdc_realtime(&ctx, MsgId::new(instance_message_id)).await
|
leave_webxdc_realtime(&ctx, MsgId::new(instance_message_id)).await
|
||||||
|
|||||||
@@ -278,18 +278,24 @@ impl Context {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns [`None`] if the peer channels has not been initialized.
|
||||||
|
pub async fn get_peer_channels(&self) -> Option<tokio::sync::RwLockReadGuard<'_, Iroh>> {
|
||||||
|
tokio::sync::RwLockReadGuard::<'_, std::option::Option<Iroh>>::try_map(
|
||||||
|
self.iroh.read().await,
|
||||||
|
|opt_iroh| opt_iroh.as_ref(),
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get or initialize the iroh peer channel.
|
/// Get or initialize the iroh peer channel.
|
||||||
pub async fn get_or_try_init_peer_channel(
|
pub async fn get_or_try_init_peer_channel(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<tokio::sync::RwLockReadGuard<'_, Iroh>> {
|
) -> Result<tokio::sync::RwLockReadGuard<'_, Iroh>> {
|
||||||
if !self.get_config_bool(Config::WebxdcRealtimeEnabled).await? {
|
if !self.get_config_bool(Config::WebxdcRealtimeEnabled).await? {
|
||||||
bail!("Attempt to get Iroh when realtime is disabled");
|
bail!("Attempt to initialize Iroh when realtime is disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(lock) = tokio::sync::RwLockReadGuard::<'_, std::option::Option<Iroh>>::try_map(
|
if let Some(lock) = self.get_peer_channels().await {
|
||||||
self.iroh.read().await,
|
|
||||||
|opt_iroh| opt_iroh.as_ref(),
|
|
||||||
) {
|
|
||||||
return Ok(lock);
|
return Ok(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,14 +485,17 @@ pub async fn send_webxdc_realtime_data(ctx: &Context, msg_id: MsgId, data: Vec<u
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Leave the gossip of the webxdc with given [MsgId].
|
/// Leave the gossip of the webxdc with given [MsgId].
|
||||||
|
///
|
||||||
|
/// NB: When this is called before closing a webxdc app in UIs, it must be guaranteed that
|
||||||
|
/// `send_webxdc_realtime_*()` functions aren't called for the given `msg_id` anymore until the app
|
||||||
|
/// is open again.
|
||||||
pub async fn leave_webxdc_realtime(ctx: &Context, msg_id: MsgId) -> Result<()> {
|
pub async fn leave_webxdc_realtime(ctx: &Context, msg_id: MsgId) -> Result<()> {
|
||||||
if !ctx.get_config_bool(Config::WebxdcRealtimeEnabled).await? {
|
let Some(iroh) = ctx.get_peer_channels().await else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
};
|
||||||
let topic = get_iroh_topic_for_msg(ctx, msg_id)
|
let Some(topic) = get_iroh_topic_for_msg(ctx, msg_id).await? else {
|
||||||
.await?
|
return Ok(());
|
||||||
.with_context(|| format!("Message {msg_id} has no gossip topic"))?;
|
};
|
||||||
let iroh = ctx.get_or_try_init_peer_channel().await?;
|
|
||||||
iroh.leave_realtime(topic).await?;
|
iroh.leave_realtime(topic).await?;
|
||||||
info!(ctx, "IROH_REALTIME: Left gossip for message {msg_id}");
|
info!(ctx, "IROH_REALTIME: Left gossip for message {msg_id}");
|
||||||
|
|
||||||
@@ -1110,7 +1119,6 @@ mod tests {
|
|||||||
|
|
||||||
assert!(alice.ctx.iroh.read().await.is_none());
|
assert!(alice.ctx.iroh.read().await.is_none());
|
||||||
|
|
||||||
// creates iroh endpoint as side effect
|
|
||||||
leave_webxdc_realtime(alice, MsgId::new(1)).await.unwrap();
|
leave_webxdc_realtime(alice, MsgId::new(1)).await.unwrap();
|
||||||
|
|
||||||
assert!(alice.ctx.iroh.read().await.is_none());
|
assert!(alice.ctx.iroh.read().await.is_none());
|
||||||
@@ -1119,4 +1127,19 @@ mod tests {
|
|||||||
// if accidentally called with the setting disabled.
|
// if accidentally called with the setting disabled.
|
||||||
assert!(alice.ctx.get_or_try_init_peer_channel().await.is_err());
|
assert!(alice.ctx.get_or_try_init_peer_channel().await.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
async fn test_leave_webxdc_realtime_uninitialized() {
|
||||||
|
let mut tcm = TestContextManager::new();
|
||||||
|
let alice = &mut tcm.alice().await;
|
||||||
|
|
||||||
|
alice
|
||||||
|
.set_config_bool(Config::WebxdcRealtimeEnabled, true)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(alice.ctx.iroh.read().await.is_none());
|
||||||
|
leave_webxdc_realtime(alice, MsgId::new(1)).await.unwrap();
|
||||||
|
assert!(alice.ctx.iroh.read().await.is_none());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user