-
Notifications
You must be signed in to change notification settings - Fork 8
Audio and voice client support #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
FiniteReality
wants to merge
7
commits into
discord-net:master
Choose a base branch
from
FiniteReality:feature/audio
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
078e2f0
Add Audio project
FiniteReality fdf4283
Primitive implementation
FiniteReality 3000445
Attempt to implement voice send
FiniteReality 66ae68d
Small clean-up
FiniteReality 280f2a2
Fix formatting errors and remove unsafe code
FiniteReality 4842541
Remove incorrect assumption in WumpusAudioDataClient
FiniteReality 9bee8ba
Use newer Roslyn to fix some compilation issues
FiniteReality File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Events | ||
{ | ||
public class VoiceHelloEvent | ||
{ | ||
// Given as float because discord returns json of the form | ||
// {"op":8,"d":{"v":4,"heartbeat_interval":13750.0}} | ||
[ModelProperty("heartbeat_interval")] | ||
public float HeartbeatInterval { get; set; } | ||
|
||
[ModelProperty("v")] | ||
public int GatewayVersion { get; set; } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Voltaic; | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Events | ||
{ | ||
public class VoiceReadyEvent | ||
{ | ||
[ModelProperty("ssrc")] | ||
public uint Ssrc { get; set; } | ||
|
||
[ModelProperty("port")] | ||
public int Port { get; set; } | ||
|
||
[ModelProperty("modes")] | ||
public Utf8String[] EncryptionSchemes { get; set; } | ||
|
||
[ModelProperty("ip")] | ||
public Utf8String IpAddress { get; set; } | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/Wumpus.Net.Audio/Events/VoiceSessionDescriptionEvent.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using Voltaic; | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Events | ||
{ | ||
public class VoiceSessionDescriptionEvent | ||
{ | ||
[ModelProperty("video_codec")] | ||
public Utf8String VideoCodec { get; set; } | ||
|
||
[ModelProperty("secret_key")] | ||
public byte[] SecretKey { get; set; } | ||
|
||
[ModelProperty("mode")] | ||
public Utf8String EncryptionScheme { get; set; } | ||
|
||
[ModelProperty("media_session_id")] | ||
public Utf8String VideoSessionId { get; set; } | ||
|
||
[ModelProperty("audio_codec")] | ||
public Utf8String AudioCodec { get; set; } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System; | ||
using System.Net; | ||
using Voltaic.Serialization.Utf8; | ||
|
||
namespace Wumpus | ||
{ | ||
public static class IPUtilities | ||
{ | ||
public static bool TryParseIPv4Address(ReadOnlySpan<byte> buffer, out IPAddress address) | ||
=> TryParseIPv4Address(ref buffer, out address); | ||
|
||
public static bool TryParseIPv4Address(ref ReadOnlySpan<byte> buffer, out IPAddress address) | ||
{ | ||
address = default; | ||
ulong value = 0; | ||
|
||
for (int i = 0; i < 4; i++) | ||
{ | ||
if (!Utf8Reader.TryReadUInt8(ref buffer, out byte section, 'g')) | ||
return false; | ||
|
||
value |= (ulong)section << (i * 8); | ||
|
||
// last value does not have a dot following it | ||
if (i != 3) | ||
{ | ||
if (buffer[0] != '.') | ||
return false; | ||
|
||
buffer = buffer.Slice(1); | ||
} | ||
} | ||
|
||
address = new IPAddress((long)value); | ||
return true; | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Voltaic; | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Requests | ||
{ | ||
public class VoiceIdentifyParams | ||
{ | ||
[ModelProperty("user_id")] | ||
public Snowflake UserId { get; set; } | ||
|
||
[ModelProperty("server_id")] | ||
public Snowflake GuildId { get; set; } | ||
|
||
[ModelProperty("session_id")] | ||
public Utf8String SessionId { get; set; } | ||
|
||
[ModelProperty("token")] | ||
public Utf8String Token { get; set; } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using Voltaic; | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Requests | ||
{ | ||
public class VoiceResumeParams | ||
{ | ||
[ModelProperty("server_id")] | ||
public Snowflake GuildId { get; set; } | ||
FiniteReality marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
[ModelProperty("session_id")] | ||
public Utf8String SessionId { get; set; } | ||
|
||
[ModelProperty("token")] | ||
public Utf8String Token { get; set; } | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/Wumpus.Net.Audio/Requests/VoiceSelectProtocolParams.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using Voltaic; | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Requests | ||
{ | ||
public class VoiceSelectProtocolParams | ||
{ | ||
[ModelProperty("protocol")] | ||
public Utf8String TransportProtocol { get; set; } | ||
|
||
[ModelProperty("data")] | ||
public VoiceSelectProtocolConnectionProperties Properties { get; set; } | ||
} | ||
|
||
public class VoiceSelectProtocolConnectionProperties | ||
{ | ||
[ModelProperty("ip")] | ||
public Utf8String Ip { get; set; } | ||
|
||
[ModelProperty("port")] | ||
public int Port { get; set; } | ||
|
||
[ModelProperty("mode")] | ||
public Utf8String EncryptionScheme { get; set; } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using Voltaic.Serialization; | ||
|
||
namespace Wumpus.Requests | ||
{ | ||
public class VoiceSpeakingParams | ||
{ | ||
[ModelProperty("speaking")] | ||
public int Speaking { get; set; } | ||
|
||
[ModelProperty("delay")] | ||
public uint DelayMilliseconds { get; set; } | ||
|
||
[ModelProperty("ssrc")] | ||
public uint Ssrc { get; set; } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace Wumpus | ||
{ | ||
internal class SodiumPrimitives | ||
{ | ||
// sodium.dll on windows, libsodium.so on linux | ||
[DllImport("sodium")] | ||
extern static int crypto_secretbox_macbytes(); | ||
[DllImport("sodium")] | ||
extern static int crypto_secretbox_keybytes(); | ||
[DllImport("sodium")] | ||
extern static int crypto_secretbox_noncebytes(); | ||
|
||
[DllImport("sodium")] | ||
extern static int crypto_secretbox_easy(ref byte c, in byte m, int mlen, in byte n, in byte k); | ||
[DllImport("sodium")] | ||
extern static int crypto_secretbox_open_easy(ref byte m, in byte c, int clen, in byte n, in byte k); | ||
|
||
[DllImport("sodium")] | ||
extern static void randombytes_buf(ref byte buf, int size); | ||
|
||
// use the functions to grab the info so it's not hardcoded in the lib | ||
private static readonly int MACBYTES = crypto_secretbox_macbytes(); | ||
private static readonly int KEYBYTES = crypto_secretbox_keybytes(); | ||
private static readonly int NONCEBYTES = crypto_secretbox_noncebytes(); | ||
|
||
public static int NonceSize => NONCEBYTES; | ||
|
||
public static int ComputeMessageLength(int messageLength) | ||
=> messageLength + MACBYTES; | ||
|
||
public static bool TryEncryptInPlace(Span<byte> ciphertext, ReadOnlySpan<byte> message, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> secret) | ||
{ | ||
if (ciphertext.Length < message.Length + MACBYTES) | ||
return false; | ||
if (secret.Length < KEYBYTES) | ||
return false; | ||
if (nonce.Length < NONCEBYTES) | ||
return false; | ||
|
||
return crypto_secretbox_easy( | ||
ref ciphertext.GetPinnableReference(), | ||
message.GetPinnableReference(), message.Length, | ||
nonce.GetPinnableReference(), | ||
secret.GetPinnableReference()) == 0; | ||
} | ||
|
||
public static void GenerateRandomBytes(Span<byte> buffer) | ||
{ | ||
randombytes_buf(ref buffer.GetPinnableReference(), buffer.Length); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
|
||
namespace Wumpus | ||
{ | ||
[Flags] | ||
public enum SpeakingState : byte | ||
{ | ||
NotSpeaking = 0b0, | ||
Speaking = 0b1, | ||
|
||
Priority = 0b100, | ||
|
||
PrioritySpeaking = Speaking | Priority | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
namespace Wumpus.Events | ||
{ | ||
/// <summary> | ||
/// Voice connections operate in a similar fashion to the Gateway connection. | ||
/// However, they use a different set of payloads and a separate UDP-based connection for voice data transmission. | ||
/// https://discordapp.com/developers/docs/topics/voice-connections#voice | ||
/// </summary> | ||
public enum VoiceGatewayOperation : byte | ||
{ | ||
/// <summary> C→S - Used to begin a voice websocket connection. </summary> | ||
Identify = 0, | ||
/// <summary> C→S - Used to select the voice protocol. </summary> | ||
SelectProtocol = 1, | ||
/// <summary> C←S - Used to complete the websocket handshake. </summary> | ||
Ready = 2, | ||
/// <summary> C→S - Used to keep the websocket connection alive. </summary> | ||
Heartbeat = 3, | ||
/// <summary> C→S - Used to describe the session. </summary> | ||
SessionDescription = 4, | ||
/// <summary> C↔S - Used to indicate which users are speaking. </summary> | ||
Speaking = 5, | ||
/// <summary> C←S - Used to reply to a heartbeat. </summary> | ||
HeartbeatAck = 6, | ||
/// <summary> C→S - Used to resume a connection. </summary> | ||
Resume = 7, | ||
/// <summary> C→S - Used to begin the websocket handshake. </summary> | ||
Hello = 8, | ||
/// <summary> C←S - Used to complete the websocket handshake with an existing session. </summary> | ||
Resumed = 9 | ||
|
||
//NOTE: these do not have official names! | ||
//They are documented here for future expansion purposes | ||
|
||
//ssrc update, occurs when a user connects or changes screenshare settings | ||
//SsrcUpdate = 12, | ||
//user disconnected, occurs when a user disconnects | ||
//UserDisconnected = 13, | ||
//change channel, occurs whenever the client gets moved into another channel | ||
//ChangeChannel = 14 | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Voltaic.Serialization; | ||
using Wumpus.Entities; | ||
using Wumpus.Requests; | ||
|
||
namespace Wumpus.Events | ||
{ | ||
public class VoiceGatewayPayload | ||
{ | ||
[ModelProperty("op")] | ||
public VoiceGatewayOperation Operation { get; set; } | ||
|
||
[ModelProperty("d")] | ||
[ModelTypeSelector(nameof(Operation), nameof(OpCodeTypeSelector))] | ||
public object Data { get; set; } | ||
|
||
private static Dictionary<VoiceGatewayOperation, Type> OpCodeTypeSelector => new Dictionary<VoiceGatewayOperation, Type>() | ||
{ | ||
[VoiceGatewayOperation.Hello] = typeof(VoiceHelloEvent), | ||
[VoiceGatewayOperation.Ready] = typeof(VoiceReadyEvent), | ||
[VoiceGatewayOperation.HeartbeatAck] = typeof(int), | ||
|
||
[VoiceGatewayOperation.Identify] = typeof(VoiceIdentifyParams), | ||
[VoiceGatewayOperation.SelectProtocol] = typeof(VoiceSelectProtocolParams), | ||
[VoiceGatewayOperation.SessionDescription] = typeof(VoiceSessionDescriptionEvent), | ||
[VoiceGatewayOperation.Resume] = typeof(VoiceResumeParams), | ||
[VoiceGatewayOperation.Heartbeat] = typeof(int), | ||
|
||
[VoiceGatewayOperation.Speaking] = typeof(VoiceSpeakingParams), | ||
}; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Import Project="../Wumpus.Net.targets" /> | ||
<PropertyGroup> | ||
<RootNamespace>Wumpus</RootNamespace> | ||
<AssemblyName>Wumpus.Net.Audio</AssemblyName> | ||
<PackageTags>discord;discordapp;wumpus;audio;websocket;api;rogueexception</PackageTags> | ||
<Description>Provides a low-level audio client for the Discord API</Description> | ||
<TargetFrameworks>netstandard2.0</TargetFrameworks> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="3.1.0"> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.1" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="../Wumpus.Net.Core/Wumpus.Net.Core.csproj" /> | ||
</ItemGroup> | ||
</Project> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.