Skip to content

Commit d4c533a

Browse files
Quahuquinchs
andauthored
Implemented resume_gateway_url. (#2423)
* Implemented resume_gateway_url. * Made the requested changes. * Implemented passing the gateway URL down from DiscordShardedClient. Co-authored-by: Quin Lynch <[email protected]>
1 parent 2a6fca6 commit d4c533a

File tree

4 files changed

+72
-9
lines changed

4 files changed

+72
-9
lines changed

src/Discord.Net.WebSocket/API/Gateway/ReadyEvent.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public class ReadState
2020
public User User { get; set; }
2121
[JsonProperty("session_id")]
2222
public string SessionId { get; set; }
23+
[JsonProperty("resume_gateway_url")]
24+
public string ResumeGatewayUrl { get; set; }
2325
[JsonProperty("read_state")]
2426
public ReadState[] ReadStates { get; set; }
2527
[JsonProperty("guilds")]

src/Discord.Net.WebSocket/DiscordShardedClient.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ private async Task ResetSemaphoresAsync()
139139

140140
internal override async Task OnLoginAsync(TokenType tokenType, string token)
141141
{
142+
var botGateway = await GetBotGatewayAsync().ConfigureAwait(false);
142143
if (_automaticShards)
143144
{
144-
var botGateway = await GetBotGatewayAsync().ConfigureAwait(false);
145145
_shardIds = Enumerable.Range(0, botGateway.Shards).ToArray();
146146
_totalShards = _shardIds.Length;
147147
_shards = new DiscordSocketClient[_shardIds.Length];
@@ -163,7 +163,12 @@ internal override async Task OnLoginAsync(TokenType tokenType, string token)
163163

164164
//Assume thread safe: already in a connection lock
165165
for (int i = 0; i < _shards.Length; i++)
166+
{
167+
// Set the gateway URL to the one returned by Discord, if a custom one isn't set.
168+
_shards[i].ApiClient.GatewayUrl = botGateway.Url;
169+
166170
await _shards[i].LoginAsync(tokenType, token);
171+
}
167172

168173
if(_defaultStickers.Length == 0 && _baseConfig.AlwaysDownloadDefaultStickers)
169174
await DownloadDefaultStickersAsync().ConfigureAwait(false);
@@ -175,7 +180,12 @@ internal override async Task OnLogoutAsync()
175180
if (_shards != null)
176181
{
177182
for (int i = 0; i < _shards.Length; i++)
183+
{
184+
// Reset the gateway URL set for the shard.
185+
_shards[i].ApiClient.GatewayUrl = null;
186+
178187
await _shards[i].LogoutAsync();
188+
}
179189
}
180190

181191
if (_automaticShards)

src/Discord.Net.WebSocket/DiscordSocketApiClient.cs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ internal class DiscordSocketApiClient : DiscordRestApiClient
2828
private readonly bool _isExplicitUrl;
2929
private CancellationTokenSource _connectCancelToken;
3030
private string _gatewayUrl;
31+
private string _resumeGatewayUrl;
3132

3233
//Store our decompression streams for zlib shared state
3334
private MemoryStream _compressed;
@@ -37,6 +38,32 @@ internal class DiscordSocketApiClient : DiscordRestApiClient
3738

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

41+
/// <summary>
42+
/// Sets the gateway URL used for identifies.
43+
/// </summary>
44+
/// <remarks>
45+
/// If a custom URL is set, setting this property does nothing.
46+
/// </remarks>
47+
public string GatewayUrl
48+
{
49+
set
50+
{
51+
// Makes the sharded client not override the custom value.
52+
if (_isExplicitUrl)
53+
return;
54+
55+
_gatewayUrl = FormatGatewayUrl(value);
56+
}
57+
}
58+
59+
/// <summary>
60+
/// Sets the gateway URL used for resumes.
61+
/// </summary>
62+
public string ResumeGatewayUrl
63+
{
64+
set => _resumeGatewayUrl = FormatGatewayUrl(value);
65+
}
66+
4067
public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent,
4168
string url = null, RetryMode defaultRetryMode = RetryMode.AlwaysRetry, JsonSerializer serializer = null,
4269
bool useSystemClock = true, Func<IRateLimitInfo, Task> defaultRatelimitCallback = null)
@@ -157,6 +184,17 @@ internal override ValueTask DisposeAsync(bool disposing)
157184
#endif
158185
}
159186

187+
/// <summary>
188+
/// Appends necessary query parameters to the specified gateway URL.
189+
/// </summary>
190+
private static string FormatGatewayUrl(string gatewayUrl)
191+
{
192+
if (gatewayUrl == null)
193+
return null;
194+
195+
return $"{gatewayUrl}?v={DiscordConfig.APIVersion}&encoding={DiscordSocketConfig.GatewayEncoding}&compress=zlib-stream";
196+
}
197+
160198
public async Task ConnectAsync()
161199
{
162200
await _stateLock.WaitAsync().ConfigureAwait(false);
@@ -191,24 +229,32 @@ internal override async Task ConnectInternalAsync()
191229
if (WebSocketClient != null)
192230
WebSocketClient.SetCancelToken(_connectCancelToken.Token);
193231

194-
if (!_isExplicitUrl)
232+
string gatewayUrl;
233+
if (_resumeGatewayUrl == null)
234+
{
235+
if (!_isExplicitUrl && _gatewayUrl == null)
236+
{
237+
var gatewayResponse = await GetBotGatewayAsync().ConfigureAwait(false);
238+
_gatewayUrl = FormatGatewayUrl(gatewayResponse.Url);
239+
}
240+
241+
gatewayUrl = _gatewayUrl;
242+
}
243+
else
195244
{
196-
var gatewayResponse = await GetGatewayAsync().ConfigureAwait(false);
197-
_gatewayUrl = $"{gatewayResponse.Url}?v={DiscordConfig.APIVersion}&encoding={DiscordSocketConfig.GatewayEncoding}&compress=zlib-stream";
245+
gatewayUrl = _resumeGatewayUrl;
198246
}
199247

200248
#if DEBUG_PACKETS
201-
Console.WriteLine("Connecting to gateway: " + _gatewayUrl);
249+
Console.WriteLine("Connecting to gateway: " + gatewayUrl);
202250
#endif
203251

204-
await WebSocketClient.ConnectAsync(_gatewayUrl).ConfigureAwait(false);
252+
await WebSocketClient.ConnectAsync(gatewayUrl).ConfigureAwait(false);
205253

206254
ConnectionState = ConnectionState.Connected;
207255
}
208256
catch
209257
{
210-
if (!_isExplicitUrl)
211-
_gatewayUrl = null; //Uncache in case the gateway url changed
212258
await DisconnectInternalAsync().ConfigureAwait(false);
213259
throw;
214260
}

src/Discord.Net.WebSocket/DiscordSocketClient.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@ private async Task OnConnectingAsync()
322322
}
323323
private async Task OnDisconnectingAsync(Exception ex)
324324
{
325-
326325
await _gatewayLogger.DebugAsync("Disconnecting ApiClient").ConfigureAwait(false);
327326
await ApiClient.DisconnectAsync(ex).ConfigureAwait(false);
328327

@@ -353,6 +352,10 @@ private async Task OnDisconnectingAsync(Exception ex)
353352
if (guild.IsAvailable)
354353
await GuildUnavailableAsync(guild).ConfigureAwait(false);
355354
}
355+
356+
_sessionId = null;
357+
_lastSeq = 0;
358+
ApiClient.ResumeGatewayUrl = null;
356359
}
357360

358361
/// <inheritdoc />
@@ -834,6 +837,7 @@ private async Task ProcessMessageAsync(GatewayOpCode opCode, int? seq, string ty
834837

835838
_sessionId = null;
836839
_lastSeq = 0;
840+
ApiClient.ResumeGatewayUrl = null;
837841

838842
if (_shardedClient != null)
839843
{
@@ -891,6 +895,7 @@ private async Task ProcessMessageAsync(GatewayOpCode opCode, int? seq, string ty
891895
AddPrivateChannel(data.PrivateChannels[i], state);
892896

893897
_sessionId = data.SessionId;
898+
ApiClient.ResumeGatewayUrl = data.ResumeGatewayUrl;
894899
_unavailableGuildCount = unavailableGuilds;
895900
CurrentUser = currentUser;
896901
_previousSessionUser = CurrentUser;

0 commit comments

Comments
 (0)