* Fix race between stopping and starting the receive thread
When the last receive handler was removed, receiveThread was cleared
before the thread had stopped. A handler added in that window, e.g. by
a client reconnecting to the daemon in on-connection receive mode,
started a second receive thread. While the stop request for the old
thread was still set, each new thread ended immediately and started the
next one. When the old thread ended, it cleared the reference to the
newer thread and started yet another one, leaving two receive loops on
the same websocket. The unreferenced loop was never stopped and kept
receiving and acknowledging messages after all clients had gone.
Keep receiveThread set until the receive thread has finished and only
let the thread itself clear it. Its end block already starts a new
receive thread if handlers were added in the meantime. Clear a stop
request right before a new receive loop is started instead of when a
loop ends, so it can neither be cleared by another loop nor stop a
later one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add test for adding a receive handler while the receive thread stops
The receive loop is replaced by a fake one that can be held while it
stops, so the test doesn't connect to the server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: iddo <917594+iddo@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Fix voice calls from linked devices
(cherry picked from commit f3e22de14e4463adb785fb797791bc826b765a10)
* Verify primary and linked call configuration through account state
---------
Co-authored-by: Daniel <dan@gainengineering.com.au>
Each event of /api/v1/events now has an id. The last 1000 events are
kept in memory, and a client that reconnects with a Last-Event-ID header
first gets the events it missed. The keep-alive interval can be set with
the new daemon option --sse-keepalive-interval.
Closes#2132
Co-authored-by: Romain Boulay <169323+RomainBoulay@users.noreply.github.com>
* Support linking phone-numberless Signal accounts
* Align numberless account support with project style
* Support numberless accounts over D-Bus
* Keep superseded accounts out of numberless account discovery
Record numberless accounts explicitly instead of treating every retained ACI
as a discoverable account. Resolve older index entries against saved account
state, preserving ACI lookup and retrying unavailable state on later reads.
The optional index field remains compatible with version 2 readers. Update
native-image reflection metadata and cover replacement, legacy migration,
locked and missing state, and mismatched ACIs in regression tests.
* Address numberless linking review cleanup
Reuse AccountApiV2 through SignalDependencies and use the shared suspend response helper while preserving linking error handling. Remove the unused account-number accessor and unsupported D-Bus version fallback. Keep numberless linking documentation in the man page and point the README to the wiki.
Validate linking errors through HTTP response fixtures. All 196 tests pass on JDK 25 with an isolated D-Bus session; build and JSON schema generation also pass. Account-index classification is unchanged pending review discussion.
* Accept caller-supplied attachment dimensions
Forward positional WIDTHxHEIGHT metadata supplied by the caller. Validate dimensions before sending and retain automatic image detection for omitted entries.
* Accept caller-supplied attachment BlurHashes
Forward positional BlurHashes supplied by the caller alongside attachment dimensions. Reject BlurHashes whose length doesn't match their size digit.
* Skip image probing when dimensions are supplied
Caller-supplied dimensions replace the probed values, so don't buffer and decode the image to measure it.
* Show and enforce the terminated state of a group
A group admin can permanently terminate a group. Afterwards the group is
read-only for everyone, not even an admin can send messages or start calls;
members keep access to the existing history. Other clients silently drop
messages sent to a terminated group.
Read the DecryptedGroup.terminated flag through GroupInfo.isTerminated() and:
- surface it in listGroups (json and plain text) and as the DBus IsTerminated
group property
- refuse to send to a terminated group locally (messages, reactions, typing and
group stories) rather than send one that other clients ignore
- drop incoming messages addressed to a terminated group
* Add terminateGroup command to terminate a group for everyone
Let a group admin permanently terminate a GroupV2 group via the
TerminateGroupAction (Groups.proto field 28, change epoch 7) the pinned library
already exposes as GroupsV2Operations.createTerminateGroup().
- GroupV2Helper.terminateGroup builds and commits the change
- GroupHelper.terminateGroup resolves/refreshes the group (v2 only), sends the
update to members and syncs storage, with the same conflict-retry as
updateGroup
- exposed through Manager.terminateGroup, the terminateGroup CLI/JSON-RPC command
and the DBus Group.terminateGroup method
---------
Co-authored-by: FailSpy <FailSpy@users.noreply.github.com>