/// <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); } } } }