Kill chat process when pipe closes due to idle time.

This commit is contained in:
Jared Goodwin 2020-02-01 11:31:29 -08:00
parent 9164c10490
commit 329ac46b52
4 changed files with 46 additions and 24 deletions

View File

@ -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; }
}
}

View File

@ -21,7 +21,7 @@ namespace Remotely.Agent.Services
private ConnectionInfo ConnectionInfo { get; }
public async Task LaunchChatService(string requesterID, HubConnection hubConnection)
public async Task<int> 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;
}
}
}

View File

@ -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)

View File

@ -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();