diff --git a/deltachat-rpc-client/tests/test_iroh_webxdc.py b/deltachat-rpc-client/tests/test_iroh_webxdc.py index 0eb6c15a4..53217c922 100644 --- a/deltachat-rpc-client/tests/test_iroh_webxdc.py +++ b/deltachat-rpc-client/tests/test_iroh_webxdc.py @@ -24,6 +24,13 @@ def path_to_webxdc(request): return str(p) +@pytest.fixture +def path_to_large_webxdc(request): + p = request.path.parent.parent.parent.joinpath("test-data/webxdc/realtime-check.xdc") + assert p.exists() + return str(p) + + def log(msg): logging.info(msg) @@ -227,3 +234,29 @@ def test_advertisement_after_chatting(acfactory, path_to_webxdc): ac2_webxdc_msg.send_webxdc_realtime_advertisement() event = ac1.wait_for_event(EventType.WEBXDC_REALTIME_ADVERTISEMENT_RECEIVED) assert event.msg_id == ac1_webxdc_msg.id + + +def test_realtime_large_webxdc(acfactory, path_to_large_webxdc): + """Tests initializing realtime channel on a large webxdc. + + This is a regression test for a bug that existed in version 2.42.0. + Large webxdc is split into pre- and post- message, + and this previously resulted in failure to initialize realtime. + """ + ac1, ac2 = acfactory.get_online_accounts(2) + ac1.set_config("webxdc_realtime_enabled", "1") + ac2.set_config("webxdc_realtime_enabled", "1") + + ac2.create_chat(ac1) + ac1_ac2_chat = ac1.create_chat(ac2) + ac1_webxdc_msg = ac1_ac2_chat.send_message(text="realtime check", file=path_to_large_webxdc) + + # Receive pre-message. + ac2_webxdc_msg = ac2.wait_for_incoming_msg() + + # Receive post-message. + ac2_webxdc_msg = ac2.wait_for_msg(EventType.MSGS_CHANGED) + + ac2_webxdc_msg.send_webxdc_realtime_advertisement() + event = ac1.wait_for_event(EventType.WEBXDC_REALTIME_ADVERTISEMENT_RECEIVED) + assert event.msg_id == ac1_webxdc_msg.id diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 31e089b8d..6fa166685 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -521,6 +521,18 @@ pub(crate) async fn create_iroh_header(ctx: &Context, msg_id: MsgId) -> Result Result { + let mut topic_raw = [0u8; 32]; + BASE32_NOPAD + .decode_mut(topic.to_ascii_uppercase().as_bytes(), &mut topic_raw) + .map_err(|e| e.error) + .context("Wrong gossip topic header")?; + + let topic = TopicId::from_bytes(topic_raw); + Ok(topic) +} + async fn subscribe_loop( context: &Context, mut stream: iroh_gossip::net::GossipReceiver, diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 906489c9b..adbc786d1 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -6,12 +6,10 @@ use std::iter; use std::sync::LazyLock; use anyhow::{Context as _, Result, ensure}; -use data_encoding::BASE32_NOPAD; use deltachat_contact_tools::{ ContactAddress, addr_cmp, addr_normalize, may_be_valid_addr, sanitize_bidi_characters, sanitize_single_line, }; -use iroh_gossip::proto::TopicId; use mailparse::SingleInfo; use num_traits::FromPrimitive; use regex::Regex; @@ -39,7 +37,7 @@ use crate::mimeparser::{ AvatarAction, GossipedKey, MimeMessage, PreMessageMode, SystemMessage, parse_message_ids, }; use crate::param::{Param, Params}; -use crate::peer_channels::{add_gossip_peer_from_header, insert_topic_stub}; +use crate::peer_channels::{add_gossip_peer_from_header, insert_topic_stub, iroh_topic_from_str}; use crate::reaction::{Reaction, set_msg_reaction}; use crate::rusqlite::OptionalExtension; use crate::securejoin::{ @@ -2298,21 +2296,12 @@ RETURNING id // Maybe set logging xdc and add gossip topics for webxdcs. for (part, msg_id) in mime_parser.parts.iter().zip(&created_db_entries) { - // check if any part contains a webxdc topic id - if part.typ == Viewtype::Webxdc { - if let Some(topic) = mime_parser.get_header(HeaderDef::IrohGossipTopic) { - // default encoding of topic ids is `hex`. - let mut topic_raw = [0u8; 32]; - BASE32_NOPAD - .decode_mut(topic.to_ascii_uppercase().as_bytes(), &mut topic_raw) - .map_err(|e| e.error) - .context("Wrong gossip topic header")?; - - let topic = TopicId::from_bytes(topic_raw); - insert_topic_stub(context, *msg_id, topic).await?; - } else { - warn!(context, "webxdc doesn't have a gossip topic") - } + if mime_parser.pre_message != PreMessageMode::Post + && part.typ == Viewtype::Webxdc + && let Some(topic) = mime_parser.get_header(HeaderDef::IrohGossipTopic) + { + let topic = iroh_topic_from_str(topic)?; + insert_topic_stub(context, *msg_id, topic).await?; } maybe_set_logging_xdc_inner( @@ -2517,6 +2506,13 @@ async fn handle_post_message( return Ok(()); } + if part.typ == Viewtype::Webxdc + && let Some(topic) = mime_parser.get_header(HeaderDef::IrohGossipTopic) + { + let topic = iroh_topic_from_str(topic)?; + insert_topic_stub(context, msg_id, topic).await?; + } + let mut new_params = original_msg.param.clone(); new_params .merge_in_params(part.param.clone()) diff --git a/test-data/webxdc/realtime-check.xdc b/test-data/webxdc/realtime-check.xdc new file mode 100644 index 000000000..254a728b4 Binary files /dev/null and b/test-data/webxdc/realtime-check.xdc differ