From ff9b84c561b17a084a7bc1656ea5b662f37c0edf Mon Sep 17 00:00:00 2001 From: Renato Alcara Date: Mon, 16 Mar 2026 22:59:28 -0300 Subject: [PATCH] fix: unify PN and LID session reuse for 1:1 sends (#293) fix: unify PN and LID session reuse for 1:1 sends (#293) --- src/Socket/messages-send.ts | 89 +++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 992aa1f8..4ddae005 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -417,6 +417,39 @@ export const makeMessagesSocket = (config: SocketConfig) => { ) } + const resolveSessionJid = async (jid: string) => { + if (isLidUser(jid) || isHostedLidUser(jid)) { + return jid + } + + if (isPnUser(jid) || isHostedPnUser(jid)) { + return await signalRepository.lidMapping.getLIDForPN(jid) || jid + } + + return jid + } + + const canonicalizeSessionRecipients = async (recipientJids: string[]) => { + const uniqueRecipients = [...new Set(recipientJids)] + const canonicalRecipients: string[] = [] + + for (const jid of uniqueRecipients) { + const canonicalJid = await resolveSessionJid(jid) + if (!canonicalRecipients.includes(canonicalJid)) { + canonicalRecipients.push(canonicalJid) + } + } + + if (canonicalRecipients.length !== uniqueRecipients.length || canonicalRecipients.some((jid, index) => jid !== uniqueRecipients[index])) { + logger.debug( + { before: uniqueRecipients, after: canonicalRecipients }, + '[SESSION] Canonicalized recipient addressing for session reuse' + ) + } + + return canonicalRecipients + } + const assertSessions = async (jids: string[], force?: boolean) => { let didFetchNewSession = false const uniqueJids = [...new Set(jids)] // Deduplicate JIDs @@ -426,22 +459,32 @@ export const makeMessagesSocket = (config: SocketConfig) => { // Check peerSessionsCache and validate sessions using libsignal loadSession for (const jid of uniqueJids) { - const signalId = signalRepository.jidToSignalProtocolAddress(jid) - const cachedSession = peerSessionsCache.get(signalId) + const canonicalJid = await resolveSessionJid(jid) + const signalIds = [ + signalRepository.jidToSignalProtocolAddress(jid), + signalRepository.jidToSignalProtocolAddress(canonicalJid) + ] + const cachedSession = signalIds + .map(signalId => peerSessionsCache.get(signalId)) + .find(session => session !== undefined) + if (cachedSession !== undefined) { if (cachedSession && !force) { continue // Session exists in cache } } else { - const sessionValidation = await signalRepository.validateSession(jid) + const sessionValidation = await signalRepository.validateSession(canonicalJid) const hasSession = sessionValidation.exists - peerSessionsCache.set(signalId, hasSession) + for (const signalId of signalIds) { + peerSessionsCache.set(signalId, hasSession) + } + if (hasSession && !force) { continue } } - jidsRequiringFetch.push(jid) + jidsRequiringFetch.push(canonicalJid) } if (jidsRequiringFetch.length) { @@ -682,33 +725,6 @@ export const makeMessagesSocket = (config: SocketConfig) => { return false } - const canonicalizeCarouselRecipients = async (recipientJids: string[]) => { - const uniqueRecipients = [...new Set(recipientJids)] - const pnRecipients = uniqueRecipients.filter(jid => isPnUser(jid) || isHostedPnUser(jid)) - const lidMappings = pnRecipients.length > 0 - ? await signalRepository.lidMapping.getLIDsForPNs(pnRecipients) - : [] - - const lidByPn = new Map((lidMappings || []).map(({ pn, lid }) => [pn, lid])) - const canonicalRecipients: string[] = [] - - for (const jid of uniqueRecipients) { - const canonicalJid = lidByPn.get(jid) || jid - if (!canonicalRecipients.includes(canonicalJid)) { - canonicalRecipients.push(canonicalJid) - } - } - - if (canonicalRecipients.length !== uniqueRecipients.length || canonicalRecipients.some((jid, index) => jid !== uniqueRecipients[index])) { - logger.debug( - { before: uniqueRecipients, after: canonicalRecipients }, - '[CAROUSEL] Canonicalized recipient addressing for session reuse' - ) - } - - return canonicalRecipients - } - const relayMessage = async ( jid: string, message: proto.IMessage, @@ -995,13 +1011,8 @@ export const makeMessagesSocket = (config: SocketConfig) => { allRecipients.push(jid) } - const isCarouselFanout = isCarouselMessage(message) - const effectiveMeRecipients = isCarouselFanout - ? await canonicalizeCarouselRecipients(meRecipients) - : meRecipients - const effectiveOtherRecipients = isCarouselFanout - ? await canonicalizeCarouselRecipients(otherRecipients) - : otherRecipients + const effectiveMeRecipients = await canonicalizeSessionRecipients(meRecipients) + const effectiveOtherRecipients = await canonicalizeSessionRecipients(otherRecipients) const effectiveAllRecipients = [...effectiveMeRecipients, ...effectiveOtherRecipients] await assertSessions(effectiveAllRecipients)