Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
22a38b5
create bindings project
quinchs Dec 24, 2025
1b8bc2c
adjust structure
quinchs Dec 24, 2025
b92647f
spite misha
quinchs Dec 24, 2025
c3f5368
integrate dave into audio client
quinchs Jan 4, 2026
04259d0
Merge branch 'dev' into voice/big-dave-support
quinchs Jan 4, 2026
a74fe2d
working send/receive audio with dave
quinchs Jan 4, 2026
a12830c
add doc section about libdave
quinchs Jan 4, 2026
0bf681c
make voice api model internal
quinchs Jan 4, 2026
18ac71e
add xml docs to new close codes
quinchs Jan 4, 2026
198b1dc
document new voice op codes
quinchs Jan 4, 2026
ff4e500
add xml docs to the libdave binding
quinchs Jan 4, 2026
0e2ce5f
fix docs samples
quinchs Jan 4, 2026
5ffe264
Update tools/Discord.Net.Dave/Utils.cs
quinchs Jan 5, 2026
b4dcb1a
cap. snake case -> pascal case for constants
quinchs Jan 5, 2026
ac130d0
switch to hard cast of JToken
quinchs Jan 5, 2026
39aee51
Merge branch 'voice/big-dave-support' of https://github.com/discord-n…
quinchs Jan 5, 2026
4b14b84
add PATH to libdave docs
quinchs Jan 5, 2026
f9b025d
ensure log sink isn't gc collected
quinchs Jan 5, 2026
124bb55
improve thread and memory safety
quinchs Jan 5, 2026
f59ce91
rename constant to pascal case
quinchs Jan 5, 2026
7114de9
remove 'CChar' alias
quinchs Jan 5, 2026
f906814
use ext. and add project imports
quinchs Jan 5, 2026
7bb8813
add dave to gh workflow
quinchs Jan 5, 2026
2a4365e
fix incorrect opcode for dave
quinchs Jan 5, 2026
1616b15
add logs for MLS failure
quinchs Jan 5, 2026
993e8e6
add docs to libdave binding
quinchs Jan 7, 2026
783c4fb
update to newer libdave api
quinchs Jan 7, 2026
4975dcb
update to latest libdave
quinchs Jan 19, 2026
8149248
update to latest libdave spec
quinchs Jan 30, 2026
e809b97
(mostly) working
quinchs Jan 30, 2026
2cb49bf
ok its fixed
quinchs Jan 30, 2026
2623e3d
update libdave docs
quinchs Jan 30, 2026
2d3a6fd
remove comments
quinchs Jan 30, 2026
52cb82f
ensure previous dave sessions are cleaned
quinchs Jan 30, 2026
274deb6
readd set speaking call
quinchs Jan 30, 2026
7b4deea
update log to be synchronous
quinchs Jan 30, 2026
ea05b45
grammar
quinchs Jan 30, 2026
e0e0b11
return rented array to pool
quinchs Jan 30, 2026
05e47d1
doc new streams and fix warning message
quinchs Jan 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ jobs:
dotnet pack "src\Discord.Net.Commands\Discord.Net.Commands.csproj" --no-restore --no-build -v minimal -c Release -o ${{ env.ArtifactStagingDirectory }} /p:BuildNumber=${{ env.Suffix }} /p:IsTagBuild=${{ env.IsTagBuild }}
dotnet pack "src\Discord.Net.Webhook\Discord.Net.Webhook.csproj" --no-restore --no-build -v minimal -c Release -o ${{ env.ArtifactStagingDirectory }} /p:BuildNumber=${{ env.Suffix }} /p:IsTagBuild=${{ env.IsTagBuild }}
dotnet pack "src\Discord.Net.Interactions\Discord.Net.Interactions.csproj" --no-restore --no-build -v minimal -c Release -o ${{ env.ArtifactStagingDirectory }} /p:BuildNumber=${{ env.Suffix }} /p:IsTagBuild=${{ env.IsTagBuild }}
dotnet pack "tools\Discord.Net.Dave\Discord.Net.Dave.csproj" --no-restore --no-build -v minimal -c Release -o ${{ env.ArtifactStagingDirectory }} /p:BuildNumber=${{ env.Suffix }} /p:IsTagBuild=${{ env.IsTagBuild }}
# dotnet pack "experiment\Discord.Net.BuildOverrides\Discord.Net.BuildOverrides.csproj" --no-restore --no-build -v minimal -c Release -o ${{ env.ArtifactStagingDirectory }} /p:BuildNumber=${{ env.Suffix }} /p:IsTagBuild=${{ env.IsTagBuild }}

- name: Publish Artifacts
Expand Down
19 changes: 18 additions & 1 deletion Discord.Net.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.31903.286
MinimumVisualStudioVersion = 10.0.40219.1
Expand Down Expand Up @@ -42,6 +42,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{BB59
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.BuildOverrides", "experiment\Discord.Net.BuildOverrides\Discord.Net.BuildOverrides.csproj", "{115F4921-B44D-4F69-996B-69796959C99D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Dave", "tools\Discord.Net.Dave\Discord.Net.Dave.csproj", "{A9198992-68A2-4DE0-A871-EB1A9768A47F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{5239E8F8-5B8B-48DF-BEA1-1C7745D25D08}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -244,6 +248,18 @@ Global
{115F4921-B44D-4F69-996B-69796959C99D}.Release|x64.Build.0 = Release|Any CPU
{115F4921-B44D-4F69-996B-69796959C99D}.Release|x86.ActiveCfg = Release|Any CPU
{115F4921-B44D-4F69-996B-69796959C99D}.Release|x86.Build.0 = Release|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Debug|x64.ActiveCfg = Debug|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Debug|x64.Build.0 = Debug|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Debug|x86.ActiveCfg = Debug|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Debug|x86.Build.0 = Debug|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Release|Any CPU.Build.0 = Release|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Release|x64.ActiveCfg = Release|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Release|x64.Build.0 = Release|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Release|x86.ActiveCfg = Release|Any CPU
{A9198992-68A2-4DE0-A871-EB1A9768A47F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -264,6 +280,7 @@ Global
{B61AAE66-15CC-40E4-873A-C23E697C3411} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{4A03840B-9EBE-47E3-89AB-E0914DF21AFB} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{115F4921-B44D-4F69-996B-69796959C99D} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}
{A9198992-68A2-4DE0-A871-EB1A9768A47F} = {5239E8F8-5B8B-48DF-BEA1-1C7745D25D08}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D2404771-EEC8-45F2-9D71-F3373F6C1495}
Expand Down
6 changes: 5 additions & 1 deletion docs/guides/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@
- name: Bearer Tokens
topicUid: Guides.BearerToken
- name: Voice
topicUid: Guides.Voice.SendingVoice
items:
- name: Connecting and Sending
topicUid: Guides.Voice.SendingVoice
- name: libdave Support
topicUid: Guides.Voice.LibDave
- name: Polls
topicUid: Guides.Polls
- name: Deployment
Expand Down
20 changes: 20 additions & 0 deletions docs/guides/voice/libdave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
uid: Guides.Voice.LibDave
title: Using libdave e2ee
---

# Setup

You'll need a build of Discord's [libdave](https://github.com/discord/libdave) library as either `libdave.dll`, `libdave.so` or `libdave.o` in your apps executing directory or `PATH`. The library will resolve `libdave` and start using it automatically.

## Force enable/disable

You can opt-in/opt-out of libdave with the following config option:

[!code-csharp[Opt-in to libdave](samples/libdave_config.cs)]

### libdave Log Sink

By default, `libdave` writes its logs to standard output, you can override that by specifying a custom log sink:

[!code-csharp[libdave sink](samples/libdave_sink.cs)]
5 changes: 5 additions & 0 deletions docs/guides/voice/samples/libdave_config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var client = new DiscordSocketClient(new DiscordSocketConfig()
{
EnableVoiceDaveEncryption = true,
...
});
12 changes: 12 additions & 0 deletions docs/guides/voice/samples/libdave_sink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Discord.LibDave.Dave.SetLogSink(MyLogSink);

void MyLogSink(
Discord.LibDave.LoggingSeverity severity,
string filePath,
int lineNumber,
string message
)
{
// do what you want with the logs
Console.WriteLine($"[{severity} | LIBDAVE @ {file}#{line}]: {message}");
}
9 changes: 9 additions & 0 deletions src/Discord.Net.WebSocket/API/Voice/ClientsConnect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Newtonsoft.Json;

namespace Discord.API.Voice;

internal class ClientsConnect
{
[JsonProperty("user_ids")]
public ulong[] UserIds { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Newtonsoft.Json;

namespace Discord.API.Voice;

internal class DaveMLSTransitionParams
{
[JsonProperty("transition_id")]
public ushort TransitionId { get; set; }
}
12 changes: 12 additions & 0 deletions src/Discord.Net.WebSocket/API/Voice/DavePrepareEpoch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace Discord.API.Voice;

internal class DavePrepareEpoch
{
[JsonProperty("protocol_version")]
public ushort ProtocolVersion { get; set; }

[JsonProperty("epoch")]
public ulong Epoch { get; set; }
}
12 changes: 12 additions & 0 deletions src/Discord.Net.WebSocket/API/Voice/DavePrepareTransition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace Discord.API.Voice;

internal class DavePrepareTransition
{
[JsonProperty("transition_id")]
public ushort TransitionId { get; set; }

[JsonProperty("protocol_version")]
public ushort ProtocolVersion { get; set; }
}
2 changes: 2 additions & 0 deletions src/Discord.Net.WebSocket/API/Voice/IdentifyParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ internal class IdentifyParams
public string SessionId { get; set; }
[JsonProperty("token")]
public string Token { get; set; }
[JsonProperty("max_dave_protocol_version")]
public Optional<ushort> MaxDaveProtocolVersion { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ internal class SessionDescriptionEvent
public byte[] SecretKey { get; set; }
[JsonProperty("mode")]
public string Mode { get; set; }
[JsonProperty("dave_protocol_version")]
public ushort DaveProtocolVersion { get; set; }
}
}
27 changes: 27 additions & 0 deletions src/Discord.Net.WebSocket/API/Voice/VoiceCloseCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,76 @@ public enum VoiceCloseCode
/// You sent an invalid opcode.
/// </summary>
UnknownOpcode = 4001,

/// <summary>
/// You sent an invalid payload in your identifying to the Gateway.
/// </summary>
DecodeFailure = 4002,

/// <summary>
/// You sent a payload before identifying with the Gateway.
/// </summary>
NotAuthenticated = 4003,

/// <summary>
/// The token you sent in your identify payload is incorrect.
/// </summary>
AuthenticationFailed = 4004,

/// <summary>
/// You sent more than one identify payload. Stahp.
/// </summary>
AlreadyAuthenticated = 4005,

/// <summary>
/// Your session is no longer valid.
/// </summary>
SessionNolongerValid = 4006,

/// <summary>
/// Your session has timed out.
/// </summary>
SessionTimeout = 4009,

/// <summary>
/// We can't find the server you're trying to connect to.
/// </summary>
ServerNotFound = 4011,

/// <summary>
/// We didn't recognize the protocol you sent.
/// </summary>
UnknownProtocol = 4012,

/// <summary>
/// Channel was deleted, you were kicked, voice server changed, or the main gateway session was dropped. Should not reconnect.
/// </summary>
Disconnected = 4014,

/// <summary>
/// The server crashed. Our bad! Try resuming.
/// </summary>
VoiceServerCrashed = 4015,

/// <summary>
/// We didn't recognize your encryption.
/// </summary>
UnknownEncryptionMode = 4016,

/// <summary>
/// You sent a malformed request.
/// </summary>
BadRequest = 4020,

/// <summary>
/// Disconnect due to rate limit exceeded. Should not reconnect.
/// </summary>
RateLimited = 4021,

/// <summary>
/// Disconnect all clients due to call terminated (channel deleted, voice server changed, etc.). Should not
/// reconnect.
/// </summary>
CallTerminated = 4022
}
}
52 changes: 52 additions & 0 deletions src/Discord.Net.WebSocket/API/Voice/VoiceOpCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,83 @@ internal enum VoiceOpCode : byte
{
/// <summary> C→S - Used to associate a connection with a token. </summary>
Identify = 0,

/// <summary> C→S - Used to specify configuration. </summary>
SelectProtocol = 1,

/// <summary> C←S - Used to notify that the voice connection was successful and informs the client of available protocols. </summary>
Ready = 2,

/// <summary> C→S - Used to keep the connection alive and measure latency. </summary>
Heartbeat = 3,

/// <summary> C←S - Used to provide an encryption key to the client. </summary>
SessionDescription = 4,

/// <summary> C↔S - Used to inform that a certain user is speaking. </summary>
Speaking = 5,

/// <summary> C←S - Used to reply to a client's heartbeat. </summary>
HeartbeatAck = 6,

/// <summary> C→S - Used to resume a connection. </summary>
Resume = 7,

/// <summary> C←S - Used to inform the client the heartbeat interval. </summary>
Hello = 8,

/// <summary> C←S - Used to acknowledge a resumed connection. </summary>
Resumed = 9,

/// <summary> C←S - One or more clients have connected to the voice channel. </summary>
ClientConnect = 11,

/// <summary> C←S - Used to notify that a client has disconnected. </summary>
ClientDisconnect = 13,

/// <summary> C←S - Contains the flags of a user that connected to voice, also sent on initial connection for each existing user. </summary>
ClientFlags = 18,

/// <summary> C←S - Contains the platform type of a user that connected to voice, also sent on initial connection for each existing user. </summary>
ClientPlatform = 20,

/// <summary> C←S - A downgrade from the DAVE protocol is upcoming.</summary>
DavePrepareTransition = 21,

/// <summary> C←S - Execute a previously announced protocol transition.</summary>
DaveExecuteTransition = 22,

/// <summary> C→S - Acknowledge readiness previously announced transition.</summary>
DaveTransitionReady = 23,

/// <summary> C←S - A DAVE protocol version or group change is upcoming.</summary>
DavePrepareEpoc = 24,

/// <summary> C←S - Credential and public key for MLS external sender.</summary>
/// <remarks>Binary message format only.</remarks>
DaveMLSExternalSender = 25,

/// <summary> C→S - MLS Key Package for pending group member.</summary>
/// <remarks>Binary message format only.</remarks>
DaveMLSKeyPackage = 26,

/// <summary> C←S - MLS Proposals to be appended or revoked.</summary>
/// <remarks>Binary message format only.</remarks>
DaveMLSProposals = 27,

/// <summary> C→S - MLS Commit with optional MLS Welcome messages.</summary>
/// <remarks>Binary message format only.</remarks>
DaveMLSCommitWelcome = 28,

/// <summary> C←S - MLS Commit to be processed for upcoming transition.</summary>
/// <remarks>Binary message format only.</remarks>
DaveAnnounceCommitTransaction = 29,

/// <summary> C←S - MLS Welcome to group for upcoming transition.</summary>
/// <remarks>Binary message format only.</remarks>
DaveMLSWelcome = 30,

/// <summary> C←S - Flag invalid commit or welcome, request re-add.</summary>
DaveMLSInvalidCommitWelcome = 31
}
}
Loading