From 329ac46b52a71ec2852b89c75bad2ef7853d2a39 Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Sat, 1 Feb 2020 11:31:29 -0800 Subject: [PATCH] Kill chat process when pipe closes due to idle time. --- Agent/Models/ChatSession.cs | 13 ++++++++++++ Agent/Services/AppLauncher.cs | 17 ++++++++++------ Agent/Services/ChatClientService.cs | 22 ++++++++++++--------- ScreenCast.Core/Services/ChatHostService.cs | 18 ++++++++--------- 4 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 Agent/Models/ChatSession.cs diff --git a/Agent/Models/ChatSession.cs b/Agent/Models/ChatSession.cs new file mode 100644 index 00000000..f7bb0b2f --- /dev/null +++ b/Agent/Models/ChatSession.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Text; + +namespace Remotely.Agent.Models +{ + public class ChatSession + { + public int ProcessID { get; set; } + public NamedPipeClientStream PipeStream { get; set; } + } +} diff --git a/Agent/Services/AppLauncher.cs b/Agent/Services/AppLauncher.cs index ac781743..fe7bd168 100644 --- a/Agent/Services/AppLauncher.cs +++ b/Agent/Services/AppLauncher.cs @@ -21,7 +21,7 @@ namespace Remotely.Agent.Services private ConnectionInfo ConnectionInfo { get; } - public async Task LaunchChatService(string requesterID, HubConnection hubConnection) + public async Task LaunchChatService(string requesterID, HubConnection hubConnection) { try { @@ -39,21 +39,25 @@ namespace Remotely.Agent.Services if (Program.IsDebug) { - Process.Start("conhost.exe", $"{rcBinaryPath} -mode Chat -requester {requesterID}"); + return Process.Start("conhost.exe", $"{rcBinaryPath} -mode Chat -requester {requesterID}").Id; } else { - var result = Win32Interop.OpenInteractiveProcess($"{rcBinaryPath} -mode Chat -requester {requesterID}", "default", false, out _); + var result = Win32Interop.OpenInteractiveProcess($"{rcBinaryPath} -mode Chat -requester {requesterID}", "default", false, out var procInfo); if (!result) { await hubConnection.InvokeAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); } + else + { + return procInfo.dwProcessId; + } } } else if (OSUtils.IsLinux) { var args = $"xterm -e {rcBinaryPath} -mode Chat -requester {requesterID} & disown"; - StartLinuxScreenCaster(args); + return StartLinuxScreenCaster(args); } } catch (Exception ex) @@ -61,6 +65,7 @@ namespace Remotely.Agent.Services Logger.Write(ex); await hubConnection.InvokeAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); } + return -1; } public async Task LaunchRemoteControl(string requesterID, string serviceID, HubConnection hubConnection) @@ -155,7 +160,7 @@ namespace Remotely.Agent.Services } } - private void StartLinuxScreenCaster(string args) + private int StartLinuxScreenCaster(string args) { var xauthority = OSUtils.StartProcessWithResults("find", $"/ -name Xauthority").Split('\n', StringSplitOptions.RemoveEmptyEntries).First(); var display = ":0"; @@ -180,7 +185,7 @@ namespace Remotely.Agent.Services psi.Environment.Add("DISPLAY", display); psi.Environment.Add("XAUTHORITY", xauthority); Logger.Write($"Attempting to launch screen caster with username {username}, xauthority {xauthority}, and display {display}."); - Process.Start(psi); + return Process.Start(psi).Id; } } } diff --git a/Agent/Services/ChatClientService.cs b/Agent/Services/ChatClientService.cs index b2016a79..1dec4d72 100644 --- a/Agent/Services/ChatClientService.cs +++ b/Agent/Services/ChatClientService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.SignalR.Client; +using Remotely.Agent.Models; using Remotely.Shared.Services; using System; using System.Collections.Generic; @@ -27,7 +28,9 @@ namespace Remotely.Agent.Services SlidingExpiration = TimeSpan.FromMinutes(10), RemovedCallback = new CacheEntryRemovedCallback(args => { - (args.CacheItem.Value as NamedPipeClientStream).Dispose(); + var chatSession = (args.CacheItem.Value as ChatSession); + chatSession.PipeStream.Dispose(); + Process.GetProcessById(chatSession.ProcessID)?.Kill(); }) }; @@ -38,38 +41,39 @@ namespace Remotely.Agent.Services { if (await MessageLock.WaitAsync(30000)) { - NamedPipeClientStream clientPipe; + ChatSession chatSession; if (!ChatClients.Contains(senderConnectionID)) { var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ScreenCast", OSUtils.ScreenCastExecutableFileName); - await AppLauncher.LaunchChatService(senderConnectionID, hubConnection); + var procID = await AppLauncher.LaunchChatService(senderConnectionID, hubConnection); - clientPipe = new NamedPipeClientStream(".", "Remotely_Chat" + senderConnectionID, PipeDirection.InOut, PipeOptions.Asynchronous); + var clientPipe = new NamedPipeClientStream(".", "Remotely_Chat" + senderConnectionID, PipeDirection.InOut, PipeOptions.Asynchronous); clientPipe.Connect(15000); if (!clientPipe.IsConnected) { Logger.Write("Failed to connect to chat host."); return; } - ChatClients.Add(senderConnectionID, clientPipe, CacheItemPolicy); + chatSession = new ChatSession() { PipeStream = clientPipe, ProcessID = procID }; + ChatClients.Add(senderConnectionID, chatSession, CacheItemPolicy); } - clientPipe = (NamedPipeClientStream)ChatClients.Get(senderConnectionID); + chatSession = (ChatSession)ChatClients.Get(senderConnectionID); - if (!clientPipe.IsConnected) + if (!chatSession.PipeStream.IsConnected) { ChatClients.Remove(senderConnectionID); await hubConnection.SendAsync("DisplayMessage", "Chat disconnected. Please try again.", "Chat disconnected."); return; } - using (var sw = new StreamWriter(clientPipe, leaveOpen: true)) + using (var sw = new StreamWriter(chatSession.PipeStream, leaveOpen: true)) { await sw.WriteLineAsync(message); await sw.FlushAsync(); } - _ = Task.Run(async () => { await ReadFromStream(clientPipe, senderConnectionID, hubConnection); }); + _ = Task.Run(async () => { await ReadFromStream(chatSession.PipeStream, senderConnectionID, hubConnection); }); } } catch (Exception ex) diff --git a/ScreenCast.Core/Services/ChatHostService.cs b/ScreenCast.Core/Services/ChatHostService.cs index e79d5901..262f5e0d 100644 --- a/ScreenCast.Core/Services/ChatHostService.cs +++ b/ScreenCast.Core/Services/ChatHostService.cs @@ -46,16 +46,16 @@ namespace Remotely.ScreenCast.Core.Services Console.WriteLine("Connecting..."); Console.WriteLine(); - // Cancellation token doesn't work. - _ = Task.Run(async () => { - await Task.Delay(10000); - if (!NamedPipeStream.IsConnected) - { - await Close(); - } - }); var cts = new CancellationTokenSource(10000); - await NamedPipeStream.WaitForConnectionAsync(cts.Token); + try + { + await NamedPipeStream.WaitForConnectionAsync(cts.Token); + } + catch (TaskCanceledException) + { + await Close(); + return; + } _ = Task.Run(ReadFromStream); Console.WriteLine("You're now connected with a technician."); Console.WriteLine();