コード例 #1
0
        private async Task HeartbeatAsync()
        {
            await _ackMutex.WaitAsync();

            bool needRelease = true;

            try {
                if (_heardAck)
                {
                    _heardAck = false;
                }
                else
                {
                    await _connect(true, true);

                    _heardAck = false;
                    bool oldFire = _fire;
                    _fire = false;
                    _ackMutex.Release();
                    needRelease = false;
                    if (oldFire)
                    {
                        Started?.Invoke(this, false);
                    }
                }
            } finally {
                if (needRelease)
                {
                    _ackMutex.Release();
                }
            }
            await _seqMutex.WaitAsync();

            JObject obj;

            try {
                obj = SendGatewayData.Create(GatewayOpCode.Heartbeat, _seqGetter());
            } finally {
                _seqMutex.Release();
            }
            await _listener.SendAsync(obj, GatewayOpCode.HeartbeatAck);

            await _ackMutex.WaitAsync();

            try {
                _heardAck = true;
            } finally {
                _ackMutex.Release();
            }
        }
コード例 #2
0
ファイル: GatewayClient.cs プロジェクト: hujgup/DiscordApi
        private async Task <Server[]> IdentAsync(bool reconnect, bool resumable)
        {
            bool ident = true;

            if (reconnect && resumable)
            {
                ReceiveGatewayData resumed = await _listener.SendAsync(SendGatewayData.Create(GatewayOpCode.Resume, MakeResume()), new[] {
                    GatewayOpCode.Dispatch,
                    GatewayOpCode.InvalidSession
                }, GatewayEvent.Resumed.Id);

                ident = resumed.OpCode == GatewayOpCode.InvalidSession;
                if (ident)
                {
                    // Per specs, client must wait 1-5 seconds before sending a fresh Identify payload (https://discordapp.com/developers/docs/topics/gateway#resuming)
                    await Task.Delay(2000);
                }
            }
            await _asMutex.WaitAsync();

            bool needRelease = true;

            Server[] res = null;
            try {
                while (ident)
                {
                    DiscordDebug.WriteLine("Identing...");
                    ReceiveGatewayData ready = await _listener.SendAsync(SendGatewayData.Create(GatewayOpCode.Identify, (JObject)MakeIdentify()), new[] {
                        GatewayOpCode.Dispatch,
                        GatewayOpCode.InvalidSession
                    }, GatewayEvent.Ready.Id);

                    ident = ready.OpCode == GatewayOpCode.InvalidSession;
                    if (ident)
                    {
                        DiscordDebug.WriteLine("Ident rate-limited, waiting and trying again...");
                        // Per specs, the only case in which this occurs is when you hit the 5-second Identify rate limit (https://discordapp.com/developers/docs/topics/gateway#identifying)
                        await Task.Delay(5000);
                    }
                    else
                    {
                        DiscordDebug.WriteLine("Ident successful, copying session data...");
                        var readyData = (GatewayEvent.Ready)ready.Data;
                        _sessionId = readyData.SessionId;
                        DiscordDebug.WriteLine("Session data copied.");
                        DiscordDebug.WriteLine("Awaiting server create events (expecting [" + string.Join(", ", readyData.ServersToCreate) + "] (" + readyData.ServersToCreate.Count + "))...");
                        _awaitServers = readyData.ServersToCreate;
                        _listener.Listen(GuildCreate, _awaitServers.Count, GatewayOpCode.Dispatch, GatewayEvent.EvtServer.CreateId);
                        _asDone = new Semaphore(0, 1);
                        _asMutex.Release();
                        needRelease = false;
                        res         = readyData.ServersToCreate.Select(Server.GetCached).ToArray();
                        _asDone.WaitOne();
                        DiscordDebug.WriteLine("All expected server create events have occured.");
                    }
                    DiscordDebug.WriteLine("Ident done.");
                }
            } finally {
                if (needRelease)
                {
                    _asMutex.Release();
                }
            }
            DiscordDebug.WriteLine("Setting up event listener...");
            _dispatcher = new Dispatcher(this, _listener);
            DiscordDebug.WriteLine("Event listener set up.");
            DiscordDebug.WriteLine("Socket ready to use");
            // ReSharper disable once AssignNullToNotNullAttribute
            return(res);
        }