mirror of
https://github.com/openziti/desktop-edge-win.git
synced 2026-10-13 16:21:25 +00:00
217 lines
7.6 KiB
C#
217 lines
7.6 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.ServiceProcess;
|
|
using System.IO;
|
|
using System.Timers;
|
|
using System.Configuration;
|
|
using System.Threading.Tasks;
|
|
|
|
using ZitiDesktopEdge.ServiceClient;
|
|
using NLog;
|
|
using System.Reflection;
|
|
|
|
namespace ZitiUpdateService {
|
|
public partial class UpdateService : ServiceBase {
|
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
|
|
|
private Timer _updateTimer = new Timer();
|
|
private bool inUpdateCheck = false;
|
|
private string _rootDirectory = "";
|
|
private string _logDirectory = "";
|
|
private string _versionType = "latest";
|
|
|
|
private Client svc = new Client();
|
|
private bool running = false;
|
|
|
|
ServiceController controller;
|
|
public UpdateService() {
|
|
InitializeComponent();
|
|
|
|
Logger.Info("Initializing");
|
|
svc.OnClientConnected += Svc_OnClientConnected;
|
|
svc.OnTunnelStatusEvent += Svc_OnTunnelStatusEvent;
|
|
svc.OnClientDisconnected += Svc_OnClientDisconnected;
|
|
svc.OnShutdownEvent += Svc_OnShutdownEvent;
|
|
}
|
|
|
|
public void Debug() {
|
|
OnStart(null);
|
|
}
|
|
|
|
protected override void OnStart(string[] args) {
|
|
Logger.Info("ziti-monitor service is starting");
|
|
try {
|
|
if (ConfigurationManager.AppSettings.Get("Version") != null) _versionType = ConfigurationManager.AppSettings.Get("Version");
|
|
} catch (Exception e) {
|
|
Logger.Info(e.ToString());
|
|
}
|
|
_rootDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "OpenZiti");
|
|
if (!Directory.Exists(_rootDirectory)) Directory.CreateDirectory(_rootDirectory);
|
|
_logDirectory = Path.Combine(_rootDirectory, "Logs");
|
|
if (!Directory.Exists(_logDirectory)) Directory.CreateDirectory(_logDirectory);
|
|
if (!running) {
|
|
running = true;
|
|
Task.Run(() => {
|
|
SetupServiceWatchers();
|
|
});
|
|
}
|
|
Logger.Info("ziti-monitor service is initialized and running");
|
|
}
|
|
|
|
protected override void OnStop() {
|
|
Logger.Info("ziti-monitor service is stopping");
|
|
}
|
|
|
|
private void SetupServiceWatchers() {
|
|
|
|
var updateTimerInterval = ConfigurationManager.AppSettings.Get("UpdateTimer");
|
|
var upInt = TimeSpan.Zero;
|
|
if (!TimeSpan.TryParse(updateTimerInterval, out upInt)) {
|
|
upInt = new TimeSpan(0, 1, 0);
|
|
}
|
|
|
|
_updateTimer = new Timer();
|
|
_updateTimer.Elapsed += CheckUpdate;
|
|
_updateTimer.Interval = upInt.TotalMilliseconds;
|
|
_updateTimer.Enabled = true;
|
|
_updateTimer.Start();
|
|
Logger.Info("Version Checker is running");
|
|
CheckUpdate(null, null); //check immediately
|
|
|
|
try {
|
|
svc.Connect();
|
|
} catch {
|
|
svc.Reconnect();
|
|
}
|
|
|
|
svc.WaitForConnection();
|
|
}
|
|
|
|
private void CheckUpdate(object sender, ElapsedEventArgs e) {
|
|
if (inUpdateCheck) return;
|
|
inUpdateCheck = true; //simple semaphone
|
|
try {
|
|
Logger.Debug("checking for update");
|
|
var updateUrl = ConfigurationManager.AppSettings.Get("UpdateUrl");
|
|
if (string.IsNullOrEmpty(updateUrl)) {
|
|
updateUrl = "https://api.github.com/repos/openziti/desktop-edge-win/releases/latest";
|
|
}
|
|
IUpdateCheck check = new GithubCheck(updateUrl);
|
|
//IUpdateCheck check = new FilesystemCheck();
|
|
|
|
string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); //fetch from ziti?
|
|
Version installed = new Version(currentVersion);
|
|
if (!check.IsUpdateAvailable(installed)) {
|
|
Logger.Debug("update check complete. no update available");
|
|
inUpdateCheck = false;
|
|
return;
|
|
}
|
|
|
|
Logger.Info("update is available.");
|
|
|
|
var curdir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
|
|
var updateFolder = $"{curdir}{Path.DirectorySeparatorChar}updates";
|
|
Directory.CreateDirectory(updateFolder);
|
|
|
|
Logger.Info("copying update package");
|
|
string filename = check.FileName();
|
|
|
|
if (check.AlreadyDownloaded(updateFolder, filename)) {
|
|
Logger.Info("package has already been downloaded - moving to install phase");
|
|
} else {
|
|
Logger.Info("copying update package begins");
|
|
check.CopyUpdatePackage(updateFolder, filename);
|
|
Logger.Info("copying update package complete");
|
|
}
|
|
|
|
StopZiti();
|
|
|
|
// shell out to a new process and run the uninstall, reinstall steps which SHOULD stop this current process as well
|
|
string fileDestination = Path.Combine(updateFolder, filename);
|
|
Process.Start(fileDestination, "/passive");
|
|
} catch (Exception ex) {
|
|
Logger.Error(ex, "Unexpected error has occurred");
|
|
}
|
|
inUpdateCheck = false;
|
|
}
|
|
|
|
private void StartZiti() {
|
|
controller = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName == "ziti");
|
|
if (controller != null && controller.Status != ServiceControllerStatus.Running && controller.Status != ServiceControllerStatus.StartPending && controller.Status != ServiceControllerStatus.ContinuePending) {
|
|
try {
|
|
Logger.Info("Starting Service");
|
|
controller.Start();
|
|
controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
|
|
SetupServiceWatchers();
|
|
} catch (Exception e) {
|
|
Logger.Info("Cannot Start Service - " + e.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
private void StopZiti() {
|
|
Logger.Info("Stopping the ziti service...");
|
|
controller = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName == "ziti");
|
|
if (controller != null && controller.Status != ServiceControllerStatus.Stopped) {
|
|
try {
|
|
controller.Stop();
|
|
controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
|
|
} catch (Exception e) {
|
|
Logger.Error(e, "Timout while trying to stop service!");
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void Svc_OnShutdownEvent(object sender, StatusEvent e) {
|
|
Logger.Info("the service is shutting down normally...");
|
|
}
|
|
|
|
private static void Svc_OnTunnelStatusEvent(object sender, TunnelStatusEvent e) {
|
|
string dns = e?.Status?.IpInfo?.DNS;
|
|
string version = e?.Status?.ServiceVersion.Version;
|
|
string op = e?.Op;
|
|
Logger.Info($"Operation {op}. running dns: {dns} at version {version}");
|
|
}
|
|
|
|
private static void Svc_OnClientConnected(object sender, object e) {
|
|
Logger.Info("successfully connected to service");
|
|
}
|
|
|
|
private static void Svc_OnClientDisconnected(object sender, object e) {
|
|
Client svc = (Client)sender;
|
|
if (svc.CleanShutdown) {
|
|
//then this is fine and expected - the service is shutting down
|
|
Logger.Info("client disconnected due to clean service shutdown");
|
|
} else {
|
|
Logger.Error("SERVICE IS DOWN and did not exit cleanly. initiating DNS cleanup");
|
|
//EnumerateDNS();
|
|
var ps = System.Management.Automation.PowerShell.Create();
|
|
string script = "Get-NetIPInterface | ForEach-Object { Set-DnsClientServerAddress -InterfaceIndex $_.ifIndex -ResetServerAddresses }";
|
|
ps.Commands.AddScript(script);
|
|
Logger.Info("No longer connected to the service. Resetting the network by executing reset script.");
|
|
Task.Delay(1000).Wait();
|
|
ps.Invoke();
|
|
Logger.Info("Reset script executed.");
|
|
//EnumerateDNS();
|
|
}
|
|
}
|
|
|
|
private static void EnumerateDNS() {
|
|
var ps = System.Management.Automation.PowerShell.Create();
|
|
ps.AddScript("Get-DnsClientServerAddress");
|
|
var results = ps.Invoke();
|
|
|
|
using (StringWriter sw = new StringWriter()) {
|
|
foreach (var r in results) {
|
|
string name = (string)r.Properties["InterfaceAlias"].Value;
|
|
string[] dnses = (string[])r.Properties["ServerAddresses"].Value;
|
|
sw.WriteLine($"Interface: {name}. DNS: {string.Join(",", dnses)}");
|
|
}
|
|
Logger.Info("DNS RESULTS:\n{0}", sw.ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|