mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
190 lines
6.3 KiB
C#
190 lines
6.3 KiB
C#
using Remotely.Agent.Interfaces;
|
|
using Remotely.Shared.Utilities;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Remotely.Agent.Services
|
|
{
|
|
public class UpdaterLinux : IUpdater
|
|
{
|
|
public UpdaterLinux(ConfigService configService)
|
|
{
|
|
ConfigService = configService;
|
|
}
|
|
|
|
private SemaphoreSlim CheckForUpdatesLock { get; } = new SemaphoreSlim(1, 1);
|
|
private ConfigService ConfigService { get; }
|
|
private SemaphoreSlim InstallLatestVersionLock { get; } = new SemaphoreSlim(1, 1);
|
|
private DateTimeOffset LastUpdateFailure { get; set; }
|
|
private System.Timers.Timer UpdateTimer { get; } = new System.Timers.Timer(TimeSpan.FromHours(6).TotalMilliseconds);
|
|
|
|
|
|
public async Task BeginChecking()
|
|
{
|
|
if (EnvironmentHelper.IsDebug)
|
|
{
|
|
return;
|
|
}
|
|
|
|
await CheckForUpdates();
|
|
UpdateTimer.Elapsed += UpdateTimer_Elapsed;
|
|
UpdateTimer.Start();
|
|
}
|
|
|
|
public async Task CheckForUpdates()
|
|
{
|
|
try
|
|
{
|
|
await CheckForUpdatesLock.WaitAsync();
|
|
|
|
if (EnvironmentHelper.IsDebug)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (LastUpdateFailure.AddDays(1) > DateTimeOffset.Now)
|
|
{
|
|
Logger.Write("Skipping update check due to previous failure. Restart the service to try again, or manually install the update.");
|
|
return;
|
|
}
|
|
|
|
|
|
var connectionInfo = ConfigService.GetConnectionInfo();
|
|
var serverUrl = ConfigService.GetConnectionInfo().Host;
|
|
|
|
var fileUrl = serverUrl + $"/Content/Remotely-Linux.zip";
|
|
|
|
var lastEtag = string.Empty;
|
|
|
|
if (File.Exists("etag.txt"))
|
|
{
|
|
lastEtag = await File.ReadAllTextAsync("etag.txt");
|
|
}
|
|
|
|
try
|
|
{
|
|
var wr = WebRequest.CreateHttp(fileUrl);
|
|
wr.Method = "Head";
|
|
wr.Headers.Add("If-None-Match", lastEtag);
|
|
using var response = (HttpWebResponse)await wr.GetResponseAsync();
|
|
if (response.StatusCode == HttpStatusCode.NotModified)
|
|
{
|
|
Logger.Write("Service Updater: Version is current.");
|
|
return;
|
|
}
|
|
}
|
|
catch (WebException ex) when ((ex.Response as HttpWebResponse).StatusCode == HttpStatusCode.NotModified)
|
|
{
|
|
Logger.Write("Service Updater: Version is current.");
|
|
return;
|
|
}
|
|
|
|
Logger.Write("Service Updater: Update found.");
|
|
|
|
await InstallLatestVersion();
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Write(ex);
|
|
}
|
|
finally
|
|
{
|
|
CheckForUpdatesLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task InstallLatestVersion()
|
|
{
|
|
try
|
|
{
|
|
await InstallLatestVersionLock.WaitAsync();
|
|
|
|
var connectionInfo = ConfigService.GetConnectionInfo();
|
|
var serverUrl = connectionInfo.Host;
|
|
|
|
Logger.Write("Service Updater: Downloading install package.");
|
|
|
|
using var wc = new WebClientEx((int)UpdateTimer.Interval);
|
|
var downloadId = Guid.NewGuid().ToString();
|
|
var zipPath = Path.Combine(Path.GetTempPath(), "RemotelyUpdate.zip");
|
|
|
|
var installerPath = Path.Combine(Path.GetTempPath(), "RemotelyUpdate.sh");
|
|
|
|
string platform;
|
|
|
|
if (RuntimeInformation.OSDescription.Contains("Ubuntu", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
platform = "UbuntuInstaller-x64";
|
|
}
|
|
else if (RuntimeInformation.OSDescription.Contains("Manjaro", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
platform = "ManjaroInstaller-x64";
|
|
}
|
|
else
|
|
{
|
|
throw new PlatformNotSupportedException();
|
|
}
|
|
|
|
await wc.DownloadFileTaskAsync(
|
|
serverUrl + $"/API/ClientDownloads/{connectionInfo.OrganizationID}/{platform}",
|
|
installerPath);
|
|
|
|
await wc.DownloadFileTaskAsync(
|
|
serverUrl + $"/API/AgentUpdate/DownloadPackage/linux/{downloadId}",
|
|
zipPath);
|
|
|
|
(await WebRequest.CreateHttp(serverUrl + $"/api/AgentUpdate/ClearDownload/{downloadId}").GetResponseAsync()).Dispose();
|
|
|
|
Logger.Write("Launching installer to perform update.");
|
|
|
|
Process.Start("sudo", $"chmod +x {installerPath}").WaitForExit();
|
|
|
|
Process.Start("sudo", $"{installerPath} --path {zipPath}");
|
|
}
|
|
catch (WebException ex) when (ex.Status == WebExceptionStatus.Timeout)
|
|
{
|
|
Logger.Write("Timed out while waiting to download update.", Shared.Enums.EventType.Warning);
|
|
LastUpdateFailure = DateTimeOffset.Now;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Write(ex);
|
|
LastUpdateFailure = DateTimeOffset.Now;
|
|
}
|
|
finally
|
|
{
|
|
InstallLatestVersionLock.Release();
|
|
}
|
|
}
|
|
|
|
private async void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|
{
|
|
await CheckForUpdates();
|
|
}
|
|
private class WebClientEx : WebClient
|
|
{
|
|
private readonly int _requestTimeout;
|
|
|
|
public WebClientEx(int requestTimeout)
|
|
{
|
|
_requestTimeout = requestTimeout;
|
|
}
|
|
protected override WebRequest GetWebRequest(Uri uri)
|
|
{
|
|
WebRequest webRequest = base.GetWebRequest(uri);
|
|
webRequest.Timeout = _requestTimeout;
|
|
return webRequest;
|
|
}
|
|
}
|
|
}
|
|
}
|