/// <summary> /// Disconnects this client from Discord. This method must be called when you are finished with this object. /// </summary> public void Disconnect() { _heartbeater.Dispose(); _dispatcher.TearDown(); _listener.Dispose(); _heartbeater = null; _listener = null; _dispatcher = null; // TODO: Disconnect }
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); } }