WS
in package
implements
GatewayCoordinatorHost
uses
HandlesDaveOpcodes
Handles the Discord voice WebSocket connection.
This class manages the WebSocket connection to the Discord voice gateway, handling events, sending messages, and managing the voice connection state.
Tags
Table of Contents
Interfaces
- GatewayCoordinatorHost
- Narrow interface exposing WS capabilities required by GatewayCoordinator.
Constants
- MAX_DAVE_PROTOCOL_VERSION : mixed = 1
- The maximum DAVE protocol version supported.
- VOICE_OP_HANDLERS : array<int, string> = [\Discord\WebSockets\Op::VOICE_READY => 'handle...
- Dispatch table mapping Discord Voice Gateway opcodes to handler methods.
Properties
- $data : array<string|int, mixed>|null
- $mode : string
- The Voice WebSocket mode.
- $ssrc : null|string|int
- The SSRC identifier for the voice connection client.
- $vc : Client
- $daveState : State
- DAVE protocol state for this voice connection.
- $discord : Discord|null
- $hbInterval : mixed
- The heartbeat interval for the voice connection.
- $hbSequence : int
- The heartbeat sequence number.
- $heartbeat : TimerInterface
- The heartbeat timer for the voice connection.
- $maxDaveProtocolVersion : int
- Maximum supported DAVE protocol version for this runtime.
- $rawKey : array<string|int, mixed>|null
- The raw secret key.
- $secretKey : string|null
- The secret key used for encrypting voice.
- $socket : WebSocket
- The WebSocket instance for the voice connection.
- $udpfac : SocketFactory
- The SocketFactory instance for creating UDP sockets.
- $version : mixed
- The Discord voice gateway version.
- $coordinator : GatewayCoordinator|null
- The DAVE gateway coordinator for this voice connection.
- $sentLoginFrame : bool
- Indicates whether the login frame has been sent.
Methods
- __construct() : mixed
- The WebSocket connection for the voice client.
- __debugInfo() : array<string|int, mixed>
- Redacts sensitive cryptographic material from debug output.
- closeConnection() : void
- Closes the underlying WebSocket connection.
- getDaveProtocolVersion() : int
- The active DAVE protocol version for this connection.
- getDaveState() : State
- The per-connection {@see DaveState}.
- getLogger() : LoggerInterface
- Returns the PSR-3 logger for this voice connection.
- getMaxDaveProtocolVersion() : int
- Returns the maximum DAVE protocol version supported at runtime.
- getVoiceClient() : VoiceClient
- Returns the VoiceClient associated with this connection.
- handleAny() : void
- Handles the any event from the voice server.
- handleClose() : void
- Handles the close event of the WebSocket connection.
- handleCloseVoiceDisconnected() : void
- Handles a VOICE_DISCONNECTED close opcode (logs it; the reconnect path is driven elsewhere).
- handleConnection() : void
- Handles a WebSocket connection.
- handleHeartbeatAck() : void
- Handles the heartbeat acknowledgement from the voice WebSocket connection.
- handleSendingOfLoginFrame() : void
- Handles sending the login frame to the voice WebSocket.
- make() : WS
- Creates a new instance of the WS class.
- send() : void
- Sends a message to the voice websocket.
- sendDaveBinary() : void
- Sends a DAVE binary payload over the voice websocket.
- sendHeartbeat() : void
- Sends a heartbeat to the voice WebSocket.
- handleBinaryVoiceMessage() : void
- Handles binary voice websocket frames.
- handleClientConnect() : void
- Handles the event when a client connects to the voice server.
- handleClientDisconnect() : void
- Handles the event when a client disconnects from the voice server.
- handleDaveExecuteTransition() : void
- Routes the VOICE_DAVE_EXECUTE_TRANSITION opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveExecuteTransition()}.
- handleDaveMlsAnnounceCommitTransition() : void
- Routes the VOICE_DAVE_MLS_ANNOUNCE_COMMIT_TRANSITION opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsAnnounceCommitTransition()}.
- handleDaveMlsCommitWelcome() : void
- Routes the VOICE_DAVE_MLS_COMMIT_WELCOME opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsCommitWelcome()}.
- handleDaveMlsExternalSender() : void
- Routes the VOICE_DAVE_MLS_EXTERNAL_SENDER_PACKAGE opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsExternalSender()}.
- handleDaveMlsInvalidCommitWelcome() : void
- Routes the VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsInvalidCommitWelcome()}.
- handleDaveMlsKeyPackage() : void
- Handle an inbound opcode 26 (VOICE_DAVE_MLS_KEY_PACKAGE) frame from the gateway.
- handleDaveMlsProposals() : void
- Routes the VOICE_DAVE_MLS_PROPOSALS opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsProposals()}.
- handleDaveMlsWelcome() : void
- Routes the VOICE_DAVE_MLS_WELCOME opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsWelcome()}.
- handleDavePrepareEpoch() : void
- Routes the VOICE_DAVE_PREPARE_EPOCH opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDavePrepareEpoch()}.
- handleDavePrepareTransition() : void
- Routes the VOICE_DAVE_PREPARE_TRANSITION opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDavePrepareTransition()}.
- handleDaveTransitionReady() : void
- Routes the VOICE_DAVE_TRANSITION_READY opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveTransitionReady()}.
- handleFlags() : void
- Handles the flags event from the voice server.
- handleHello() : void
- Handles the "Hello" event from the Discord voice server.
- handlePlatform() : void
- Handles the platform event from the voice server.
- handleReady() : void
- Handles the "ready" event for the voice client, initializing UDP connection and heartbeat.
- handleResume() : void
- Resumes a previously established voice connection.
- handleResumed() : void
- Handles the 'resumed' event for the voice client.
- handleSessionDescription() : void
- Handles the session description packet received from the Discord voice server.
- handleSpeaking() : void
- Handles the speaking state of a user.
- handleUndocumented() : void
- Handles undocumented voice opcodes not intended for use by bots.
- extractProtocolVersion() : int
- getCoordinator() : GatewayCoordinator
- Returns the GatewayCoordinator, creating it lazily if needed.
- initializeDaveRuntimeState() : bool
- Delegates to {@see \Discord\Voice\Dave\GatewayCoordinator::initializeDaveRuntimeState()}.
- recordGatewaySequence() : void
- Records the last gateway sequence in the DAVE state and mirrors it into `$this->data['seq']` for resume.
- resolveDaveGroupId() : int|string|null
- The MLS group id for this connection: the channel id, falling back to the guild id.
- resolveDaveProtocolVersion() : int
- Delegates to {@see \Discord\Voice\Dave\GatewayCoordinator::resolveDaveProtocolVersion()}.
- sendDaveKeyPackage() : void
- Delegates to {@see \Discord\Voice\Dave\GatewayCoordinator::sendDaveKeyPackage()}.
Constants
MAX_DAVE_PROTOCOL_VERSION
The maximum DAVE protocol version supported.
public
mixed
MAX_DAVE_PROTOCOL_VERSION
= 1
VOICE_OP_HANDLERS
Dispatch table mapping Discord Voice Gateway opcodes to handler methods.
public
array<int, string>
VOICE_OP_HANDLERS
= [\Discord\WebSockets\Op::VOICE_READY => 'handleReady', \Discord\WebSockets\Op::VOICE_SESSION_DESCRIPTION => 'handleSessionDescription', \Discord\WebSockets\Op::VOICE_SPEAKING => 'handleSpeaking', \Discord\WebSockets\Op::VOICE_HEARTBEAT_ACK => 'handleHeartbeatAck', \Discord\WebSockets\Op::VOICE_HELLO => 'handleHello', \Discord\WebSockets\Op::VOICE_RESUMED => 'handleResumed', \Discord\WebSockets\Op::VOICE_CLIENT_CONNECT => 'handleClientConnect', \Discord\WebSockets\Op::VOICE_CLIENT_DISCONNECT => 'handleClientDisconnect', \Discord\WebSockets\Op::VOICE_CLIENT_UNKNOWN_15 => 'handleAny', \Discord\WebSockets\Op::VOICE_CLIENT_UNKNOWN_18 => 'handleFlags', \Discord\WebSockets\Op::VOICE_CLIENT_PLATFORM => 'handlePlatform', \Discord\WebSockets\Op::VOICE_DAVE_PREPARE_TRANSITION => 'handleDavePrepareTransition', \Discord\WebSockets\Op::VOICE_DAVE_EXECUTE_TRANSITION => 'handleDaveExecuteTransition', \Discord\WebSockets\Op::VOICE_DAVE_PREPARE_EPOCH => 'handleDavePrepareEpoch', \Discord\WebSockets\Op::VOICE_DAVE_MLS_EXTERNAL_SENDER => 'handleDaveMlsExternalSender', \Discord\WebSockets\Op::VOICE_DAVE_MLS_PROPOSALS => 'handleDaveMlsProposals', \Discord\WebSockets\Op::VOICE_DAVE_MLS_ANNOUNCE_COMMIT_TRANSITION => 'handleDaveMlsAnnounceCommitTransition', \Discord\WebSockets\Op::VOICE_DAVE_MLS_WELCOME => 'handleDaveMlsWelcome', \Discord\WebSockets\Op::VOICE_DAVE_TRANSITION_READY => 'handleDaveTransitionReady', \Discord\WebSockets\Op::VOICE_DAVE_MLS_KEY_PACKAGE => 'handleDaveMlsKeyPackage', \Discord\WebSockets\Op::VOICE_DAVE_MLS_COMMIT_WELCOME => 'handleDaveMlsCommitWelcome', \Discord\WebSockets\Op::VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME => 'handleDaveMlsInvalidCommitWelcome', \Discord\WebSockets\Op::CLOSE_VOICE_DISCONNECTED => 'handleCloseVoiceDisconnected']
Method name indexed by opcode constant.
Properties
$data
public
array<string|int, mixed>|null
$data
= []
$mode
The Voice WebSocket mode.
public
string
$mode
= 'aead_aes256_gcm_rtpsize'
Negotiated from the modes offered in Ready (op 2) and confirmed by the session description (op 4); see EncryptionMode::negotiate().
Tags
$ssrc
The SSRC identifier for the voice connection client.
public
null|string|int
$ssrc
$vc
public
Client
$vc
$daveState
DAVE protocol state for this voice connection.
protected
State
$daveState
$discord
protected
Discord|null
$discord
= null
$hbInterval
The heartbeat interval for the voice connection.
protected
mixed
$hbInterval
$hbSequence
The heartbeat sequence number.
protected
int
$hbSequence
= 0
This is used to track the sequence of heartbeat messages sent to the voice gateway.
$heartbeat
The heartbeat timer for the voice connection.
protected
TimerInterface
$heartbeat
$maxDaveProtocolVersion
Maximum supported DAVE protocol version for this runtime.
protected
int
$maxDaveProtocolVersion
= self::MAX_DAVE_PROTOCOL_VERSION
$rawKey
The raw secret key.
protected
array<string|int, mixed>|null
$rawKey
$secretKey
The secret key used for encrypting voice.
protected
string|null
$secretKey
$socket
The WebSocket instance for the voice connection.
protected
WebSocket
$socket
$udpfac
The SocketFactory instance for creating UDP sockets.
protected
SocketFactory
$udpfac
$version
The Discord voice gateway version.
protected
static mixed
$version
= 8
Tags
$coordinator
The DAVE gateway coordinator for this voice connection.
private
GatewayCoordinator|null
$coordinator
= null
$sentLoginFrame
Indicates whether the login frame has been sent.
private
bool
$sentLoginFrame
= false
Methods
__construct()
The WebSocket connection for the voice client.
public
__construct(Client $vc[, Discord|null $discord = null ][, array<string|int, mixed>|null $data = [] ]) : mixed
This is used to send and receive messages over the WebSocket connection.
Parameters
- $vc : Client
- $discord : Discord|null = null
- $data : array<string|int, mixed>|null = []
__debugInfo()
Redacts sensitive cryptographic material from debug output.
public
__debugInfo() : array<string|int, mixed>
Return values
array<string|int, mixed>closeConnection()
Closes the underlying WebSocket connection.
public
closeConnection() : void
getDaveProtocolVersion()
The active DAVE protocol version for this connection.
public
getDaveProtocolVersion() : int
Return values
intgetDaveState()
The per-connection {@see DaveState}.
public
getDaveState() : State
Return values
StategetLogger()
Returns the PSR-3 logger for this voice connection.
public
getLogger() : LoggerInterface
Return values
LoggerInterfacegetMaxDaveProtocolVersion()
Returns the maximum DAVE protocol version supported at runtime.
public
getMaxDaveProtocolVersion() : int
Return values
intgetVoiceClient()
Returns the VoiceClient associated with this connection.
public
getVoiceClient() : VoiceClient
Return values
VoiceClienthandleAny()
Handles the any event from the voice server.
public
handleAny(Payload $data) : void
Parameters
- $data : Payload
handleClose()
Handles the close event of the WebSocket connection.
public
handleClose(int $op, string $reason) : void
Parameters
- $op : int
-
The opcode of the close event.
- $reason : string
-
The reason for closing the connection.
handleCloseVoiceDisconnected()
Handles a VOICE_DISCONNECTED close opcode (logs it; the reconnect path is driven elsewhere).
public
handleCloseVoiceDisconnected(Payload $data) : void
Parameters
- $data : Payload
handleConnection()
Handles a WebSocket connection.
public
handleConnection(WebSocket $ws) : void
Parameters
- $ws : WebSocket
handleHeartbeatAck()
Handles the heartbeat acknowledgement from the voice WebSocket connection.
public
handleHeartbeatAck(Payload $data) : void
Parameters
- $data : Payload
handleSendingOfLoginFrame()
Handles sending the login frame to the voice WebSocket.
public
handleSendingOfLoginFrame() : void
This method sends the initial identification payload to the voice gateway to establish the voice connection.
Tags
make()
Creates a new instance of the WS class.
public
static make(Client $vc[, null|Discord $discord = null ][, null|array<string|int, mixed> $data = null ]) : WS
Parameters
- $vc : Client
- $discord : null|Discord = null
- $data : null|array<string|int, mixed> = null
Return values
WSsend()
Sends a message to the voice websocket.
public
send(VoicePayload|array<string|int, mixed> $data) : void
Parameters
- $data : VoicePayload|array<string|int, mixed>
sendDaveBinary()
Sends a DAVE binary payload over the voice websocket.
public
sendDaveBinary(int $opcode[, string $payload = '' ]) : void
Parameters
- $opcode : int
- $payload : string = ''
sendHeartbeat()
Sends a heartbeat to the voice WebSocket.
public
sendHeartbeat() : void
handleBinaryVoiceMessage()
Handles binary voice websocket frames.
protected
handleBinaryVoiceMessage(string $payload) : void
Parameters
- $payload : string
handleClientConnect()
Handles the event when a client connects to the voice server.
protected
handleClientConnect(Payload $data) : void
Parameters
- $data : Payload
handleClientDisconnect()
Handles the event when a client disconnects from the voice server.
protected
handleClientDisconnect(Payload $data) : void
Parameters
- $data : Payload
handleDaveExecuteTransition()
Routes the VOICE_DAVE_EXECUTE_TRANSITION opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveExecuteTransition()}.
protected
handleDaveExecuteTransition(Payload $data) : void
Parameters
- $data : Payload
handleDaveMlsAnnounceCommitTransition()
Routes the VOICE_DAVE_MLS_ANNOUNCE_COMMIT_TRANSITION opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsAnnounceCommitTransition()}.
protected
handleDaveMlsAnnounceCommitTransition(Payload $data) : void
Parameters
- $data : Payload
handleDaveMlsCommitWelcome()
Routes the VOICE_DAVE_MLS_COMMIT_WELCOME opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsCommitWelcome()}.
protected
handleDaveMlsCommitWelcome(Payload $data) : void
Parameters
- $data : Payload
handleDaveMlsExternalSender()
Routes the VOICE_DAVE_MLS_EXTERNAL_SENDER_PACKAGE opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsExternalSender()}.
protected
handleDaveMlsExternalSender(Payload $data) : void
Parameters
- $data : Payload
handleDaveMlsInvalidCommitWelcome()
Routes the VOICE_DAVE_MLS_INVALID_COMMIT_WELCOME opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsInvalidCommitWelcome()}.
protected
handleDaveMlsInvalidCommitWelcome(Payload $data) : void
Parameters
- $data : Payload
handleDaveMlsKeyPackage()
Handle an inbound opcode 26 (VOICE_DAVE_MLS_KEY_PACKAGE) frame from the gateway.
protected
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()
Routes the VOICE_DAVE_MLS_PROPOSALS opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsProposals()}.
protected
handleDaveMlsProposals(Payload $data) : void
Parameters
- $data : Payload
handleDaveMlsWelcome()
Routes the VOICE_DAVE_MLS_WELCOME opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveMlsWelcome()}.
protected
handleDaveMlsWelcome(Payload $data) : void
Parameters
- $data : Payload
handleDavePrepareEpoch()
Routes the VOICE_DAVE_PREPARE_EPOCH opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDavePrepareEpoch()}.
protected
handleDavePrepareEpoch(Payload $data) : void
Parameters
- $data : Payload
handleDavePrepareTransition()
Routes the VOICE_DAVE_PREPARE_TRANSITION opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDavePrepareTransition()}.
protected
handleDavePrepareTransition(Payload $data) : void
Parameters
- $data : Payload
handleDaveTransitionReady()
Routes the VOICE_DAVE_TRANSITION_READY opcode to the {@see \Discord\Voice\Dave\GatewayCoordinator::handleDaveTransitionReady()}.
protected
handleDaveTransitionReady(Payload $data) : void
Parameters
- $data : Payload
handleFlags()
Handles the flags event from the voice server.
protected
handleFlags(Payload $data) : void
Parameters
- $data : Payload
handleHello()
Handles the "Hello" event from the Discord voice server.
protected
handleHello(Payload $data) : void
Parameters
- $data : Payload
handlePlatform()
Handles the platform event from the voice server.
protected
handlePlatform(Payload $data) : void
Parameters
- $data : Payload
handleReady()
Handles the "ready" event for the voice client, initializing UDP connection and heartbeat.
protected
handleReady(Payload $data) : void
Parameters
- $data : Payload
-
The data object containing voice server connection details:
- $data->d['ssrc']: The synchronization source identifier.
- $data->d['ip']: The IP address for the UDP connection.
- $data->d['port']: The port for the UDP connection.
- $data->d['modes']: Supported encryption modes.
handleResume()
Resumes a previously established voice connection.
protected
handleResume() : void
handleResumed()
Handles the 'resumed' event for the voice client.
protected
handleResumed(Payload $data) : void
Parameters
- $data : Payload
handleSessionDescription()
Handles the session description packet received from the Discord voice server.
protected
handleSessionDescription(Payload $data) : void
Parameters
- $data : Payload
handleSpeaking()
Handles the speaking state of a user.
protected
handleSpeaking(Payload $data) : void
Parameters
- $data : Payload
-
The data object received from the WebSocket.
handleUndocumented()
Handles undocumented voice opcodes not intended for use by bots.
protected
handleUndocumented(Payload $data) : void
Parameters
- $data : Payload
extractProtocolVersion()
private
extractProtocolVersion(array<string|int, mixed> $data) : int
Parameters
- $data : array<string|int, mixed>
Return values
intgetCoordinator()
Returns the GatewayCoordinator, creating it lazily if needed.
private
getCoordinator() : GatewayCoordinator
Lazy initialisation allows tests that bypass the constructor to still exercise DAVE methods without explicitly injecting the coordinator.
Return values
GatewayCoordinatorinitializeDaveRuntimeState()
Delegates to {@see \Discord\Voice\Dave\GatewayCoordinator::initializeDaveRuntimeState()}.
private
initializeDaveRuntimeState(int $protocolVersion[, bool $resetState = false ]) : bool
Parameters
- $protocolVersion : int
- $resetState : bool = false
Return values
boolrecordGatewaySequence()
Records the last gateway sequence in the DAVE state and mirrors it into `$this->data['seq']` for resume.
private
recordGatewaySequence(int|null $sequence) : void
Parameters
- $sequence : int|null
resolveDaveGroupId()
The MLS group id for this connection: the channel id, falling back to the guild id.
private
resolveDaveGroupId() : int|string|null
Return values
int|string|nullresolveDaveProtocolVersion()
Delegates to {@see \Discord\Voice\Dave\GatewayCoordinator::resolveDaveProtocolVersion()}.
private
resolveDaveProtocolVersion(int $protocolVersion) : int
Parameters
- $protocolVersion : int
Return values
intsendDaveKeyPackage()
Delegates to {@see \Discord\Voice\Dave\GatewayCoordinator::sendDaveKeyPackage()}.
private
sendDaveKeyPackage() : void