From 2afb7268a1e51ce4ec9cd351802291b1a19c80c7 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 4 Oct 2026 15:46:14 +0200 Subject: [PATCH] Restore PM group route and verify messaging after invite JOIN --- src/dm/dm_core.c | 15 ++++++++------- tests/test_dm_invite.c | 17 +++++++++++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/dm/dm_core.c b/src/dm/dm_core.c index 8b61cff7..a6d37952 100644 --- a/src/dm/dm_core.c +++ b/src/dm/dm_core.c @@ -1108,13 +1108,14 @@ void dm_invite_trampoline(void* arg) { } snprintf(conv, sizeof(conv), "%llu", (unsigned long long)dm_derive_conv_id(req->inst->node_id, req->peer_node_id)); struct dm_conv c; - if (dm_conv_load(dm, conv, &c) != 0) { - uint8_t x25519[32], ed25519[32]; - if (dm_node_pubkeys(dm, req->peer_node_id, x25519, ed25519) != 0 || - dm_start(req->inst, req->peer_node_id, x25519, ed25519, req->peer_name, req->source_ch_id) != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: conversation failed peer=%llu", (unsigned long long)req->peer_node_id); - dm_invite_done(req, DM_INVITE_START_ERROR); return; - } + if (dm_conv_load(dm, conv, &c) != 0 && dm_node_pubkeys(dm, req->peer_node_id, c.peer_x25519, c.peer_ed25519) != 0) { + DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: recipient keys missing peer=%llu", (unsigned long long)req->peer_node_id); + dm_invite_done(req, DM_INVITE_START_ERROR); return; + } + /* dm_start также восстанавливает маршрут через исходную группу для авто-созданной PM. */ + if (dm_start(req->inst, req->peer_node_id, c.peer_x25519, c.peer_ed25519, req->peer_name, req->source_ch_id) != 0) { + DEBUG_ERROR(DEBUG_CATEGORY_DM, "invite PM: conversation failed peer=%llu", (unsigned long long)req->peer_node_id); + dm_invite_done(req, DM_INVITE_START_ERROR); return; } DEBUG_INFO(DEBUG_CATEGORY_DM, "invite PM: building request=%llu peer=%llu source=%s ch=%s conv=%s", (unsigned long long)req->request_id, (unsigned long long)req->peer_node_id, req->source_ch_id, channel, conv); diff --git a/tests/test_dm_invite.c b/tests/test_dm_invite.c index f17db024..823d6c55 100644 --- a/tests/test_dm_invite.c +++ b/tests/test_dm_invite.c @@ -118,8 +118,6 @@ int main(void) { debug_set_category_level(DEBUG_CATEGORY_DM, DEBUG_LEVEL_DEBUG); debug_set_category_level(DEBUG_CATEGORY_CHAT_SYNC, DEBUG_LEVEL_DEBUG); debug_set_category_level(DEBUG_CATEGORY_MEMBER_SYNC, DEBUG_LEVEL_INFO); - debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_DEBUG); - debug_set_category_level(DEBUG_CATEGORY_CONNECTION, DEBUG_LEVEL_DEBUG); } utun_instance_set_tun_init_enabled(0); struct UASYNC* ua = uasync_create(); @@ -151,10 +149,15 @@ int main(void) { request(3, 0, source_id, 0); CHECK(wait_result(ua, 3, DM_INVITE_BUILD_ERROR) && !message_count(), "invalid group sends nothing"); + CHECK(sqlite3_exec(nodes[0]->topo_sqlite_db, "UPDATE dm_conversations SET group_id=0", NULL, NULL, NULL) == SQLITE_OK, + "simulate automatically created PM without group route"); CHECK(sqlite3_exec(nodes[0]->topo_sqlite_db, "CREATE TEMP TRIGGER fail_invite BEFORE INSERT ON dm_outbox " "BEGIN SELECT RAISE(ABORT,'test invite commit failure'); END", NULL, NULL, NULL) == SQLITE_OK, "install failed commit"); request(4, target, source_id, 0); CHECK(wait_result(ua, 4, DM_INVITE_SEND_ERROR) && !message_count(), "failed commit returns error and rolls back PM"); + uint64_t route = 0; + CHECK(!scalar(nodes[0], "SELECT group_id FROM dm_conversations LIMIT 1", &route) && route == source, + "member invitation restores the existing PM's source group route"); CHECK(sqlite3_exec(nodes[0]->topo_sqlite_db, "DROP TRIGGER fail_invite", NULL, NULL, NULL) == SQLITE_OK, "remove failed commit"); request(5, target, "", 0); /* из шапки существующей PM исходная группа не передаётся */ @@ -186,6 +189,16 @@ int main(void) { topo_node_sqlite_member_in_channel(nodes[1]->topo_sqlite_db, target_id, nodes[1]->node_id)); CHECK(topo_node_sqlite_member_in_channel(nodes[0]->topo_sqlite_db, target_id, nodes[1]->node_id) && topo_node_sqlite_member_in_channel(nodes[1]->topo_sqlite_db, target_id, nodes[1]->node_id), "membership committed on both nodes"); + const char* text = "joined through PM invitation"; + struct chat_msg_submit message = {0}; + snprintf(message.channel_id, sizeof(message.channel_id), "%s", target_id); + snprintf(message.content_type, sizeof(message.content_type), "text"); + message.data = (uint8_t*)text; message.data_len = (uint32_t)strlen(text); + chat_core_submit_message(nodes[1], &message); + deadline = get_time_tb() + 100000; + while (!chat_core_count(nodes[0], target_id) && get_time_tb() < deadline) uasync_poll(ua, 100); + CHECK(!chat_core_get_messages_json(nodes[0], target_id, 10, 0, messages, sizeof(messages), &length) && strstr(messages, text), + "joined client can send a group message to the inviter"); request(6, target, "", 0); dm_core_destroy(nodes[0]); CHECK(calls[6] == 1 && results[6] == DM_INVITE_CANCELLED && message_count() == 1, "teardown cancels pending invitation");