Improved voice socket error handling
This commit is contained in:
@@ -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);
|
|
||||||
_dataSocket.SendJoinVoice(_voiceServerId, channelId);
|
|
||||||
|
|
||||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
await _voiceSocket.SetChannel(_voiceServerId, channelId).ConfigureAwait(false);
|
||||||
try
|
_dataSocket.SendJoinVoice(_voiceServerId, channelId);
|
||||||
{
|
await _voiceSocket.WaitForConnection(_config.ConnectionTimeout);
|
||||||
await Task.Run(() => _voiceSocket.WaitForConnection(tokenSource.Token))
|
|
||||||
.Timeout(_config.ConnectionTimeout, tokenSource)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (TimeoutException)
|
|
||||||
{
|
|
||||||
tokenSource.Cancel();
|
|
||||||
await _voiceSocket.Disconnect().ConfigureAwait(false);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*async Task IDiscordVoiceClient.Disconnect()
|
/*async Task IDiscordVoiceClient.Disconnect()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -79,12 +79,9 @@ namespace Discord.WebSockets
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual async Task Connect()
|
protected async Task BeginConnect()
|
||||||
{
|
{
|
||||||
if (_state != (int)WebSocketState.Disconnected)
|
try
|
||||||
throw new InvalidOperationException("Client is already connected or connecting to the server.");
|
|
||||||
|
|
||||||
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();
|
||||||
|
|||||||
Reference in New Issue
Block a user