From a6d9ae87aa8e18b8d4b05bbd2e764828d8c02b61 Mon Sep 17 00:00:00 2001 From: Mohammad Mahdi Date: Sun, 24 Aug 2025 09:34:54 +0330 Subject: [PATCH] Refactor YAML parsing logic and settings handling across Client and Server projects, improve request building in the client. --- .../Context/YamlStaticContextClient.cs | 9 +++++ .../Helpers/YamlParser.cs | 13 ++----- VirtualDDNSRouter.Client/Models/Settings.cs | 19 +++++++--- VirtualDDNSRouter.Client/Program.cs | 37 ++++++++++++++----- .../VirtualDDNSRouter.Client.csproj | 1 + .../Context/YamlStaticContext.cs | 2 +- .../Services/YamlParser.cs | 5 +-- 7 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 VirtualDDNSRouter.Client/Context/YamlStaticContextClient.cs diff --git a/VirtualDDNSRouter.Client/Context/YamlStaticContextClient.cs b/VirtualDDNSRouter.Client/Context/YamlStaticContextClient.cs new file mode 100644 index 0000000..cdd0b4b --- /dev/null +++ b/VirtualDDNSRouter.Client/Context/YamlStaticContextClient.cs @@ -0,0 +1,9 @@ +using YamlDotNet.Serialization; + +namespace VirtualDDNSRouter.Client.Context; + +[YamlStaticContext] +[YamlSerializable(typeof(Settings))] +public partial class YamlStaticContextClient : StaticContext +{ +} \ No newline at end of file diff --git a/VirtualDDNSRouter.Client/Helpers/YamlParser.cs b/VirtualDDNSRouter.Client/Helpers/YamlParser.cs index e1a5043..64d5d91 100644 --- a/VirtualDDNSRouter.Client/Helpers/YamlParser.cs +++ b/VirtualDDNSRouter.Client/Helpers/YamlParser.cs @@ -1,3 +1,4 @@ +using VirtualDDNSRouter.Client.Context; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; using Settings = VirtualDDNSRouter.Client.Models.Settings; @@ -16,7 +17,7 @@ public class Helpers var yamlContent = await File.ReadAllTextAsync(YamlFilePath).ConfigureAwait(false); // Build the deserializer with explicit naming convention - var deserializer = new StaticDeserializerBuilder(new YamlStaticContext()) + var deserializer = new StaticDeserializerBuilder(new YamlStaticContextClient()) .WithNamingConvention(UnderscoredNamingConvention.Instance) .IgnoreUnmatchedProperties() .Build(); @@ -24,16 +25,10 @@ public class Helpers // Deserialize into Settings var settings = deserializer.Deserialize(yamlContent); - if (settings is null || string.IsNullOrWhiteSpace(settings.Host) || string.IsNullOrWhiteSpace(settings.Path) || - string.IsNullOrWhiteSpace(settings.ApiKey)) + if (settings is null || string.IsNullOrWhiteSpace(settings.host) || string.IsNullOrWhiteSpace(settings.path) || + string.IsNullOrWhiteSpace(settings.apiKey)) throw new Exception("Invalid settings file"); return settings; } - - [YamlStaticContext] - [YamlSerializable(typeof(Settings))] - private partial class YamlStaticContext : StaticContext - { - } } \ No newline at end of file diff --git a/VirtualDDNSRouter.Client/Models/Settings.cs b/VirtualDDNSRouter.Client/Models/Settings.cs index 67fb5e9..c9e405d 100644 --- a/VirtualDDNSRouter.Client/Models/Settings.cs +++ b/VirtualDDNSRouter.Client/Models/Settings.cs @@ -1,10 +1,17 @@ +using YamlDotNet.Serialization; + namespace VirtualDDNSRouter.Client.Models; -public class Settings +[YamlSerializable] +public record Settings { - public string Host { get; set; } = string.Empty; - public string Path { get; set; } = string.Empty; - public ushort DestinationPort { get; set; } = 80; - public string ApiKey { get; set; } = string.Empty; - public ushort RefreshIntervalMinutes { get; set; } = 5; + public string host { get; set; } = string.Empty; + public string path { get; set; } = string.Empty; + public ushort destinationPort { get; set; } = 80; + public string apiKey { get; set; } = string.Empty; + public ushort refreshIntervalMinutes { get; set; } = 5; + + public Settings() + { + } } \ No newline at end of file diff --git a/VirtualDDNSRouter.Client/Program.cs b/VirtualDDNSRouter.Client/Program.cs index 65e8ce7..a34c827 100644 --- a/VirtualDDNSRouter.Client/Program.cs +++ b/VirtualDDNSRouter.Client/Program.cs @@ -10,17 +10,34 @@ Console.CancelKeyPress += (s, e) => cts.Cancel(); }; -var timer = new PeriodicTimer(TimeSpan.FromMinutes(settings.RefreshIntervalMinutes)); +var timer = new PeriodicTimer(TimeSpan.FromMinutes(settings.refreshIntervalMinutes)); var client = new HttpClient { Timeout = TimeSpan.FromSeconds(10) }; -var request = new HttpRequestMessage(HttpMethod.Get, - new Uri($"{settings.Host}/setip/{settings.Path}/{settings.DestinationPort}/{settings.ApiKey}")); -while (await timer.WaitForNextTickAsync()) +var builder = new UriBuilder { - if (cts.IsCancellationRequested) break; - var response = await client.SendAsync(request, cts.Token); - if (response.IsSuccessStatusCode) - Console.WriteLine("[INFO] IP address updated at " + DateTime.Now.ToString("HH:mm:ss")); - else - Console.WriteLine("[ERROR] IP address update failed at " + DateTime.Now.ToString("HH:mm:ss")); + Scheme = "http", + Host = settings.host, + Path = $"setip/{settings.path}/{settings.destinationPort}/{settings.apiKey}" +}; + +var request = new HttpRequestMessage(HttpMethod.Get, builder.Uri); + +Console.WriteLine("[INFO] App started. Scheduling IP address update every " + settings.refreshIntervalMinutes + + " minutes."); + +try +{ + while (await timer.WaitForNextTickAsync(cts.Token)) + { + if (cts.IsCancellationRequested) break; + var response = await client.SendAsync(request, cts.Token); + if (response.IsSuccessStatusCode) + Console.WriteLine("[INFO] IP address updated at " + DateTime.Now.ToString("HH:mm:ss")); + else + Console.WriteLine("[ERROR] IP address update failed at " + DateTime.Now.ToString("HH:mm:ss")); + } +} +catch (OperationCanceledException) +{ + Console.WriteLine("[INFO] Shutdown complete."); } \ No newline at end of file diff --git a/VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj b/VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj index e273f26..3d31121 100644 --- a/VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj +++ b/VirtualDDNSRouter.Client/VirtualDDNSRouter.Client.csproj @@ -18,6 +18,7 @@ + diff --git a/VirtualDDNSRouter.Server/Context/YamlStaticContext.cs b/VirtualDDNSRouter.Server/Context/YamlStaticContext.cs index 6c98bee..e98fd4b 100644 --- a/VirtualDDNSRouter.Server/Context/YamlStaticContext.cs +++ b/VirtualDDNSRouter.Server/Context/YamlStaticContext.cs @@ -5,6 +5,6 @@ namespace VirtualDDNSRouter.Server.Context; [YamlStaticContext] [YamlSerializable(typeof(Rule))] -public partial class YamlStaticContext : StaticContext +public partial class YamlStaticContextServer : StaticContext { } \ No newline at end of file diff --git a/VirtualDDNSRouter.Server/Services/YamlParser.cs b/VirtualDDNSRouter.Server/Services/YamlParser.cs index 8346293..da12878 100644 --- a/VirtualDDNSRouter.Server/Services/YamlParser.cs +++ b/VirtualDDNSRouter.Server/Services/YamlParser.cs @@ -1,4 +1,3 @@ -using System.Diagnostics.CodeAnalysis; using VirtualDDNSRouter.Server.Context; using VirtualDDNSRouter.Server.Interfaces; using VirtualDDNSRouter.Server.Models; @@ -19,7 +18,7 @@ public class YamlParser : IYamlParser var yamlContent = await File.ReadAllTextAsync(_yamlFilePath).ConfigureAwait(false); // Build the deserializer with explicit naming convention - var deserializer = new StaticDeserializerBuilder(new YamlStaticContext()) + var deserializer = new StaticDeserializerBuilder(new YamlStaticContextServer()) .WithNamingConvention(UnderscoredNamingConvention.Instance) // maps api_key -> apiKey .IgnoreUnmatchedProperties() .Build(); @@ -27,6 +26,6 @@ public class YamlParser : IYamlParser // Deserialize into a list of Rule var rules = deserializer.Deserialize>(yamlContent); - return rules ?? new List(); + return rules; } } \ No newline at end of file