diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 8d12301618..7f41b6014b 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -523,6 +523,9 @@ char* dc_get_blobdir (const dc_context_t* context); * e.g. `ui.desktop.foo`, `ui.desktop.linux.bar`, `ui.android.foo`, `ui.dc40.bar`, `ui.bot.simplebot.baz`. * These keys go to backups and allow easy per-account settings when using @ref dc_accounts_t, * however, are not handled by the core otherwise. + * - `webxdc_realtime_enabled` = Whether the realtime APIs should be enabled. + * 0 = WebXDC realtime API is disabled and behaves as noop (default). + * 1 = WebXDC realtime API is enabled. * * If you want to retrieve a value, use dc_get_config(). * diff --git a/deltachat-rpc-client/tests/test_iroh_webxdc.py b/deltachat-rpc-client/tests/test_iroh_webxdc.py index 7afd76053d..bf09c0f111 100644 --- a/deltachat-rpc-client/tests/test_iroh_webxdc.py +++ b/deltachat-rpc-client/tests/test_iroh_webxdc.py @@ -29,6 +29,8 @@ def log(msg): def setup_realtime_webxdc(ac1, ac2, path_to_webxdc): + assert ac1.get_config("webxdc_realtime_enabled") == "1" + assert ac2.get_config("webxdc_realtime_enabled") == "1" ac1_ac2_chat = ac1.create_chat(ac2) ac2.create_chat(ac1) @@ -75,6 +77,8 @@ def wait_receive_realtime_data(msg_data_list): def test_realtime_sequentially(acfactory, path_to_webxdc): """Test two peers trying to establish connection sequentially.""" ac1, ac2 = acfactory.get_online_accounts(2) + ac1.set_config("webxdc_realtime_enabled", "1") + ac2.set_config("webxdc_realtime_enabled", "1") ac1.create_chat(ac2) ac2.create_chat(ac1) @@ -115,6 +119,8 @@ def test_realtime_sequentially(acfactory, path_to_webxdc): def test_realtime_simultaneously(acfactory, path_to_webxdc): """Test two peers trying to establish connection simultaneously.""" ac1, ac2 = acfactory.get_online_accounts(2) + ac1.set_config("webxdc_realtime_enabled", "1") + ac2.set_config("webxdc_realtime_enabled", "1") ac1_webxdc_msg, ac2_webxdc_msg = setup_realtime_webxdc(ac1, ac2, path_to_webxdc) @@ -125,6 +131,8 @@ def test_realtime_simultaneously(acfactory, path_to_webxdc): def test_two_parallel_realtime_simultaneously(acfactory, path_to_webxdc): """Test two peers trying to establish connection simultaneously.""" ac1, ac2 = acfactory.get_online_accounts(2) + ac1.set_config("webxdc_realtime_enabled", "1") + ac2.set_config("webxdc_realtime_enabled", "1") ac1_webxdc_msg, ac2_webxdc_msg = setup_realtime_webxdc(ac1, ac2, path_to_webxdc) ac1_webxdc_msg2, ac2_webxdc_msg2 = setup_realtime_webxdc(ac1, ac2, path_to_webxdc) @@ -141,6 +149,8 @@ def test_two_parallel_realtime_simultaneously(acfactory, path_to_webxdc): def test_no_duplicate_messages(acfactory, path_to_webxdc): """Test that messages are received only once.""" ac1, ac2 = acfactory.get_online_accounts(2) + ac1.set_config("webxdc_realtime_enabled", "1") + ac2.set_config("webxdc_realtime_enabled", "1") ac1_ac2_chat = ac1.create_chat(ac2) diff --git a/src/config.rs b/src/config.rs index bbe74021ec..46fa34cb21 100644 --- a/src/config.rs +++ b/src/config.rs @@ -363,8 +363,8 @@ pub enum Config { /// MsgId of webxdc map integration. WebxdcIntegration, - /// Iroh secret key. - IrohSecretKey, + /// Enable webxdc realtime features. + WebxdcRealtimeEnabled, } impl Config { diff --git a/src/context.rs b/src/context.rs index fd86f84b6f..bf6973e64c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -967,6 +967,12 @@ impl Context { .await? .to_string(), ); + res.insert( + "webxdc_realtime_enabled", + self.get_config_bool(Config::WebxdcRealtimeEnabled) + .await? + .to_string(), + ); let elapsed = time_elapsed(&self.creation_time); res.insert("uptime", duration_to_str(elapsed)); @@ -1673,7 +1679,6 @@ mod tests { "socks5_password", "key_id", "webxdc_integration", - "iroh_secret_key", ]; let t = TestContext::new().await; let info = t.get_info().await.unwrap(); diff --git a/src/peer_channels.rs b/src/peer_channels.rs index bf50592530..a481596b00 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -37,6 +37,7 @@ use tokio::task::JoinHandle; use url::Url; use crate::chat::send_msg; +use crate::config::Config; use crate::context::Context; use crate::headerdef::HeaderDef; use crate::message::{Message, MsgId, Viewtype}; @@ -338,6 +339,10 @@ pub async fn send_webxdc_realtime_advertisement( ctx: &Context, msg_id: MsgId, ) -> Result> { + if !ctx.get_config_bool(Config::WebxdcRealtimeEnabled).await? { + return Ok(None); + } + let iroh = ctx.get_or_try_init_peer_channel().await?; let conn = iroh.join_and_subscribe_gossip(ctx, msg_id).await?; @@ -351,8 +356,12 @@ pub async fn send_webxdc_realtime_advertisement( Ok(conn) } -/// Send realtime data to the gossip swarm. +/// Send realtime data to other peers using iroh. pub async fn send_webxdc_realtime_data(ctx: &Context, msg_id: MsgId, data: Vec) -> Result<()> { + if !ctx.get_config_bool(Config::WebxdcRealtimeEnabled).await? { + return Ok(()); + } + let iroh = ctx.get_or_try_init_peer_channel().await?; iroh.send_webxdc_realtime_data(ctx, msg_id, data).await?; Ok(()) @@ -360,6 +369,10 @@ pub async fn send_webxdc_realtime_data(ctx: &Context, msg_id: MsgId, data: Vec Result<()> { + if !ctx.get_config_bool(Config::WebxdcRealtimeEnabled).await? { + return Ok(()); + } + let iroh = ctx.get_or_try_init_peer_channel().await?; iroh.leave_realtime(get_iroh_topic_for_msg(ctx, msg_id).await?) .await?; @@ -465,6 +478,17 @@ mod tests { let alice = &mut tcm.alice().await; let bob = &mut tcm.bob().await; + bob.ctx + .set_config_bool(Config::WebxdcRealtimeEnabled, true) + .await + .unwrap(); + + alice + .ctx + .set_config_bool(Config::WebxdcRealtimeEnabled, true) + .await + .unwrap(); + // Alice sends webxdc to bob let alice_chat = alice.create_chat(bob).await; let mut instance = Message::new(Viewtype::File); @@ -596,6 +620,21 @@ mod tests { let alice = &mut tcm.alice().await; let bob = &mut tcm.bob().await; + bob.ctx + .set_config_bool(Config::WebxdcRealtimeEnabled, true) + .await + .unwrap(); + + alice + .ctx + .set_config_bool(Config::WebxdcRealtimeEnabled, true) + .await + .unwrap(); + + assert!(alice + .get_config_bool(Config::WebxdcRealtimeEnabled) + .await + .unwrap()); // Alice sends webxdc to bob let alice_chat = alice.create_chat(bob).await; let mut instance = Message::new(Viewtype::File); @@ -731,6 +770,17 @@ mod tests { let alice = &mut tcm.alice().await; let bob = &mut tcm.bob().await; + bob.ctx + .set_config_bool(Config::WebxdcRealtimeEnabled, true) + .await + .unwrap(); + + alice + .ctx + .set_config_bool(Config::WebxdcRealtimeEnabled, true) + .await + .unwrap(); + // Alice sends webxdc to bob let alice_chat = alice.create_chat(bob).await; let mut instance = Message::new(Viewtype::File); @@ -793,4 +843,29 @@ mod tests { } } } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_peer_channels_disabled() { + let mut tcm = TestContextManager::new(); + let alice = &mut tcm.alice().await; + + // creates iroh endpoint as side effect + send_webxdc_realtime_advertisement(alice, MsgId::new(1)) + .await + .unwrap(); + + assert!(alice.ctx.iroh.get().is_none()); + + // creates iroh endpoint as side effect + send_webxdc_realtime_data(alice, MsgId::new(1), vec![]) + .await + .unwrap(); + + assert!(alice.ctx.iroh.get().is_none()); + + // creates iroh endpoint as side effect + leave_webxdc_realtime(alice, MsgId::new(1)).await.unwrap(); + + assert!(alice.ctx.iroh.get().is_none()) + } }