コード例 #1
0
        protected override void OnCloseReceived(WebSocketCloseStatus closeStatus, string closeDescription)
        {
            // If we initiated a disconnect, this is just the remote end's acknowledgment
            // and we should not start reconnecting
            if (areWeDisconnecting)
            {
                return;
            }

            GatewayCloseCode code = (GatewayCloseCode)closeStatus;

            switch (code)
            {
            case GatewayCloseCode.InvalidShard:
            case GatewayCloseCode.AuthenticationFailed:
            case GatewayCloseCode.ShardingRequired:
                // Not safe to reconnect
                log.LogError($"[{code} ({(int)code})] Unsafe to continue, NOT reconnecting gateway.");
                OnFatalDisconnection?.Invoke(this, code);
                break;

            case GatewayCloseCode.InvalidSeq:
            case GatewayCloseCode.InvalidSession:
            case GatewayCloseCode.SessionTimeout:
            case GatewayCloseCode.UnknownError:
                // Safe to reconnect, but needs a new session.
                OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(true));
                break;

            case GatewayCloseCode.NotAuthenticated:
                // This really should never happen, but will require a new session.
                log.LogWarning("[NotAuthenticated] Sent gateway payload before we identified!");
                OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(true));
                break;

            case GatewayCloseCode.RateLimited:
                // Doesn't require a new session, but we need to wait a bit.
                log.LogError("Gateway is being rate limited!");     // Error level because we have code that should prevent this.
                OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(false, 5000));
                break;

            default:
                // Safe to just resume
                OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(false));
                break;
            }
        }
コード例 #2
0
        void HandleInvalidSessionPayload(DiscordApiData payload, DiscordApiData data)
        {
            bool isResumable = data.ToBoolean().Value;

            if (isResumable)
            {
                // Resume
                log.LogInfo("[InvalidSession] Resuming...");
                OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(false, 5000));
            }
            else
            {
                // Start new session
                log.LogInfo("[InvalidSession] Starting new session...");
                OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(true, rnd.Next(1000, 5001)));
            }
        }
コード例 #3
0
 void HandleReconnectPayload(DiscordApiData payload, DiscordApiData data)
 {
     // Resume
     log.LogInfo("[Reconnect] Performing resume...");
     OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(false));
 }
コード例 #4
0
ファイル: GatewaySocket.cs プロジェクト: Perksey/Discore
        async Task HeartbeatLoop()
        {
            // Default to true for the first heartbeat payload we send.
            receivedHeartbeatAck = true;

            log.LogVerbose("[HeartbeatLoop] Begin.");

            while (State == WebSocketState.Open && !heartbeatCancellationSource.IsCancellationRequested)
            {
                if (receivedHeartbeatAck)
                {
                    receivedHeartbeatAck = false;

                    try
                    {
                        // Send heartbeat
                        await SendHeartbeatPayload().ConfigureAwait(false);
                    }
                    catch (InvalidOperationException)
                    {
                        // Socket was closed between the loop check and sending the heartbeat
                        break;
                    }
                    catch (DiscordWebSocketException dwex)
                    {
                        // Expected to be the socket closing while sending a heartbeat
                        if (dwex.Error != DiscordWebSocketError.ConnectionClosed)
                        {
                            // Unexpected errors may not be the socket closing/aborting, so just log and loop around.
                            log.LogError("[HeartbeatLoop] Unexpected error occured while sending a heartbeat: " +
                                         $"code = {dwex.Error}, error = {dwex}");
                        }
                        else
                        {
                            break;
                        }
                    }

                    try
                    {
                        // Wait heartbeat interval
                        await Task.Delay(heartbeatInterval, heartbeatCancellationSource.Token)
                        .ConfigureAwait(false);
                    }
                    catch (ObjectDisposedException)
                    {
                        // GatewaySocket was disposed between sending a heartbeat payload and beginning to wait
                        break;
                    }
                    catch (OperationCanceledException)
                    {
                        // Socket is disconnecting
                        break;
                    }
                }
                else
                {
                    // Gateway connection has timed out
                    log.LogInfo("Gateway connection timed out (did not receive ack for last heartbeat).");

                    // Notify that this connection needs to be resumed
                    OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(false));

                    break;
                }
            }

            log.LogVerbose($"[HeartbeatLoop] Done. isDisposed = {isDisposed}");
        }
コード例 #5
0
ファイル: GatewaySocket.cs プロジェクト: Perksey/Discore
 protected override void OnClosedPrematurely()
 {
     // Attempt to resume
     OnReconnectionRequired?.Invoke(this, new ReconnectionEventArgs(false));
 }