2using System.Collections.Generic;
4using System.Threading.Tasks;
37 public override string Resource =>
"/Settings/DNS.md";
59 return Task.CompletedTask;
77 this.testDns = WebServer.
Register(
"/Settings/TestDns",
null, this.TestDns,
true,
false,
true);
79 return base.InitSetup(WebServer);
90 return base.UnregisterSetup(WebServer);
106 if (!(Obj is
string TabID))
109 Response.StatusCode = 200;
111 Task _ = Task.Run(async () => await this.Test(TabID));
114 private async Task Test(params
string[] TabIDs)
118 Dictionary<CaseInsensitiveString, bool> Processed =
new Dictionary<CaseInsensitiveString, bool>();
119 List<KeyValuePair<string, string>> DomainNames =
new List<KeyValuePair<string, string>>() { };
130 foreach (KeyValuePair<string, string> P
in DomainNames)
132 string DomainName = P.Key;
133 if (Processed.ContainsKey(DomainName))
140 if (Exchanges.Length != 1)
141 throw new Exception(
"Invalid number of host names.");
143 if (Exchanges[0] != DomainName &&
144 Exchanges[0] != await Networking.SMTP.Server.SmtpServer.GetSalutation(DomainName))
146 throw new Exception(
"Does not point to correct host.");
149 this.PushResult(TabIDs, DomainName,
"MX",
true,
string.Empty, P.Value);
153 this.PushResult(TabIDs, DomainName,
"MX",
false, ex.Message, P.Value);
154 await this.DiagnoseQuery(TabIDs, DomainName,
QTYPE.MX);
162 foreach (
string Row
in Rows)
164 string s = Row.Trim();
166 if (s.StartsWith(
"\"") && s.EndsWith(
"\""))
167 s = s.Substring(1, s.Length - 2);
169 if (s.StartsWith(
"v=spf1"))
174 throw new Exception(
"Exactly one SPF record must be configured.");
176 this.PushResult(TabIDs, DomainName,
"SPF",
true,
string.Empty, P.Value);
180 this.PushResult(TabIDs, DomainName,
"SPF",
false, ex.Message, P.Value);
181 await this.DiagnoseQuery(TabIDs, DomainName,
QTYPE.TXT);
189 bool BoshValid =
true;
193 foreach (
string Row
in Rows)
195 string s = Row.Trim();
197 if (s.StartsWith(
"_xmpp-client-xbosh="))
200 if (s.Substring(19) != WebServices.WebHostMetaDataXml.BoshLink(DomainName))
203 else if (s.StartsWith(
"_xmpp-client-websocket="))
206 if (s.Substring(23) != WebServices.WebHostMetaDataXml.WebSocketLink(DomainName))
211 if (BoshFound == 1 && BoshValid)
212 this.PushResult(TabIDs, DomainName,
"BOSH",
true,
string.Empty, P.Value);
218 this.PushResult(TabIDs, DomainName,
"BOSH",
false,
"TXT Record for BOSH not found.", P.Value);
219 else if (BoshFound > 1)
220 this.PushResult(TabIDs, DomainName,
"BOSH",
false,
"More than one TXT Record for BOSH found.", P.Value);
222 this.PushResult(TabIDs, DomainName,
"BOSH",
false,
"TXT record for BOSH incorrect.", P.Value);
225 if (WsFound == 1 && WsValid)
226 this.PushResult(TabIDs, DomainName,
"WS",
true,
string.Empty, P.Value);
232 this.PushResult(TabIDs, DomainName,
"WS",
false,
"TXT Record for WebSockets not found.", P.Value);
233 else if (WsFound > 1)
234 this.PushResult(TabIDs, DomainName,
"WS",
false,
"More than one TXT Record for WebSockets found.", P.Value);
236 this.PushResult(TabIDs, DomainName,
"WS",
false,
"TXT record for WebSockets incorrect.", P.Value);
240 await this.DiagnoseQuery(TabIDs,
"_xmppconnect." + DomainName,
QTYPE.TXT);
244 this.PushResult(TabIDs, DomainName,
"BOSH",
false, ex.Message, P.Value);
245 this.PushResult(TabIDs, DomainName,
"WS",
false, ex.Message, P.Value);
247 await this.DiagnoseQuery(TabIDs,
"_xmppconnect." + DomainName,
QTYPE.TXT);
255 throw new Exception(
"Invalid c2s port number.");
258 throw new Exception(
"Does not point to correct host.");
260 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpClient",
true,
string.Empty, P.Value);
264 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpClient",
false, ex.Message, P.Value);
265 await this.DiagnoseQuery(TabIDs,
"_xmpp-client._tcp." + DomainName,
QTYPE.SRV);
273 throw new Exception(
"Invalid s2s port number.");
276 throw new Exception(
"Does not point to correct host.");
278 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpServer",
true,
string.Empty, P.Value);
282 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpServer",
false, ex.Message, P.Value);
283 await this.DiagnoseQuery(TabIDs,
"_xmpp-server._tcp." + DomainName,
QTYPE.SRV);
288 string ComponentDomainName = Component.Subdomain.Value +
"." + DomainName;
295 throw new Exception(
"Invalid s2s port number.");
298 throw new Exception(
"Does not point to correct host.");
300 this.PushResult(TabIDs, ComponentDomainName,
"SRV_Component",
true,
string.Empty, P.Value);
304 this.PushResult(TabIDs, ComponentDomainName,
"SRV_Component",
false, ex.Message, P.Value);
305 await this.DiagnoseQuery(TabIDs,
"_xmpp-server._tcp." + ComponentDomainName,
QTYPE.SRV);
316 private async Task DiagnoseQuery(
string[] TabIDs,
string Name,
QTYPE TYPE)
318 StringBuilder sb =
new StringBuilder();
320 sb.AppendLine(
"============ QUERY ============");
324 sb.AppendLine(
TYPE.ToString());
325 sb.AppendLine(
"Class: IN");
327 sb.AppendLine(
"========== RESPONSE ===========");
336 sb.AppendLine(ex.Message);
342 private void PushResult(
string[] TabIDs,
string DomainName,
string Suffix,
bool Ok,
string Message,
string VariableName)
353 {
"domainName", DomainName },
354 {
"suffix", Suffix },
356 {
"message", Message }
367 return Task.FromResult(
true);
378 await this.Test(
null);
Helps with common JSON-related tasks.
static string Encode(string s)
Encodes a string for inclusion in JSON.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
The ClientEvents class allows applications to push information asynchronously to web clients connecte...
static Task< int > PushEvent(string[] TabIDs, string Type, object Data)
Puses an event to a set of Tabs, given their Tab IDs.
Static class managing the runtime environment of the IoT Gateway.
static CaseInsensitiveString Domain
Domain name.
static IUser AssertUserAuthenticated(HttpRequest Request, string Privilege)
Makes sure a request is being made from a session with a successful user login.
static DomainConfiguration Instance
Current instance of configuration.
const string GATEWAY_DOMAIN_NAME
Main Domain Name of the gateway, if defined. If not provided, the gateway will not use a domain name.
string[] AlternativeDomains
Alternative domain names
const string GATEWAY_DOMAIN_ALT
Comma-separated list of alternative domain names for the gateway, if defined.
string Domain
Principal domain name
Abstract base class for system configurations.
void LogEnvironmentError(string EnvironmentVariable, object Value)
Logs an error to the event log, telling the operator an environment variable value contains an error.
override string ToString()
DNS resolver, as defined in:
static async Task< string[]> LookupText(string Name)
Looks up text (TXT) records for a name.
static async Task< string[]> LookupMailExchange(string DomainName)
Looks up the Mail Exchanges related to a given domain name.
static Task< DnsResponse > Query(string Name, QTYPE TYPE, QCLASS CLASS)
Resolves a DNS name.
static Task< SRV > LookupServiceEndpoint(string DomainName, string ServiceName, string Protocol)
Looks up a service endpoint for a domain. If multiple are available, an appropriate one is selected a...
string TargetHost
Target Host
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Represents an HTTP request.
bool HasData
If the request has data.
async Task< object > DecodeDataAsync()
Decodes data sent in request.
Base class for all HTTP resources.
Represets a response of an HTTP client request.
Implements an HTTP server.
HttpResource Register(HttpResource Resource)
Registers a resource with the server.
bool Unregister(HttpResource Resource)
Unregisters a resource from the server.
Base class for components.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
Contains information about a language.
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Provides the user with information about what DNS configurations must be performed for the broker to ...
override Task InitSetup(HttpServer WebServer)
Initializes the setup object.
override void SetStaticInstance(ISystemConfiguration Configuration)
Sets the static instance of the configuration.
override Task UnregisterSetup(HttpServer WebServer)
Unregisters the setup object.
override async Task< bool > EnvironmentConfiguration()
Environment configuration by configuring values available in environment variables.
override string Resource
Resource to be redirected to, to perform the configuration.
override string ConfigPrivilege
Minimum required privilege for a user to be allowed to change the configuration defined by the class.
override Task< string > Title(Language Language)
Gets a title for the system configuration.
override Task< bool > SimplifiedConfiguration()
Simplified configuration by configuring simple default values.
static DnsConfiguration Instance
Current instance of configuration.
override Task ConfigureSystem()
Is called during startup to configure the system.
override int Priority
Priority of the setting. Configurations are sorted in ascending order.
Service Module hosting the XMPP broker and its components.
Interface for system configurations. The gateway will scan all module for system configuration classe...
Interface for components.
QTYPE
QTYPE fields appear in the question part of a query.
QCLASS
QCLASS fields appear in the question section of a query.
TYPE
TYPE fields are used in resource records.