/// <summary>
        ///     Processes an incoming payload asynchronously.
        /// </summary>
        /// <remarks>
        ///     This method should not be called manually. It is called in the connection life cycle,
        ///     see: <see cref="RunLifeCycleAsync"/>.
        /// </remarks>
        /// <returns>a task that represents the asynchronous operation</returns>
        /// <exception cref="ObjectDisposedException">thrown if the instance is disposed</exception>
        private async Task ProcessNextPayload()
        {
            EnsureNotDisposed();

            WebSocketReceiveResult result;

            try
            {
                result = await _webSocket !.ReceiveAsync(new ArraySegment <byte>(_receiveBuffer, 0, _receiveBuffer.Length), _cancellationTokenSource !.Token);
            }
            catch (WebSocketException ex)
            {
                if (_cancellationTokenSource !.IsCancellationRequested)
                {
                    return;
                }

                Logger?.Log(ex, "Lavalink Node disconnected (without handshake, maybe connection loss or server crash)");
                await OnDisconnectedAsync(new DisconnectedEventArgs(_webSocketUri, WebSocketCloseStatus.Empty, string.Empty, true));

                _webSocket?.Dispose();
                _webSocket = null;
                return;
            }

            // check if the web socket received a close frame
            if (result.MessageType == WebSocketMessageType.Close)
            {
                Logger?.Log(this, string.Format("Lavalink Node disconnected: {0}, {1}.", result.CloseStatus.GetValueOrDefault(), result.CloseStatusDescription), LogLevel.Warning);
                await OnDisconnectedAsync(new DisconnectedEventArgs(_webSocketUri, result.CloseStatus.GetValueOrDefault(), result.CloseStatusDescription, true));

                _webSocket.Dispose();
                _webSocket = null;
                return;
            }

            var content = Encoding.UTF8.GetString(_receiveBuffer, 0, result.Count);

            if (!result.EndOfMessage)
            {
                // the server sent a message frame that is incomplete
                _overflowBuffer.Append(content);
                return;
            }

            // check if old data exists
            if (result.EndOfMessage && _overflowBuffer.Length > 0)
            {
                _overflowBuffer.Append(content);
                content = _overflowBuffer.ToString();
                _overflowBuffer.Clear();
            }

            if (_ioDebug)
            {
                Logger?.Log(this, string.Format("Received payload: `{0}` from: {1}.", content, _webSocketUri), LogLevel.Trace);
            }

            // process data
            try
            {
                var payload   = PayloadConverter.ReadPayload(content);
                var eventArgs = new PayloadReceivedEventArgs(payload, content);
                await OnPayloadReceived(eventArgs);
            }
            catch (Exception ex)
            {
                Logger?.Log(this, string.Format("Received bad payload: {0}.", content), LogLevel.Warning, ex);
                await CloseAsync(WebSocketCloseStatus.InvalidPayloadData);
            }
        }