Browse Source

Added connection timeout. Dont require a lock to abort a failed connection attempt.

tags/1.0-rc
RogueException 8 years ago
parent
commit
774b54de72
4 changed files with 45 additions and 16 deletions
  1. +15
    -2
      src/Discord.Net/Rpc/DiscordRpcClient.cs
  2. +5
    -2
      src/Discord.Net/Rpc/DiscordRpcConfig.cs
  3. +21
    -10
      src/Discord.Net/WebSocket/DiscordSocketClient.cs
  4. +4
    -2
      src/Discord.Net/WebSocket/DiscordSocketConfig.cs

+ 15
- 2
src/Discord.Net/Rpc/DiscordRpcClient.cs View File

@@ -6,7 +6,6 @@ using Discord.Rest;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;


@@ -21,9 +20,13 @@ namespace Discord.Rpc
private CancellationTokenSource _cancelToken, _reconnectCancelToken; private CancellationTokenSource _cancelToken, _reconnectCancelToken;
private Task _reconnectTask; private Task _reconnectTask;
private bool _canReconnect; private bool _canReconnect;
private int _connectionTimeout;


public ConnectionState ConnectionState { get; private set; } public ConnectionState ConnectionState { get; private set; }


//From DiscordRpcConfig
internal int ConnectionTimeout { get; private set; }

public new API.DiscordRpcApiClient ApiClient => base.ApiClient as API.DiscordRpcApiClient; public new API.DiscordRpcApiClient ApiClient => base.ApiClient as API.DiscordRpcApiClient;


/// <summary> Creates a new RPC discord client. </summary> /// <summary> Creates a new RPC discord client. </summary>
@@ -32,6 +35,7 @@ namespace Discord.Rpc
public DiscordRpcClient(DiscordRpcConfig config) public DiscordRpcClient(DiscordRpcConfig config)
: base(config, CreateApiClient(config)) : base(config, CreateApiClient(config))
{ {
ConnectionTimeout = config.ConnectionTimeout;
_rpcLogger = LogManager.CreateLogger("RPC"); _rpcLogger = LogManager.CreateLogger("RPC");


_serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() }; _serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() };
@@ -95,8 +99,17 @@ namespace Discord.Rpc
await _rpcLogger.InfoAsync("Connecting").ConfigureAwait(false); await _rpcLogger.InfoAsync("Connecting").ConfigureAwait(false);
try try
{ {
_connectTask = new TaskCompletionSource<bool>();
var connectTask = new TaskCompletionSource<bool>();
_connectTask = connectTask;
_cancelToken = new CancellationTokenSource(); _cancelToken = new CancellationTokenSource();

//Abort connection on timeout
Task.Run(async () =>
{
await Task.Delay(_connectionTimeout);
connectTask.TrySetException(new TimeoutException());
});

await ApiClient.ConnectAsync().ConfigureAwait(false); await ApiClient.ConnectAsync().ConfigureAwait(false);
await _connectedEvent.InvokeAsync().ConfigureAwait(false); await _connectedEvent.InvokeAsync().ConfigureAwait(false);




+ 5
- 2
src/Discord.Net/Rpc/DiscordRpcConfig.cs View File

@@ -17,9 +17,12 @@ namespace Discord.Rpc
} }


/// <summary> Gets or sets the Discord client/application id used for this RPC connection. </summary> /// <summary> Gets or sets the Discord client/application id used for this RPC connection. </summary>
public string ClientId { get; set; }
public string ClientId { get; }
/// <summary> Gets or sets the origin used for this RPC connection. </summary> /// <summary> Gets or sets the origin used for this RPC connection. </summary>
public string Origin { get; set; }
public string Origin { get; }

/// <summary> Gets or sets the time, in milliseconds, to wait for a connection to complete before aborting. </summary>
public int ConnectionTimeout { get; set; } = 30000;


/// <summary> Gets or sets the provider used to generate new websocket connections. </summary> /// <summary> Gets or sets the provider used to generate new websocket connections. </summary>
public WebSocketProvider WebSocketProvider { get; set; } = () => new DefaultWebSocketClient(); public WebSocketProvider WebSocketProvider { get; set; } = () => new DefaultWebSocketClient();


+ 21
- 10
src/Discord.Net/WebSocket/DiscordSocketClient.cs View File

@@ -51,6 +51,7 @@ namespace Discord.WebSocket
internal int LargeThreshold { get; private set; } internal int LargeThreshold { get; private set; }
internal AudioMode AudioMode { get; private set; } internal AudioMode AudioMode { get; private set; }
internal DataStore DataStore { get; private set; } internal DataStore DataStore { get; private set; }
internal int ConnectionTimeout { get; private set; }
internal WebSocketProvider WebSocketProvider { get; private set; } internal WebSocketProvider WebSocketProvider { get; private set; }


public new API.DiscordSocketApiClient ApiClient => base.ApiClient as API.DiscordSocketApiClient; public new API.DiscordSocketApiClient ApiClient => base.ApiClient as API.DiscordSocketApiClient;
@@ -70,6 +71,7 @@ namespace Discord.WebSocket
LargeThreshold = config.LargeThreshold; LargeThreshold = config.LargeThreshold;
AudioMode = config.AudioMode; AudioMode = config.AudioMode;
WebSocketProvider = config.WebSocketProvider; WebSocketProvider = config.WebSocketProvider;
ConnectionTimeout = config.ConnectionTimeout;


DataStore = new DataStore(0, 0); DataStore = new DataStore(0, 0);
_nextAudioId = 1; _nextAudioId = 1;
@@ -158,8 +160,17 @@ namespace Discord.WebSocket
try try
{ {
_connectTask = new TaskCompletionSource<bool>();
var connectTask = new TaskCompletionSource<bool>();
_connectTask = connectTask;
_cancelToken = new CancellationTokenSource(); _cancelToken = new CancellationTokenSource();

//Abort connection on timeout
Task.Run(async () =>
{
await Task.Delay(ConnectionTimeout);
connectTask.TrySetException(new TimeoutException());
});

await ApiClient.ConnectAsync().ConfigureAwait(false); await ApiClient.ConnectAsync().ConfigureAwait(false);
await _connectedEvent.InvokeAsync().ConfigureAwait(false); await _connectedEvent.InvokeAsync().ConfigureAwait(false);


@@ -249,6 +260,15 @@ namespace Discord.WebSocket


private async Task StartReconnectAsync(Exception ex) private async Task StartReconnectAsync(Exception ex)
{ {
if (ex == null)
{
if (_connectTask?.TrySetCanceled() ?? false) return;
}
else
{
if (_connectTask?.TrySetException(ex) ?? false) return;
}

await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
@@ -260,15 +280,6 @@ namespace Discord.WebSocket
} }
private async Task ReconnectInternalAsync(Exception ex, CancellationToken cancelToken) private async Task ReconnectInternalAsync(Exception ex, CancellationToken cancelToken)
{ {
if (ex == null)
{
if (_connectTask?.TrySetCanceled() ?? false) return;
}
else
{
if (_connectTask?.TrySetException(ex) ?? false) return;
}

try try
{ {
Random jitter = new Random(); Random jitter = new Random();


+ 4
- 2
src/Discord.Net/WebSocket/DiscordSocketConfig.cs View File

@@ -8,6 +8,9 @@ namespace Discord.WebSocket
{ {
public const string GatewayEncoding = "json"; public const string GatewayEncoding = "json";


/// <summary> Gets or sets the time, in milliseconds, to wait for a connection to complete before aborting. </summary>
public int ConnectionTimeout { get; set; } = 30000;

/// <summary> Gets or sets the id for this shard. Must be less than TotalShards. </summary> /// <summary> Gets or sets the id for this shard. Must be less than TotalShards. </summary>
public int ShardId { get; set; } = 0; public int ShardId { get; set; } = 0;
/// <summary> Gets or sets the total number of shards for this application. </summary> /// <summary> Gets or sets the total number of shards for this application. </summary>
@@ -16,8 +19,7 @@ namespace Discord.WebSocket
/// <summary> Gets or sets the number of messages per channel that should be kept in cache. Setting this to zero disables the message cache entirely. </summary> /// <summary> Gets or sets the number of messages per channel that should be kept in cache. Setting this to zero disables the message cache entirely. </summary>
public int MessageCacheSize { get; set; } = 0; public int MessageCacheSize { get; set; } = 0;
/// <summary> /// <summary>
/// Gets or sets the max number of users a guild may have for offline users to be included in the READY packet. Max is 250.
/// Decreasing this may reduce CPU usage while increasing login time and network usage.
/// Gets or sets the max number of users a guild may have for offline users to be included in the READY packet. Max is 250.
/// </summary> /// </summary>
public int LargeThreshold { get; set; } = 250; public int LargeThreshold { get; set; } = 250;




Loading…
Cancel
Save