Skip to content

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:

  1. Initialising the MLS group for a given voice channel and protocol version
  2. Processing incoming MLS proposals, commits, and welcome messages
  3. Producing key packages that allow other participants to add this client to the group
  4. Deriving per-user key ratchets that feed into the Encryptor and Decryptor
  5. 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.

Session.handle  :: SessionHandle
Session.mlsFailureClosure  :: FFIPointer
Session.mlsFailureCallbackRef  :: {
current: ((source,
reason: string) -> ())?,
}
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.

Parameters

version: number
groupId: string
selfUserId: string
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.

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
Session : getProtocolVersion ( )  -> number

Returns the protocol version currently active on the session. Returns 0 if the session has not yet been initialised.

Returns

number
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
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
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?
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
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?
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
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
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.

Parameters

version: number
userId: string

Returns

string?
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) -> ()
Session : destroy ( )  -> ()

Destroys the session and frees all associated libdave resources. The session must not be used after this call.

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