Beispiel #1
0
        private void Socket_OnFatalDisconnection(object sender, GatewayCloseCode e)
        {
            if (isDisposed)
            {
                return;
            }

            log.LogVerbose("Fatal disconnection occured, setting state to Disconnected.");
            state = GatewayState.Disconnected;

            (string message, ShardFailureReason reason) = GatewayCloseCodeToReason(e);
            gatewayFailureData = new GatewayFailureData(message, reason, null);
            handshakeCompleteEvent.Set();

            OnFailure?.Invoke(this, gatewayFailureData);
        }
Beispiel #2
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;
            }
        }
        public DiscordSocketClient(DiscordSocketConfig config = null) : base()
        {
            RequestLock = new object();

            if (config == null)
            {
                config = new DiscordSocketConfig();
            }

            Config      = new LockedSocketConfig(config);
            base.Config = Config;

            FinishConfig();

            if (Config.Cache)
            {
                GuildCache             = new ConcurrentDictionary <ulong, SocketGuild>();
                PrivateChannels        = new ConcurrentList <PrivateChannel>();
                Presences              = new ConcurrentDictionary <ulong, DiscordPresence>();
                VoiceStates            = new AutoConcurrentDictionary <ulong, DiscordVoiceStateContainer>((userId) => new DiscordVoiceStateContainer(userId));
                GuildSettings          = new ConcurrentDictionary <ulong, ClientGuildSettings>();
                PrivateChannelSettings = new List <DiscordChannelSettings>();
                ClientMembers          = new ConcurrentDictionary <ulong, GuildMember>();
            }

            WebSocket = new DiscordWebSocket <GatewayOpcode>($"wss://gateway.discord.gg/?v={Config.ApiVersion}&encoding=json");

            WebSocket.OnClosed += (s, args) =>
            {
                State = GatewayConnectionState.NotConnected;

                Reset();

                bool lostConnection = args.Code == 1006 || args.Code == 1001;

                if (lostConnection)
                {
                    Thread.Sleep(200);
                }

                GatewayCloseCode err = (GatewayCloseCode)args.Code;

                if (LoggedIn && (lostConnection || err == GatewayCloseCode.RateLimited || err == GatewayCloseCode.SessionTimedOut || err == GatewayCloseCode.UnknownError))
                {
                    Login(Token);
                }
                else
                {
                    OnLoggedOut?.Invoke(this, new LogoutEventArgs(err, args.Reason));
                }
            };

            WebSocket.OnMessageReceived += WebSocket_OnMessageReceived;

            VoiceClients = new VoiceClientDictionary(this);

            OnMediaServer += (s, e) =>
            {
                if (e.StreamKey == null)
                {
                    if (e.Guild == null)
                    {
                        VoiceClients.Private.SetServer(e);
                    }
                    else
                    {
                        VoiceClients[e.Guild.Id].SetServer(e);
                    }
                }
                else
                {
                    var key = new StreamKey(e.StreamKey);
                    VoiceClients[key.GuildId].Livestream.SetSessionServer(key.UserId, e);
                }
            };
        }
Beispiel #4
0
        public DiscordSocketClient(DiscordSocketConfig config = null) : base()
        {
            RequestLock = new object();

            if (config == null)
            {
                config = new DiscordSocketConfig();
            }

            Config      = new LockedSocketConfig(config);
            base.Config = Config;

            FinishConfig();

            if (Config.Cache)
            {
                GuildCache             = new ConcurrentDictionary <ulong, SocketGuild>();
                PrivateChannels        = new ConcurrentList <PrivateChannel>();
                VoiceStates            = new AutoConcurrentDictionary <ulong, DiscordVoiceStateContainer>((userId) => new DiscordVoiceStateContainer(userId));
                GuildSettings          = new ConcurrentDictionary <ulong, ClientGuildSettings>();
                PrivateChannelSettings = new List <DiscordChannelSettings>();
            }

            VoiceSessions = new ConcurrentDictionary <ulong, DiscordVoiceSession>();
            Livestreams   = new ConcurrentDictionary <string, DiscordGoLiveSession>();

            WebSocket = new DiscordWebSocket <GatewayOpcode>($"wss://gateway.discord.gg/?v={Config.ApiVersion}&encoding=json");

            WebSocket.OnClosed += (s, args) =>
            {
                State = GatewayConnectionState.NotConnected;

                Reset();

                bool lostConnection = args.Code == 1006 || args.Code == 1001;

                if (lostConnection)
                {
                    Thread.Sleep(200);
                }

                GatewayCloseCode err = (GatewayCloseCode)args.Code;

                if (LoggedIn && (lostConnection || err == GatewayCloseCode.RateLimited || err == GatewayCloseCode.SessionTimedOut || err == GatewayCloseCode.UnknownError))
                {
                    Login(Token);
                }
                else
                {
                    OnLoggedOut?.Invoke(this, new LogoutEventArgs(err, args.Reason));
                }
            };

            WebSocket.OnMessageReceived += WebSocket_OnMessageReceived;

            #region media event handlers
            OnSessionVoiceState += (c, state) =>
            {
                lock (VoiceSessions.Lock)
                {
                    foreach (var session in VoiceSessions.Values)
                    {
                        if (session.GuildId == (state.Guild == null ? null : (ulong?)state.Guild.Id))
                        {
                            if (state.Channel == null || session.SessionId != state.SessionId)
                            {
                                session.Kill();
                            }
                            else if (state.SessionId == session.SessionId)
                            {
                                session.ChannelId = state.Channel.Id;
                            }

                            break;
                        }
                    }
                }
            };

            OnMediaServer += (c, args) =>
            {
                if (args.StreamKey == null)
                {
                    lock (VoiceSessions.Lock)
                    {
                        foreach (var session in VoiceSessions.Values)
                        {
                            if (args.GuildId == session.GuildId)
                            {
                                session.UpdateServer(args);

                                break;
                            }
                        }
                    }
                }
                else if (Livestreams.TryGetValue(args.StreamKey, out DiscordGoLiveSession session))
                {
                    args.GuildId = session.Guild.Id;
                    session.UpdateServer(args);

                    if (StreamKey.Deserialize(args.StreamKey).UserId == User.Id)
                    {
                        session.ParentSession.Livestream = session;
                    }
                    else
                    {
                        session.ParentSession.WatchingDictionary[args.StreamKey] = session;
                    }
                }
            };

            OnStreamUpdated += (c, update) =>
            {
                if (Livestreams.TryGetValue(update.StreamKey, out DiscordGoLiveSession session))
                {
                    session.Update(update);
                }
            };

            OnStreamDeleted += (c, delete) =>
            {
                if (Livestreams.TryGetValue(delete.StreamKey, out DiscordGoLiveSession session))
                {
                    Livestreams.Remove(delete.StreamKey);

                    if (delete.StreamKey.Split(':').Last() == User.Id.ToString())
                    {
                        session.ParentSession.Livestream = null;
                    }
                    else
                    {
                        session.ParentSession.WatchingDictionary.Remove(delete.StreamKey);
                    }

                    session.Disconnect(delete);
                }
            };
            #endregion
        }