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));
await _voiceSocket.Disconnect().ConfigureAwait(false);
_voiceSocket.SetChannel(_voiceServerId, channelId);
await _voiceSocket.SetChannel(_voiceServerId, channelId).ConfigureAwait(false);
_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()


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

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

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

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

return base.BeginConnect();
}
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
await DisconnectInternal(new Exception("Server transfer occurred."), isUnexpected: false);
@@ -79,7 +81,7 @@ namespace Discord.WebSockets.Voice
_sessionId = sessionId;
_token = token;
await Connect().ConfigureAwait(false);
await Start().ConfigureAwait(false);
}
public async Task Reconnect()
{
@@ -91,7 +93,7 @@ namespace Discord.WebSockets.Voice
{
try
{
await Connect().ConfigureAwait(false);
await Start().ConfigureAwait(false);
break;
}
catch (OperationCanceledException) { throw; }
@@ -245,7 +247,7 @@ namespace Discord.WebSockets.Voice
int port = packet[68] | packet[69] << 8;
string ip = Encoding.ASCII.GetString(packet, 4, 70 - 6).TrimEnd('\0');

CompleteConnect();
EndConnect();

var login2 = new Login2Command();
login2.Payload.Protocol = "udp";
@@ -599,9 +601,20 @@ namespace Discord.WebSockets.Voice
{
_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) =>
{
_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) =>
{
string code = e.WasClean ? e.Code.ToString() : "Unexpected";
string reason = e.Reason != "" ? e.Reason : "No 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.Connect();
@@ -59,7 +59,12 @@ namespace Discord.WebSockets
{
string ignored;
while (_sendQueue.TryDequeue(out ignored)) { }
_webSocket.Close();

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

return TaskHelper.CompletedTask;
}

@@ -77,7 +82,7 @@ namespace Discord.WebSockets
{
try
{
while (_webSocket.IsAlive && !cancelToken.IsCancellationRequested)
while (!cancelToken.IsCancellationRequested)
{
string 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);

@@ -93,19 +90,34 @@ namespace Discord.WebSockets
_cancelTokenSource = new CancellationTokenSource();
_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;
await _engine.Connect(Host, _cancelToken).ConfigureAwait(false);

_state = (int)WebSocketState.Connecting;
_runTask = RunTasks();
}
catch (Exception ex)
{
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;
_connectedEvent.Set();


Loading…
Cancel
Save