Skip to content

Commit

Permalink
Swap chat host/client roles.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Jan 27, 2021
1 parent 4cf06e4 commit 2fe3660
Show file tree
Hide file tree
Showing 18 changed files with 98 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Agent.Installer.Win/Agent.Installer.Win.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<OutputType>WinExe</OutputType>
<RootNamespace>Remotely.Agent.Installer.Win</RootNamespace>
<AssemblyName>Remotely_Installer</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
Expand Down
2 changes: 1 addition & 1 deletion Agent.Installer.Win/App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
2 changes: 1 addition & 1 deletion Agent/Models/ChatSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Remotely.Agent.Models
public class ChatSession
{
public int ProcessID { get; set; }
public NamedPipeClientStream PipeStream { get; set; }
public NamedPipeServerStream PipeStream { get; set; }
}
}
2 changes: 1 addition & 1 deletion Agent/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private static void BuildServices()
builder.AddConsole().AddDebug();
});
serviceCollection.AddSingleton<AgentSocket>();
serviceCollection.AddScoped<ChatClientService>();
serviceCollection.AddScoped<ChatHostService>();
serviceCollection.AddTransient<Bash>();
serviceCollection.AddTransient<CMD>();
serviceCollection.AddTransient<PSCore>();
Expand Down
4 changes: 2 additions & 2 deletions Agent/Services/AgentSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public AgentSocket(ConfigService configService,
Uninstaller uninstaller,
CommandExecutor commandExecutor,
ScriptRunner scriptRunner,
ChatClientService chatService,
ChatHostService chatService,
IAppLauncher appLauncher,
IUpdater updater)
{
Expand All @@ -40,7 +40,7 @@ public AgentSocket(ConfigService configService,
}
public bool IsConnected => HubConnection?.State == HubConnectionState.Connected;
private IAppLauncher AppLauncher { get; }
private ChatClientService ChatService { get; }
private ChatHostService ChatService { get; }
private CommandExecutor CommandExecutor { get; }
private ConfigService ConfigService { get; }
private ConnectionInfo ConnectionInfo { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

namespace Remotely.Agent.Services
{
public class ChatClientService
public class ChatHostService
{
public ChatClientService(IAppLauncher appLauncher)
public ChatHostService(IAppLauncher appLauncher)
{
AppLauncher = appLauncher;
}
Expand Down Expand Up @@ -71,15 +71,20 @@ public async Task SendMessage(string senderName,
Logger.Write($"Chat app did not start successfully.");
return;
}
var serverStream = new NamedPipeServerStream("Remotely_Chat" + senderConnectionID,
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous);

var clientPipe = new NamedPipeClientStream(".", "Remotely_Chat" + senderConnectionID, PipeDirection.InOut, PipeOptions.Asynchronous);
clientPipe.Connect(15000);
if (!clientPipe.IsConnected)
var cts = new CancellationTokenSource(15000);
await serverStream.WaitForConnectionAsync(cts.Token);
if (!serverStream.IsConnected)
{
Logger.Write("Failed to connect to chat host.");
Logger.Write("Failed to connect to chat client.");
return;
}
chatSession = new ChatSession() { PipeStream = clientPipe, ProcessID = procID };
chatSession = new ChatSession() { PipeStream = serverStream, ProcessID = procID };
_ = Task.Run(async () => { await ReadFromStream(chatSession.PipeStream, senderConnectionID, hubConnection); });
ChatClients.Add(senderConnectionID, chatSession, CacheItemPolicy);
}
Expand Down Expand Up @@ -108,11 +113,11 @@ public async Task SendMessage(string senderName,
}
}

private async Task ReadFromStream(NamedPipeClientStream clientPipe, string senderConnectionID, HubConnection hubConnection)
private async Task ReadFromStream(NamedPipeServerStream clientPipe, string senderConnectionID, HubConnection hubConnection)
{
using var sr = new StreamReader(clientPipe, leaveOpen: true);
while (clientPipe.IsConnected)
{
using var sr = new StreamReader(clientPipe, leaveOpen: true);
var messageJson = await sr.ReadLineAsync();
if (!string.IsNullOrWhiteSpace(messageJson))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Remotely.Desktop.Core.Interfaces
{
public interface IChatHostService
public interface IChatClientService
{
Task StartChat(string requesterID, string organizationName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,42 @@

namespace Remotely.Desktop.Core.Services
{
public class ChatHostService : IChatHostService
public class ChatClientService : IChatClientService
{
private readonly IChatUiService _chatUiService;

public ChatHostService(IChatUiService chatUiService)
public ChatClientService(IChatUiService chatUiService)
{
_chatUiService = chatUiService;
}

private NamedPipeServerStream NamedPipeStream { get; set; }
private NamedPipeClientStream NamedPipeStream { get; set; }
private StreamReader Reader { get; set; }
private StreamWriter Writer { get; set; }

public async Task StartChat(string requesterID, string organizationName)
{
NamedPipeStream = new NamedPipeServerStream("Remotely_Chat" + requesterID, PipeDirection.InOut, 10, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
NamedPipeStream = new NamedPipeClientStream(".", "Remotely_Chat" + requesterID, PipeDirection.InOut, PipeOptions.Asynchronous);
Writer = new StreamWriter(NamedPipeStream);
Reader = new StreamReader(NamedPipeStream);

var cts = new CancellationTokenSource(10000);

try
{
await NamedPipeStream.WaitForConnectionAsync(cts.Token);
await NamedPipeStream.ConnectAsync(15_000);
}
catch (TaskCanceledException)
{
Logger.Write("A chat session was attempted, but the client failed to connect in time.", Shared.Enums.EventType.Warning);
Environment.Exit(0);
}

if (!NamedPipeStream.IsConnected)
{
Logger.Write("Failed to connect to chat host.");
return;
}

_chatUiService.ChatWindowClosed += OnChatWindowClosed;

_chatUiService.ShowChatWindow(organizationName, Writer);
Expand All @@ -54,7 +60,6 @@ private void OnChatWindowClosed(object sender, EventArgs e)
{
try
{
NamedPipeStream?.Disconnect();
NamedPipeStream?.Dispose();
}
catch { }
Expand Down
4 changes: 2 additions & 2 deletions Desktop.Linux/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static async Task Main(string[] args)

if (Conductor.Mode == Core.Enums.AppMode.Chat)
{
await Services.GetRequiredService<IChatHostService>().StartChat(Conductor.RequesterID, Conductor.OrganizationName);
await Services.GetRequiredService<IChatClientService>().StartChat(Conductor.RequesterID, Conductor.OrganizationName);
}
else if (Conductor.Mode == Core.Enums.AppMode.Unattended)
{
Expand Down Expand Up @@ -107,7 +107,7 @@ private static void BuildServices()
serviceCollection.AddSingleton<ICasterSocket, CasterSocket>();
serviceCollection.AddSingleton<IdleTimer>();
serviceCollection.AddSingleton<Conductor>();
serviceCollection.AddSingleton<IChatHostService, ChatHostService>();
serviceCollection.AddSingleton<IChatClientService, ChatClientService>();
serviceCollection.AddSingleton<IChatUiService, ChatUiServiceLinux>();
serviceCollection.AddTransient<IScreenCapturer, ScreenCapturerLinux>();
serviceCollection.AddTransient<Viewer>();
Expand Down
4 changes: 2 additions & 2 deletions Desktop.Win/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public static void Main(string[] args)
StartUiThreads(false);
_ = Task.Run(async () =>
{
var chatService = Services.GetRequiredService<IChatHostService>();
var chatService = Services.GetRequiredService<IChatClientService>();
await chatService.StartChat(Conductor.RequesterID, Conductor.OrganizationName);
});
}
Expand Down Expand Up @@ -105,7 +105,7 @@ private static void BuildServices()
serviceCollection.AddSingleton<ICasterSocket, CasterSocket>();
serviceCollection.AddSingleton<IdleTimer>();
serviceCollection.AddSingleton<Conductor>();
serviceCollection.AddSingleton<IChatHostService, ChatHostService>();
serviceCollection.AddSingleton<IChatClientService, ChatClientService>();
serviceCollection.AddSingleton<IChatUiService, ChatUiServiceWin>();
serviceCollection.AddTransient<IScreenCapturer, ScreenCapturerWin>();
serviceCollection.AddTransient<Viewer>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@
<br />
<span asp-validation-for="AppSettingsInput.MaxConcurrentUpdates" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AppSettingsInput.MessageOfTheDay" class="control-label"></label>
<br />
<input asp-for="AppSettingsInput.MessageOfTheDay" class="form-control" />
<br />
<span asp-validation-for="AppSettingsInput.MessageOfTheDay" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AppSettingsInput.RedirectToHttps"></label>
<br />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ public class AppSettingsModel

[Display(Name = "Max Organizations")]
public int MaxOrganizationCount { get; set; }
[Display(Name = "Message of the Day")]
public string MessageOfTheDay { get; set; }

[Display(Name = "Redirect To HTTPS")]
public bool RedirectToHttps { get; set; }
Expand Down
11 changes: 11 additions & 0 deletions Server/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@page
@model IndexModel
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostEnv
@{
ViewData["Title"] = "Home";

}

@if (!User.Identity.IsAuthenticated)
Expand All @@ -10,6 +12,15 @@
}
else
{
if (!string.IsNullOrWhiteSpace(Model.Motd))
{
<div id="motdAlert" class="alert alert-info alert-dismissible mr-5" role="alert" hidden>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<span id="motdContentSpan">@Model.Motd</span>
</div>

}

<partial name="_LoadingWheel" model="Model" />
<partial name="_IndexLoggedIn" model="Model" />
}
38 changes: 23 additions & 15 deletions Server/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,72 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Remotely.Server.Services;
using Remotely.Shared.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Remotely.Server.Pages
{
public class IndexModel : PageModel
{
private readonly IApplicationConfig _appConfig;

private readonly IDataService _dataService;

private readonly SignInManager<RemotelyUser> _signInManager;

public IndexModel(IDataService dataService,
SignInManager<RemotelyUser> signInManager,
IApplicationConfig appConfig)
{
DataService = dataService;
SignInManager = signInManager;
AppConfig = appConfig;
_dataService = dataService;
_signInManager = signInManager;
_appConfig = appConfig;
}

public List<Alert> Alerts { get; set; } = new List<Alert>();
public string DefaultPrompt { get; set; }
public string Motd { get; set; }
public List<SelectListItem> DeviceGroups { get; set; } = new List<SelectListItem>();
public List<Alert> Alerts { get; set; } = new List<Alert>();
private IApplicationConfig AppConfig { get; }
private IDataService DataService { get; }
private SignInManager<RemotelyUser> SignInManager { get; }
public async Task<IActionResult> OnGet()
{
if (User?.Identity?.IsAuthenticated == true)
{
var user = DataService.GetUserByName(User.Identity.Name);
var user = _dataService.GetUserByName(User.Identity.Name);
if (user is null)
{
await SignInManager.SignOutAsync();
await _signInManager.SignOutAsync();
return RedirectToPage();
}

if (AppConfig.Require2FA && !user.TwoFactorEnabled)
if (_appConfig.Require2FA && !user.TwoFactorEnabled)
{
return RedirectToPage("TwoFactorRequired");
}

DefaultPrompt = DataService.GetDefaultPrompt(User.Identity.Name);
var groups = DataService.GetDeviceGroups(User.Identity.Name);
DefaultPrompt = _dataService.GetDefaultPrompt(User.Identity.Name);
var groups = _dataService.GetDeviceGroups(User.Identity.Name);
if (groups?.Any() == true)
{
DeviceGroups.AddRange(groups.Select(x => new SelectListItem(x.Name, x.ID)));
}
var alerts = DataService.GetAlerts(user.Id);
var alerts = _dataService.GetAlerts(user.Id);
if (alerts.Any())
{
Alerts.AddRange(alerts);
}

Motd = _appConfig.MessageOfTheDay;
}
else
{
DefaultPrompt = DataService.GetDefaultPrompt();
DefaultPrompt = _dataService.GetDefaultPrompt();
}

return Page();
Expand Down
2 changes: 2 additions & 0 deletions Server/Services/ApplicationConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public interface IApplicationConfig
string[] KnownProxies { get; }
int MaxConcurrentUpdates { get; }
int MaxOrganizationCount { get; }
string MessageOfTheDay { get; }
bool RedirectToHttps { get; }
bool RemoteControlNotifyUser { get; }
bool RemoteControlRequiresAuthentication { get; }
Expand Down Expand Up @@ -58,6 +59,7 @@ public ApplicationConfig(IConfiguration config)
public string[] KnownProxies => Config.GetSection("ApplicationOptions:KnownProxies").Get<string[]>() ?? new string[0];
public int MaxConcurrentUpdates => int.Parse(Config["ApplicationOptions:MaxConcurrentUpdates"] ?? "10");
public int MaxOrganizationCount => int.Parse(Config["ApplicationOptions:MaxOrganizationCount"] ?? "1");
public string MessageOfTheDay => Config["ApplicationOptions:MessageOfTheDay"];
public bool RedirectToHttps => bool.Parse(Config["ApplicationOptions:RedirectToHttps"] ?? "false");
public bool RemoteControlNotifyUser => bool.Parse(Config["ApplicationOptions:RemoteControlNotifyUser"] ?? "true");
public bool RemoteControlRequiresAuthentication => bool.Parse(Config["ApplicationOptions:RemoteControlRequiresAuthentication"] ?? "true");
Expand Down
1 change: 1 addition & 0 deletions Server/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"KnownProxies": [],
"MaxConcurrentUpdates": 10,
"MaxOrganizationCount": 1,
"MessageOfTheDay": "",
"RedirectToHttps": false,
"RemoteControlNotifyUser": true,
"RemoteControlSessionLimit": 3,
Expand Down
12 changes: 12 additions & 0 deletions Server/wwwroot/src/Main/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,19 @@ export const MainApp = {
HubConnection: BrowserHubConnection,
UserSettings: UserSettings,
Sound: Sound,
GetMotd() {
if (!UI.MotdContentSpan.innerHTML || localStorage["remotely-motd"] == UI.MotdContentSpan.innerHTML) {
return;
}

UI.MotdAlert.querySelector("button").addEventListener("click", () => {
localStorage["remotely-motd"] = UI.MotdContentSpan.innerHTML;
});

UI.MotdAlert.removeAttribute("hidden");
},
Init() {
MainApp.GetMotd();
UI.ConsoleTextArea.focus();
ApplyInputEventHandlers();
BrowserHubConnection.Connect();
Expand Down
4 changes: 3 additions & 1 deletion Server/wwwroot/src/Main/UI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ export var RightPaginationButton = document.querySelector("#rightPaginationButto
export var TabContentWrapper = document.getElementById("tabContentWrapper") as HTMLDivElement;
export var ToastsWrapper = document.getElementById("toastsWrapper") as HTMLDivElement;
export var TotalDevicesCount = document.querySelector("#totalDevicesSpan") as HTMLSpanElement;
export var TotalPagesSpan = document.querySelector("#totalPagesSpan") as HTMLSpanElement;
export var TotalPagesSpan = document.querySelector("#totalPagesSpan") as HTMLSpanElement;
export var MotdAlert = document.getElementById("motdAlert") as HTMLDivElement;
export var MotdContentSpan = document.getElementById("motdContentSpan") as HTMLSpanElement;

0 comments on commit 2fe3660

Please sign in to comment.