diff --git a/src/Discord.Net.Audio/API/Messages/VoiceSocket.cs b/src/Discord.Net.Audio/API/Messages/VoiceSocket.cs
index 262a97ec0..bf6d57ca3 100644
--- a/src/Discord.Net.Audio/API/Messages/VoiceSocket.cs
+++ b/src/Discord.Net.Audio/API/Messages/VoiceSocket.cs
@@ -7,10 +7,26 @@ using Newtonsoft.Json;
namespace Discord.API
{
+ public enum VoiceOpCodes : byte
+ {
+ /// Client --> Server - Used to associate a connection with a token.
+ Identify = 0,
+ /// Client --> Server - Used to specify configuration.
+ SelectProtocol = 1,
+ /// Client <-- Server - Used to notify that the voice connection was successful and informs the client of available protocols.
+ Ready = 2,
+ /// Client <-> Server - Used to keep the connection alive and measure latency.
+ Heartbeat = 3,
+ /// Client <-- Server - Used to provide an encryption key to the client.
+ SessionDescription = 4,
+ /// Client <-> Server - Used to inform that a certain user is speaking.
+ Speaking = 5
+ }
+
//Commands
- internal sealed class VoiceLoginCommand : WebSocketMessage
+ internal sealed class IdentifyCommand : WebSocketMessage
{
- public VoiceLoginCommand() : base(0) { }
+ public IdentifyCommand() : base((int)VoiceOpCodes.Identify) { }
public class Data
{
[JsonProperty("server_id")]
@@ -25,9 +41,9 @@ namespace Discord.API
public string Token;
}
}
- internal sealed class VoiceLogin2Command : WebSocketMessage
+ internal sealed class SelectProtocolCommand : WebSocketMessage
{
- public VoiceLogin2Command() : base(1) { }
+ public SelectProtocolCommand() : base((int)VoiceOpCodes.SelectProtocol) { }
public class Data
{
public class SocketInfo
@@ -45,13 +61,13 @@ namespace Discord.API
public SocketInfo SocketData = new SocketInfo();
}
}
- internal sealed class VoiceKeepAliveCommand : WebSocketMessage
+ internal sealed class HeartbeatCommand : WebSocketMessage
{
- public VoiceKeepAliveCommand() : base(3, EpochTime.GetMilliseconds()) { }
+ public HeartbeatCommand() : base((int)VoiceOpCodes.Heartbeat, EpochTime.GetMilliseconds()) { }
}
- internal sealed class IsTalkingCommand : WebSocketMessage
+ internal sealed class SpeakingCommand : WebSocketMessage
{
- public IsTalkingCommand() : base(5) { }
+ public SpeakingCommand() : base((int)VoiceOpCodes.Speaking) { }
public class Data
{
[JsonProperty("delay")]
diff --git a/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs b/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs
index 88a3dbe76..0a44f773b 100644
--- a/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs
+++ b/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs
@@ -17,16 +17,6 @@ namespace Discord.Net.WebSockets
{
public partial class VoiceWebSocket : WebSocket
{
- public enum OpCodes : byte
- {
- Identify = 0,
- SelectProtocol = 1,
- Ready = 2,
- Heartbeat = 3,
- SessionDescription = 4,
- Speaking = 5
- }
-
private const int MaxOpusSize = 4000;
private const string EncryptedMode = "xsalsa20_poly1305";
private const string UnencryptedMode = "plain";
@@ -114,12 +104,7 @@ namespace Discord.Net.WebSockets
{
_udp = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
- VoiceLoginCommand msg = new VoiceLoginCommand();
- msg.Payload.ServerId = _serverId.Value;
- msg.Payload.SessionId = _sessionId;
- msg.Payload.Token = _token;
- msg.Payload.UserId = _userId.Value;
- QueueMessage(msg);
+ SendIdentify();
List tasks = new List();
if ((_audioConfig.Mode & AudioMode.Outgoing) != 0)
@@ -224,15 +209,10 @@ namespace Discord.Net.WebSockets
if (packetLength != 70)
return;
- int port = packet[68] | packet[69] << 8;
string ip = Encoding.UTF8.GetString(packet, 4, 70 - 6).TrimEnd('\0');
+ int port = packet[68] | packet[69] << 8;
- var login2 = new VoiceLogin2Command();
- login2.Payload.Protocol = "udp";
- login2.Payload.SocketData.Address = ip;
- login2.Payload.SocketData.Mode = _encryptionMode;
- login2.Payload.SocketData.Port = port;
- QueueMessage(login2);
+ SendSelectProtocol(ip, port);
if ((_audioConfig.Mode & AudioMode.Incoming) == 0)
return;
}
@@ -441,10 +421,10 @@ namespace Discord.Net.WebSockets
{
await base.ProcessMessage(json).ConfigureAwait(false);
var msg = JsonConvert.DeserializeObject(json);
- var opCode = (OpCodes)msg.Operation;
+ var opCode = (VoiceOpCodes)msg.Operation;
switch (opCode)
{
- case OpCodes.Ready:
+ case VoiceOpCodes.Ready:
{
if (_state != (int)WebSocketState.Connected)
{
@@ -481,7 +461,7 @@ namespace Discord.Net.WebSockets
}
}
break;
- case OpCodes.Heartbeat:
+ case VoiceOpCodes.Heartbeat:
{
long time = EpochTime.GetMilliseconds();
var payload = (long)msg.Payload;
@@ -489,7 +469,7 @@ namespace Discord.Net.WebSockets
//TODO: Use this to estimate latency
}
break;
- case OpCodes.SessionDescription:
+ case VoiceOpCodes.SessionDescription:
{
var payload = (msg.Payload as JToken).ToObject(_serializer);
_secretKey = payload.SecretKey;
@@ -497,7 +477,7 @@ namespace Discord.Net.WebSockets
EndConnect();
}
break;
- case OpCodes.Speaking:
+ case VoiceOpCodes.Speaking:
{
var payload = (msg.Payload as JToken).ToObject(_serializer);
RaiseIsSpeaking(payload.UserId, payload.IsSpeaking);
@@ -519,19 +499,6 @@ namespace Discord.Net.WebSockets
_sendBuffer.Clear(_cancelToken);
}
- private void SendIsTalking(bool value)
- {
- var isTalking = new IsTalkingCommand();
- isTalking.Payload.IsSpeaking = value;
- isTalking.Payload.Delay = 0;
- QueueMessage(isTalking);
- }
-
- public override void SendHeartbeat()
- {
- QueueMessage(new VoiceKeepAliveCommand());
- }
-
public void WaitForQueue()
{
_sendBuffer.Wait(_cancelToken);
@@ -551,5 +518,38 @@ namespace Discord.Net.WebSockets
}
});
}
+
+ public void SendIdentify()
+ {
+ var msg = new IdentifyCommand();
+ msg.Payload.ServerId = _serverId.Value;
+ msg.Payload.SessionId = _sessionId;
+ msg.Payload.Token = _token;
+ msg.Payload.UserId = _userId.Value;
+ QueueMessage(msg);
+ }
+
+ public void SendSelectProtocol(string externalIp, int externalPort)
+ {
+ var msg = new SelectProtocolCommand();
+ msg.Payload.Protocol = "udp";
+ msg.Payload.SocketData.Address = externalIp;
+ msg.Payload.SocketData.Mode = _encryptionMode;
+ msg.Payload.SocketData.Port = externalPort;
+ QueueMessage(msg);
+ }
+
+ public void SendIsTalking(bool value)
+ {
+ var isTalking = new SpeakingCommand();
+ isTalking.Payload.IsSpeaking = value;
+ isTalking.Payload.Delay = 0;
+ QueueMessage(isTalking);
+ }
+
+ public override void SendHeartbeat()
+ {
+ QueueMessage(new HeartbeatCommand());
+ }
}
}
\ No newline at end of file
diff --git a/src/Discord.Net/API/Messages/GatewaySocket.cs b/src/Discord.Net/API/Messages/GatewaySocket.cs
index 18895da48..d84fbc761 100644
--- a/src/Discord.Net/API/Messages/GatewaySocket.cs
+++ b/src/Discord.Net/API/Messages/GatewaySocket.cs
@@ -11,14 +11,23 @@ namespace Discord.API
{
public enum GatewayOpCodes : byte
{
+ /// Client <-- Server - Used to send most events.
Dispatch = 0,
+ /// Client <-> Server - Used to keep the connection alive and measure latency.
Heartbeat = 1,
+ /// Client --> Server - Used to associate a connection with a token and specify configuration.
Identify = 2,
+ /// Client --> Server - Used to update client's status and current game id.
StatusUpdate = 3,
+ /// Client --> Server - Used to join a particular voice channel.
VoiceStateUpdate = 4,
- //VoiceServerPing = 5, (Unused?)
+ /// Client --> Server - Used to ensure the server's voice server is alive. Only send this if voice connection fails or suddenly drops.
+ VoiceServerPing = 5,
+ /// Client --> Server - Used to resume a connection after a redirect occurs.
Resume = 6,
+ /// Client <-- Server - Used to notify a client that they must reconnect to another gateway.
Redirect = 7,
+ /// Client --> Server - Used to request all members that were withheld by large_threshold
RequestGuildMembers = 8
}
@@ -92,8 +101,6 @@ namespace Discord.API
}
}
-
- //Commands
internal sealed class JoinVoiceCommand : WebSocketMessage
{
public JoinVoiceCommand() : base((int)GatewayOpCodes.VoiceStateUpdate) { }
@@ -112,7 +119,6 @@ namespace Discord.API
}
}
- //Events
internal sealed class ResumeCommand : WebSocketMessage
{
public ResumeCommand() : base((int)GatewayOpCodes.Resume) { }
diff --git a/src/Discord.Net/Net/WebSockets/GatewayWebSocket.cs b/src/Discord.Net/Net/WebSockets/GatewayWebSocket.cs
index 8e0a52a50..b6c292268 100644
--- a/src/Discord.Net/Net/WebSockets/GatewayWebSocket.cs
+++ b/src/Discord.Net/Net/WebSockets/GatewayWebSocket.cs
@@ -109,7 +109,7 @@ namespace Discord.Net.WebSockets
public void SendIdentify(string token)
{
- IdentifyCommand msg = new IdentifyCommand();
+ var msg = new IdentifyCommand();
msg.Payload.Token = token;
msg.Payload.Properties["$device"] = "Discord.Net";
if (_config.UseLargeThreshold)
@@ -120,10 +120,10 @@ namespace Discord.Net.WebSockets
public void SendResume()
{
- var resumeMsg = new ResumeCommand();
- resumeMsg.Payload.SessionId = _sessionId;
- resumeMsg.Payload.Sequence = _lastSeq;
- QueueMessage(resumeMsg);
+ var msg = new ResumeCommand();
+ msg.Payload.SessionId = _sessionId;
+ msg.Payload.Sequence = _lastSeq;
+ QueueMessage(msg);
}
public override void SendHeartbeat()
@@ -133,31 +133,31 @@ namespace Discord.Net.WebSockets
public void SendStatusUpdate(long? idleSince, int? gameId)
{
- var updateStatus = new StatusUpdateCommand();
- updateStatus.Payload.IdleSince = idleSince;
- updateStatus.Payload.GameId = gameId;
- QueueMessage(updateStatus);
+ var msg = new StatusUpdateCommand();
+ msg.Payload.IdleSince = idleSince;
+ msg.Payload.GameId = gameId;
+ QueueMessage(msg);
}
public void SendJoinVoice(long serverId, long channelId)
{
- var joinVoice = new JoinVoiceCommand();
- joinVoice.Payload.ServerId = serverId;
- joinVoice.Payload.ChannelId = channelId;
- QueueMessage(joinVoice);
+ var msg = new JoinVoiceCommand();
+ msg.Payload.ServerId = serverId;
+ msg.Payload.ChannelId = channelId;
+ QueueMessage(msg);
}
public void SendLeaveVoice(long serverId)
{
- var leaveVoice = new JoinVoiceCommand();
- leaveVoice.Payload.ServerId = serverId;
- QueueMessage(leaveVoice);
+ var msg = new JoinVoiceCommand();
+ msg.Payload.ServerId = serverId;
+ QueueMessage(msg);
}
public void SendRequestUsers(long serverId, string query = "", int limit = 0)
{
- var getOfflineUsers = new GetUsersCommand();
- getOfflineUsers.Payload.ServerId = serverId;
- QueueMessage(getOfflineUsers);
+ var msg = new GetUsersCommand();
+ msg.Payload.ServerId = serverId;
+ QueueMessage(msg);
}
}
}