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);
115 Response.StatusCode = 200;
116 Response.StatusMessage =
"OK";
118 Task
_ = Task.Run(async () => await this.Test(TabID));
121 private async Task Test(params
string[] TabIDs)
125 Dictionary<CaseInsensitiveString, bool> Processed =
new Dictionary<CaseInsensitiveString, bool>();
126 List<KeyValuePair<string, string>> DomainNames =
new List<KeyValuePair<string, string>>() { };
137 foreach (KeyValuePair<string, string> P
in DomainNames)
139 string DomainName = P.Key;
140 if (Processed.ContainsKey(DomainName))
147 if (Exchanges is
null || Exchanges.Length != 1)
148 throw new Exception(
"Invalid number of host names.");
150 if (Exchanges[0] != DomainName &&
151 Exchanges[0] != await Networking.SMTP.Server.SmtpServer.GetSalutation(DomainName))
153 throw new Exception(
"Does not point to correct host.");
156 this.PushResult(TabIDs, DomainName,
"MX",
true,
string.Empty, P.Value);
160 this.PushResult(TabIDs, DomainName,
"MX",
false, ex.Message, P.Value);
161 await this.DiagnoseQuery(TabIDs, DomainName,
QTYPE.MX);
171 foreach (
string Row
in Rows)
173 string s = Row.Trim();
175 if (s.StartsWith(
"\"") && s.EndsWith(
"\""))
178 if (s.StartsWith(
"v=spf1"))
184 throw new Exception(
"Exactly one SPF record must be configured.");
186 this.PushResult(TabIDs, DomainName,
"SPF",
true,
string.Empty, P.Value);
190 this.PushResult(TabIDs, DomainName,
"SPF",
false, ex.Message, P.Value);
191 await this.DiagnoseQuery(TabIDs, DomainName,
QTYPE.TXT);
199 bool BoshValid =
true;
205 foreach (
string Row
in Rows)
207 string s = Row.Trim();
209 if (s.StartsWith(
"_xmpp-client-xbosh="))
212 if (s[19..] != WebServices.WebHostMetaDataXml.BoshLink(DomainName))
215 else if (s.StartsWith(
"_xmpp-client-websocket="))
218 if (s[23..] != WebServices.WebHostMetaDataXml.WebSocketLink(DomainName))
224 if (BoshFound == 1 && BoshValid)
225 this.PushResult(TabIDs, DomainName,
"BOSH",
true,
string.Empty, P.Value);
231 this.PushResult(TabIDs, DomainName,
"BOSH",
false,
"TXT Record for BOSH not found.", P.Value);
232 else if (BoshFound > 1)
233 this.PushResult(TabIDs, DomainName,
"BOSH",
false,
"More than one TXT Record for BOSH found.", P.Value);
235 this.PushResult(TabIDs, DomainName,
"BOSH",
false,
"TXT record for BOSH incorrect.", P.Value);
238 if (WsFound == 1 && WsValid)
239 this.PushResult(TabIDs, DomainName,
"WS",
true,
string.Empty, P.Value);
245 this.PushResult(TabIDs, DomainName,
"WS",
false,
"TXT Record for WebSockets not found.", P.Value);
246 else if (WsFound > 1)
247 this.PushResult(TabIDs, DomainName,
"WS",
false,
"More than one TXT Record for WebSockets found.", P.Value);
249 this.PushResult(TabIDs, DomainName,
"WS",
false,
"TXT record for WebSockets incorrect.", P.Value);
253 await this.DiagnoseQuery(TabIDs,
"_xmppconnect." + DomainName,
QTYPE.TXT);
257 this.PushResult(TabIDs, DomainName,
"BOSH",
false, ex.Message, P.Value);
258 this.PushResult(TabIDs, DomainName,
"WS",
false, ex.Message, P.Value);
260 await this.DiagnoseQuery(TabIDs,
"_xmppconnect." + DomainName,
QTYPE.TXT);
268 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpClient",
false,
"XMPP Client TCP service not defined in DNS.", P.Value);
269 await this.DiagnoseQuery(TabIDs,
"_xmpp-client._tcp." + DomainName,
QTYPE.SRV);
274 throw new Exception(
"Invalid c2s port number.");
277 throw new Exception(
"Does not point to correct host.");
279 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpClient",
true,
string.Empty, P.Value);
284 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpClient",
false, ex.Message, P.Value);
285 await this.DiagnoseQuery(TabIDs,
"_xmpp-client._tcp." + DomainName,
QTYPE.SRV);
294 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpServer",
false,
"XMPP Server TCP service not defined in DNS.", P.Value);
295 await this.DiagnoseQuery(TabIDs,
"_xmpp-server._tcp." + DomainName,
QTYPE.SRV);
300 throw new Exception(
"Invalid s2s port number.");
303 throw new Exception(
"Does not point to correct host.");
305 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpServer",
true,
string.Empty, P.Value);
310 this.PushResult(TabIDs, DomainName,
"SRV_XmppTcpServer",
false, ex.Message, P.Value);
311 await this.DiagnoseQuery(TabIDs,
"_xmpp-server._tcp." + DomainName,
QTYPE.SRV);
316 string ComponentDomainName = Component.Subdomain.Value +
"." + DomainName;
324 this.PushResult(TabIDs, ComponentDomainName,
"SRV_Component",
false,
"XMPP Server Component TCP service not defined in DNS.", P.Value);
325 await this.DiagnoseQuery(TabIDs,
"_xmpp-server._tcp." + ComponentDomainName,
QTYPE.SRV);
330 throw new Exception(
"Invalid s2s port number.");
333 throw new Exception(
"Does not point to correct host.");
335 this.PushResult(TabIDs, ComponentDomainName,
"SRV_Component",
true,
string.Empty, P.Value);
340 this.PushResult(TabIDs, ComponentDomainName,
"SRV_Component",
false, ex.Message, P.Value);
341 await this.DiagnoseQuery(TabIDs,
"_xmpp-server._tcp." + ComponentDomainName,
QTYPE.SRV);
352 private async Task DiagnoseQuery(
string[] TabIDs,
string Name,
QTYPE TYPE)
354 StringBuilder sb =
new StringBuilder();
356 sb.AppendLine(
"============ QUERY ============");
360 sb.AppendLine(
TYPE.ToString());
361 sb.AppendLine(
"Class: IN");
363 sb.AppendLine(
"========== RESPONSE ===========");
366 if (Response is
null)
367 sb.AppendLine(
"Unable to resolve DNS query.");
374 private void PushResult(
string[] TabIDs,
string DomainName,
string Suffix,
bool Ok,
string Message,
string VariableName)
385 {
"domainName", DomainName },
386 {
"suffix", Suffix },
388 {
"message", Message }
399 return Task.FromResult(
true);
410 await this.Test(
null);
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
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 Task< SRV > TryLookupServiceEndpoint(string DomainName, string ServiceName, string Protocol)
Tries to look up a service endpoint for a domain. If multiple are available, an appropriate one is se...
static Task< string[]> TryLookupMailExchange(string DomainName)
Tries to look up the Mail Exchanges related to a given domain name.
static Task< string[]> LookupText(string Name)
Looks up text (TXT) records for a name.
static Task< DnsResponse > TryQuery(string Name, QTYPE TYPE, QCLASS CLASS)
Tries to query a DNS name.
static Task< string[]> TryLookupText(string Name)
Tries to look up text (TXT) records for a name.
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< ContentResponse > DecodeDataAsync()
Decodes data sent in request.
Base class for all HTTP resources.
Represets a response of an HTTP client request.
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
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 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.