Skip to content

Commit

Permalink
Small refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Dec 3, 2024
1 parent 18ee36d commit 6e4f840
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 76 deletions.
129 changes: 72 additions & 57 deletions ControlR.Agent.Common/Services/Windows/StreamerLauncherWindows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using ControlR.Agent.Common.Models;
using ControlR.Libraries.Shared.Constants;
using Result = ControlR.Libraries.Shared.Primitives.Result;
using Microsoft.Extensions.Options;

namespace ControlR.Agent.Common.Services.Windows;

Expand All @@ -14,11 +15,18 @@ internal class StreamerLauncherWindows(
IProcessManager processes,
ISystemEnvironment environment,
IStreamingSessionCache streamingSessionCache,
ISettingsProvider settings,
IFileSystem fileSystem,
ISettingsProvider settings,
ILogger<StreamerLauncherWindows> logger) : IStreamerLauncher
{
private readonly SemaphoreSlim _createSessionLock = new(1, 1);
private readonly IWin32Interop _win32Interop = win32Interop;
private readonly IProcessManager _processes = processes;
private readonly ISystemEnvironment _environment = environment;
private readonly IStreamingSessionCache _streamingSessionCache = streamingSessionCache;
private readonly IFileSystem _fileSystem = fileSystem;
private readonly ISettingsProvider _settings = settings;
private readonly ILogger<StreamerLauncherWindows> _logger = logger;

public async Task<Result> CreateSession(
Guid sessionId,
Expand All @@ -34,93 +42,56 @@ public async Task<Result> CreateSession(
{
var session = new StreamingSession(viewerConnectionId);

var serverUri = settings.ServerUri.ToString().TrimEnd('/');
var serverUri = _settings.ServerUri.ToString().TrimEnd('/');
var args =
$"--session-id {sessionId} --viewer-id {viewerConnectionId} --origin {serverUri} --websocket-uri {websocketUri} --notify-user {notifyViewerOnSessionStart}";
$"--session-id {sessionId} --origin {serverUri} --websocket-uri {websocketUri} --notify-user {notifyViewerOnSessionStart}";
if (!string.IsNullOrWhiteSpace(viewerName))
{
args += $" --viewer-name=\"{viewerName}\"";
}

logger.LogInformation("Launching remote control with args: {StreamerArguments}", args);
_logger.LogInformation("Launching remote control with args: {StreamerArguments}", args);

if (!environment.IsDebug)
if (_environment.IsDebug)
{
session.StreamerProcess = StartDebugSession(args);
if (session.StreamerProcess is null)
{
return Result.Fail("Failed to start remote control process.");
}
}
else
{
var startupDir = environment.StartupDirectory;
var startupDir = _environment.StartupDirectory;
var streamerDir = Path.Combine(startupDir, "Streamer");
var binaryPath = Path.Combine(streamerDir, AppConstants.StreamerFileName);

win32Interop.CreateInteractiveSystemProcess(
_win32Interop.CreateInteractiveSystemProcess(
commandLine: $"\"{binaryPath}\" {args}",
targetSessionId: targetWindowsSession,
hiddenWindow: true,
startedProcess: out var process);

if (process is null || process.Id == -1)
{
_logger.LogError("Failed to start remote control process. Removing files before next attempt.");
var streamerZipPath = Path.Combine(startupDir, AppConstants.StreamerZipFileName);
// Delete streamer files so a clean install will be performed on the next attempt.
fileSystem.DeleteDirectory(streamerDir, true);
fileSystem.DeleteFile(streamerZipPath);
_fileSystem.DeleteDirectory(streamerDir, true);
_fileSystem.DeleteFile(streamerZipPath);
return Result.Fail("Failed to start remote control process.");
}

session.StreamerProcess = process;
}
else
{
var solutionDirReult = GetSolutionDir(Environment.CurrentDirectory);

if (solutionDirReult.IsSuccess)
{
var streamerBin = Path.Combine(
solutionDirReult.Value,
"ControlR.Streamer",
"bin",
"Debug");

var streamerPath = fileSystem
.GetFiles(streamerBin, AppConstants.StreamerFileName, SearchOption.AllDirectories)
.OrderByDescending(x => new FileInfo(x).CreationTime)
.FirstOrDefault();

if (string.IsNullOrWhiteSpace(streamerPath))
{
throw new FileNotFoundException("Streamer binary not found.", streamerPath);
}

//var psi = new ProcessStartInfo()
//{
// FileName = "cmd.exe",
// Arguments = $"/k {streamerPath} {args}",
// WorkingDirectory = Path.GetDirectoryName(streamerPath),
// UseShellExecute = true
//};

var psi = new ProcessStartInfo
{
FileName = streamerPath,
Arguments = args,
WorkingDirectory = Path.GetDirectoryName(streamerPath),
UseShellExecute = true
};

session.StreamerProcess = processes.Start(psi);
}

if (session.StreamerProcess is null)
{
return Result.Fail("Failed to start remote control process.");
}
}

await streamingSessionCache.AddOrUpdate(session);
await _streamingSessionCache.AddOrUpdate(session);

return Result.Ok();
}
catch (Exception ex)
{
logger.LogError(ex, "Error while creating remote control session.");
_logger.LogError(ex, "Error while creating remote control session.");
return Result.Fail("An error occurred while starting remote control.");
}
finally
Expand All @@ -129,6 +100,50 @@ public async Task<Result> CreateSession(
}
}

private Process? StartDebugSession(string args)
{
var solutionDirReult = GetSolutionDir(Environment.CurrentDirectory);

if (!solutionDirReult.IsSuccess)
{
return null;
}

var streamerBin = Path.Combine(
solutionDirReult.Value,
"ControlR.Streamer",
"bin",
"Debug");

var streamerPath = _fileSystem
.GetFiles(streamerBin, AppConstants.StreamerFileName, SearchOption.AllDirectories)
.OrderByDescending(x => new FileInfo(x).CreationTime)
.FirstOrDefault();

if (string.IsNullOrWhiteSpace(streamerPath))
{
throw new FileNotFoundException("Streamer binary not found.", streamerPath);
}

//var psi = new ProcessStartInfo()
//{
// FileName = "cmd.exe",
// Arguments = $"/k {streamerPath} {args}",
// WorkingDirectory = Path.GetDirectoryName(streamerPath),
// UseShellExecute = true
//};

var psi = new ProcessStartInfo
{
FileName = streamerPath,
Arguments = args,
WorkingDirectory = Path.GetDirectoryName(streamerPath),
UseShellExecute = true
};

return _processes.Start(psi);
}

// For debugging.
private static Result<string> GetSolutionDir(string currentDir)
{
Expand Down
2 changes: 0 additions & 2 deletions ControlR.Streamer/Options/StartupOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ public Uri ServerOrigin

public Guid SessionId { get; set; }

public string ViewerConnectionId { get; set; } = string.Empty;

public string? ViewerName { get; set; }

public Uri WebSocketUri
Expand Down
16 changes: 3 additions & 13 deletions ControlR.Streamer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,6 @@
["-n", "--notify-user"],
"Whether to notify the user when a remote control session starts.");

var viewerIdOption = new Option<string>(
["-vi", "--viewer-id"],
"The connection ID of the viewer who is requesting the streaming session.")
{
IsRequired = true
};

var viewerNameOption = new Option<string?>(
["-vn", "--viewer-name"],
"The name of the viewer requesting the session.");
Expand All @@ -52,13 +45,12 @@
{
originUriOption,
websocketUriOption,
viewerIdOption,
notifyUserOption,
sessionIdOption,
viewerNameOption,
};

rootCommand.SetHandler(async (originUri, websocketUri, viewerConnectionId, notifyUser, sessionId, viewerName) =>
rootCommand.SetHandler(async (originUri, websocketUri, notifyUser, sessionId, viewerName) =>
{
var builder = Host.CreateApplicationBuilder(args);
var configuration = builder.Configuration;
Expand All @@ -73,10 +65,8 @@

services.Configure<StartupOptions>(options =>
{
options.ServerOrigin = originUri;
options.WebSocketUri = websocketUri;
options.NotifyUser = notifyUser;
options.ViewerConnectionId = viewerConnectionId;
options.ViewerName = viewerName;
options.SessionId = sessionId;
});
Expand All @@ -86,7 +76,7 @@
services.AddSingleton(WeakReferenceMessenger.Default);
services.AddSingleton<IWin32Interop, Win32Interop>();
services.AddSingleton<IToaster, Toaster>();
services.AddSingleton<IDesktopCapturer, DisplayManager>();
services.AddSingleton<IDesktopCapturer, DesktopCapturer>();
services.AddSingleton<IInputSimulator, InputSimulatorWindows>();
services.AddSingleton<IMemoryProvider, MemoryProvider>();
services.AddSingleton<ISystemTime, SystemTime>();
Expand All @@ -108,7 +98,7 @@
var host = builder.Build();
await host.RunAsync();

}, originUriOption, websocketUriOption, viewerIdOption, notifyUserOption, sessionIdOption, viewerNameOption);
}, originUriOption, websocketUriOption, notifyUserOption, sessionIdOption, viewerNameOption);

var exitCode = await rootCommand.InvokeAsync(args);
Environment.Exit(exitCode);
8 changes: 4 additions & 4 deletions ControlR.Streamer/Services/DesktopCapturer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal interface IDesktopCapturer
Task StartCapturingChanges();
}

internal class DisplayManager : IDesktopCapturer
internal class DesktopCapturer : IDesktopCapturer
{
private const int DefaultImageQuality = 75;
private const int MinimumQuality = 20;
Expand All @@ -36,7 +36,7 @@ internal class DisplayManager : IDesktopCapturer
private readonly IDelayer _delayer;
private readonly AutoResetEventAsync _frameReadySignal = new();
private readonly AutoResetEventAsync _frameRequestedSignal = new(true);
private readonly ILogger<DisplayManager> _logger;
private readonly ILogger<DesktopCapturer> _logger;
private readonly IMemoryProvider _memoryProvider;
private readonly IMessenger _messenger;
private readonly Stopwatch _metricsBroadcastTimer = Stopwatch.StartNew();
Expand All @@ -60,7 +60,7 @@ internal class DisplayManager : IDesktopCapturer
private DisplayInfo? _selectedDisplay;


public DisplayManager(
public DesktopCapturer(
IMessenger messenger,
IScreenCapturer screenCapturer,
IBitmapUtility bitmapUtility,
Expand All @@ -70,7 +70,7 @@ public DisplayManager(
IDelayer delayer,
IHostApplicationLifetime appLifetime,
IOptions<StartupOptions> startupOptions,
ILogger<DisplayManager> logger)
ILogger<DesktopCapturer> logger)
{
_messenger = messenger;
_screenCapturer = screenCapturer;
Expand Down

0 comments on commit 6e4f840

Please sign in to comment.