예제 #1
0
        private async Task <Server[]> HandshakeAsync(bool reconnect, bool resumable, GatewaySocket socket, IRef <bool> loop)
        {
            DiscordDebug.WriteLine("Getting Hello data...");
            ReceiveGatewayData data = await socket.ReadAsync();

            DiscordDebug.WriteLine("Got Hello data.");
            if (reconnect)
            {
                _listener.UpdateSocket(socket);
            }
            else
            {
                DiscordDebug.WriteLine("Initializing response listener and heartbeater...");
                _listener    = new ResponseListener(socket);
                _heartbeater = new GatewayHeartbeater(_listener, _seqMutex, () => _lastSequence, ConnectAsync);
                DiscordDebug.WriteLine("Response listener and heartbeater initialized.");
            }
            // Need to handle cases where heartbeat timer elapses, thus the event/semaphore model
            DiscordDebug.WriteLine("Waiting for initial heartbeat ack...");
            var  signal  = new Semaphore(0, 1);
            bool success = false;

            void EvtListener(object sender, bool e)
            {
                success = e;
                signal.Release();
            }

            _heartbeater.Started += EvtListener;
            _heartbeater.Start(data, reconnect);
            signal.WaitOne();
            _heartbeater.Started -= EvtListener;
            if (success)
            {
                DiscordDebug.WriteLine("Heartbeat ack heard.");
                return(await IdentAsync(reconnect, resumable));

                // ReSharper disable once RedundantIfElseBlock
            }
            else
            {
                DiscordDebug.WriteLine("Heartbeat ack not heard, trying again...");
                // Reconnect immediately
                await _heartbeater.AbortAsync();

                _heartbeater.Dispose();
                _listener.Dispose();
                loop.Value = true;
                return(null);
            }
        }
예제 #2
0
        internal async Task <Server[]> ConnectAsync(bool reconnect, bool resumable)
        {
            if (reconnect)
            {
                _dispatcher?.TearDown();
            }
            var loop  = new SharedRef <bool>(false);
            int loops = 0;

            DiscordDebug.WriteLine("Starting connection appempt...");
            Server[] res = null;
            do
            {
                if (loops >= _maxConnectAttempts)
                {
                    throw new GatewayConnectException("Gateway failed to connect " + _maxConnectAttempts + " times, and the connection attempt was aborted.");
                }
                loop.Value = false;
                await _connectMutex.WaitAsync();

                if (_listener == null)
                {
                    string url = await GetGatewayUrlAsync();

                    DiscordDebug.WriteLine("Opening socket...");
                    var socket = new GatewaySocket(this);
                    socket.Connect(url);
                    if (socket.State == WebSocketState.Open)
                    {
                        DiscordDebug.WriteLine("Socket opened.");
                        res = await HandshakeAsync(reconnect, resumable, socket, loop);
                    }
                    else
                    {
                        DiscordDebug.WriteLine("Socket opening failed, trying again...");
                        loop.Value = true;
                    }
                }
                _connectMutex.Release();
                loops++;
            } while (loop.Value);
            DiscordDebug.WriteLine("Connection attempt done.");
            // ReSharper disable once AssignNullToNotNullAttribute (null value is default to get compiler to shut up - whenever res is null, the loop should continue)
            return(res);
        }