Browse Source

Better voice error handling, moved several properties into DiscordVoiceSocket

tags/docs-0.9
Brandon Smith 9 years ago
parent
commit
52590e4153
6 changed files with 77 additions and 41 deletions
  1. +2
    -1
      src/Discord.Net.Commands/DiscordBotClient.cs
  2. +9
    -12
      src/Discord.Net/DiscordClient.cs
  3. +3
    -5
      src/Discord.Net/DiscordClientConfig.cs
  4. +5
    -0
      src/Discord.Net/DiscordDataSocket.cs
  5. +52
    -20
      src/Discord.Net/DiscordVoiceSocket.cs
  6. +6
    -3
      src/Discord.Net/DiscordWebSocket.cs

+ 2
- 1
src/Discord.Net.Commands/DiscordBotClient.cs View File

@@ -22,6 +22,7 @@ namespace Discord
_commands = new List<Command>();

CommandChar = '~';
UseCommandChar = true;
RequireCommandCharInPublic = true;
RequireCommandCharInPrivate = true;

@@ -32,7 +33,7 @@ namespace Discord
return;

//Ignore messages from ourselves
if (e.Message.UserId == _myId)
if (e.Message.UserId == _myId)
return;

//Check for the command character


+ 9
- 12
src/Discord.Net/DiscordClient.cs View File

@@ -49,8 +49,7 @@ namespace Discord
private bool _isDebugMode;

#if !DNXCORE50
public Server CurrentVoiceServer => _currentVoiceToken != null ? _servers[_currentVoiceServerId] : null;
private string _currentVoiceServerId, _currentVoiceToken;
public Server CurrentVoiceServer => GetServer(_voiceWebSocket.CurrentVoiceServerId);
#endif

//Constructor
@@ -142,13 +141,12 @@ namespace Discord
//Reconnect if we didn't cause the disconnect
if (e.WasUnexpected)
{
await Task.Delay(_config.ReconnectDelay);
while (!_disconnectToken.IsCancellationRequested)
{
try
{
await Task.Delay(_config.ReconnectDelay);
await _voiceWebSocket.ReconnectAsync();
await _voiceWebSocket.Login(_currentVoiceServerId, _myId, _sessionId, _currentVoiceToken);
break;
}
catch (Exception ex)
@@ -425,11 +423,10 @@ namespace Discord
try { RaiseVoiceServerUpdated(server, data.Endpoint); } catch { }

#if !DNXCORE50
if (_config.EnableVoice && data.ServerId == _currentVoiceServerId)
if (_config.EnableVoice)
{
_currentVoiceToken = data.Token;
_voiceWebSocket.SetSessionData(data.ServerId, _myId, _sessionId, data.Token);
await _voiceWebSocket.ConnectAsync("wss://" + data.Endpoint.Split(':')[0]);
await _voiceWebSocket.Login(_currentVoiceServerId, _myId, _sessionId, data.Token);
}
#endif
}
@@ -627,19 +624,19 @@ namespace Discord
if (channel == null) throw new ArgumentNullException(nameof(channel));

await LeaveVoiceServer();
_currentVoiceServerId = channel.ServerId;
//_currentVoiceServerId = channel.ServerId;
_webSocket.JoinVoice(channel);
await _voiceWebSocket.BeginConnect();
}

public async Task LeaveVoiceServer()
{
CheckReady();
if (!_config.EnableVoice) throw new InvalidOperationException("Voice is not enabled for this client.");

await _voiceWebSocket.DisconnectAsync();
if (_currentVoiceServerId != null)
_webSocket.LeaveVoice();
_currentVoiceServerId = null;
_currentVoiceToken = null;
//if (_voiceWebSocket.CurrentVoiceServerId != null)
_webSocket.LeaveVoice();
}

/// <summary> Sends a PCM frame to the voice server. </summary>


+ 3
- 5
src/Discord.Net/DiscordClientConfig.cs View File

@@ -3,8 +3,7 @@
public class DiscordClientConfig
{
#if !DNXCORE50
/// <summary> Enables the voice websocket and UDP client (Experimental!). </summary>
/// <remarks> This option requires the opus .dll or .so be in the local lib/ folder. </remarks>
/// <summary> Enables the voice websocket and UDP client (Experimental!). This option requires the opus .dll or .so be in the local lib/ folder. </remarks>
public bool EnableVoice { get; set; } = false;
#endif
/// <summary> Enables the verbose DebugMessage event handler. May hinder performance but should help debug any issues. </summary>
@@ -24,9 +23,8 @@
public bool UseMessageQueue { get; set; } = false;
/// <summary> Gets or sets the time (in milliseconds) to wait when the message queue is empty before checking again. </summary>
public int MessageQueueInterval { get; set; } = 100;
/// <summary> Gets or sets the max buffer length (in milliseconds) for outgoing voice packets. </summary>
/// <remarks> This value is the target maximum but is not guaranteed. The buffer will often go a bit above this value. </remarks>
public int VoiceBufferLength { get; set; } = 1000;
/// <summary> Gets or sets the max buffer length (in milliseconds) for outgoing voice packets. This value is the target maximum but is not guaranteed, the buffer will often go slightly above this value. </remarks>
public int VoiceBufferLength { get; set; } = 3000;

public DiscordClientConfig() { }
}


+ 5
- 0
src/Discord.Net/DiscordDataSocket.cs View File

@@ -20,6 +20,11 @@ namespace Discord
_connectWaitOnLogin2 = new ManualResetEventSlim(false);
}

public override Task ConnectAsync(string url)
{
BeginConnect();
return base.ConnectAsync(url);
}
public async Task Login(string token)
{
var cancelToken = _disconnectToken.Token;


+ 52
- 20
src/Discord.Net/DiscordVoiceSocket.cs View File

@@ -1,4 +1,4 @@
//#define USE_THREAD
#define USE_THREAD
#if !DNXCORE50
using Discord.API.Models;
using Discord.Opus;
@@ -35,10 +35,14 @@ namespace Discord
private ushort _sequence;
private string _mode;
private byte[] _encodingBuffer;
private string _serverId, _userId, _sessionId, _token;

#if USE_THREAD
private Thread _sendThread;
#endif

public string CurrentVoiceServerId => _serverId;

public DiscordVoiceSocket(DiscordClient client, int timeout, int interval, int audioBufferLength, bool isDebug)
: base(client, timeout, interval, isDebug)
{
@@ -54,25 +58,54 @@ namespace Discord
protected override void OnConnect()
{
_udp = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
#if !DNX451 && !MONO
#if !DNX451
_udp.AllowNatTraversal(true);
#endif
_isReady = false;
_isClearing = false;
}

var cancelToken = _disconnectToken.Token;
Task.Factory.StartNew(async () =>
{
_connectWaitOnLogin.Reset();

VoiceWebSocketCommands.Login msg = new VoiceWebSocketCommands.Login();
msg.Payload.ServerId = _serverId;
msg.Payload.SessionId = _sessionId;
msg.Payload.Token = _token;
msg.Payload.UserId = _userId;
await SendMessage(msg, cancelToken);

try
{
if (!_connectWaitOnLogin.Wait(_timeout, cancelToken))
return;
}
catch (OperationCanceledException)
{
return;
}

SetConnected();
});
}
protected override void OnDisconnect()
{
_udp = null;
_serverId = null;
_userId = null;
_sessionId = null;
_token = null;
#if USE_THREAD
_sendThread.Join();
_sendThread = null;
#endif
}
}

protected override Task[] CreateTasks()
{
#if USE_THREAD
_sendThread = new Thread(new ThreadStart(() => SendAsync(_disconnectToken)));
_sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(_disconnectToken)));
_sendThread.Start();
#endif
return new Task[]
@@ -85,19 +118,20 @@ namespace Discord
}.Concat(base.CreateTasks()).ToArray();
}

public async Task Login(string serverId, string userId, string sessionId, string token)
public void SetSessionData(string serverId, string userId, string sessionId, string token)
{
var cancelToken = _disconnectToken.Token;

_connectWaitOnLogin.Reset();
_serverId = serverId;
_userId = userId;
_sessionId = sessionId;
_token = token;
}

VoiceWebSocketCommands.Login msg = new VoiceWebSocketCommands.Login();
msg.Payload.ServerId = serverId;
msg.Payload.SessionId = sessionId;
msg.Payload.Token = token;
msg.Payload.UserId = userId;
await SendMessage(msg, cancelToken);
public new async Task BeginConnect()
{
base.BeginConnect();
var cancelToken = _disconnectToken.Token;

await Task.Yield();
try
{
if (!_connectWaitOnLogin.Wait(_timeout, cancelToken)) //Waiting on JoinServer message
@@ -110,8 +144,6 @@ namespace Discord
else
_disconnectReason.Throw();
}

SetConnected();
}
private async Task ReceiveVoiceAsync()
@@ -143,6 +175,7 @@ namespace Discord
var cancelSource = _disconnectToken;
var cancelToken = cancelSource.Token;
await Task.Yield();
#endif

byte[] packet;
try
@@ -189,7 +222,7 @@ namespace Discord
rtpPacket[7] = (byte)((timestamp >> 0) & 0xFF);
Buffer.BlockCopy(packet, 0, rtpPacket, 12, packet.Length);
#if USE_THREAD
_udp.Send(rtpPacket, packet.Count + 12);
_udp.Send(rtpPacket, packet.Length + 12);
#else
await _udp.SendAsync(rtpPacket, packet.Length + 12);
#endif
@@ -222,8 +255,7 @@ namespace Discord
catch (ObjectDisposedException) { }
catch (Exception ex) { DisconnectInternal(ex); }
}
#endif
//Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken
//Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken
private async Task WatcherAsync()
{
var cancelToken = _disconnectToken.Token;


+ 6
- 3
src/Discord.Net/DiscordWebSocket.cs View File

@@ -40,12 +40,15 @@ namespace Discord
_sendQueue = new ConcurrentQueue<byte[]>();
}

public async Task ConnectAsync(string url)
protected void BeginConnect()
{
await DisconnectAsync();

_disconnectToken = new CancellationTokenSource();
_disconnectReason = null;
}
public virtual async Task ConnectAsync(string url)
{
await DisconnectAsync();

var cancelToken = _disconnectToken.Token;

_webSocket = new ClientWebSocket();


Loading…
Cancel
Save