Browse Source

Improved voice socket error handling

tags/docs-0.9
RogueException 9 years ago
parent
commit
7c024ecda8
5 changed files with 58 additions and 37 deletions
  1. +3
    -15
      src/Discord.Net/DiscordSimpleClient.Voice.cs
  2. +6
    -3
      src/Discord.Net/WebSockets/Data/DataWebSocket.cs
  3. +20
    -7
      src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs
  4. +9
    -4
      src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs
  5. +20
    -8
      src/Discord.Net/WebSockets/WebSocket.cs

+ 3
- 15
src/Discord.Net/DiscordSimpleClient.Voice.cs View File

@@ -24,22 +24,10 @@ namespace Discord
if (channelId == null) throw new ArgumentNullException(nameof(channelId)); if (channelId == null) throw new ArgumentNullException(nameof(channelId));
await _voiceSocket.Disconnect().ConfigureAwait(false); await _voiceSocket.Disconnect().ConfigureAwait(false);
_voiceSocket.SetChannel(_voiceServerId, channelId);
await _voiceSocket.SetChannel(_voiceServerId, channelId).ConfigureAwait(false);
_dataSocket.SendJoinVoice(_voiceServerId, channelId); _dataSocket.SendJoinVoice(_voiceServerId, channelId);

CancellationTokenSource tokenSource = new CancellationTokenSource();
try
{
await Task.Run(() => _voiceSocket.WaitForConnection(tokenSource.Token))
.Timeout(_config.ConnectionTimeout, tokenSource)
.ConfigureAwait(false);
}
catch (TimeoutException)
{
tokenSource.Cancel();
await _voiceSocket.Disconnect().ConfigureAwait(false);
throw;
}
await _voiceSocket.WaitForConnection(_config.ConnectionTimeout);
} }


/*async Task IDiscordVoiceClient.Disconnect() /*async Task IDiscordVoiceClient.Disconnect()


+ 6
- 3
src/Discord.Net/WebSockets/Data/DataWebSocket.cs View File

@@ -19,7 +19,8 @@ namespace Discord.WebSockets.Data


public async Task Login(string token) public async Task Login(string token)
{ {
await Connect().ConfigureAwait(false);
await BeginConnect().ConfigureAwait(false);
await Start().ConfigureAwait(false);
LoginCommand msg = new LoginCommand(); LoginCommand msg = new LoginCommand();
msg.Payload.Token = token; msg.Payload.Token = token;
@@ -29,7 +30,9 @@ namespace Discord.WebSockets.Data
private async Task Redirect(string server) private async Task Redirect(string server)
{ {
await DisconnectInternal(isUnexpected: false).ConfigureAwait(false); await DisconnectInternal(isUnexpected: false).ConfigureAwait(false);
await Connect().ConfigureAwait(false);

await BeginConnect().ConfigureAwait(false);
await Start().ConfigureAwait(false);


var resumeMsg = new ResumeCommand(); var resumeMsg = new ResumeCommand();
resumeMsg.Payload.SessionId = _sessionId; resumeMsg.Payload.SessionId = _sessionId;
@@ -87,7 +90,7 @@ namespace Discord.WebSockets.Data
} }
RaiseReceivedEvent(msg.Type, token); RaiseReceivedEvent(msg.Type, token);
if (msg.Type == "READY" || msg.Type == "RESUMED") if (msg.Type == "READY" || msg.Type == "RESUMED")
CompleteConnect();
EndConnect();
} }
break; break;
case 7: //Redirect case 7: //Redirect


+ 20
- 7
src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs View File

@@ -61,14 +61,16 @@ namespace Discord.WebSockets.Voice
_encoder = new OpusEncoder(48000, 1, 20, Opus.Application.Audio); _encoder = new OpusEncoder(48000, 1, 20, Opus.Application.Audio);
} }


public void SetChannel(string serverId, string channelId)
public Task SetChannel(string serverId, string channelId)
{ {
_serverId = serverId; _serverId = serverId;
_channelId = channelId; _channelId = channelId;

return base.BeginConnect();
} }
public async Task Login(string userId, string sessionId, string token, CancellationToken cancelToken) public async Task Login(string userId, string sessionId, string token, CancellationToken cancelToken)
{ {
if ((WebSocketState)_state != WebSocketState.Disconnected)
if ((WebSocketState)_state == WebSocketState.Connected)
{ {
//Adjust the host and tell the system to reconnect //Adjust the host and tell the system to reconnect
await DisconnectInternal(new Exception("Server transfer occurred."), isUnexpected: false); await DisconnectInternal(new Exception("Server transfer occurred."), isUnexpected: false);
@@ -79,7 +81,7 @@ namespace Discord.WebSockets.Voice
_sessionId = sessionId; _sessionId = sessionId;
_token = token; _token = token;
await Connect().ConfigureAwait(false);
await Start().ConfigureAwait(false);
} }
public async Task Reconnect() public async Task Reconnect()
{ {
@@ -91,7 +93,7 @@ namespace Discord.WebSockets.Voice
{ {
try try
{ {
await Connect().ConfigureAwait(false);
await Start().ConfigureAwait(false);
break; break;
} }
catch (OperationCanceledException) { throw; } catch (OperationCanceledException) { throw; }
@@ -245,7 +247,7 @@ namespace Discord.WebSockets.Voice
int port = packet[68] | packet[69] << 8; int port = packet[68] | packet[69] << 8;
string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0'); string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0');


CompleteConnect();
EndConnect();


var login2 = new Login2Command(); var login2 = new Login2Command();
login2.Payload.Protocol = "udp"; login2.Payload.Protocol = "udp";
@@ -599,9 +601,20 @@ namespace Discord.WebSockets.Voice
{ {
_sendQueueEmptyWait.Wait(_cancelToken); _sendQueueEmptyWait.Wait(_cancelToken);
} }
public void WaitForConnection(CancellationToken cancelToken)
public Task WaitForConnection(int timeout)
{ {
_connectedEvent.Wait(cancelToken);
return Task.Run(() =>
{
try
{
if (!_connectedEvent.Wait(timeout, _cancelToken))
throw new TimeoutException();
}
catch (OperationCanceledException ex)
{
ThrowError();
}
});
} }
} }
} }

+ 9
- 4
src/Discord.Net/WebSockets/WebSocket.WebSocketSharp.cs View File

@@ -41,14 +41,14 @@ namespace Discord.WebSockets
_webSocket.OnError += async (s, e) => _webSocket.OnError += async (s, e) =>
{ {
_parent.RaiseOnLog(LogMessageSeverity.Error, $"Websocket Error: {e.Message}"); _parent.RaiseOnLog(LogMessageSeverity.Error, $"Websocket Error: {e.Message}");
await _parent.DisconnectInternal(e.Exception, isUnexpected: true, skipAwait: true);
await _parent.DisconnectInternal(e.Exception, skipAwait: true);
}; };
_webSocket.OnClose += async (s, e) => _webSocket.OnClose += async (s, e) =>
{ {
string code = e.WasClean ? e.Code.ToString() : "Unexpected"; string code = e.WasClean ? e.Code.ToString() : "Unexpected";
string reason = e.Reason != "" ? e.Reason : "No Reason"; string reason = e.Reason != "" ? e.Reason : "No Reason";
Exception ex = new Exception($"Got Close Message ({code}): {reason}"); Exception ex = new Exception($"Got Close Message ({code}): {reason}");
await _parent.DisconnectInternal(ex, isUnexpected: !e.WasClean, skipAwait: true);
await _parent.DisconnectInternal(ex, skipAwait: true);
}; };
_webSocket.Log.Output = (e, m) => { }; //Dont let websocket-sharp print to console _webSocket.Log.Output = (e, m) => { }; //Dont let websocket-sharp print to console
_webSocket.Connect(); _webSocket.Connect();
@@ -59,7 +59,12 @@ namespace Discord.WebSockets
{ {
string ignored; string ignored;
while (_sendQueue.TryDequeue(out ignored)) { } while (_sendQueue.TryDequeue(out ignored)) { }
_webSocket.Close();

var socket = _webSocket;
_webSocket = null;
if (socket != null)
socket.Close();

return TaskHelper.CompletedTask; return TaskHelper.CompletedTask;
} }


@@ -77,7 +82,7 @@ namespace Discord.WebSockets
{ {
try try
{ {
while (_webSocket.IsAlive && !cancelToken.IsCancellationRequested)
while (!cancelToken.IsCancellationRequested)
{ {
string json; string json;
while (_sendQueue.TryDequeue(out json)) while (_sendQueue.TryDequeue(out json))


+ 20
- 8
src/Discord.Net/WebSockets/WebSocket.cs View File

@@ -79,12 +79,9 @@ namespace Discord.WebSockets
}; };
} }


protected virtual async Task Connect()
protected async Task BeginConnect()
{ {
if (_state != (int)WebSocketState.Disconnected)
throw new InvalidOperationException("Client is already connected or connecting to the server.");

try
try
{ {
await Disconnect().ConfigureAwait(false); await Disconnect().ConfigureAwait(false);


@@ -93,19 +90,34 @@ namespace Discord.WebSockets
_cancelTokenSource = new CancellationTokenSource(); _cancelTokenSource = new CancellationTokenSource();
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, ParentCancelToken.Value).Token; _cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, ParentCancelToken.Value).Token;


_state = (int)WebSocketState.Connecting;
}
catch (Exception ex)
{
await DisconnectInternal(ex, isUnexpected: false).ConfigureAwait(false);
throw;
}
}

protected virtual async Task Start()
{
try
{
if (_state != (int)WebSocketState.Connecting)
throw new InvalidOperationException("Socket is in the wrong state.");

_lastHeartbeat = DateTime.UtcNow; _lastHeartbeat = DateTime.UtcNow;
await _engine.Connect(Host, _cancelToken).ConfigureAwait(false); await _engine.Connect(Host, _cancelToken).ConfigureAwait(false);


_state = (int)WebSocketState.Connecting;
_runTask = RunTasks(); _runTask = RunTasks();
} }
catch (Exception ex) catch (Exception ex)
{ {
await DisconnectInternal(ex, isUnexpected: false).ConfigureAwait(false); await DisconnectInternal(ex, isUnexpected: false).ConfigureAwait(false);
throw; //Dont handle this exception internally, send up it upwards
throw;
} }
} }
protected void CompleteConnect()
protected void EndConnect()
{ {
_state = (int)WebSocketState.Connected; _state = (int)WebSocketState.Connected;
_connectedEvent.Set(); _connectedEvent.Set();


Loading…
Cancel
Save