Skip to content

feat: libdave support#3222

Merged
quinchs merged 42 commits into
devfrom
voice/big-dave-support
Feb 22, 2026
Merged

feat: libdave support#3222
quinchs merged 42 commits into
devfrom
voice/big-dave-support

Conversation

@quinchs

@quinchs quinchs commented Jan 4, 2026

Copy link
Copy Markdown
Member

Summary

This PR adds libdave support into the audio client, as well as some small audio client refractors.

Remarks

A new project, Discord.Net.Dave was created in the tools/ folder that provides the low level bindings (libdave class) and some higher level wrappers around them (Dave, DaveSession, etc).

Since this is a low level binding, manual memory management is required, the current allocs/FFI boundaries should be investigated for any leaking memory.

Notice on breaking changes

This PR is implemented in a way to prevent breaking change, libdave e2ee support is gated behind a new configuration option EnableVoiceDaveEncryption within the socket config. The default value for the new configuration option is false, so users will have to opt-in to libdave support. This is up for discussion as Discord plans to require libdave e2ee by march.

I don't know how we want to distribute libdave along with dnet when it becomes required, do we bundle builds in with the WS project? I'm happy for feedback on this.


If you have an app with audio functionality, It'd be great if you can test this PR and report any bugs you find with it.

@github-actions

github-actions Bot commented Jan 4, 2026

Copy link
Copy Markdown

Test Results

  1 files  ±0    1 suites  ±0   0s ⏱️ ±0s
230 tests ±0  230 ✅ ±0  0 💤 ±0  0 ❌ ±0 
237 runs  ±0  237 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit e30831b. ± Comparison against base commit 4fdebdc.

♻️ This comment has been updated with latest results.

@quinchs quinchs marked this pull request as ready for review January 4, 2026 22:03
Comment thread docs/guides/voice/libdave.md Outdated
Comment thread src/Discord.Net.WebSocket/Audio/AudioClient.cs Outdated
Comment thread tools/Discord.Net.Dave/Dave.cs Outdated
Comment thread tools/Discord.Net.Dave/Utils.cs Outdated
@quinchs quinchs requested a review from Misha-133 January 5, 2026 00:51
@quinchs

quinchs commented Jan 5, 2026

Copy link
Copy Markdown
Member Author

It might be a good idea to expose either the DaveSession object on IAudioClient, or expose some method to get the verification code from the IAudioClient

Comment thread docs/guides/voice/libdave.md Outdated
Comment thread src/Discord.Net.WebSocket/Audio/DaveSessionManager.cs Outdated
@moiph

moiph commented Jan 10, 2026

Copy link
Copy Markdown
Contributor

Will test this out this weekend

Update: weekend arrived, so far successful testing. Flood of debug output from logs, about 50 per second of "Buffer under run".

Buffer under run
(D:\a\libdave\libdave\cpp\src\dave\frame_processors.cpp:191) Encrypted frame is too small to contain min supplemental bytes

Comment thread src/Discord.Net.WebSocket/Audio/Streams/DaveDecryptStream.cs
Comment thread src/Discord.Net.WebSocket/Audio/Streams/DaveEncryptStream.cs
Comment thread src/Discord.Net.WebSocket/Audio/AudioClient.cs Outdated
Comment thread src/Discord.Net.WebSocket/Audio/AudioClient.cs Outdated
Comment thread src/Discord.Net.WebSocket/Audio/AudioClient.cs Outdated
@quinchs quinchs requested a review from Misha-133 January 30, 2026 14:49
@brunoamancio

Copy link
Copy Markdown
Contributor

Hi, please take a look at the the PR I created to be merged into this branch: #3241

brunoamancio and others added 3 commits February 21, 2026 02:07
…t layer on early streams (#3241)

* Fix SelectProtocol sending local port instead of external port

The UDP discovery response from Discord contains the external IP and
port as seen by the voice server. SendSelectProtocol was passing
UdpPort (the local socket port) instead of the external port from
the discovery packet. Behind NAT, these differ, causing the voice
server to send audio to the wrong port.

Extract the external port from bytes 72-73 of the discovery response
and pass it to SendSelectProtocol alongside the external IP.

* Rebuild input streams after initial DAVE key exchange

When a user joins a voice channel, SocketGuild.RepopulateAudioStreamsAsync
fires StreamCreated before AudioClient.OnConnectingAsync initializes
the DaveSessionManager. This means input streams are created without
the DaveDecryptStream layer in the pipeline.

Once the MLS key exchange completes and the initial transition fires,
the encrypted audio reaches OpusDecodeStream directly — causing
InvalidPacket errors since the data is still DAVE-encrypted.

Add RebuildInputStreamsForDaveAsync to AudioClient which tears down
existing streams and recreates them with the DaveDecryptStream layer.
Call it from DaveSessionManager.PrepareProtocolTransitionAsync when
the initial transition (transitionId == InitTransitionId) completes.
@quinchs quinchs enabled auto-merge (squash) February 22, 2026 20:18
@quinchs quinchs merged commit 0195461 into dev Feb 22, 2026
5 checks passed
@quinchs quinchs deleted the voice/big-dave-support branch February 22, 2026 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants