Session
Manages a single MLS (Messaging Layer Security) session for Discord’s DAVE protocol.
A session handles the cryptographic group state shared between participants in a voice channel. Its responsibilities include:
- Initialising the MLS group for a given voice channel and protocol version
- Processing incoming MLS proposals, commits, and welcome messages
- Producing key packages that allow other participants to add this client to the group
- Deriving per-user key ratchets that feed into the Encryptor and Decryptor
- Computing pairwise identity fingerprints for out-of-band verification
In normal operation the Discord voice server acts as an external sender: it sends the
setExternalSender payload first, then relays proposal/commit/welcome messages between
participants. getMarshalledKeyPackage returns an empty buffer until setExternalSender
has been called and the session has a valid MLS leaf node.
Summary
Properties
Session.handle :: Sys.SessionHandleSession.mlsFailureClosure :: FFIPointerSession.mlsFailureCallbackRef :: { current: ((source: string, reason: string) -> ())? }Methods
Session:init(version: number, groupId: string, selfUserId: string)Session:reset()Session:setProtocolVersion(version: number)Session:getProtocolVersion() → numberSession:getLastEpochAuthenticator() → bufferSession:setExternalSender(data: buffer)Session:processProposals(proposals: buffer, recognizedUserIds: { string }) → buffer?Session:processCommit(commit: buffer) → CommitResult.CommitResultSession:processWelcome(welcome: buffer, recognizedUserIds: { string }) → WelcomeResult.WelcomeResult?Session:getMarshalledKeyPackage() → bufferSession:getKeyRatchet(userId: string) → KeyRatchet.KeyRatchetSession:getPairwiseFingerprint(version: number, userId: string) → string?Session:setMlsFailureCallback(callback: (source: string, reason: string) -> ())Session:destroy()Properties
Section titled “Properties”handle
Section titled “handle”mlsFailureClosure
Section titled “mlsFailureClosure”mlsFailureCallbackRef
Section titled “mlsFailureCallbackRef”Methods
Section titled “Methods”Session : init ( version , groupId , selfUserId ) -> ()
Initialises the MLS group state for the given protocol version, voice channel group ID,
and local user ID. Must be called before getMarshalledKeyPackage or any proposal/commit
processing. setExternalSender must also be called (with data from the voice server)
before the session can produce a valid key package.
Session : reset ( ) -> ()
Resets the session back to its uninitialised state, discarding all MLS group state.
The session must be re-initialised via init before it can be used again.
setProtocolVersion
Section titled “setProtocolVersion”Session : setProtocolVersion ( version ) -> ()
Overrides the protocol version in use without fully re-initialising the session. Used when the voice server signals a version upgrade mid-session.
Parameters
| version: number |
getProtocolVersion
Section titled “getProtocolVersion”Session : getProtocolVersion ( ) -> number
Returns the protocol version currently active on the session. Returns 0 if the
session has not yet been initialised.
Returns
| number |
getLastEpochAuthenticator
Section titled “getLastEpochAuthenticator”Session : getLastEpochAuthenticator ( ) -> buffer
Returns the authenticator bytes for the most recently committed MLS epoch. The authenticator uniquely identifies the current group state and can be compared across participants to detect tampering.
Returns an empty buffer before any commit has been processed.
Returns
| buffer |
setExternalSender
Section titled “setExternalSender”Session : setExternalSender ( data ) -> ()
Provides the external sender credential package received from the Discord voice server. This must be called before the session can produce a valid MLS key package.
Parameters
| data: buffer |
processProposals
Section titled “processProposals”Session : processProposals ( proposals , recognizedUserIds ) -> buffer?
Processes one or more serialised MLS proposal messages from other participants and produces a combined commit+welcome message to be relayed back through the voice server.
Returns nil when there is nothing to commit (e.g. the proposals were redundant).
recognizedUserIds should be the full set of user IDs currently known to be in the
channel.
Parameters
| proposals: buffer | |
| recognizedUserIds: { string } |
Returns
| buffer? |
processCommit
Section titled “processCommit”Session : processCommit ( commit ) -> CommitResult
Applies a serialised MLS commit message to advance the group epoch. Returns a
CommitResult describing the new roster state. Inspect CommitResult:isFailed() to
detect hard rejections and CommitResult:isIgnored() for soft rejections.
Parameters
| commit: buffer |
Returns
| CommitResult |
processWelcome
Section titled “processWelcome”Session : processWelcome ( welcome , recognizedUserIds ) -> WelcomeResult?
Processes an MLS welcome message to join an existing group as a new participant.
Returns a WelcomeResult containing the initial roster. recognizedUserIds should
list every user ID this client considers valid for this channel.
Parameters
| welcome: buffer | |
| recognizedUserIds: { string } |
Returns
| WelcomeResult? |
getMarshalledKeyPackage
Section titled “getMarshalledKeyPackage”Session : getMarshalledKeyPackage ( ) -> buffer
Returns the serialised MLS key package for this session, which other participants send as a proposal to add this client to the group.
Returns an empty buffer if the session does not yet have a valid leaf node (i.e.
setExternalSender has not been called yet).
Returns
| buffer |
getKeyRatchet
Section titled “getKeyRatchet”Session : getKeyRatchet ( userId ) -> KeyRatchet
Derives a KeyRatchet for the given user ID from the current MLS group state.
The ratchet is passed to an Encryptor or Decryptor to enable authenticated
encryption for that participant’s media stream.
Parameters
| userId: string |
Returns
| KeyRatchet |
getPairwiseFingerprint
Section titled “getPairwiseFingerprint”Session : getPairwiseFingerprint ( version , userId ) -> string?
Computes and returns the pairwise identity fingerprint between this client and
userId as a lowercase hex string. The fingerprint is derived from both parties’
MLS leaf credentials and can be compared out-of-band to verify there is no
man-in-the-middle.
The callback fires synchronously inside libdave.
setMlsFailureCallback
Section titled “setMlsFailureCallback”Session : setMlsFailureCallback ( callback ) -> ()
Replaces the MLS failure callback without re-creating the session. The new callback will be invoked for any subsequent MLS failures on this session.
Parameters
| callback: (source: string, reason: string) -> () |
destroy
Section titled “destroy”Session : destroy ( ) -> ()
Destroys the session and frees all associated libdave resources. The session must not be used after this call.
Functions
Section titled “Functions”Session . new ( authSessionId , onMlsFailure ) -> Session
Constructs a new DAVE session. authSessionId is an opaque string used by the
library to persist MLS signature keys across restarts. onMlsFailure is called
if the library encounters a hard MLS error; it can be replaced later via
setMlsFailureCallback.
Parameters
| authSessionId: string | |
| onMlsFailure: ((source: string, reason: string) -> ())? |
Returns
| Session |