mirror of
https://github.com/fergalmoran/DnsServer.git
synced 2026-02-24 00:37:08 +00:00
Failover: Removed newtonsoft. Added retries for send alert email.
This commit is contained in:
@@ -18,11 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<DnsResourceRecord> answers)
|
||||
private void GetAnswers(JsonElement jsonAddresses, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List<DnsResourceRecord> 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<DnsResourceRecord> answers)
|
||||
private void GetStatusAnswers(JsonElement jsonAddresses, FailoverType type, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List<DnsResourceRecord> 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<DnsResourceRecord> answers = new List<DnsResourceRecord>();
|
||||
|
||||
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<DnsDatagram>(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<DnsResourceRecord> answers = new List<DnsResourceRecord>();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -18,11 +18,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<DnsResourceRecord> answers;
|
||||
IReadOnlyList<DnsResourceRecord> 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<DnsDatagram>(null);
|
||||
|
||||
List<DnsResourceRecord> txtAnswers = new List<DnsResourceRecord>();
|
||||
|
||||
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<DnsDatagram>(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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<HealthCheckType>(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<HealthCheckType>(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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -17,14 +17,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user