@@ -6,7 +6,6 @@ using Discord.Rest; | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
using System; | |||
using System.Runtime.InteropServices; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
@@ -21,9 +20,13 @@ namespace Discord.Rpc | |||
private CancellationTokenSource _cancelToken, _reconnectCancelToken; | |||
private Task _reconnectTask; | |||
private bool _canReconnect; | |||
private int _connectionTimeout; | |||
public ConnectionState ConnectionState { get; private set; } | |||
//From DiscordRpcConfig | |||
internal int ConnectionTimeout { get; private set; } | |||
public new API.DiscordRpcApiClient ApiClient => base.ApiClient as API.DiscordRpcApiClient; | |||
/// <summary> Creates a new RPC discord client. </summary> | |||
@@ -32,6 +35,7 @@ namespace Discord.Rpc | |||
public DiscordRpcClient(DiscordRpcConfig config) | |||
: base(config, CreateApiClient(config)) | |||
{ | |||
ConnectionTimeout = config.ConnectionTimeout; | |||
_rpcLogger = LogManager.CreateLogger("RPC"); | |||
_serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() }; | |||
@@ -95,8 +99,17 @@ namespace Discord.Rpc | |||
await _rpcLogger.InfoAsync("Connecting").ConfigureAwait(false); | |||
try | |||
{ | |||
_connectTask = new TaskCompletionSource<bool>(); | |||
var connectTask = new TaskCompletionSource<bool>(); | |||
_connectTask = connectTask; | |||
_cancelToken = new CancellationTokenSource(); | |||
//Abort connection on timeout | |||
Task.Run(async () => | |||
{ | |||
await Task.Delay(_connectionTimeout); | |||
connectTask.TrySetException(new TimeoutException()); | |||
}); | |||
await ApiClient.ConnectAsync().ConfigureAwait(false); | |||
await _connectedEvent.InvokeAsync().ConfigureAwait(false); | |||
@@ -17,9 +17,12 @@ namespace Discord.Rpc | |||
} | |||
/// <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> | |||
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> | |||
public WebSocketProvider WebSocketProvider { get; set; } = () => new DefaultWebSocketClient(); | |||
@@ -51,6 +51,7 @@ namespace Discord.WebSocket | |||
internal int LargeThreshold { get; private set; } | |||
internal AudioMode AudioMode { get; private set; } | |||
internal DataStore DataStore { get; private set; } | |||
internal int ConnectionTimeout { get; private set; } | |||
internal WebSocketProvider WebSocketProvider { get; private set; } | |||
public new API.DiscordSocketApiClient ApiClient => base.ApiClient as API.DiscordSocketApiClient; | |||
@@ -70,6 +71,7 @@ namespace Discord.WebSocket | |||
LargeThreshold = config.LargeThreshold; | |||
AudioMode = config.AudioMode; | |||
WebSocketProvider = config.WebSocketProvider; | |||
ConnectionTimeout = config.ConnectionTimeout; | |||
DataStore = new DataStore(0, 0); | |||
_nextAudioId = 1; | |||
@@ -158,8 +160,17 @@ namespace Discord.WebSocket | |||
try | |||
{ | |||
_connectTask = new TaskCompletionSource<bool>(); | |||
var connectTask = new TaskCompletionSource<bool>(); | |||
_connectTask = connectTask; | |||
_cancelToken = new CancellationTokenSource(); | |||
//Abort connection on timeout | |||
Task.Run(async () => | |||
{ | |||
await Task.Delay(ConnectionTimeout); | |||
connectTask.TrySetException(new TimeoutException()); | |||
}); | |||
await ApiClient.ConnectAsync().ConfigureAwait(false); | |||
await _connectedEvent.InvokeAsync().ConfigureAwait(false); | |||
@@ -249,6 +260,15 @@ namespace Discord.WebSocket | |||
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); | |||
try | |||
{ | |||
@@ -260,15 +280,6 @@ namespace Discord.WebSocket | |||
} | |||
private async Task ReconnectInternalAsync(Exception ex, CancellationToken cancelToken) | |||
{ | |||
if (ex == null) | |||
{ | |||
if (_connectTask?.TrySetCanceled() ?? false) return; | |||
} | |||
else | |||
{ | |||
if (_connectTask?.TrySetException(ex) ?? false) return; | |||
} | |||
try | |||
{ | |||
Random jitter = new Random(); | |||
@@ -8,6 +8,9 @@ namespace Discord.WebSocket | |||
{ | |||
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> | |||
public int ShardId { get; set; } = 0; | |||
/// <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> | |||
public int MessageCacheSize { get; set; } = 0; | |||
/// <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> | |||
public int LargeThreshold { get; set; } = 250; | |||