GatewayCoordinator
in package
Handles all DAVE E2EE gateway protocol logic on behalf of the voice WebSocket.
This class owns every DAVE opcode handler and helper that was previously embedded in WS. WS keeps thin proxy methods so the opcode dispatch table remains unchanged; all real work happens here.
Tags
Table of Contents
Properties
Methods
- __construct() : mixed
- applySelfDaveEncryptor() : void
- Public to allow delegation from WS proxy methods and direct testing via reflection.
- extractProtocolVersion() : int
- Extracts the DAVE protocol version from a gateway payload data array.
- handleDaveExecuteTransition() : void
- Handles opcode 22 (VOICE_DAVE_EXECUTE_TRANSITION): promotes the pending `transition_id` so its staged protocol version becomes the active one.
- handleDaveMlsAnnounceCommitTransition() : void
- Handles opcode 29 (VOICE_DAVE_MLS_ANNOUNCE_COMMIT_TRANSITION): applies the announced commit and, unless it was ignored, prepares and completes the media transition. A failed commit triggers re-add with a fresh key package.
- handleDaveMlsCommitWelcome() : void
- Handles opcode 28 (VOICE_DAVE_MLS_COMMIT_WELCOME): processes the commit for the carried transition id (falling back to processing it as a welcome), then prepares and completes the media transition. On failure, requests re-add to the MLS group.
- handleDaveMlsExternalSender() : void
- Handles opcode 25 (VOICE_DAVE_MLS_EXTERNAL_SENDER_PACKAGE): stores the group's external-sender package, installs it on the live MLS session and (re)sends this client's key package. Non-binary payloads are ignored.
- handleDaveMlsInvalidCommitWelcome() : void
- Handles opcode 31 (VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME): recovers DAVE state after the gateway reports our commit/welcome was unprocessable by requesting re-add to the MLS group with a fresh key package.
- handleDaveMlsKeyPackage() : void
- Handle an inbound opcode 26 (VOICE_DAVE_MLS_KEY_PACKAGE) frame from the gateway.
- handleDaveMlsProposals() : void
- Handles opcode 27 (VOICE_DAVE_MLS_PROPOSALS): builds an MLS commit+welcome from the proposals payload and replies with opcode 28. Per spec, an unbuildable commit is not answered with INVALID_COMMIT_WELCOME; instead the consecutive-failure counter is bumped and the connection is dropped after three failures so a fresh DAVE epoch is obtained on reconnect.
- handleDaveMlsWelcome() : void
- Handles opcode 30 (VOICE_DAVE_MLS_WELCOME): joins the MLS group from the welcome for the carried transition id, then prepares and completes the media transition. Failure to join triggers re-add with a fresh key package.
- handleDavePrepareEpoch() : void
- Handles opcode 24 (VOICE_DAVE_PREPARE_EPOCH): records the MLS `epoch`, stages the transition and protocol version, and for a non-passthrough version initialises the DAVE runtime fail-closed (closing the connection on failure), sending the local key package when `epoch === 1`.
- handleDavePrepareTransition() : void
- Handles opcode 21 (VOICE_DAVE_PREPARE_TRANSITION): stages the move to `protocol_version` for `transition_id`, pre-creating remote decryptors, then readies the transition or (for id 0) executes it immediately.
- handleDaveTransitionReady() : void
- Handles opcode 23 (VOICE_DAVE_TRANSITION_READY): when it matches the pending transition, applies this client's own encryptor for the staged protocol version and marks the transition executed.
- handleInvalidDaveTransition() : void
- Public to allow delegation from WS proxy methods and direct testing via reflection.
- initializeDaveRuntimeState() : bool
- Ensures a DAVE MLS session and encryptor are ready for the given protocol version.
- prepareRemoteDaveDecryptor() : void
- Prepares a DAVE decryptor for a remote user.
- resolveDaveProtocolVersion() : int
- Clamps the offered protocol version to the maximum supported by this runtime.
- sendDaveKeyPackage() : void
- Sends the local MLS key package to the gateway.
- completeDaveMediaTransition() : void
- Finishes a prepared transition: id 0 is executed immediately with no gateway round-trip; any other id sends VOICE_DAVE_TRANSITION_READY and waits for the gateway to drive execution.
- executeDaveMediaTransition() : void
- Promotes the pending transition when `$transitionId` matches: for a non-positive protocol version it downgrades to passthrough and resets the session; otherwise it sets the session protocol version, applies this client's encryptor and marks the transition executed.
- prepareDaveMediaTransition() : void
- Records the pending transition and target protocol version, then pre-creates a decryptor for every recognised remote user so inbound media keeps decoding across the switch.
- sendDaveInvalidCommitWelcome() : void
- Sends VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME (opcode 31) with no payload.
- sendDaveTransitionReady() : void
- Sends VOICE_DAVE_TRANSITION_READY (opcode 23) for `$transitionId`.
Properties
$host read-only
private
GatewayCoordinatorHost
$host
Methods
__construct()
public
__construct(GatewayCoordinatorHost $host) : mixed
Parameters
- $host : GatewayCoordinatorHost
-
The voice WebSocket that owns this coordinator and exposes the DAVE state, logger and send primitives.
applySelfDaveEncryptor()
Public to allow delegation from WS proxy methods and direct testing via reflection.
public
applySelfDaveEncryptor(int $protocolVersion) : void
Parameters
- $protocolVersion : int
extractProtocolVersion()
Extracts the DAVE protocol version from a gateway payload data array.
public
extractProtocolVersion(array<string|int, mixed> $data) : int
Parameters
- $data : array<string|int, mixed>
Return values
inthandleDaveExecuteTransition()
Handles opcode 22 (VOICE_DAVE_EXECUTE_TRANSITION): promotes the pending `transition_id` so its staged protocol version becomes the active one.
public
handleDaveExecuteTransition(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveMlsAnnounceCommitTransition()
Handles opcode 29 (VOICE_DAVE_MLS_ANNOUNCE_COMMIT_TRANSITION): applies the announced commit and, unless it was ignored, prepares and completes the media transition. A failed commit triggers re-add with a fresh key package.
public
handleDaveMlsAnnounceCommitTransition(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveMlsCommitWelcome()
Handles opcode 28 (VOICE_DAVE_MLS_COMMIT_WELCOME): processes the commit for the carried transition id (falling back to processing it as a welcome), then prepares and completes the media transition. On failure, requests re-add to the MLS group.
public
handleDaveMlsCommitWelcome(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveMlsExternalSender()
Handles opcode 25 (VOICE_DAVE_MLS_EXTERNAL_SENDER_PACKAGE): stores the group's external-sender package, installs it on the live MLS session and (re)sends this client's key package. Non-binary payloads are ignored.
public
handleDaveMlsExternalSender(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveMlsInvalidCommitWelcome()
Handles opcode 31 (VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME): recovers DAVE state after the gateway reports our commit/welcome was unprocessable by requesting re-add to the MLS group with a fresh key package.
public
handleDaveMlsInvalidCommitWelcome(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveMlsKeyPackage()
Handle an inbound opcode 26 (VOICE_DAVE_MLS_KEY_PACKAGE) frame from the gateway.
public
handleDaveMlsKeyPackage(mixed $data) : void
Opcode 26 is primarily client→server: we send our own key package to the gateway via sendDaveKeyPackage() during the DAVE epoch-1 setup. The gateway may also forward a remote member's key package back to us as an informational notice — that is what this handler receives.
The gateway (server) is responsible for aggregating all key packages and driving the subsequent proposal/commit flow. We passively receive the forwarded package; no action is required on the client side.
Per the Discord DAVE spec: "Key packages are only used one time" — each time we need to join or rejoin a session we generate and send a fresh key package.
Parameters
- $data : mixed
handleDaveMlsProposals()
Handles opcode 27 (VOICE_DAVE_MLS_PROPOSALS): builds an MLS commit+welcome from the proposals payload and replies with opcode 28. Per spec, an unbuildable commit is not answered with INVALID_COMMIT_WELCOME; instead the consecutive-failure counter is bumped and the connection is dropped after three failures so a fresh DAVE epoch is obtained on reconnect.
public
handleDaveMlsProposals(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveMlsWelcome()
Handles opcode 30 (VOICE_DAVE_MLS_WELCOME): joins the MLS group from the welcome for the carried transition id, then prepares and completes the media transition. Failure to join triggers re-add with a fresh key package.
public
handleDaveMlsWelcome(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDavePrepareEpoch()
Handles opcode 24 (VOICE_DAVE_PREPARE_EPOCH): records the MLS `epoch`, stages the transition and protocol version, and for a non-passthrough version initialises the DAVE runtime fail-closed (closing the connection on failure), sending the local key package when `epoch === 1`.
public
handleDavePrepareEpoch(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDavePrepareTransition()
Handles opcode 21 (VOICE_DAVE_PREPARE_TRANSITION): stages the move to `protocol_version` for `transition_id`, pre-creating remote decryptors, then readies the transition or (for id 0) executes it immediately.
public
handleDavePrepareTransition(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleDaveTransitionReady()
Handles opcode 23 (VOICE_DAVE_TRANSITION_READY): when it matches the pending transition, applies this client's own encryptor for the staged protocol version and marks the transition executed.
public
handleDaveTransitionReady(BinaryFrame|Payload $data) : void
Parameters
- $data : BinaryFrame|Payload
handleInvalidDaveTransition()
Public to allow delegation from WS proxy methods and direct testing via reflection.
public
handleInvalidDaveTransition(int $transitionId[, bool $regenerateKeyPackage = false ]) : void
Parameters
- $transitionId : int
- $regenerateKeyPackage : bool = false
initializeDaveRuntimeState()
Ensures a DAVE MLS session and encryptor are ready for the given protocol version.
public
initializeDaveRuntimeState(int $protocolVersion[, bool $resetState = false ]) : bool
Returns true on success, false if initialization failed (caller should close the connection).
Parameters
- $protocolVersion : int
- $resetState : bool = false
Return values
boolprepareRemoteDaveDecryptor()
Prepares a DAVE decryptor for a remote user.
public
prepareRemoteDaveDecryptor(string $userId, int $protocolVersion) : void
Public to allow delegation from WS proxy methods and direct testing via reflection.
Parameters
- $userId : string
- $protocolVersion : int
resolveDaveProtocolVersion()
Clamps the offered protocol version to the maximum supported by this runtime.
public
resolveDaveProtocolVersion(int $protocolVersion) : int
Parameters
- $protocolVersion : int
Return values
intsendDaveKeyPackage()
Sends the local MLS key package to the gateway.
public
sendDaveKeyPackage() : void
completeDaveMediaTransition()
Finishes a prepared transition: id 0 is executed immediately with no gateway round-trip; any other id sends VOICE_DAVE_TRANSITION_READY and waits for the gateway to drive execution.
private
completeDaveMediaTransition(int $transitionId) : void
Parameters
- $transitionId : int
executeDaveMediaTransition()
Promotes the pending transition when `$transitionId` matches: for a non-positive protocol version it downgrades to passthrough and resets the session; otherwise it sets the session protocol version, applies this client's encryptor and marks the transition executed.
private
executeDaveMediaTransition(int $transitionId) : void
Parameters
- $transitionId : int
prepareDaveMediaTransition()
Records the pending transition and target protocol version, then pre-creates a decryptor for every recognised remote user so inbound media keeps decoding across the switch.
private
prepareDaveMediaTransition(int $transitionId, int $protocolVersion) : void
Parameters
- $transitionId : int
- $protocolVersion : int
sendDaveInvalidCommitWelcome()
Sends VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME (opcode 31) with no payload.
private
sendDaveInvalidCommitWelcome() : void
sendDaveTransitionReady()
Sends VOICE_DAVE_TRANSITION_READY (opcode 23) for `$transitionId`.
private
sendDaveTransitionReady(int $transitionId) : void
Parameters
- $transitionId : int