private static async Task StartWebSocketAsync(
        TcpClient tcpClient,
        CancellationTokenSource innerCancellationTokenSource)
    {
        //var client = new MessageWebsocketRx(tcpClient)
        var client = new MessageWebsocketRx(tcpClient, hasTransferTcpSocketLifeCycleOwnership: false)
        {
            IgnoreServerCertificateErrors = true,
            Headers = new Dictionary <string, string> {
                { "Pragma", "no-cache" }, { "Cache-Control", "no-cache" }
            },
            TlsProtocolType = SslProtocols.Tls12,
            //ExcludeZeroApplicationDataInPong = true,
        };

        Console.WriteLine("Start");

        var websocketConnectionObservable =
            client.WebsocketConnectWithStatusObservable(
                uri: new Uri(WebsocketTestServerUrl),
                hasClientPing: true,
                clientPingInterval: TimeSpan.FromSeconds(10),
                clientPingMessage: "ping message");

        var disposableConnectionStatus = websocketConnectionObservable
                                         .Do(tuple =>
        {
            Console.ForegroundColor = (int)tuple.state switch
            {
                >= 1000 and <= 1999 => ConsoleColor.Magenta,
                >= 2000 and <= 2999 => ConsoleColor.Green,
                >= 3000 and <= 3999 => ConsoleColor.Cyan,
                >= 4000 and <= 4999 => ConsoleColor.DarkYellow,
                _ => ConsoleColor.Gray,
            };
        internal static async Task <WebsocketService> Create(
            Func <bool> isSecureConnectionSchemeFunc,
            Func <object, X509Certificate, X509Chain, SslPolicyErrors, bool> validateServerCertificateFunc,
            EventLoopScheduler eventLoopScheduler,
            IObserver <ConnectionStatus> observerConnectionStatus,
            MessageWebsocketRx messageWebSocketRx)
        {
            var tcpConnectionHandler = new TcpConnectionService(
                isSecureConnectionSchemeFunc: isSecureConnectionSchemeFunc,
                validateServerCertificateFunc: validateServerCertificateFunc,
                connectTcpClientFunc: ConnectTcpClient,
                ReadOneByteFromStream,
                //readOneByteFunc: (stream, bytes, cts) => RunOnScheduler(ReadOneByteFromStream(stream, bytes, cts), eventLoopScheduler),
                connectionStatusAction: ConnectionStatusAction,
                messageWebSocketRx.HasTransferSocketLifeCycleOwnership,
                tcpClient: messageWebSocketRx.TcpClient);

            var websocketServices = new WebsocketService(
                new WebsocketConnectionHandler(
                    tcpConnectionHandler,
                    new WebsocketParserHandler(
                        tcpConnectionHandler),
                    ConnectionStatusAction,
                    (stream, connectionStatusAction) =>
                    new WebsocketSenderHandler(
                        tcpConnectionHandler,
                        ConnectionStatusAction,
                        //WriteToStream
                        (stream, bytes, cts) => RunOnScheduler(WriteToStream(stream, bytes, cts), eventLoopScheduler),
                        messageWebSocketRx.ExcludeZeroApplicationDataInPong
                        )
                    )
                );

            await Task.CompletedTask;

            return(websocketServices);

            void ConnectionStatusAction(ConnectionStatus status, Exception?ex)
            {
                if (status is ConnectionStatus.Disconnected)
                {
                    observerConnectionStatus.OnCompleted();
                }

                if (status is ConnectionStatus.Aborted)
                {
                    observerConnectionStatus.OnError(
                        ex ?? new WebsocketClientLiteException("Unknown error."));
                }
                observerConnectionStatus.OnNext(status);
            }

            async Task <bool> WriteToStream(Stream stream, byte[] byteArray, CancellationToken ct)
            {
                await stream.WriteAsync(byteArray, 0, byteArray.Length, ct).ConfigureAwait(false);

                await stream.FlushAsync().ConfigureAwait(false);

                return(true);
            }

            async Task <int> ReadOneByteFromStream(Stream stream, byte[] byteArray, CancellationToken ct)
            {
                try
                {
                    return(await stream.ReadAsync(byteArray, 0, byteArray.Length, ct).ConfigureAwait(false));
                }
                catch (OperationCanceledException)
                {
                    return(-1);
                }
            }

            async Task ConnectTcpClient(TcpClient tcpClient, Uri uri)
            => await tcpClient
            .ConnectAsync(uri.Host, uri.Port)
            .ConfigureAwait(false);

            // Running sends and/or writes on the Event Loop Scheduler serializes them.
            async Task <T> RunOnScheduler <T>(Task <T> task, IScheduler scheduler)
            => await task.ToObservable().ObserveOn(scheduler);
        }