diff --git a/Apps/FailoverApp/Address.cs b/Apps/FailoverApp/Address.cs
index cda6b414..cf60fd9e 100644
--- a/Apps/FailoverApp/Address.cs
+++ b/Apps/FailoverApp/Address.cs
@@ -18,11 +18,11 @@ along with this program. If not, see .
*/
using DnsServerCore.ApplicationCommon;
-using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
+using System.Text.Json;
using System.Threading.Tasks;
using TechnitiumLibrary;
using TechnitiumLibrary.Net.Dns;
@@ -64,17 +64,14 @@ namespace Failover
#region private
- private void GetAnswers(dynamic jsonAddresses, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List answers)
+ private void GetAnswers(JsonElement jsonAddresses, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List answers)
{
- if (jsonAddresses == null)
- return;
-
switch (question.Type)
{
case DnsResourceRecordType.A:
- foreach (dynamic jsonAddress in jsonAddresses)
+ foreach (JsonElement jsonAddress in jsonAddresses.EnumerateArray())
{
- IPAddress address = IPAddress.Parse(jsonAddress.Value);
+ IPAddress address = IPAddress.Parse(jsonAddress.GetString());
if (address.AddressFamily == AddressFamily.InterNetwork)
{
@@ -94,9 +91,9 @@ namespace Failover
break;
case DnsResourceRecordType.AAAA:
- foreach (dynamic jsonAddress in jsonAddresses)
+ foreach (JsonElement jsonAddress in jsonAddresses.EnumerateArray())
{
- IPAddress address = IPAddress.Parse(jsonAddress.Value);
+ IPAddress address = IPAddress.Parse(jsonAddress.GetString());
if (address.AddressFamily == AddressFamily.InterNetworkV6)
{
@@ -117,14 +114,11 @@ namespace Failover
}
}
- private void GetStatusAnswers(dynamic jsonAddresses, FailoverType type, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List answers)
+ private void GetStatusAnswers(JsonElement jsonAddresses, FailoverType type, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List answers)
{
- if (jsonAddresses == null)
- return;
-
- foreach (dynamic jsonAddress in jsonAddresses)
+ foreach (JsonElement jsonAddress in jsonAddresses.EnumerateArray())
{
- IPAddress address = IPAddress.Parse(jsonAddress.Value);
+ IPAddress address = IPAddress.Parse(jsonAddress.GetString());
HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, false);
string text = "app=failover; addressType=" + type.ToString() + "; address=" + address.ToString() + "; healthCheck=" + healthCheck + (healthCheckUrl is null ? "" : "; healthCheckUrl=" + healthCheckUrl.AbsoluteUri) + "; healthStatus=" + response.Status.ToString() + ";";
@@ -145,7 +139,7 @@ namespace Failover
if (_healthService is null)
_healthService = HealthService.Create(dnsServer);
- _healthService.Initialize(JsonConvert.DeserializeObject(config));
+ _healthService.Initialize(config);
return Task.CompletedTask;
}
@@ -158,17 +152,18 @@ namespace Failover
case DnsResourceRecordType.A:
case DnsResourceRecordType.AAAA:
{
- dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
+ using JsonDocument jsonDocument = JsonDocument.Parse(appRecordData);
+ JsonElement jsonAppRecordData = jsonDocument.RootElement;
- string healthCheck = jsonAppRecordData.healthCheck?.Value;
+ string healthCheck = jsonAppRecordData.GetPropertyValue("healthCheck", null);
Uri healthCheckUrl = null;
if (_healthService.HealthChecks.TryGetValue(healthCheck, out HealthCheck hc) && ((hc.Type == HealthCheckType.Https) || (hc.Type == HealthCheckType.Http)) && (hc.Url is null))
{
//read health check url only for http/https type checks and only when app config does not have an url configured
- if ((jsonAppRecordData.healthCheckUrl is not null) && (jsonAppRecordData.healthCheckUrl.Value is not null))
+ if (jsonAppRecordData.TryGetProperty("healthCheckUrl", out JsonElement jsonHealthCheckUrl) && (jsonHealthCheckUrl.ValueKind != JsonValueKind.Null))
{
- healthCheckUrl = new Uri(jsonAppRecordData.healthCheckUrl.Value);
+ healthCheckUrl = new Uri(jsonHealthCheckUrl.GetString());
}
else
{
@@ -181,19 +176,23 @@ namespace Failover
List answers = new List();
- GetAnswers(jsonAppRecordData.primary, question, appRecordTtl, healthCheck, healthCheckUrl, answers);
+ if (jsonAppRecordData.TryGetProperty("primary", out JsonElement jsonPrimary))
+ GetAnswers(jsonPrimary, question, appRecordTtl, healthCheck, healthCheckUrl, answers);
+
if (answers.Count == 0)
{
- GetAnswers(jsonAppRecordData.secondary, question, appRecordTtl, healthCheck, healthCheckUrl, answers);
+ if (jsonAppRecordData.TryGetProperty("secondary", out JsonElement jsonSecondary))
+ GetAnswers(jsonSecondary, question, appRecordTtl, healthCheck, healthCheckUrl, answers);
+
if (answers.Count == 0)
{
- if (jsonAppRecordData.serverDown is not null)
+ if (jsonAppRecordData.TryGetProperty("serverDown", out JsonElement jsonServerDown))
{
if (question.Type == DnsResourceRecordType.A)
{
- foreach (dynamic jsonAddress in jsonAppRecordData.serverDown)
+ foreach (JsonElement jsonAddress in jsonServerDown.EnumerateArray())
{
- IPAddress address = IPAddress.Parse(jsonAddress.Value);
+ IPAddress address = IPAddress.Parse(jsonAddress.GetString());
if (address.AddressFamily == AddressFamily.InterNetwork)
answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 30, new DnsARecordData(address)));
@@ -201,9 +200,9 @@ namespace Failover
}
else
{
- foreach (dynamic jsonAddress in jsonAppRecordData.serverDown)
+ foreach (JsonElement jsonAddress in jsonServerDown.EnumerateArray())
{
- IPAddress address = IPAddress.Parse(jsonAddress.Value);
+ IPAddress address = IPAddress.Parse(jsonAddress.GetString());
if (address.AddressFamily == AddressFamily.InterNetworkV6)
answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 30, new DnsAAAARecordData(address)));
@@ -224,27 +223,22 @@ namespace Failover
case DnsResourceRecordType.TXT:
{
- dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
-
- bool allowTxtStatus;
-
- if (jsonAppRecordData.allowTxtStatus == null)
- allowTxtStatus = false;
- else
- allowTxtStatus = jsonAppRecordData.allowTxtStatus.Value;
+ using JsonDocument jsonDocument = JsonDocument.Parse(appRecordData);
+ JsonElement jsonAppRecordData = jsonDocument.RootElement;
+ bool allowTxtStatus = jsonAppRecordData.GetPropertyValue("allowTxtStatus", false);
if (!allowTxtStatus)
return Task.FromResult(null);
- string healthCheck = jsonAppRecordData.healthCheck?.Value;
+ string healthCheck = jsonAppRecordData.GetPropertyValue("healthCheck", null);
Uri healthCheckUrl = null;
if (_healthService.HealthChecks.TryGetValue(healthCheck, out HealthCheck hc) && ((hc.Type == HealthCheckType.Https) || (hc.Type == HealthCheckType.Http)) && (hc.Url is null))
{
//read health check url only for http/https type checks and only when app config does not have an url configured
- if ((jsonAppRecordData.healthCheckUrl is not null) && (jsonAppRecordData.healthCheckUrl.Value is not null))
+ if (jsonAppRecordData.TryGetProperty("healthCheckUrl", out JsonElement jsonHealthCheckUrl) && (jsonHealthCheckUrl.ValueKind != JsonValueKind.Null))
{
- healthCheckUrl = new Uri(jsonAppRecordData.healthCheckUrl.Value);
+ healthCheckUrl = new Uri(jsonHealthCheckUrl.GetString());
}
else
{
@@ -257,8 +251,11 @@ namespace Failover
List answers = new List();
- GetStatusAnswers(jsonAppRecordData.primary, FailoverType.Primary, question, 30, healthCheck, healthCheckUrl, answers);
- GetStatusAnswers(jsonAppRecordData.secondary, FailoverType.Secondary, question, 30, healthCheck, healthCheckUrl, answers);
+ if (jsonAppRecordData.TryGetProperty("primary", out JsonElement jsonPrimary))
+ GetStatusAnswers(jsonPrimary, FailoverType.Primary, question, 30, healthCheck, healthCheckUrl, answers);
+
+ if (jsonAppRecordData.TryGetProperty("secondary", out JsonElement jsonSecondary))
+ GetStatusAnswers(jsonSecondary, FailoverType.Secondary, question, 30, healthCheck, healthCheckUrl, answers);
return Task.FromResult(new DnsDatagram(request.Identifier, true, request.OPCODE, true, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, answers));
}
diff --git a/Apps/FailoverApp/CNAME.cs b/Apps/FailoverApp/CNAME.cs
index e6dcd076..785b7e43 100644
--- a/Apps/FailoverApp/CNAME.cs
+++ b/Apps/FailoverApp/CNAME.cs
@@ -18,11 +18,12 @@ along with this program. If not, see .
*/
using DnsServerCore.ApplicationCommon;
-using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
+using System.Text.Json;
using System.Threading.Tasks;
+using TechnitiumLibrary;
using TechnitiumLibrary.Net.Dns;
using TechnitiumLibrary.Net.Dns.ResourceRecords;
@@ -119,17 +120,18 @@ namespace Failover
{
DnsQuestionRecord question = request.Question[0];
- dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
+ using JsonDocument jsonDocument = JsonDocument.Parse(appRecordData);
+ JsonElement jsonAppRecordData = jsonDocument.RootElement;
- string healthCheck = jsonAppRecordData.healthCheck?.Value;
+ string healthCheck = jsonAppRecordData.GetPropertyValue("healthCheck", null);
Uri healthCheckUrl = null;
if (_healthService.HealthChecks.TryGetValue(healthCheck, out HealthCheck hc) && ((hc.Type == HealthCheckType.Https) || (hc.Type == HealthCheckType.Http)) && (hc.Url is null))
{
//read health check url only for http/https type checks and only when app config does not have an url configured
- if ((jsonAppRecordData.healthCheckUrl is not null) && (jsonAppRecordData.healthCheckUrl.Value is not null))
+ if (jsonAppRecordData.TryGetProperty("healthCheckUrl", out JsonElement jsonHealthCheckUrl) && (jsonHealthCheckUrl.ValueKind != JsonValueKind.Null))
{
- healthCheckUrl = new Uri(jsonAppRecordData.healthCheckUrl.Value);
+ healthCheckUrl = new Uri(jsonHealthCheckUrl.GetString());
}
else
{
@@ -140,47 +142,50 @@ namespace Failover
}
}
- IReadOnlyList answers;
+ IReadOnlyList answers = null;
if (question.Type == DnsResourceRecordType.TXT)
{
- bool allowTxtStatus;
-
- if (jsonAppRecordData.allowTxtStatus == null)
- allowTxtStatus = false;
- else
- allowTxtStatus = jsonAppRecordData.allowTxtStatus.Value;
-
+ bool allowTxtStatus = jsonAppRecordData.GetPropertyValue("allowTxtStatus", false);
if (!allowTxtStatus)
return Task.FromResult(null);
List txtAnswers = new List();
- GetStatusAnswers(jsonAppRecordData.primary.Value, FailoverType.Primary, question, 30, healthCheck, healthCheckUrl, txtAnswers);
+ if (jsonAppRecordData.TryGetProperty("primary", out JsonElement jsonPrimary))
+ GetStatusAnswers(jsonPrimary.GetString(), FailoverType.Primary, question, 30, healthCheck, healthCheckUrl, txtAnswers);
- foreach (dynamic jsonDomain in jsonAppRecordData.secondary)
- GetStatusAnswers(jsonDomain.Value, FailoverType.Secondary, question, 30, healthCheck, healthCheckUrl, txtAnswers);
+ if (jsonAppRecordData.TryGetProperty("secondary", out JsonElement jsonSecondary))
+ {
+ foreach (JsonElement jsonDomain in jsonSecondary.EnumerateArray())
+ GetStatusAnswers(jsonDomain.GetString(), FailoverType.Secondary, question, 30, healthCheck, healthCheckUrl, txtAnswers);
+ }
answers = txtAnswers;
}
else
{
- answers = GetAnswers(jsonAppRecordData.primary.Value, question, zoneName, appRecordTtl, healthCheck, healthCheckUrl);
+ if (jsonAppRecordData.TryGetProperty("primary", out JsonElement jsonPrimary))
+ answers = GetAnswers(jsonPrimary.GetString(), question, zoneName, appRecordTtl, healthCheck, healthCheckUrl);
+
if (answers is null)
{
- foreach (dynamic jsonDomain in jsonAppRecordData.secondary)
+ if (jsonAppRecordData.TryGetProperty("secondary", out JsonElement jsonSecondary))
{
- answers = GetAnswers(jsonDomain.Value, question, zoneName, appRecordTtl, healthCheck, healthCheckUrl);
- if (answers is not null)
- break;
+ foreach (JsonElement jsonDomain in jsonSecondary.EnumerateArray())
+ {
+ answers = GetAnswers(jsonDomain.GetString(), question, zoneName, appRecordTtl, healthCheck, healthCheckUrl);
+ if (answers is not null)
+ break;
+ }
}
if (answers is null)
{
- if ((jsonAppRecordData.serverDown is null) || (jsonAppRecordData.serverDown.Value is null))
+ if (!jsonAppRecordData.TryGetProperty("serverDown", out JsonElement jsonServerDown) || (jsonServerDown.ValueKind == JsonValueKind.Null))
return Task.FromResult(null);
- string serverDown = jsonAppRecordData.serverDown.Value;
+ string serverDown = jsonServerDown.GetString();
if (question.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)) //check for zone apex
answers = new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.ANAME, DnsClass.IN, 30, new DnsANAMERecordData(serverDown)) }; //use ANAME
diff --git a/Apps/FailoverApp/EmailAlert.cs b/Apps/FailoverApp/EmailAlert.cs
index dea45264..d45c8d56 100644
--- a/Apps/FailoverApp/EmailAlert.cs
+++ b/Apps/FailoverApp/EmailAlert.cs
@@ -23,8 +23,10 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Mail;
using System.Text;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
+using TechnitiumLibrary;
using TechnitiumLibrary.Net.Dns;
using TechnitiumLibrary.Net.Dns.ResourceRecords;
using TechnitiumLibrary.Net.Mail;
@@ -37,7 +39,7 @@ namespace Failover
readonly HealthService _service;
- string _name;
+ readonly string _name;
bool _enabled;
MailAddress[] _alertTo;
string _smtpServer;
@@ -54,13 +56,15 @@ namespace Failover
#region constructor
- public EmailAlert(HealthService service, dynamic jsonEmailAlert)
+ public EmailAlert(HealthService service, JsonElement jsonEmailAlert)
{
_service = service;
_smtpClient = new SmtpClientEx();
_smtpClient.DnsClient = new DnsClientInternal(_service.DnsServer);
+ _name = jsonEmailAlert.GetPropertyValue("name", "default");
+
Reload(jsonEmailAlert);
}
@@ -98,7 +102,24 @@ namespace Failover
{
try
{
- await _smtpClient.SendMailAsync(message);
+ const int MAX_RETRIES = 3;
+ const int WAIT_INTERVAL = 30000;
+
+ for (int retries = 0; retries < MAX_RETRIES; retries++)
+ {
+ try
+ {
+ await _smtpClient.SendMailAsync(message);
+ break;
+ }
+ catch
+ {
+ if (retries == MAX_RETRIES - 1)
+ throw;
+
+ await Task.Delay(WAIT_INTERVAL);
+ }
+ }
}
catch (Exception ex)
{
@@ -110,71 +131,33 @@ namespace Failover
#region public
- public void Reload(dynamic jsonEmailAlert)
+ public void Reload(JsonElement jsonEmailAlert)
{
- if (jsonEmailAlert.name is null)
- _name = "default";
- else
- _name = jsonEmailAlert.name.Value;
+ _enabled = jsonEmailAlert.GetPropertyValue("enabled", false);
- if (jsonEmailAlert.enabled is null)
- _enabled = false;
+ if (jsonEmailAlert.TryReadArray("alertTo", delegate (string emailAddress) { return new MailAddress(emailAddress); }, out MailAddress[] alertTo))
+ _alertTo = alertTo;
else
- _enabled = jsonEmailAlert.enabled.Value;
-
- if (jsonEmailAlert.alertTo is null)
- {
_alertTo = null;
- }
- else
+
+ _smtpServer = jsonEmailAlert.GetPropertyValue("smtpServer", null);
+ _smtpPort = jsonEmailAlert.GetPropertyValue("smtpPort", 25);
+ _startTls = jsonEmailAlert.GetPropertyValue("startTls", false);
+ _smtpOverTls = jsonEmailAlert.GetPropertyValue("smtpOverTls", false);
+ _username = jsonEmailAlert.GetPropertyValue("username", null);
+ _password = jsonEmailAlert.GetPropertyValue("password", null);
+
+ if (jsonEmailAlert.TryGetProperty("mailFrom", out JsonElement jsonMailFrom))
{
- _alertTo = new MailAddress[jsonEmailAlert.alertTo.Count];
-
- for (int i = 0; i < _alertTo.Length; i++)
- _alertTo[i] = new MailAddress(jsonEmailAlert.alertTo[i].Value);
+ if (jsonEmailAlert.TryGetProperty("mailFromName", out JsonElement jsonMailFromName))
+ _mailFrom = new MailAddress(jsonMailFrom.GetString(), jsonMailFromName.GetString(), Encoding.UTF8);
+ else
+ _mailFrom = new MailAddress(jsonMailFrom.GetString());
}
-
- if (jsonEmailAlert.smtpServer is null)
- _smtpServer = null;
else
- _smtpServer = jsonEmailAlert.smtpServer.Value;
-
- if (jsonEmailAlert.smtpPort is null)
- _smtpPort = 25;
- else
- _smtpPort = Convert.ToInt32(jsonEmailAlert.smtpPort.Value);
-
- if (jsonEmailAlert.startTls is null)
- _startTls = false;
- else
- _startTls = jsonEmailAlert.startTls.Value;
-
- if (jsonEmailAlert.smtpOverTls is null)
- _smtpOverTls = false;
- else
- _smtpOverTls = jsonEmailAlert.smtpOverTls.Value;
-
- if (jsonEmailAlert.username is null)
- _username = null;
- else
- _username = jsonEmailAlert.username.Value;
-
- if (jsonEmailAlert.password is null)
- _password = null;
- else
- _password = jsonEmailAlert.password.Value;
-
- if (jsonEmailAlert.mailFrom is null)
{
_mailFrom = null;
}
- else
- {
- if (jsonEmailAlert.mailFromName is null)
- _mailFrom = new MailAddress(jsonEmailAlert.mailFrom.Value);
- else
- _mailFrom = new MailAddress(jsonEmailAlert.mailFrom.Value, jsonEmailAlert.mailFromName.Value, Encoding.UTF8);
- }
//update smtp client settings
_smtpClient.Host = _smtpServer;
diff --git a/Apps/FailoverApp/HealthCheck.cs b/Apps/FailoverApp/HealthCheck.cs
index ce202abd..85c02a2d 100644
--- a/Apps/FailoverApp/HealthCheck.cs
+++ b/Apps/FailoverApp/HealthCheck.cs
@@ -23,6 +23,7 @@ using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets;
+using System.Text.Json;
using System.Threading.Tasks;
using TechnitiumLibrary;
using TechnitiumLibrary.Net;
@@ -49,7 +50,7 @@ namespace Failover
readonly HealthService _service;
- string _name;
+ readonly string _name;
HealthCheckType _type;
int _interval;
int _retries;
@@ -66,10 +67,12 @@ namespace Failover
#region constructor
- public HealthCheck(HealthService service, dynamic jsonHealthCheck)
+ public HealthCheck(HealthService service, JsonElement jsonHealthCheck)
{
_service = service;
+ _name = jsonHealthCheck.GetPropertyValue("name", "default");
+
Reload(jsonHealthCheck);
}
@@ -200,63 +203,25 @@ namespace Failover
#region public
- public void Reload(dynamic jsonHealthCheck)
+ public void Reload(JsonElement jsonHealthCheck)
{
- if (jsonHealthCheck.name is null)
- _name = "default";
- else
- _name = jsonHealthCheck.name.Value;
+ _type = Enum.Parse(jsonHealthCheck.GetPropertyValue("type", "Tcp"), true);
+ _interval = jsonHealthCheck.GetPropertyValue("interval", 60) * 1000;
+ _retries = jsonHealthCheck.GetPropertyValue("retries", 3);
+ _timeout = jsonHealthCheck.GetPropertyValue("timeout", 10) * 1000;
+ _port = jsonHealthCheck.GetPropertyValue("port", 80);
- if (jsonHealthCheck.type == null)
- _type = HealthCheckType.Tcp;
+ if (jsonHealthCheck.TryGetProperty("url", out JsonElement jsonUrl) && (jsonUrl.ValueKind != JsonValueKind.Null))
+ _url = new Uri(jsonUrl.GetString());
else
- _type = Enum.Parse(jsonHealthCheck.type.Value, true);
-
- if (jsonHealthCheck.interval is null)
- _interval = 60000;
- else
- _interval = Convert.ToInt32(jsonHealthCheck.interval.Value) * 1000;
-
- if (jsonHealthCheck.retries is null)
- _retries = 3;
- else
- _retries = Convert.ToInt32(jsonHealthCheck.retries.Value);
-
- if (jsonHealthCheck.timeout is null)
- _timeout = 10000;
- else
- _timeout = Convert.ToInt32(jsonHealthCheck.timeout.Value) * 1000;
-
- if (jsonHealthCheck.port is null)
- _port = 80;
- else
- _port = Convert.ToInt32(jsonHealthCheck.port.Value);
-
- if ((jsonHealthCheck.url is null) || (jsonHealthCheck.url.Value is null))
_url = null;
- else
- _url = new Uri(jsonHealthCheck.url.Value);
- string emailAlertName;
-
- if (jsonHealthCheck.emailAlert is null)
- emailAlertName = null;
- else
- emailAlertName = jsonHealthCheck.emailAlert.Value;
-
- if ((emailAlertName is not null) && _service.EmailAlerts.TryGetValue(emailAlertName, out EmailAlert emailAlert))
+ if (jsonHealthCheck.TryGetProperty("emailAlert", out JsonElement jsonEmailAlert) && _service.EmailAlerts.TryGetValue(jsonEmailAlert.GetString(), out EmailAlert emailAlert))
_emailAlert = emailAlert;
else
_emailAlert = null;
- string webHookName;
-
- if (jsonHealthCheck.webHook is null)
- webHookName = null;
- else
- webHookName = jsonHealthCheck.webHook.Value;
-
- if ((webHookName is not null) && _service.WebHooks.TryGetValue(webHookName, out WebHook webHook))
+ if (jsonHealthCheck.TryGetProperty("webHook", out JsonElement jsonWebHook) && _service.WebHooks.TryGetValue(jsonWebHook.GetString(), out WebHook webHook))
_webHook = webHook;
else
_webHook = null;
diff --git a/Apps/FailoverApp/HealthService.cs b/Apps/FailoverApp/HealthService.cs
index adf55513..67b26511 100644
--- a/Apps/FailoverApp/HealthService.cs
+++ b/Apps/FailoverApp/HealthService.cs
@@ -1,6 +1,6 @@
/*
Technitium DNS Server
-Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
+Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,7 +22,9 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
+using System.Text.Json;
using System.Threading;
+using TechnitiumLibrary;
using TechnitiumLibrary.Net;
using TechnitiumLibrary.Net.Dns.ResourceRecords;
@@ -178,19 +180,19 @@ namespace Failover
#region public
- public void Initialize(dynamic jsonConfig)
+ public void Initialize(string config)
{
+ using JsonDocument jsonDocument = JsonDocument.Parse(config);
+ JsonElement jsonConfig = jsonDocument.RootElement;
+
//email alerts
{
- //add or update email alerts
- foreach (dynamic jsonEmailAlert in jsonConfig.emailAlerts)
- {
- string name;
+ JsonElement jsonEmailAlerts = jsonConfig.GetProperty("emailAlerts");
- if (jsonEmailAlert.name is null)
- name = "default";
- else
- name = jsonEmailAlert.name.Value;
+ //add or update email alerts
+ foreach (JsonElement jsonEmailAlert in jsonEmailAlerts.EnumerateArray())
+ {
+ string name = jsonEmailAlert.GetPropertyValue("name", "default");
if (_emailAlerts.TryGetValue(name, out EmailAlert existingEmailAlert))
{
@@ -201,7 +203,6 @@ namespace Failover
{
//add
EmailAlert emailAlert = new EmailAlert(this, jsonEmailAlert);
-
_emailAlerts.TryAdd(emailAlert.Name, emailAlert);
}
}
@@ -211,15 +212,9 @@ namespace Failover
{
bool emailAlertExists = false;
- foreach (dynamic jsonEmailAlert in jsonConfig.emailAlerts)
+ foreach (JsonElement jsonEmailAlert in jsonEmailAlerts.EnumerateArray())
{
- string name;
-
- if (jsonEmailAlert.name is null)
- name = "default";
- else
- name = jsonEmailAlert.name.Value;
-
+ string name = jsonEmailAlert.GetPropertyValue("name", "default");
if (name == emailAlert.Key)
{
emailAlertExists = true;
@@ -237,15 +232,12 @@ namespace Failover
//web hooks
{
- //add or update email alerts
- foreach (dynamic jsonWebHook in jsonConfig.webHooks)
- {
- string name;
+ JsonElement jsonWebHooks = jsonConfig.GetProperty("webHooks");
- if (jsonWebHook.name is null)
- name = "default";
- else
- name = jsonWebHook.name.Value;
+ //add or update email alerts
+ foreach (JsonElement jsonWebHook in jsonWebHooks.EnumerateArray())
+ {
+ string name = jsonWebHook.GetPropertyValue("name", "default");
if (_webHooks.TryGetValue(name, out WebHook existingWebHook))
{
@@ -256,7 +248,6 @@ namespace Failover
{
//add
WebHook webHook = new WebHook(this, jsonWebHook);
-
_webHooks.TryAdd(webHook.Name, webHook);
}
}
@@ -266,15 +257,9 @@ namespace Failover
{
bool webHookExists = false;
- foreach (dynamic jsonWebHook in jsonConfig.webHooks)
+ foreach (JsonElement jsonWebHook in jsonWebHooks.EnumerateArray())
{
- string name;
-
- if (jsonWebHook.name is null)
- name = "default";
- else
- name = jsonWebHook.name.Value;
-
+ string name = jsonWebHook.GetPropertyValue("name", "default");
if (name == webHook.Key)
{
webHookExists = true;
@@ -292,15 +277,12 @@ namespace Failover
//health checks
{
- //add or update health checks
- foreach (dynamic jsonHealthCheck in jsonConfig.healthChecks)
- {
- string name;
+ JsonElement jsonHealthChecks = jsonConfig.GetProperty("healthChecks");
- if (jsonHealthCheck.name is null)
- name = "default";
- else
- name = jsonHealthCheck.name.Value;
+ //add or update health checks
+ foreach (JsonElement jsonHealthCheck in jsonHealthChecks.EnumerateArray())
+ {
+ string name = jsonHealthCheck.GetPropertyValue("name", "default");
if (_healthChecks.TryGetValue(name, out HealthCheck existingHealthCheck))
{
@@ -311,7 +293,6 @@ namespace Failover
{
//add
HealthCheck healthCheck = new HealthCheck(this, jsonHealthCheck);
-
_healthChecks.TryAdd(healthCheck.Name, healthCheck);
}
}
@@ -321,15 +302,9 @@ namespace Failover
{
bool healthCheckExists = false;
- foreach (dynamic jsonHealthCheck in jsonConfig.healthChecks)
+ foreach (JsonElement jsonHealthCheck in jsonHealthChecks.EnumerateArray())
{
- string name;
-
- if (jsonHealthCheck.name is null)
- name = "default";
- else
- name = jsonHealthCheck.name.Value;
-
+ string name = jsonHealthCheck.GetPropertyValue("name", "default");
if (name == healthCheck.Key)
{
healthCheckExists = true;
@@ -353,12 +328,12 @@ namespace Failover
//under maintenance networks
_underMaintenance.Clear();
- if (jsonConfig.underMaintenance is not null)
+ if (jsonConfig.TryGetProperty("underMaintenance", out JsonElement jsonUnderMaintenance))
{
- foreach (dynamic jsonNetwork in jsonConfig.underMaintenance)
+ foreach (JsonElement jsonNetwork in jsonUnderMaintenance.EnumerateArray())
{
- string network = jsonNetwork.network.Value;
- bool enable = jsonNetwork.enable.Value;
+ string network = jsonNetwork.GetProperty("network").GetString();
+ bool enable = jsonNetwork.GetProperty("enable").GetBoolean();
_underMaintenance.TryAdd(NetworkAddress.Parse(network), enable);
}
diff --git a/Apps/FailoverApp/WebHook.cs b/Apps/FailoverApp/WebHook.cs
index 7aecc7f0..5356c972 100644
--- a/Apps/FailoverApp/WebHook.cs
+++ b/Apps/FailoverApp/WebHook.cs
@@ -17,14 +17,15 @@ along with this program. If not, see .
*/
-using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
+using System.Text.Json;
using System.Threading.Tasks;
+using TechnitiumLibrary;
using TechnitiumLibrary.Net.Dns.ResourceRecords;
using TechnitiumLibrary.Net.Proxy;
@@ -36,7 +37,7 @@ namespace Failover
readonly HealthService _service;
- string _name;
+ readonly string _name;
bool _enabled;
Uri[] _urls;
@@ -47,10 +48,12 @@ namespace Failover
#region constructor
- public WebHook(HealthService service, dynamic jsonWebHook)
+ public WebHook(HealthService service, JsonElement jsonWebHook)
{
_service = service;
+ _name = jsonWebHook.GetPropertyValue("name", "default");
+
Reload(jsonWebHook);
}
@@ -176,29 +179,14 @@ namespace Failover
#region public
- public void Reload(dynamic jsonWebHook)
+ public void Reload(JsonElement jsonWebHook)
{
- if (jsonWebHook.name is null)
- _name = "default";
- else
- _name = jsonWebHook.name.Value;
+ _enabled = jsonWebHook.GetPropertyValue("enabled", false);
- if (jsonWebHook.enabled is null)
- _enabled = false;
+ if (jsonWebHook.TryReadArray("urls", delegate (string uri) { return new Uri(uri); }, out Uri[] urls))
+ _urls = urls;
else
- _enabled = jsonWebHook.enabled.Value;
-
- if (jsonWebHook.urls is null)
- {
_urls = null;
- }
- else
- {
- _urls = new Uri[jsonWebHook.urls.Count];
-
- for (int i = 0; i < _urls.Length; i++)
- _urls[i] = new Uri(jsonWebHook.urls[i].Value);
- }
ConditionalHttpReload();
}
@@ -212,26 +200,17 @@ namespace Failover
{
using (MemoryStream mS = new MemoryStream())
{
- JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
+ Utf8JsonWriter jsonWriter = new Utf8JsonWriter(mS);
jsonWriter.WriteStartObject();
- jsonWriter.WritePropertyName("address");
- jsonWriter.WriteValue(address.ToString());
-
- jsonWriter.WritePropertyName("healthCheck");
- jsonWriter.WriteValue(healthCheck);
-
- jsonWriter.WritePropertyName("status");
- jsonWriter.WriteValue(healthCheckResponse.Status.ToString());
+ jsonWriter.WriteString("address", address.ToString());
+ jsonWriter.WriteString("healthCheck", healthCheck);
+ jsonWriter.WriteString("status", healthCheckResponse.Status.ToString());
if (healthCheckResponse.Status == HealthStatus.Failed)
- {
- jsonWriter.WritePropertyName("failureReason");
- jsonWriter.WriteValue(healthCheckResponse.FailureReason);
- }
+ jsonWriter.WriteString("failureReason", healthCheckResponse.FailureReason);
- jsonWriter.WritePropertyName("dateTime");
- jsonWriter.WriteValue(healthCheckResponse.DateTime);
+ jsonWriter.WriteString("dateTime", healthCheckResponse.DateTime);
jsonWriter.WriteEndObject();
jsonWriter.Flush();
@@ -253,23 +232,14 @@ namespace Failover
{
using (MemoryStream mS = new MemoryStream())
{
- JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
+ Utf8JsonWriter jsonWriter = new Utf8JsonWriter(mS);
jsonWriter.WriteStartObject();
- jsonWriter.WritePropertyName("address");
- jsonWriter.WriteValue(address.ToString());
-
- jsonWriter.WritePropertyName("healthCheck");
- jsonWriter.WriteValue(healthCheck);
-
- jsonWriter.WritePropertyName("status");
- jsonWriter.WriteValue("Error");
-
- jsonWriter.WritePropertyName("failureReason");
- jsonWriter.WriteValue(ex.ToString());
-
- jsonWriter.WritePropertyName("dateTime");
- jsonWriter.WriteValue(DateTime.UtcNow);
+ jsonWriter.WriteString("address", address.ToString());
+ jsonWriter.WriteString("healthCheck", healthCheck);
+ jsonWriter.WriteString("status", "Error");
+ jsonWriter.WriteString("failureReason", ex.ToString());
+ jsonWriter.WriteString("dateTime", DateTime.UtcNow);
jsonWriter.WriteEndObject();
jsonWriter.Flush();
@@ -291,29 +261,18 @@ namespace Failover
{
using (MemoryStream mS = new MemoryStream())
{
- JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
+ Utf8JsonWriter jsonWriter = new Utf8JsonWriter(mS);
jsonWriter.WriteStartObject();
- jsonWriter.WritePropertyName("domain");
- jsonWriter.WriteValue(domain);
-
- jsonWriter.WritePropertyName("recordType");
- jsonWriter.WriteValue(type.ToString());
-
- jsonWriter.WritePropertyName("healthCheck");
- jsonWriter.WriteValue(healthCheck);
-
- jsonWriter.WritePropertyName("status");
- jsonWriter.WriteValue(healthCheckResponse.Status.ToString());
+ jsonWriter.WriteString("domain", domain);
+ jsonWriter.WriteString("recordType", type.ToString());
+ jsonWriter.WriteString("healthCheck", healthCheck);
+ jsonWriter.WriteString("status", healthCheckResponse.Status.ToString());
if (healthCheckResponse.Status == HealthStatus.Failed)
- {
- jsonWriter.WritePropertyName("failureReason");
- jsonWriter.WriteValue(healthCheckResponse.FailureReason);
- }
+ jsonWriter.WriteString("failureReason", healthCheckResponse.FailureReason);
- jsonWriter.WritePropertyName("dateTime");
- jsonWriter.WriteValue(healthCheckResponse.DateTime);
+ jsonWriter.WriteString("dateTime", healthCheckResponse.DateTime);
jsonWriter.WriteEndObject();
jsonWriter.Flush();
@@ -335,26 +294,15 @@ namespace Failover
{
using (MemoryStream mS = new MemoryStream())
{
- JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS));
+ Utf8JsonWriter jsonWriter = new Utf8JsonWriter(mS);
jsonWriter.WriteStartObject();
- jsonWriter.WritePropertyName("domain");
- jsonWriter.WriteValue(domain);
-
- jsonWriter.WritePropertyName("recordType");
- jsonWriter.WriteValue(type.ToString());
-
- jsonWriter.WritePropertyName("healthCheck");
- jsonWriter.WriteValue(healthCheck);
-
- jsonWriter.WritePropertyName("status");
- jsonWriter.WriteValue("Error");
-
- jsonWriter.WritePropertyName("failureReason");
- jsonWriter.WriteValue(ex.ToString());
-
- jsonWriter.WritePropertyName("dateTime");
- jsonWriter.WriteValue(DateTime.UtcNow);
+ jsonWriter.WriteString("domain", domain);
+ jsonWriter.WriteString("recordType", type.ToString());
+ jsonWriter.WriteString("healthCheck", healthCheck);
+ jsonWriter.WriteString("status", "Error");
+ jsonWriter.WriteString("failureReason", ex.ToString());
+ jsonWriter.WriteString("dateTime", DateTime.UtcNow);
jsonWriter.WriteEndObject();
jsonWriter.Flush();