diff --git a/ControlR.Agent/Interfaces/IDeviceDataGenerator.cs b/ControlR.Agent/Interfaces/IDeviceDataGenerator.cs index 5af7fc82..3a58cbb5 100644 --- a/ControlR.Agent/Interfaces/IDeviceDataGenerator.cs +++ b/ControlR.Agent/Interfaces/IDeviceDataGenerator.cs @@ -2,14 +2,14 @@ public interface IDeviceDataGenerator { - Task CreateDevice(double cpuUtilization, string deviceId); + Task CreateDevice(double cpuUtilization, Guid deviceId); string GetAgentVersion(); List GetAllDrives(); DeviceDto GetDeviceBase( - string deviceId, + Guid deviceId, string currentUser, List drives, double usedStorage, diff --git a/ControlR.Agent/Services/AgentHubConnection.cs b/ControlR.Agent/Services/AgentHubConnection.cs index 186f3138..0605ba0b 100644 --- a/ControlR.Agent/Services/AgentHubConnection.cs +++ b/ControlR.Agent/Services/AgentHubConnection.cs @@ -116,12 +116,9 @@ public Task> GetAgentAppSettings() [SupportedOSPlatform("windows6.0.6000")] public Task GetWindowsSessions() { - if (environmentHelper.Platform != SystemPlatform.Windows) - { - return Array.Empty().AsTaskResult(); - } - - return win32Interop.GetActiveSessions().ToArray().AsTaskResult(); + return environmentHelper.Platform == SystemPlatform.Windows + ? win32Interop.GetActiveSessions().ToArray().AsTaskResult() + : Array.Empty().AsTaskResult(); } public Task ReceiveAgentAppSettings(AgentAppSettings appSettings) diff --git a/ControlR.Agent/Services/Base/AgentInstallerBase.cs b/ControlR.Agent/Services/Base/AgentInstallerBase.cs index 2e78d460..d8de2343 100644 --- a/ControlR.Agent/Services/Base/AgentInstallerBase.cs +++ b/ControlR.Agent/Services/Base/AgentInstallerBase.cs @@ -27,10 +27,10 @@ protected async Task UpdateAppSettings(Uri? serverUri, string? authorizedKey, st logger.LogInformation("Setting server URI to {ServerUri}.", updatedServerUri); currentOptions.ServerUri = updatedServerUri; - if (string.IsNullOrWhiteSpace(currentOptions.DeviceId)) + if (currentOptions.DeviceId == Guid.Empty) { logger.LogInformation("DeviceId is empty. Generating new one."); - currentOptions.DeviceId = RandomGenerator.CreateDeviceToken(); + currentOptions.DeviceId = Guid.NewGuid(); } logger.LogInformation("Writing results to disk."); diff --git a/ControlR.Agent/Services/Base/DeviceDataGeneratorBase.cs b/ControlR.Agent/Services/Base/DeviceDataGeneratorBase.cs index de67eb2f..a11ce884 100644 --- a/ControlR.Agent/Services/Base/DeviceDataGeneratorBase.cs +++ b/ControlR.Agent/Services/Base/DeviceDataGeneratorBase.cs @@ -53,7 +53,7 @@ public List GetAllDrives() } public DeviceDto GetDeviceBase( - string deviceId, + Guid deviceId, string currentUser, List drives, double usedStorage, diff --git a/ControlR.Agent/Services/Linux/DeviceGeneratorLinux.cs b/ControlR.Agent/Services/Linux/DeviceGeneratorLinux.cs index 52a47099..d47c4df4 100644 --- a/ControlR.Agent/Services/Linux/DeviceGeneratorLinux.cs +++ b/ControlR.Agent/Services/Linux/DeviceGeneratorLinux.cs @@ -12,7 +12,7 @@ internal class DeviceDataGeneratorLinux( private readonly ILogger _logger = logger; private readonly IProcessManager _processInvoker = processInvoker; - public async Task CreateDevice(double cpuUtilization, string deviceId) + public async Task CreateDevice(double cpuUtilization, Guid deviceId) { try { diff --git a/ControlR.Agent/Services/Mac/DeviceGeneratorMac.cs b/ControlR.Agent/Services/Mac/DeviceGeneratorMac.cs index 2b4d3d6a..482ca270 100644 --- a/ControlR.Agent/Services/Mac/DeviceGeneratorMac.cs +++ b/ControlR.Agent/Services/Mac/DeviceGeneratorMac.cs @@ -12,7 +12,7 @@ internal class DeviceDataGeneratorMac( private readonly ILogger _logger = logger; private readonly IProcessManager _processService = processInvoker; - public async Task CreateDevice(double cpuUtilization, string deviceId) + public async Task CreateDevice(double cpuUtilization, Guid deviceId) { try { diff --git a/ControlR.Agent/Services/SettingsProvider.cs b/ControlR.Agent/Services/SettingsProvider.cs index 954cc1d2..8c29c1d0 100644 --- a/ControlR.Agent/Services/SettingsProvider.cs +++ b/ControlR.Agent/Services/SettingsProvider.cs @@ -7,7 +7,7 @@ namespace ControlR.Agent.Services; internal interface ISettingsProvider { - string DeviceId { get; } + Guid DeviceId { get; } bool IsConnectedToPublicServer { get; } Uri ServerUri { get; } string GetAppSettingsPath(); @@ -23,7 +23,7 @@ internal class SettingsProvider( private readonly JsonSerializerOptions _jsonOptions = new() { WriteIndented = true }; private readonly SemaphoreSlim _updateLock = new(1, 1); - public string DeviceId => appOptions.CurrentValue.DeviceId; + public Guid DeviceId => appOptions.CurrentValue.DeviceId; public Uri ServerUri => appOptions.CurrentValue.ServerUri ?? diff --git a/ControlR.Agent/Services/Windows/DeviceDataGeneratorWin.cs b/ControlR.Agent/Services/Windows/DeviceDataGeneratorWin.cs index f96f7ca3..412eb8f8 100644 --- a/ControlR.Agent/Services/Windows/DeviceDataGeneratorWin.cs +++ b/ControlR.Agent/Services/Windows/DeviceDataGeneratorWin.cs @@ -14,7 +14,7 @@ internal class DeviceDataGeneratorWin( { private readonly ILogger _logger = logger; - public async Task CreateDevice(double cpuUtilization, string deviceId) + public async Task CreateDevice(double cpuUtilization, Guid deviceId) { try { diff --git a/ControlR.Viewer/Services/DevicesCache.cs b/ControlR.Viewer/Services/DevicesCache.cs index f327f737..00e78d13 100644 --- a/ControlR.Viewer/Services/DevicesCache.cs +++ b/ControlR.Viewer/Services/DevicesCache.cs @@ -18,13 +18,13 @@ public interface IDeviceCache Task SetAllOffline(); - bool TryGet(string deviceId, [NotNullWhen(true)] out DeviceDto? device); + bool TryGet(Guid deviceId, [NotNullWhen(true)] out DeviceDto? device); } internal class DeviceCache(IFileSystem fileSystem, IFileIo fileIo, ILogger logger) : IDeviceCache { - private static readonly ConcurrentDictionary _cache = new(); + private static readonly ConcurrentDictionary _cache = new(); private static readonly SemaphoreSlim _fileLock = new(1, 1); private readonly string _deviceCachePath = Path.Combine(fileSystem.AppDataDirectory, "DeviceCache.json"); @@ -101,7 +101,7 @@ public async Task SetAllOffline() await TrySaveCache(); } - public bool TryGet(string deviceId, [NotNullWhen(true)] out DeviceDto? device) + public bool TryGet(Guid deviceId, [NotNullWhen(true)] out DeviceDto? device) { return _cache.TryGetValue(deviceId, out device); } diff --git a/ControlR.Viewer/Services/ViewerHubConnection.cs b/ControlR.Viewer/Services/ViewerHubConnection.cs index 3cf7f76e..7deb21a9 100644 --- a/ControlR.Viewer/Services/ViewerHubConnection.cs +++ b/ControlR.Viewer/Services/ViewerHubConnection.cs @@ -23,7 +23,7 @@ public interface IViewerHubConnection : IHubConnectionBase Task GetWebsocketBridgeOrigin(); Task> GetWindowsSessions(DeviceDto device); - Task InvokeCtrlAltDel(string deviceId); + Task InvokeCtrlAltDel(Guid deviceId); Task Reconnect(CancellationToken cancellationToken); @@ -103,7 +103,7 @@ await TryInvoke( } - public async Task CloseTerminalSession(string deviceId, Guid terminalId) + public async Task CloseTerminalSession(Guid deviceId, Guid terminalId) { await TryInvoke(async () => { @@ -204,7 +204,7 @@ await Connection.InvokeAsync(nameof(IViewerHub.GetWindowsSessi } } - public async Task InvokeCtrlAltDel(string deviceId) + public async Task InvokeCtrlAltDel(Guid deviceId) { await TryInvoke(async () => { diff --git a/ControlR.Web.Client/Services/DevicesCache.cs b/ControlR.Web.Client/Services/DevicesCache.cs index f73c2124..903028eb 100644 --- a/ControlR.Web.Client/Services/DevicesCache.cs +++ b/ControlR.Web.Client/Services/DevicesCache.cs @@ -15,12 +15,12 @@ public interface IDeviceCache Task SetAllOffline(); - bool TryGet(string deviceId, [NotNullWhen(true)] out DeviceDto? device); + bool TryGet(Guid deviceId, [NotNullWhen(true)] out DeviceDto? device); } internal class DeviceCache(ILogger logger) : IDeviceCache { - private static readonly ConcurrentDictionary _cache = new(); + private static readonly ConcurrentDictionary _cache = new(); private static readonly SemaphoreSlim _initLock = new(1, 1); public IEnumerable Devices => _cache.Values; @@ -68,7 +68,7 @@ public Task SetAllOffline() return Task.CompletedTask; } - public bool TryGet(string deviceId, [NotNullWhen(true)] out DeviceDto? device) + public bool TryGet(Guid deviceId, [NotNullWhen(true)] out DeviceDto? device) { return _cache.TryGetValue(deviceId, out device); } diff --git a/ControlR.Web.Client/Services/ViewerHubConnection.cs b/ControlR.Web.Client/Services/ViewerHubConnection.cs index d52a488e..9d3667f6 100644 --- a/ControlR.Web.Client/Services/ViewerHubConnection.cs +++ b/ControlR.Web.Client/Services/ViewerHubConnection.cs @@ -11,7 +11,7 @@ namespace ControlR.Web.Client.Services; public interface IViewerHubConnection : IHubConnectionBase { Task ClearAlert(); - Task CloseTerminalSession(string agentConnectionId, Guid terminalId); + Task CloseTerminalSession(Guid deviceId, Guid terminalId); Task> CreateTerminalSession(string agentConnectionId, Guid terminalId); @@ -23,7 +23,7 @@ public interface IViewerHubConnection : IHubConnectionBase Task GetWebsocketBridgeOrigin(); Task> GetWindowsSessions(DeviceDto device); - Task InvokeCtrlAltDel(string deviceId); + Task InvokeCtrlAltDel(Guid deviceId); Task Reconnect(CancellationToken cancellationToken); @@ -102,7 +102,7 @@ await TryInvoke( } - public async Task CloseTerminalSession(string deviceId, Guid terminalId) + public async Task CloseTerminalSession(Guid deviceId, Guid terminalId) { await TryInvoke(async () => { @@ -112,8 +112,7 @@ await TryInvoke(async () => }); } - public async Task> CreateTerminalSession(string agentConnectionId, - Guid terminalId) + public async Task> CreateTerminalSession(string agentConnectionId, Guid terminalId) { return await TryInvoke( async () => @@ -197,7 +196,7 @@ public async Task> GetWindowsSessions(DeviceDto device) } } - public async Task InvokeCtrlAltDel(string deviceId) + public async Task InvokeCtrlAltDel(Guid deviceId) { await TryInvoke(async () => { diff --git a/ControlR.Web.Server/Hubs/AgentHub.cs b/ControlR.Web.Server/Hubs/AgentHub.cs index b4e7cc1d..cd9597c3 100644 --- a/ControlR.Web.Server/Hubs/AgentHub.cs +++ b/ControlR.Web.Server/Hubs/AgentHub.cs @@ -53,7 +53,7 @@ public async Task UpdateDevice(DeviceDto device) // TODO: Save to DB. - await Groups.AddToGroupAsync(Context.ConnectionId, device.Id); + await Groups.AddToGroupAsync(Context.ConnectionId, HubGroupNames.GetDeviceGroupName(device.Id)); Device = device; diff --git a/ControlR.Web.Server/Hubs/HubGroupNames.cs b/ControlR.Web.Server/Hubs/HubGroupNames.cs index 848bef30..2ddb79df 100644 --- a/ControlR.Web.Server/Hubs/HubGroupNames.cs +++ b/ControlR.Web.Server/Hubs/HubGroupNames.cs @@ -2,5 +2,10 @@ public static class HubGroupNames { - public const string ServerAdministrators = "server-administrators"; -} + public const string ServerAdministrators = "server-administrators"; + + public static string GetDeviceGroupName(Guid deviceId) + { + return $"device-{deviceId}"; + } +} \ No newline at end of file diff --git a/ControlR.Web.Server/Hubs/ViewerHub.cs b/ControlR.Web.Server/Hubs/ViewerHub.cs index 3bc55d55..04ad9d2c 100644 --- a/ControlR.Web.Server/Hubs/ViewerHub.cs +++ b/ControlR.Web.Server/Hubs/ViewerHub.cs @@ -218,11 +218,11 @@ public async Task SendAlertBroadcast(AlertBroadcastDto alertDto) } } - public async Task SendDtoToAgent(string deviceId, DtoWrapper wrapper) + public async Task SendDtoToAgent(Guid deviceId, DtoWrapper wrapper) { using var scope = logger.BeginMemberScope(); - await agentHub.Clients.Group(deviceId).ReceiveDto(wrapper); + await agentHub.Clients.Group(HubGroupNames.GetDeviceGroupName(deviceId)).ReceiveDto(wrapper); } public Task SendDtoToUserGroups(DtoWrapper wrapper) diff --git a/ControlR.sln.DotSettings b/ControlR.sln.DotSettings index 7b0cca49..8d242280 100644 --- a/ControlR.sln.DotSettings +++ b/ControlR.sln.DotSettings @@ -19,4 +19,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/Libraries/ControlR.Libraries.Shared/Dtos/DeviceDto.cs b/Libraries/ControlR.Libraries.Shared/Dtos/DeviceDto.cs index f68e61c4..e72a48d0 100644 --- a/Libraries/ControlR.Libraries.Shared/Dtos/DeviceDto.cs +++ b/Libraries/ControlR.Libraries.Shared/Dtos/DeviceDto.cs @@ -35,7 +35,7 @@ public class DeviceDto [MsgPackKey] [Display(Name = "Device Id")] - public string Id { get; init; } = string.Empty; + public Guid Id { get; init; } [MsgPackKey] [Display(Name = "64-bit")] diff --git a/Libraries/ControlR.Libraries.Shared/Hubs/IViewerHub.cs b/Libraries/ControlR.Libraries.Shared/Hubs/IViewerHub.cs index 4e20b2d4..ea07ba78 100644 --- a/Libraries/ControlR.Libraries.Shared/Hubs/IViewerHub.cs +++ b/Libraries/ControlR.Libraries.Shared/Hubs/IViewerHub.cs @@ -6,26 +6,27 @@ namespace ControlR.Libraries.Shared.Hubs; public interface IViewerHub { - Task CheckIfServerAdministrator(); + Task CheckIfServerAdministrator(); - Task ClearAlert(); + Task ClearAlert(); - Task> CreateTerminalSession(string agentConnectionId, TerminalSessionRequest requestDto); + Task> CreateTerminalSession(string agentConnectionId, + TerminalSessionRequest requestDto); - Task> GetAgentAppSettings(string agentConnectionId); + Task> GetAgentAppSettings(string agentConnectionId); - Task> GetCurrentAlert(); + Task> GetCurrentAlert(); - Task> GetServerStats(); + Task> GetServerStats(); - Task GetWebSocketBridgeOrigin(); - Task GetWindowsSessions(string agentConnectionId); + Task GetWebSocketBridgeOrigin(); + Task GetWindowsSessions(string agentConnectionId); - Task RequestStreamingSession(string agentConnectionId, StreamerSessionRequestDto sessionRequestDto); - Task SendAgentAppSettings(string agentConnectionId, AgentAppSettings signedDto); + Task RequestStreamingSession(string agentConnectionId, StreamerSessionRequestDto sessionRequestDto); + Task SendAgentAppSettings(string agentConnectionId, AgentAppSettings signedDto); - Task SendAlertBroadcast(AlertBroadcastDto signedDto); - Task SendDtoToAgent(string deviceId, DtoWrapper wrapper); - Task SendDtoToUserGroups(DtoWrapper wrapper); - Task SendTerminalInput(string agentConnectionId, TerminalInputDto dto); + Task SendAlertBroadcast(AlertBroadcastDto signedDto); + Task SendDtoToAgent(Guid deviceId, DtoWrapper wrapper); + Task SendDtoToUserGroups(DtoWrapper wrapper); + Task SendTerminalInput(string agentConnectionId, TerminalInputDto dto); } \ No newline at end of file diff --git a/Libraries/ControlR.Libraries.Shared/Models/AgentAppOptions.cs b/Libraries/ControlR.Libraries.Shared/Models/AgentAppOptions.cs index f1f27b83..069850a7 100644 --- a/Libraries/ControlR.Libraries.Shared/Models/AgentAppOptions.cs +++ b/Libraries/ControlR.Libraries.Shared/Models/AgentAppOptions.cs @@ -9,7 +9,7 @@ public class AgentAppOptions public const string SectionKey = "AppOptions"; [MsgPackKey] - public string? DeviceId { get; set; } + public Guid DeviceId { get; set; } [MsgPackKey] public Uri? ServerUri { get; set; }