zapo-js 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/dist/appstate/WaAppStateCrypto.js +1 -1
- package/dist/appstate/WaAppStateSyncClient.js +138 -93
- package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
- package/dist/appstate/index.js +8 -6
- package/dist/appstate/utils.js +0 -5
- package/dist/auth/WaAuthClient.js +36 -47
- package/dist/auth/flow/WaAuthCredentialsFlow.js +7 -7
- package/dist/auth/index.js +1 -6
- package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
- package/dist/auth/pairing/WaPairingFlow.js +13 -3
- package/dist/client/WaClient.js +225 -101
- package/dist/client/WaClientFactory.js +294 -44
- package/dist/client/connection/WaConnectionManager.js +19 -10
- package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +292 -99
- package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
- package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
- package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
- package/dist/client/coordinators/WaRetryCoordinator.js +179 -27
- package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
- package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
- package/dist/client/dirty.js +40 -20
- package/dist/client/events/devices.js +72 -0
- package/dist/client/events/group.js +3 -11
- package/dist/client/events/identity.js +22 -0
- package/dist/client/events/privacy-token.js +39 -0
- package/dist/client/history-sync.js +50 -9
- package/dist/client/incoming.js +37 -7
- package/dist/client/mailbox.js +24 -23
- package/dist/client/messages.js +107 -31
- package/dist/client/messaging/fanout.js +21 -11
- package/dist/client/messaging/participants.js +6 -4
- package/dist/client/persistence/WriteBehindPersistence.js +129 -0
- package/dist/client/tokens/cs-token.js +50 -0
- package/dist/client/tokens/tc-token.js +25 -0
- package/dist/crypto/core/index.js +2 -2
- package/dist/crypto/core/keys.js +4 -4
- package/dist/crypto/core/nonce.js +2 -0
- package/dist/crypto/core/primitives.js +0 -8
- package/dist/crypto/core/random.js +22 -0
- package/dist/crypto/curves/X25519.js +25 -6
- package/dist/crypto/index.js +3 -0
- package/dist/crypto/math/constants.js +13 -36
- package/dist/crypto/math/edwards.js +171 -44
- package/dist/crypto/math/fe.js +706 -0
- package/dist/crypto/math/mod.js +10 -3
- package/dist/esm/appstate/WaAppStateCrypto.js +1 -1
- package/dist/esm/appstate/WaAppStateSyncClient.js +138 -93
- package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
- package/dist/esm/appstate/index.js +2 -2
- package/dist/esm/appstate/utils.js +2 -5
- package/dist/esm/auth/WaAuthClient.js +36 -47
- package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +7 -7
- package/dist/esm/auth/index.js +0 -2
- package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
- package/dist/esm/auth/pairing/WaPairingFlow.js +14 -4
- package/dist/esm/client/WaClient.js +225 -101
- package/dist/esm/client/WaClientFactory.js +295 -45
- package/dist/esm/client/connection/WaConnectionManager.js +19 -10
- package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +295 -102
- package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
- package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
- package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +181 -29
- package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
- package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
- package/dist/esm/client/dirty.js +40 -20
- package/dist/esm/client/events/devices.js +68 -0
- package/dist/esm/client/events/group.js +3 -11
- package/dist/esm/client/events/identity.js +19 -0
- package/dist/esm/client/events/privacy-token.js +36 -0
- package/dist/esm/client/history-sync.js +50 -9
- package/dist/esm/client/incoming.js +38 -8
- package/dist/esm/client/mailbox.js +24 -23
- package/dist/esm/client/messages.js +108 -32
- package/dist/esm/client/messaging/fanout.js +22 -12
- package/dist/esm/client/messaging/participants.js +6 -4
- package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
- package/dist/esm/client/tokens/cs-token.js +46 -0
- package/dist/esm/client/tokens/tc-token.js +18 -0
- package/dist/esm/crypto/core/index.js +2 -2
- package/dist/esm/crypto/core/keys.js +1 -1
- package/dist/esm/crypto/core/nonce.js +2 -0
- package/dist/esm/crypto/core/primitives.js +0 -7
- package/dist/esm/crypto/core/random.js +22 -1
- package/dist/esm/crypto/curves/X25519.js +25 -6
- package/dist/esm/crypto/index.js +1 -0
- package/dist/esm/crypto/math/constants.js +12 -35
- package/dist/esm/crypto/math/edwards.js +174 -47
- package/dist/esm/crypto/math/fe.js +691 -0
- package/dist/esm/crypto/math/mod.js +10 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
- package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
- package/dist/esm/infra/perf/PromiseDedup.js +20 -0
- package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
- package/dist/esm/infra/perf/StoreLock.js +77 -0
- package/dist/esm/media/WaMediaCrypto.js +95 -13
- package/dist/esm/media/WaMediaTransferClient.js +39 -47
- package/dist/esm/media/constants.js +2 -1
- package/dist/esm/message/WaMessageClient.js +26 -19
- package/dist/esm/message/content.js +195 -9
- package/dist/esm/message/icdc.js +76 -0
- package/dist/esm/message/incoming.js +24 -12
- package/dist/esm/message/phash.js +3 -1
- package/dist/esm/message/reporting-token.js +14 -27
- package/dist/esm/protocol/appstate.js +9 -40
- package/dist/esm/protocol/browser.js +10 -18
- package/dist/esm/protocol/constants.js +5 -3
- package/dist/esm/protocol/defaults.js +6 -0
- package/dist/esm/protocol/index.js +1 -2
- package/dist/esm/protocol/jid.js +105 -36
- package/dist/esm/protocol/message.js +61 -1
- package/dist/esm/protocol/nodes.js +2 -0
- package/dist/esm/protocol/notification.js +3 -1
- package/dist/esm/protocol/privacy-token.js +17 -0
- package/dist/esm/protocol/privacy.js +55 -0
- package/dist/esm/protocol/stream.js +26 -1
- package/dist/esm/retry/codec.js +216 -0
- package/dist/esm/retry/constants.js +1 -1
- package/dist/esm/retry/index.js +2 -2
- package/dist/esm/retry/parse.js +50 -30
- package/dist/esm/retry/replay.js +11 -7
- package/dist/esm/retry/tracker.js +50 -12
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +49 -32
- package/dist/esm/signal/api/SignalDigestSyncApi.js +13 -9
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +26 -11
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +18 -7
- package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
- package/dist/esm/signal/api/SignalSessionSyncApi.js +16 -7
- package/dist/esm/signal/api/result-map.js +10 -0
- package/dist/esm/signal/constants.js +0 -4
- package/dist/esm/signal/crypto/WaAdvSignature.js +12 -6
- package/dist/esm/signal/{store/sqlite.js → encoding.js} +78 -24
- package/dist/esm/signal/group/SenderKeyCodec.js +3 -2
- package/dist/esm/signal/group/SenderKeyManager.js +125 -106
- package/dist/esm/signal/index.js +1 -0
- package/dist/esm/signal/registration/keygen.js +6 -2
- package/dist/esm/signal/registration/utils.js +1 -0
- package/dist/esm/signal/session/SignalProtocol.js +150 -74
- package/dist/esm/signal/session/resolver.js +137 -102
- package/dist/esm/store/contracts/privacy-token.store.js +1 -0
- package/dist/esm/store/createStore.js +101 -187
- package/dist/esm/store/index.js +1 -10
- package/dist/esm/store/locks/appstate.lock.js +26 -0
- package/dist/esm/store/locks/auth.lock.js +15 -0
- package/dist/esm/store/locks/contact.lock.js +20 -0
- package/dist/esm/store/locks/device-list.lock.js +20 -0
- package/dist/esm/store/locks/message.lock.js +21 -0
- package/dist/esm/store/locks/participants.lock.js +20 -0
- package/dist/esm/store/locks/privacy-token.lock.js +18 -0
- package/dist/esm/store/locks/retry.lock.js +29 -0
- package/dist/esm/store/locks/sender-key.lock.js +52 -0
- package/dist/esm/store/locks/signal.lock.js +63 -0
- package/dist/esm/store/locks/thread.lock.js +21 -0
- package/dist/esm/store/noop.store.js +1 -1
- package/dist/esm/store/providers/memory/appstate.store.js +22 -24
- package/dist/esm/store/providers/memory/device-list.store.js +10 -5
- package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
- package/dist/esm/store/providers/memory/retry.store.js +77 -2
- package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
- package/dist/esm/store/providers/memory/signal.store.js +36 -19
- package/dist/esm/transport/WaComms.js +3 -1
- package/dist/esm/transport/WaWebSocket.js +0 -6
- package/dist/esm/transport/binary/constants.js +0 -30
- package/dist/esm/transport/binary/decoder.js +4 -4
- package/dist/esm/transport/binary/encoder.js +8 -15
- package/dist/esm/transport/binary/index.js +0 -1
- package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -19
- package/dist/esm/transport/node/builders/business.js +129 -0
- package/dist/esm/transport/node/builders/global.js +370 -0
- package/dist/esm/transport/node/builders/index.js +5 -2
- package/dist/esm/transport/node/builders/message.js +63 -239
- package/dist/esm/transport/node/builders/pairing.js +0 -24
- package/dist/esm/transport/node/builders/privacy-token.js +41 -0
- package/dist/esm/transport/node/builders/privacy.js +48 -0
- package/dist/esm/transport/node/builders/profile.js +70 -0
- package/dist/esm/transport/node/builders/retry.js +10 -22
- package/dist/esm/transport/node/builders/usync.js +6 -2
- package/dist/esm/transport/node/helpers.js +19 -1
- package/dist/esm/transport/node/usync.js +3 -33
- package/dist/esm/transport/node/xml.js +35 -14
- package/dist/esm/transport/noise/WaClientPayload.js +10 -10
- package/dist/esm/transport/noise/WaNoiseCert.js +3 -3
- package/dist/esm/transport/noise/WaNoiseSession.js +64 -23
- package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
- package/dist/esm/transport/stream/parse.js +8 -4
- package/dist/esm/util/bytes.js +22 -18
- package/dist/esm/util/index.js +5 -0
- package/dist/esm/util/primitives.js +3 -2
- package/dist/index.js +7 -1
- package/dist/infra/perf/BackgroundQueue.js +482 -0
- package/dist/infra/perf/BoundedTaskQueue.js +3 -1
- package/dist/infra/perf/PromiseDedup.js +24 -0
- package/dist/infra/perf/SharedExclusiveGate.js +113 -0
- package/dist/infra/perf/StoreLock.js +81 -0
- package/dist/media/WaMediaCrypto.js +94 -12
- package/dist/media/WaMediaTransferClient.js +39 -47
- package/dist/media/constants.js +2 -1
- package/dist/message/WaMessageClient.js +26 -19
- package/dist/message/content.js +198 -9
- package/dist/message/icdc.js +81 -0
- package/dist/message/incoming.js +24 -12
- package/dist/message/phash.js +3 -1
- package/dist/message/reporting-token.js +14 -28
- package/dist/protocol/appstate.js +10 -41
- package/dist/protocol/browser.js +10 -18
- package/dist/protocol/constants.js +21 -2
- package/dist/protocol/defaults.js +6 -0
- package/dist/protocol/index.js +8 -5
- package/dist/protocol/jid.js +111 -36
- package/dist/protocol/message.js +62 -2
- package/dist/protocol/nodes.js +2 -0
- package/dist/protocol/notification.js +3 -1
- package/dist/protocol/privacy-token.js +20 -0
- package/dist/protocol/privacy.js +58 -0
- package/dist/protocol/stream.js +27 -2
- package/dist/retry/codec.js +220 -0
- package/dist/retry/constants.js +1 -1
- package/dist/retry/index.js +5 -5
- package/dist/retry/parse.js +51 -30
- package/dist/retry/replay.js +10 -6
- package/dist/retry/tracker.js +50 -12
- package/dist/signal/api/SignalDeviceSyncApi.js +48 -31
- package/dist/signal/api/SignalDigestSyncApi.js +13 -9
- package/dist/signal/api/SignalIdentitySyncApi.js +25 -10
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
- package/dist/signal/api/SignalRotateKeyApi.js +4 -2
- package/dist/signal/api/SignalSessionSyncApi.js +16 -7
- package/dist/signal/api/result-map.js +13 -0
- package/dist/signal/constants.js +1 -5
- package/dist/signal/crypto/WaAdvSignature.js +11 -5
- package/dist/signal/{store/sqlite.js → encoding.js} +79 -25
- package/dist/signal/group/SenderKeyCodec.js +4 -3
- package/dist/signal/group/SenderKeyManager.js +125 -106
- package/dist/signal/index.js +13 -1
- package/dist/signal/registration/keygen.js +6 -2
- package/dist/signal/registration/utils.js +1 -0
- package/dist/signal/session/SignalProtocol.js +150 -74
- package/dist/signal/session/resolver.js +135 -100
- package/dist/store/contracts/privacy-token.store.js +2 -0
- package/dist/store/createStore.js +101 -187
- package/dist/store/index.js +15 -33
- package/dist/store/locks/appstate.lock.js +29 -0
- package/dist/store/locks/auth.lock.js +18 -0
- package/dist/store/locks/contact.lock.js +23 -0
- package/dist/store/locks/device-list.lock.js +23 -0
- package/dist/store/locks/message.lock.js +24 -0
- package/dist/store/locks/participants.lock.js +23 -0
- package/dist/store/locks/privacy-token.lock.js +21 -0
- package/dist/store/locks/retry.lock.js +32 -0
- package/dist/store/locks/sender-key.lock.js +55 -0
- package/dist/store/locks/signal.lock.js +66 -0
- package/dist/store/locks/thread.lock.js +24 -0
- package/dist/store/noop.store.js +1 -1
- package/dist/store/providers/memory/appstate.store.js +22 -24
- package/dist/store/providers/memory/device-list.store.js +10 -5
- package/dist/store/providers/memory/privacy-token.store.js +47 -0
- package/dist/store/providers/memory/retry.store.js +77 -2
- package/dist/store/providers/memory/sender-key.store.js +6 -1
- package/dist/store/providers/memory/signal.store.js +36 -19
- package/dist/transport/WaComms.js +3 -1
- package/dist/transport/WaWebSocket.js +0 -6
- package/dist/transport/binary/constants.js +1 -31
- package/dist/transport/binary/decoder.js +4 -4
- package/dist/transport/binary/encoder.js +8 -15
- package/dist/transport/binary/index.js +0 -4
- package/dist/transport/node/WaNodeOrchestrator.js +24 -18
- package/dist/transport/node/builders/business.js +137 -0
- package/dist/transport/node/builders/global.js +375 -0
- package/dist/transport/node/builders/index.js +18 -9
- package/dist/transport/node/builders/message.js +64 -245
- package/dist/transport/node/builders/pairing.js +0 -26
- package/dist/transport/node/builders/privacy-token.js +46 -0
- package/dist/transport/node/builders/privacy.js +55 -0
- package/dist/transport/node/builders/profile.js +78 -0
- package/dist/transport/node/builders/retry.js +9 -21
- package/dist/transport/node/builders/usync.js +6 -2
- package/dist/transport/node/helpers.js +20 -1
- package/dist/transport/node/usync.js +2 -32
- package/dist/transport/node/xml.js +35 -14
- package/dist/transport/noise/WaClientPayload.js +13 -13
- package/dist/transport/noise/WaNoiseCert.js +2 -2
- package/dist/transport/noise/WaNoiseSession.js +64 -23
- package/dist/transport/noise/WaNoiseSocket.js +8 -4
- package/dist/transport/stream/parse.js +7 -3
- package/dist/types/appstate/encoding.d.ts +7 -0
- package/dist/types/appstate/index.d.ts +3 -3
- package/dist/types/appstate/utils.d.ts +0 -2
- package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
- package/dist/types/auth/index.d.ts +0 -2
- package/dist/types/auth/types.d.ts +1 -0
- package/dist/types/client/WaClient.d.ts +27 -12
- package/dist/types/client/WaClientFactory.d.ts +12 -4
- package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
- package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +14 -0
- package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
- package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
- package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
- package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
- package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
- package/dist/types/client/events/devices.d.ts +20 -0
- package/dist/types/client/events/identity.d.ts +9 -0
- package/dist/types/client/events/privacy-token.d.ts +7 -0
- package/dist/types/client/history-sync.d.ts +9 -6
- package/dist/types/client/incoming.d.ts +3 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/mailbox.d.ts +3 -5
- package/dist/types/client/messages.d.ts +1 -2
- package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
- package/dist/types/client/tokens/cs-token.d.ts +10 -0
- package/dist/types/client/tokens/tc-token.d.ts +5 -0
- package/dist/types/client/types.d.ts +51 -3
- package/dist/types/crypto/core/index.d.ts +2 -2
- package/dist/types/crypto/core/nonce.d.ts +2 -0
- package/dist/types/crypto/core/primitives.d.ts +0 -1
- package/dist/types/crypto/core/random.d.ts +1 -0
- package/dist/types/crypto/index.d.ts +1 -0
- package/dist/types/crypto/math/constants.d.ts +4 -2
- package/dist/types/crypto/math/fe.d.ts +30 -0
- package/dist/types/crypto/math/mod.d.ts +0 -2
- package/dist/types/crypto/math/types.d.ts +11 -4
- package/dist/types/index.d.ts +5 -3
- package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
- package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
- package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
- package/dist/types/infra/perf/StoreLock.d.ts +10 -0
- package/dist/types/media/WaMediaCrypto.d.ts +3 -2
- package/dist/types/media/WaMediaTransferClient.d.ts +3 -12
- package/dist/types/media/constants.d.ts +1 -1
- package/dist/types/media/index.d.ts +1 -1
- package/dist/types/media/types.d.ts +10 -2
- package/dist/types/message/content.d.ts +8 -0
- package/dist/types/message/icdc.d.ts +13 -0
- package/dist/types/message/reporting-token.d.ts +0 -1
- package/dist/types/message/types.d.ts +45 -6
- package/dist/types/protocol/appstate.d.ts +0 -11
- package/dist/types/protocol/constants.d.ts +7 -3
- package/dist/types/protocol/defaults.d.ts +6 -0
- package/dist/types/protocol/index.d.ts +1 -2
- package/dist/types/protocol/jid.d.ts +19 -2
- package/dist/types/protocol/message.d.ts +60 -0
- package/dist/types/protocol/nodes.d.ts +2 -0
- package/dist/types/protocol/notification.d.ts +2 -0
- package/dist/types/protocol/privacy-token.d.ts +17 -0
- package/dist/types/protocol/privacy.d.ts +75 -0
- package/dist/types/protocol/stream.d.ts +30 -0
- package/dist/types/retry/codec.d.ts +3 -0
- package/dist/types/retry/index.d.ts +3 -3
- package/dist/types/retry/parse.d.ts +5 -2
- package/dist/types/retry/tracker.d.ts +1 -0
- package/dist/types/retry/types.d.ts +6 -1
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
- package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
- package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
- package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
- package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
- package/dist/types/signal/api/result-map.d.ts +1 -0
- package/dist/types/signal/constants.d.ts +0 -3
- package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
- package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
- package/dist/types/signal/index.d.ts +2 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +10 -4
- package/dist/types/signal/session/resolver.d.ts +7 -2
- package/dist/types/store/contracts/appstate.store.d.ts +1 -1
- package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
- package/dist/types/store/contracts/retry.store.d.ts +7 -0
- package/dist/types/store/contracts/signal.store.d.ts +7 -0
- package/dist/types/store/createStore.d.ts +1 -1
- package/dist/types/store/index.d.ts +5 -13
- package/dist/types/store/locks/appstate.lock.d.ts +3 -0
- package/dist/types/store/locks/auth.lock.d.ts +3 -0
- package/dist/types/store/locks/contact.lock.d.ts +3 -0
- package/dist/types/store/locks/device-list.lock.d.ts +2 -0
- package/dist/types/store/locks/message.lock.d.ts +3 -0
- package/dist/types/store/locks/participants.lock.d.ts +2 -0
- package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
- package/dist/types/store/locks/retry.lock.d.ts +2 -0
- package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
- package/dist/types/store/locks/signal.lock.d.ts +3 -0
- package/dist/types/store/locks/thread.lock.d.ts +3 -0
- package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
- package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
- package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
- package/dist/types/store/providers/memory/signal.store.d.ts +2 -1
- package/dist/types/store/types.d.ts +49 -61
- package/dist/types/transport/WaWebSocket.d.ts +0 -1
- package/dist/types/transport/binary/constants.d.ts +0 -30
- package/dist/types/transport/binary/index.d.ts +0 -1
- package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
- package/dist/types/transport/node/builders/business.d.ts +29 -0
- package/dist/types/transport/node/builders/global.d.ts +102 -0
- package/dist/types/transport/node/builders/index.d.ts +5 -2
- package/dist/types/transport/node/builders/message.d.ts +8 -7
- package/dist/types/transport/node/builders/pairing.d.ts +0 -2
- package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
- package/dist/types/transport/node/builders/privacy.d.ts +7 -0
- package/dist/types/transport/node/builders/profile.d.ts +8 -0
- package/dist/types/transport/node/builders/retry.d.ts +0 -1
- package/dist/types/transport/node/helpers.d.ts +5 -0
- package/dist/types/transport/noise/WaNoiseSession.d.ts +3 -2
- package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
- package/dist/types/util/bytes.d.ts +1 -1
- package/dist/types/util/index.d.ts +5 -0
- package/dist/types/util/primitives.d.ts +0 -1
- package/dist/util/bytes.js +22 -18
- package/dist/util/index.js +23 -0
- package/dist/util/primitives.js +2 -2
- package/package.json +29 -7
- package/proto/index.js +1 -1
- package/dist/crypto/core/constants.js +0 -4
- package/dist/esm/crypto/core/constants.js +0 -1
- package/dist/esm/retry/outbound.js +0 -82
- package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
- package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
- package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
- package/dist/esm/store/providers/sqlite/connection.js +0 -245
- package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
- package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
- package/dist/esm/store/providers/sqlite/message.store.js +0 -132
- package/dist/esm/store/providers/sqlite/migrations.js +0 -347
- package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
- package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
- package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
- package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
- package/dist/esm/store/providers/sqlite/table-names.js +0 -107
- package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
- package/dist/retry/outbound.js +0 -87
- package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
- package/dist/store/providers/sqlite/appstate.store.js +0 -254
- package/dist/store/providers/sqlite/auth.store.js +0 -180
- package/dist/store/providers/sqlite/connection.js +0 -281
- package/dist/store/providers/sqlite/contact.store.js +0 -78
- package/dist/store/providers/sqlite/device-list.store.js +0 -131
- package/dist/store/providers/sqlite/message.store.js +0 -136
- package/dist/store/providers/sqlite/migrations.js +0 -350
- package/dist/store/providers/sqlite/participants.store.js +0 -81
- package/dist/store/providers/sqlite/retry.store.js +0 -145
- package/dist/store/providers/sqlite/sender-key.store.js +0 -202
- package/dist/store/providers/sqlite/signal.store.js +0 -439
- package/dist/store/providers/sqlite/table-names.js +0 -113
- package/dist/store/providers/sqlite/thread.store.js +0 -89
- package/dist/types/appstate/store/sqlite.d.ts +0 -7
- package/dist/types/crypto/core/constants.d.ts +0 -1
- package/dist/types/retry/outbound.d.ts +0 -4
- package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
- package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
- package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
- package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
- package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
- package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
- package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
- package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
- package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
- package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
- package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
- package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
- package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
- package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toSerializedPubKey } from '../../crypto/index.js';
|
|
2
2
|
import { ConsoleLogger } from '../../infra/log/ConsoleLogger.js';
|
|
3
|
+
import { StoreLock } from '../../infra/perf/StoreLock.js';
|
|
3
4
|
import { MAX_PREV_SESSIONS } from '../constants.js';
|
|
4
5
|
import { decryptMsg, decryptMsgFromSession, encryptMsg } from '../session/SignalRatchet.js';
|
|
5
6
|
import { deserializeMsg, deserializePkMsg, requirePreKey, requireSignedPreKey } from '../session/SignalSerializer.js';
|
|
@@ -8,26 +9,37 @@ import { uint8Equal } from '../../util/bytes.js';
|
|
|
8
9
|
function signalAddressMapKey(address) {
|
|
9
10
|
return `${address.user}\u0001${address.server ?? ''}\u0001${address.device}`;
|
|
10
11
|
}
|
|
12
|
+
function signalAddressLockKey(address) {
|
|
13
|
+
return `signal:${signalAddressMapKey(address)}`;
|
|
14
|
+
}
|
|
11
15
|
export class SignalProtocol {
|
|
12
16
|
constructor(store, logger = new ConsoleLogger('info')) {
|
|
13
17
|
this.store = store;
|
|
14
18
|
this.logger = logger;
|
|
19
|
+
this.sessionMutationLock = new StoreLock();
|
|
15
20
|
}
|
|
16
|
-
async
|
|
17
|
-
return this.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
async establishOutgoingSession(address, remoteBundle, options = {}) {
|
|
22
|
+
return this.runWithAddressLock(address, async () => {
|
|
23
|
+
if (options.reuseExisting) {
|
|
24
|
+
const existing = await this.store.getSession(address);
|
|
25
|
+
if (existing) {
|
|
26
|
+
const remoteIdentity = toSerializedPubKey(remoteBundle.identity);
|
|
27
|
+
if (!uint8Equal(existing.remote.pubKey, remoteIdentity)) {
|
|
28
|
+
throw new Error('identity mismatch');
|
|
29
|
+
}
|
|
30
|
+
return existing;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const [local, localOneTimeBase] = await Promise.all([
|
|
34
|
+
requireLocalIdentity(this.store),
|
|
35
|
+
generateSerializedKeyPair()
|
|
36
|
+
]);
|
|
37
|
+
const session = await initiateSessionOutgoing(local, remoteBundle, localOneTimeBase);
|
|
38
|
+
// Keep writes ordered: a stored session without matching remote identity causes false mismatch checks.
|
|
39
|
+
await this.store.setRemoteIdentity(address, session.remote.pubKey);
|
|
40
|
+
await this.store.setSession(address, session);
|
|
41
|
+
return session;
|
|
42
|
+
});
|
|
31
43
|
}
|
|
32
44
|
async encryptMessage(address, plaintext, expectedIdentity) {
|
|
33
45
|
const [encrypted] = await this.encryptMessagesBatch([
|
|
@@ -35,77 +47,140 @@ export class SignalProtocol {
|
|
|
35
47
|
]);
|
|
36
48
|
return encrypted;
|
|
37
49
|
}
|
|
38
|
-
async encryptMessagesBatch(requests) {
|
|
50
|
+
async encryptMessagesBatch(requests, prefetchedSessions) {
|
|
39
51
|
if (requests.length === 0) {
|
|
40
52
|
return [];
|
|
41
53
|
}
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const lockKeySet = new Set();
|
|
55
|
+
for (let i = 0; i < requests.length; i += 1)
|
|
56
|
+
lockKeySet.add(signalAddressLockKey(requests[i].address));
|
|
57
|
+
const lockKeys = [...lockKeySet];
|
|
58
|
+
return this.sessionMutationLock.runMany(lockKeys, async () => {
|
|
59
|
+
const prefetchedByAddress = new Map();
|
|
60
|
+
if (prefetchedSessions && prefetchedSessions.length > 0) {
|
|
61
|
+
for (let index = 0; index < prefetchedSessions.length; index += 1) {
|
|
62
|
+
const entry = prefetchedSessions[index];
|
|
63
|
+
prefetchedByAddress.set(signalAddressMapKey(entry.address), entry.session);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const uniqueAddressKeys = new Array(requests.length);
|
|
67
|
+
const uniqueAddresses = new Array(requests.length);
|
|
68
|
+
let uniqueAddressCount = 0;
|
|
69
|
+
for (let index = 0; index < requests.length; index += 1) {
|
|
70
|
+
const address = requests[index].address;
|
|
71
|
+
const addressKey = signalAddressMapKey(address);
|
|
72
|
+
let isDuplicate = false;
|
|
73
|
+
for (let dedupIndex = 0; dedupIndex < uniqueAddressCount; dedupIndex += 1) {
|
|
74
|
+
if (uniqueAddressKeys[dedupIndex] === addressKey) {
|
|
75
|
+
isDuplicate = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (isDuplicate) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
uniqueAddressKeys[uniqueAddressCount] = addressKey;
|
|
83
|
+
uniqueAddresses[uniqueAddressCount] = address;
|
|
84
|
+
uniqueAddressCount += 1;
|
|
55
85
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
86
|
+
uniqueAddressKeys.length = uniqueAddressCount;
|
|
87
|
+
uniqueAddresses.length = uniqueAddressCount;
|
|
88
|
+
const currentSessions = await this.store.getSessionsBatch(uniqueAddresses);
|
|
89
|
+
const latestSessionByAddress = new Map();
|
|
90
|
+
for (let index = 0; index < uniqueAddressCount; index += 1) {
|
|
91
|
+
const addressKey = uniqueAddressKeys[index];
|
|
92
|
+
const current = currentSessions[index];
|
|
93
|
+
if (current) {
|
|
94
|
+
latestSessionByAddress.set(addressKey, current);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const prefetched = prefetchedByAddress.get(addressKey);
|
|
98
|
+
if (prefetched) {
|
|
99
|
+
latestSessionByAddress.set(addressKey, prefetched);
|
|
100
|
+
}
|
|
59
101
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
102
|
+
const sessionUpdatesByAddress = new Map();
|
|
103
|
+
const identityUpdatesByAddress = new Map();
|
|
104
|
+
const results = new Array(requests.length);
|
|
105
|
+
for (let index = 0; index < requests.length; index += 1) {
|
|
106
|
+
const request = requests[index];
|
|
107
|
+
const address = request.address;
|
|
108
|
+
const addressKey = signalAddressMapKey(address);
|
|
109
|
+
const session = latestSessionByAddress.get(addressKey);
|
|
110
|
+
if (!session) {
|
|
111
|
+
throw new Error('signal session not found');
|
|
112
|
+
}
|
|
113
|
+
if (request.expectedIdentity &&
|
|
114
|
+
!uint8Equal(toSerializedPubKey(request.expectedIdentity), session.remote.pubKey)) {
|
|
115
|
+
throw new Error('identity mismatch');
|
|
116
|
+
}
|
|
117
|
+
const [updatedSession, encrypted] = await encryptMsg(session, request.plaintext);
|
|
118
|
+
latestSessionByAddress.set(addressKey, updatedSession);
|
|
119
|
+
sessionUpdatesByAddress.set(addressKey, {
|
|
68
120
|
address,
|
|
69
|
-
|
|
121
|
+
session: updatedSession
|
|
70
122
|
});
|
|
123
|
+
if (!uint8Equal(updatedSession.remote.pubKey, session.remote.pubKey)) {
|
|
124
|
+
identityUpdatesByAddress.set(addressKey, {
|
|
125
|
+
address,
|
|
126
|
+
identityKey: updatedSession.remote.pubKey
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
results[index] = {
|
|
130
|
+
...encrypted,
|
|
131
|
+
baseKey: updatedSession.aliceBaseKey
|
|
132
|
+
};
|
|
71
133
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
134
|
+
// Persist remote identities first when needed so session writes never commit ahead of identity data.
|
|
135
|
+
if (identityUpdatesByAddress.size > 0) {
|
|
136
|
+
const identityUpdates = new Array(identityUpdatesByAddress.size);
|
|
137
|
+
let identityIndex = 0;
|
|
138
|
+
for (const update of identityUpdatesByAddress.values()) {
|
|
139
|
+
identityUpdates[identityIndex] = update;
|
|
140
|
+
identityIndex += 1;
|
|
141
|
+
}
|
|
142
|
+
await this.store.setRemoteIdentities(identityUpdates);
|
|
143
|
+
}
|
|
144
|
+
const sessionUpdates = new Array(sessionUpdatesByAddress.size);
|
|
145
|
+
let sessionIndex = 0;
|
|
146
|
+
for (const update of sessionUpdatesByAddress.values()) {
|
|
147
|
+
sessionUpdates[sessionIndex] = update;
|
|
148
|
+
sessionIndex += 1;
|
|
149
|
+
}
|
|
150
|
+
await this.store.setSessionsBatch(sessionUpdates);
|
|
151
|
+
return results;
|
|
152
|
+
});
|
|
82
153
|
}
|
|
83
154
|
async decryptMessage(address, envelope) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
155
|
+
return this.runWithAddressLock(address, async () => {
|
|
156
|
+
const currentSession = await this.store.getSession(address);
|
|
157
|
+
let outcome;
|
|
158
|
+
if (envelope.type === 'pkmsg') {
|
|
159
|
+
const parsedPk = deserializePkMsg(envelope.ciphertext);
|
|
160
|
+
outcome = await this.decryptPkMsg(currentSession, parsedPk);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const parsed = deserializeMsg(envelope.ciphertext);
|
|
164
|
+
outcome = await decryptMsg(currentSession, parsed, (error, previousSessionIndex) => {
|
|
165
|
+
this.logger.debug('signal decrypt fallback session failed', {
|
|
166
|
+
previousSessionIndex,
|
|
167
|
+
message: error.message
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
const nextRemoteIdentity = outcome.newSessionInfo?.newIdentity ?? outcome.updatedSession.remote.pubKey;
|
|
172
|
+
const identityChanged = !currentSession || !uint8Equal(currentSession.remote.pubKey, nextRemoteIdentity);
|
|
173
|
+
// Keep writes ordered for consistency with resolver identity checks.
|
|
174
|
+
if (identityChanged) {
|
|
175
|
+
await this.store.setRemoteIdentity(address, nextRemoteIdentity);
|
|
176
|
+
}
|
|
177
|
+
await this.store.setSession(address, outcome.updatedSession);
|
|
178
|
+
return outcome.plaintext;
|
|
107
179
|
});
|
|
108
180
|
}
|
|
181
|
+
runWithAddressLock(address, task) {
|
|
182
|
+
return this.sessionMutationLock.run(signalAddressLockKey(address), task);
|
|
183
|
+
}
|
|
109
184
|
async decryptPkMsg(currentSession, parsed) {
|
|
110
185
|
const matchingSession = findMatchingSession(currentSession, parsed.sessionBaseKey);
|
|
111
186
|
if (matchingSession) {
|
|
@@ -141,6 +216,7 @@ export class SignalProtocol {
|
|
|
141
216
|
}
|
|
142
217
|
: incoming;
|
|
143
218
|
const [updatedSession, plaintext] = await decryptMsgFromSession(baseSession, parsed);
|
|
219
|
+
// Only consume one-time prekeys after successful decrypt/session materialization.
|
|
144
220
|
if (parsed.localOneTimeKeyId !== null && parsed.localOneTimeKeyId !== undefined) {
|
|
145
221
|
await this.store.consumePreKeyById(parsed.localOneTimeKeyId);
|
|
146
222
|
}
|
|
@@ -1,30 +1,41 @@
|
|
|
1
1
|
import { toSerializedPubKey } from '../../crypto/core/keys.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
|
|
3
|
+
import { normalizeDeviceJid, parseSignalAddressFromJid, signalAddressKey } from '../../protocol/jid.js';
|
|
4
|
+
import { bytesToHex, uint8Equal } from '../../util/bytes.js';
|
|
4
5
|
import { toError } from '../../util/primitives.js';
|
|
5
6
|
export function createSignalSessionResolver(options) {
|
|
6
7
|
const { signalProtocol, signalStore, signalIdentitySync, signalSessionSync, logger } = options;
|
|
7
|
-
const
|
|
8
|
+
const dedup = new PromiseDedup();
|
|
9
|
+
const ensureSessionInternal = async (address, jid, expectedIdentity, reasonIdentity = false, prefetchedBundle) => {
|
|
8
10
|
const expectedSerializedIdentity = expectedIdentity
|
|
9
11
|
? toSerializedPubKey(expectedIdentity)
|
|
10
12
|
: null;
|
|
11
13
|
if (reasonIdentity) {
|
|
12
14
|
await signalIdentitySync.syncIdentityKeys([jid]);
|
|
13
15
|
}
|
|
14
|
-
if (await
|
|
16
|
+
if (await signalStore.hasSession(address)) {
|
|
15
17
|
if (expectedSerializedIdentity) {
|
|
16
18
|
const storedIdentity = await signalStore.getRemoteIdentity(address);
|
|
17
19
|
if (!storedIdentity || !uint8Equal(storedIdentity, expectedSerializedIdentity)) {
|
|
18
20
|
throw new Error('identity mismatch');
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
|
-
return;
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
let fetched;
|
|
26
|
+
if (prefetchedBundle) {
|
|
27
|
+
fetched = {
|
|
28
|
+
jid,
|
|
29
|
+
bundle: prefetchedBundle
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
logger.info('signal session missing, fetching remote key bundle', { jid });
|
|
34
|
+
fetched = await signalSessionSync.fetchKeyBundle({
|
|
35
|
+
jid,
|
|
36
|
+
reasonIdentity
|
|
37
|
+
});
|
|
22
38
|
}
|
|
23
|
-
logger.info('signal session missing, fetching remote key bundle', { jid });
|
|
24
|
-
const fetched = await signalSessionSync.fetchKeyBundle({
|
|
25
|
-
jid,
|
|
26
|
-
reasonIdentity
|
|
27
|
-
});
|
|
28
39
|
const remoteIdentity = toSerializedPubKey(fetched.bundle.identity);
|
|
29
40
|
if (reasonIdentity) {
|
|
30
41
|
const storedIdentity = await signalStore.getRemoteIdentity(address);
|
|
@@ -35,35 +46,49 @@ export function createSignalSessionResolver(options) {
|
|
|
35
46
|
if (expectedSerializedIdentity && !uint8Equal(remoteIdentity, expectedSerializedIdentity)) {
|
|
36
47
|
throw new Error('identity mismatch');
|
|
37
48
|
}
|
|
38
|
-
await signalProtocol.establishOutgoingSession(address, fetched.bundle
|
|
49
|
+
const session = await signalProtocol.establishOutgoingSession(address, fetched.bundle, {
|
|
50
|
+
reuseExisting: true
|
|
51
|
+
});
|
|
39
52
|
logger.info('signal session synchronized', {
|
|
40
53
|
jid,
|
|
41
54
|
regId: fetched.bundle.regId,
|
|
42
55
|
hasOneTimeKey: fetched.bundle.oneTimeKey !== undefined
|
|
43
56
|
});
|
|
57
|
+
return session;
|
|
58
|
+
};
|
|
59
|
+
const ensureSessionWithDedup = (address, jid, expectedIdentity, reasonIdentity = false, prefetchedBundle) => {
|
|
60
|
+
const expectedIdentityKey = expectedIdentity ? bytesToHex(expectedIdentity) : 'none';
|
|
61
|
+
const dedupKey = `signalSession:${signalAddressKey(address)}:${reasonIdentity ? '1' : '0'}:${expectedIdentityKey}`;
|
|
62
|
+
return dedup.run(dedupKey, () => ensureSessionInternal(address, jid, expectedIdentity, reasonIdentity, prefetchedBundle));
|
|
44
63
|
};
|
|
64
|
+
const ensureSession = (address, jid, expectedIdentity, reasonIdentity = false) => ensureSessionWithDedup(address, jid, expectedIdentity, reasonIdentity).then(() => { });
|
|
45
65
|
const ensureSessionsBatch = async (targetJids, expectedIdentityByJid) => {
|
|
46
66
|
const seenTargetJids = new Set();
|
|
47
|
-
const normalizedTargetJids =
|
|
48
|
-
const normalizedTargetAddresses =
|
|
67
|
+
const normalizedTargetJids = new Array(targetJids.length);
|
|
68
|
+
const normalizedTargetAddresses = new Array(targetJids.length);
|
|
69
|
+
let normalizedTargetCount = 0;
|
|
49
70
|
for (let index = 0; index < targetJids.length; index += 1) {
|
|
50
71
|
const jid = normalizeDeviceJid(targetJids[index]);
|
|
51
72
|
if (seenTargetJids.has(jid)) {
|
|
52
73
|
continue;
|
|
53
74
|
}
|
|
54
75
|
seenTargetJids.add(jid);
|
|
55
|
-
normalizedTargetJids
|
|
56
|
-
normalizedTargetAddresses
|
|
76
|
+
normalizedTargetJids[normalizedTargetCount] = jid;
|
|
77
|
+
normalizedTargetAddresses[normalizedTargetCount] = parseSignalAddressFromJid(jid);
|
|
78
|
+
normalizedTargetCount += 1;
|
|
57
79
|
}
|
|
58
|
-
if (
|
|
59
|
-
return;
|
|
80
|
+
if (normalizedTargetCount === 0) {
|
|
81
|
+
return [];
|
|
60
82
|
}
|
|
83
|
+
normalizedTargetJids.length = normalizedTargetCount;
|
|
84
|
+
normalizedTargetAddresses.length = normalizedTargetCount;
|
|
61
85
|
const normalizedExpectedIdentityByJid = expectedIdentityByJid && expectedIdentityByJid.size > 0
|
|
62
86
|
? new Map()
|
|
63
87
|
: undefined;
|
|
64
88
|
if (normalizedExpectedIdentityByJid && expectedIdentityByJid) {
|
|
65
89
|
for (const [jid, identity] of expectedIdentityByJid.entries()) {
|
|
66
90
|
try {
|
|
91
|
+
toSerializedPubKey(identity);
|
|
67
92
|
normalizedExpectedIdentityByJid.set(normalizeDeviceJid(jid), identity);
|
|
68
93
|
}
|
|
69
94
|
catch (error) {
|
|
@@ -71,113 +96,123 @@ export function createSignalSessionResolver(options) {
|
|
|
71
96
|
}
|
|
72
97
|
}
|
|
73
98
|
}
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
99
|
+
const resolvedByIndex = (await signalStore.getSessionsBatch(normalizedTargetAddresses));
|
|
100
|
+
const collectResolvedTargets = () => {
|
|
101
|
+
const resolvedTargets = new Array(normalizedTargetJids.length);
|
|
102
|
+
let resolvedTargetCount = 0;
|
|
78
103
|
for (let index = 0; index < normalizedTargetJids.length; index += 1) {
|
|
79
|
-
|
|
104
|
+
const session = resolvedByIndex[index];
|
|
105
|
+
if (!session) {
|
|
80
106
|
continue;
|
|
81
107
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
108
|
+
resolvedTargets[resolvedTargetCount] = {
|
|
109
|
+
jid: normalizedTargetJids[index],
|
|
110
|
+
address: normalizedTargetAddresses[index],
|
|
111
|
+
session
|
|
112
|
+
};
|
|
113
|
+
resolvedTargetCount += 1;
|
|
88
114
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
115
|
+
resolvedTargets.length = resolvedTargetCount;
|
|
116
|
+
return resolvedTargets;
|
|
117
|
+
};
|
|
118
|
+
const missingIndices = [];
|
|
119
|
+
for (let index = 0; index < normalizedTargetJids.length; index += 1) {
|
|
120
|
+
const session = resolvedByIndex[index];
|
|
121
|
+
const expectedIdentity = normalizedExpectedIdentityByJid?.get(normalizedTargetJids[index]);
|
|
122
|
+
if (session && expectedIdentity) {
|
|
123
|
+
if (!uint8Equal(session.remote.pubKey, toSerializedPubKey(expectedIdentity))) {
|
|
94
124
|
throw new Error('identity mismatch');
|
|
95
125
|
}
|
|
96
126
|
}
|
|
97
|
-
|
|
98
|
-
const missingIndices = [];
|
|
99
|
-
for (let index = 0; index < normalizedTargetJids.length; index += 1) {
|
|
100
|
-
if (!hasSessions[index]) {
|
|
127
|
+
if (!session) {
|
|
101
128
|
missingIndices.push(index);
|
|
102
129
|
}
|
|
103
130
|
}
|
|
104
131
|
if (missingIndices.length === 0) {
|
|
105
|
-
return;
|
|
132
|
+
return collectResolvedTargets();
|
|
133
|
+
}
|
|
134
|
+
const batchRequest = new Array(missingIndices.length);
|
|
135
|
+
for (let index = 0; index < missingIndices.length; index += 1) {
|
|
136
|
+
batchRequest[index] = { jid: normalizedTargetJids[missingIndices[index]] };
|
|
106
137
|
}
|
|
138
|
+
let batchResults;
|
|
107
139
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
establishedIndices.push(targetIndex);
|
|
131
|
-
establishPromises.push(signalProtocol
|
|
132
|
-
.establishOutgoingSession(normalizedTargetAddresses[targetIndex], result.bundle)
|
|
133
|
-
.then(() => {
|
|
134
|
-
logger.debug('signal session synchronized from batch key fetch', {
|
|
135
|
-
jid: targetJid,
|
|
136
|
-
regId: result.bundle.regId,
|
|
137
|
-
hasOneTimeKey: result.bundle.oneTimeKey !== undefined
|
|
138
|
-
});
|
|
139
|
-
}));
|
|
140
|
+
batchResults = await signalSessionSync.fetchKeyBundles(batchRequest);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
logger.warn('signal batch key fetch failed', {
|
|
144
|
+
requested: missingIndices.length,
|
|
145
|
+
message: toError(error).message
|
|
146
|
+
});
|
|
147
|
+
return collectResolvedTargets();
|
|
148
|
+
}
|
|
149
|
+
const ensuredTargetIndices = new Array(missingIndices.length);
|
|
150
|
+
const ensurePromises = new Array(missingIndices.length);
|
|
151
|
+
let ensureCount = 0;
|
|
152
|
+
for (let index = 0; index < missingIndices.length; index += 1) {
|
|
153
|
+
const targetIndex = missingIndices[index];
|
|
154
|
+
const targetJid = normalizedTargetJids[targetIndex];
|
|
155
|
+
const batchResult = batchResults[index];
|
|
156
|
+
if (!batchResult?.bundle) {
|
|
157
|
+
logger.warn('signal batch key fetch returned target without bundle', {
|
|
158
|
+
jid: targetJid,
|
|
159
|
+
message: batchResult?.errorText ?? 'missing key bundle user in response'
|
|
160
|
+
});
|
|
161
|
+
continue;
|
|
140
162
|
}
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
163
|
+
const expectedIdentity = normalizedExpectedIdentityByJid?.get(targetJid);
|
|
164
|
+
ensuredTargetIndices[ensureCount] = targetIndex;
|
|
165
|
+
ensurePromises[ensureCount] = ensureSessionWithDedup(normalizedTargetAddresses[targetIndex], targetJid, expectedIdentity, false, batchResult.bundle);
|
|
166
|
+
ensureCount += 1;
|
|
167
|
+
}
|
|
168
|
+
if (ensureCount === 0) {
|
|
169
|
+
return collectResolvedTargets();
|
|
170
|
+
}
|
|
171
|
+
ensuredTargetIndices.length = ensureCount;
|
|
172
|
+
ensurePromises.length = ensureCount;
|
|
173
|
+
const ensureResults = await Promise.allSettled(ensurePromises);
|
|
174
|
+
const fallbackIndices = [];
|
|
175
|
+
for (let index = 0; index < ensuredTargetIndices.length; index += 1) {
|
|
176
|
+
const targetIndex = ensuredTargetIndices[index];
|
|
177
|
+
const ensureResult = ensureResults[index];
|
|
178
|
+
if (ensureResult.status === 'rejected') {
|
|
179
|
+
const normalized = toError(ensureResult.reason);
|
|
180
|
+
if (normalized.message === 'identity mismatch') {
|
|
181
|
+
throw normalized;
|
|
150
182
|
}
|
|
151
|
-
|
|
183
|
+
logger.warn('signal session ensure failed during batch resolution', {
|
|
184
|
+
jid: normalizedTargetJids[targetIndex],
|
|
185
|
+
message: normalized.message
|
|
186
|
+
});
|
|
187
|
+
continue;
|
|
152
188
|
}
|
|
153
|
-
|
|
154
|
-
|
|
189
|
+
const session = ensureResult.value;
|
|
190
|
+
if (session) {
|
|
191
|
+
resolvedByIndex[targetIndex] = session;
|
|
155
192
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
fallbackTargets: fallbackIndices.length
|
|
159
|
-
});
|
|
160
|
-
for (let index = 0; index < fallbackIndices.length; index += 1) {
|
|
161
|
-
const targetIndex = fallbackIndices[index];
|
|
162
|
-
const jid = normalizedTargetJids[targetIndex];
|
|
163
|
-
await ensureSession(normalizedTargetAddresses[targetIndex], jid, normalizedExpectedIdentityByJid?.get(jid));
|
|
193
|
+
else {
|
|
194
|
+
fallbackIndices.push(targetIndex);
|
|
164
195
|
}
|
|
165
196
|
}
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
197
|
+
if (fallbackIndices.length > 0) {
|
|
198
|
+
const fallbackAddresses = new Array(fallbackIndices.length);
|
|
199
|
+
for (let i = 0; i < fallbackIndices.length; i++) {
|
|
200
|
+
fallbackAddresses[i] = normalizedTargetAddresses[fallbackIndices[i]];
|
|
170
201
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
202
|
+
const fallbackSessions = await signalStore.getSessionsBatch(fallbackAddresses);
|
|
203
|
+
for (let i = 0; i < fallbackIndices.length; i++) {
|
|
204
|
+
const session = fallbackSessions[i];
|
|
205
|
+
if (session) {
|
|
206
|
+
resolvedByIndex[fallbackIndices[i]] = session;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
logger.warn('signal session ensure completed without persisted session', {
|
|
210
|
+
jid: normalizedTargetJids[fallbackIndices[i]]
|
|
211
|
+
});
|
|
212
|
+
}
|
|
179
213
|
}
|
|
180
214
|
}
|
|
215
|
+
return collectResolvedTargets();
|
|
181
216
|
};
|
|
182
217
|
return {
|
|
183
218
|
ensureSession,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|