/// <summary>
        /// Read another message from the web socket and print it to the console
        /// </summary>
        /// <param name="connection">WebSocket connection</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Asynchronous task</returns>
        private static async Task ReadFromWebSocket(HttpEndpointConnection connection, CancellationToken cancellationToken)
        {
            // Note that no content has been received when we get here for the first time.
            // In this case, it may take a while before/if data can be received from the client
            do
            {
                ReceivedHttpRequest websocketRequest = await connection.ReadRequest(cancellationToken);

                Console.WriteLine(websocketRequest.Body);
            }while (!cancellationToken.IsCancellationRequested);
        }
        /// <summary>
        /// Read a message from the console and send it to the client
        /// </summary>
        /// <param name="connection">WebSocket connection</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>Asynchronous task</returns>
        private static async Task ReadFromConsole(HttpEndpointConnection connection, CancellationToken cancellationToken)
        {
            do
            {
                string input = await Task.Run(() => Console.ReadLine(), cancellationToken);

                if (input == "close")
                {
                    // Sending codes greater than or equal to 1000 closes the connection
                    await connection.SendResponse(1000, "Connection closed", HttpResponseType.StatusCode, cancellationToken);
                }
                else
                {
                    // Send input to the client
                    await connection.SendResponse(200, input, HttpResponseType.PlainText, cancellationToken);
                }
            }while (!cancellationToken.IsCancellationRequested);
        }
        /// <summary>
        /// Called when a new HTTP or WebSocket request has been received
        /// </summary>
        /// <param name="unixSocket">UNIX socket for HTTP endpoints</param>
        /// <param name="requestConnection">Connection from the UNIX socket representing the HTTP or WebSocket request</param>
        private static async void OnHttpRequestReceived(HttpEndpointUnixSocket unixSocket, HttpEndpointConnection requestConnection)
        {
            // Note that a call to ReadRequest can throw an exception in case DCS only created a test connection!
            // DCS may do that when an application attempts to register an existing endpoint twice

            if (_method == HttpEndpointType.WebSocket)
            {
                if (_websocketConnected)
                {
                    await requestConnection.SendResponse(1000, "Demo application only supports one WebSocket connection");

                    return;
                }

                _websocketConnected = true;
                if (!_quiet)
                {
                    Console.WriteLine("WebSocket connected, type 'close' to close this connection");
                }

                try
                {
                    using CancellationTokenSource cts = new CancellationTokenSource();
                    Task webSocketTask = ReadFromWebSocket(requestConnection, cts.Token);
                    Task consoleTask   = ReadFromConsole(requestConnection, cts.Token);

                    await Task.WhenAny(webSocketTask, consoleTask);

                    cts.Cancel();
                }
                catch (Exception e)
                {
                    if (!(e is OperationCanceledException) && !(e is SocketException))
                    {
                        Console.WriteLine("Unexpected error:");
                        Console.WriteLine(e);
                    }
                }
                finally
                {
                    _websocketConnected = false;
                    if (!_quiet)
                    {
                        Console.WriteLine("WebSocket disconnected");
                    }
                }
            }
            else
            {
                // Read the HTTP response from the client
                ReceivedHttpRequest request = await requestConnection.ReadRequest();

                if (string.IsNullOrWhiteSpace(_cmd))
                {
                    // Write this event to the console if possible
                    if (!_quiet)
                    {
                        Console.WriteLine("Got new HTTP request from session {0}", request.SessionId);
                    }

                    // Only print a demo response in case no process is supposed to be started
                    string response = $"This demo text has been returned from a third-party application.\n\nMethod: {_method}\nSession ID: {request.SessionId}";
                    if (request.Headers.Count > 0)
                    {
                        response += "\n\nHeaders:";
                        foreach (var kv in request.Headers)
                        {
                            response += $"\n{kv.Key} = {kv.Value}";
                        }
                    }
                    if (request.Queries.Count > 0)
                    {
                        response += "\n\nQueries:";
                        foreach (var kv in request.Queries)
                        {
                            response += $"\n{kv.Key} = {kv.Value}";
                        }
                    }
                    if (!string.IsNullOrWhiteSpace(request.Body))
                    {
                        response += "\n\nBody:\n" + request.Body;
                    }
                    await requestConnection.SendResponse(200, response, HttpResponseType.PlainText);
                }
                else
                {
                    // Replace query values in the arguments
                    string args = _cmd;
                    foreach (var kv in request.Queries)
                    {
                        args.Replace($"%{kv.Key}%", kv.Value);
                    }

                    // Prepare the process start info
                    using Process process = new Process
                          {
                              StartInfo = new ProcessStartInfo
                              {
                                  FileName  = _cmd,
                                  Arguments = args,
                                  RedirectStandardOutput = true
                              }
                          };

                    // Start a process and wait for it to exit
                    string output = "";
                    process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => output += e.Data;
                    process.ErrorDataReceived  += (object sender, DataReceivedEventArgs e) => output += e.Data;
                    if (process.Start())
                    {
                        process.BeginOutputReadLine();
                        process.BeginErrorReadLine();
                        process.WaitForExit();
                        await requestConnection.SendResponse(200, output, HttpResponseType.PlainText);
                    }
                    else
                    {
                        await requestConnection.SendResponse(501, "Failed to start process", HttpResponseType.StatusCode);
                    }
                }
            }
        }