Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
GatewayConfigSource.cs
1using System;
3using System.IO;
4using System.Reflection;
5using System.Text;
6using System.Threading.Tasks;
7using System.Xml;
8using Waher.Content;
11using Waher.Events;
24using Waher.Things;
26
28{
32 public class GatewayConfigSource : IDataSource, IDisposable
33 {
37 public const string SourceID = "GatewayConfig";
38
39 private readonly static Dictionary<string, INode> nodesById = new Dictionary<string, INode>();
40 private static IEnumerable<INode> nodes = null;
41 private static GeneralInformation generalInformation = null;
42 private static WebServer webServer = null;
43 private static DatabaseDefinition databaseDefinition = null;
44 private static Ports ports = null;
45 private static LoginAuditorNode loginAuditor = null;
46 private static EventSinksNode eventSinks = null;
47 private static DateTime writeTime = DateTime.MinValue;
48 private static GatewayConfigSource instance = null;
49 internal static DateTime nodesTimestamp = DateTime.MinValue;
50
55 {
56 instance = this;
57 this.LoadConfiguration();
58 }
59
63 public void Dispose()
64 {
65 }
66
67 private void CheckLoadConfiguration()
68 {
69 if (nodes is null || nodesTimestamp < this.LastChanged)
70 this.LoadConfiguration();
71 }
72
73 private void LoadConfiguration()
74 {
75 try
76 {
77 string GatewayConfigFileName = Gateway.ConfigFilePath;
78 if (!File.Exists(GatewayConfigFileName))
79 {
80 GatewayConfigFileName = Gateway.GatewayConfigLocalFileName;
81 if (!File.Exists(GatewayConfigFileName))
82 throw new Exception("Gateway.config not found.");
83 }
84
85 XmlDocument Config = XML.LoadFromFile(GatewayConfigFileName);
86
88 XSL.LoadSchema(typeof(Gateway).Namespace + ".Schema.GatewayConfiguration.xsd", typeof(Gateway).Assembly));
89
90 generalInformation = new GeneralInformation(this);
91 webServer = new WebServer(this)
92 {
93 Http2Enabled = Gateway.HttpServer.Http2Enabled,
94 Http2InitialStreamWindowSize = Gateway.HttpServer.Http2InitialStreamWindowSize,
95 Http2InitialConnectionWindowSize = Gateway.HttpServer.Http2InitialConnectionWindowSize,
96 Http2MaxFrameSize = Gateway.HttpServer.Http2MaxFrameSize,
97 Http2MaxConcurrentStreams = Gateway.HttpServer.Http2MaxConcurrentStreams,
98 Http2HeaderTableSize = Gateway.HttpServer.Http2HeaderTableSize,
99 Http2NoRfc7540Priorities = Gateway.HttpServer.Http2NoRfc7540Priorities
100 };
101 databaseDefinition = new DatabaseDefinition(this);
102 ports = new Ports(this);
103 loginAuditor = null;
104 eventSinks = null;
105
106 List<INode> Nodes = new List<INode>()
107 {
108 generalInformation,
109 webServer,
110 databaseDefinition,
111 ports
112 };
113
114 Dictionary<string, bool> ContentEncodingsFound = new Dictionary<string, bool>();
115
116 foreach (XmlNode N in Config.DocumentElement.ChildNodes)
117 {
118 if (N is XmlElement E)
119 {
120 switch (E.LocalName)
121 {
122 case "ApplicationName":
123 generalInformation.ApplicationName = E.InnerText;
124 break;
125
126 case "DefaultPage":
127 DefaultPage DefaultPage = new DefaultPage(this, webServer, XML.Attribute(E, "host"), E.InnerText);
128 webServer.AddInternal(DefaultPage);
129 break;
130
131 case "MutualTls":
132 webServer.ClientCertificates = XML.Attribute(E, "clientCertificates", ClientCertificates.NotUsed);
133 webServer.TrustClientCertificates = XML.Attribute(E, "trustCertificates", false);
134
135 foreach (XmlNode N2 in E.ChildNodes)
136 {
137 if (N2.LocalName == "Port" && int.TryParse(N2.InnerText, out int PortNumber))
138 {
139 XmlElement E2 = (XmlElement)N2;
140 ClientCertificates ClientCertificatesPort = XML.Attribute(E2, "clientCertificates", webServer.ClientCertificates);
141 bool TrustClientCertificatesPort = XML.Attribute(E2, "trustCertificates", webServer.TrustClientCertificates);
142
143 webServer.AddInternal(new MTlsPort(this, webServer, PortNumber, ClientCertificatesPort, TrustClientCertificatesPort));
144 }
145 }
146 break;
147
148 case "Http2Settings":
149 webServer.Http2Enabled = XML.Attribute(E, "enabled", true);
150 webServer.Http2InitialStreamWindowSize = XML.Attribute(E, "initialWindowSize", 2500000);
151 webServer.Http2InitialConnectionWindowSize = XML.Attribute(E, "initialConnectionWindowSize", 5000000);
152 webServer.Http2MaxFrameSize = XML.Attribute(E, "maxFrameSize", 16384);
153 webServer.Http2MaxConcurrentStreams = XML.Attribute(E, "maxConcurrentStreams", 100);
154 webServer.Http2HeaderTableSize = XML.Attribute(E, "headerTableSize", 8192);
155 webServer.Http2NoRfc7540Priorities = XML.Attribute(E, "noRfc7540Priorities", false);
156 webServer.Http2Profiling = XML.Attribute(E, "profiling", false);
157 webServer.HttpSniffersPerEndpoint = XML.Attribute(E, "sniffersPerEndpoint", false);
158 break;
159
160 case "ContentEncodings":
161 foreach (XmlNode N2 in E.ChildNodes)
162 {
163 if (N2.LocalName == "ContentEncoding")
164 {
165 XmlElement E2 = (XmlElement)N2;
166 string Method = XML.Attribute(E2, "method");
167 bool Dynamic = XML.Attribute(E2, "dynamic", true);
168 bool Static = XML.Attribute(E2, "static", true);
169
170 IContentEncoding Encoding = Types.FindBest<IContentEncoding, string>(Method);
171
172 Encoding?.ConfigureSupport(Dynamic, Static);
173 ContentEncodingsFound[Method] = true;
174
175 webServer.AddInternal(new ContentEncoding(this, webServer, Method, Dynamic, Static));
176 }
177 }
178
180 break;
181
182 case "ExportExceptions":
183 generalInformation.ExceptionFolder = XML.Attribute(E, "folder", "Exceptions");
184 break;
185
186 case "Database":
187 databaseDefinition.Folder = XML.Attribute(E, "folder");
188 databaseDefinition.DefaultCollectionName = XML.Attribute(E, "defaultCollectionName", string.Empty);
189 databaseDefinition.BlockSize = XML.Attribute(E, "blockSize", 0);
190 databaseDefinition.BlocksInCache = XML.Attribute(E, "blocksInCache", 0);
191 databaseDefinition.BlobBlockSize = XML.Attribute(E, "blobBlockSize", 0);
192 databaseDefinition.TimeoutMs = XML.Attribute(E, "timeoutMs", 0);
193 databaseDefinition.Encrypted = XML.Attribute(E, "encrypted", false);
194 databaseDefinition.Compiled = XML.Attribute(E, "compiled", false);
195 break;
196
197 case "Ports":
198 foreach (XmlNode N2 in E.ChildNodes)
199 {
200 if (N2.LocalName == "Port")
201 {
202 XmlElement E2 = (XmlElement)N2;
203 string Protocol = XML.Attribute(E2, "protocol");
204 if (!string.IsNullOrEmpty(Protocol) && int.TryParse(E2.InnerText, out int PortNumber))
205 ports.AddInternal(new Port(this, ports, Protocol, PortNumber));
206 }
207 }
208 break;
209
210 case "DefaultHttpResponseHeaders":
211 foreach (XmlNode N2 in E.ChildNodes)
212 {
213 if (N2.LocalName == "DefaultHttpResponseHeader")
214 {
215 XmlElement E2 = (XmlElement)N2;
216 string Name = XML.Attribute(E2, "key");
217 string Value = XML.Attribute(E2, "value");
218 webServer.AddInternal(new DefaultHttpResponseHeader(this, webServer, Name, Value));
219 }
220 }
221 break;
222
223 case "FileFolders":
224 foreach (XmlNode N2 in E.ChildNodes)
225 {
226 if (N2.LocalName == "FileFolder")
227 {
228 XmlElement E2 = (XmlElement)N2;
229 string WebFolder = XML.Attribute(E2, "webFolder");
230 string FolderPath = XML.Attribute(E2, "folderPath");
231 FileFolder Folder = new FileFolder(this, webServer, WebFolder, FolderPath);
232 webServer.AddInternal(Folder);
233
234 foreach (XmlNode N3 in E2.ChildNodes)
235 {
236 if (N3.LocalName == "DefaultHttpResponseHeader")
237 {
238 XmlElement E3 = (XmlElement)N3;
239 string Name = XML.Attribute(E3, "key");
240 string Value = XML.Attribute(E3, "value");
241 Folder.AddInternal(new DefaultHttpResponseHeader(this, Folder, Name, Value));
242 }
243 }
244 }
245 }
246 break;
247
248 case "VanityResources":
249 foreach (XmlNode N2 in E.ChildNodes)
250 {
251 if (N2.LocalName == "VanityResource")
252 {
253 XmlElement E2 = (XmlElement)N2;
254 string Regex = XML.Attribute(E2, "regex");
255 string Url = XML.Attribute(E2, "url");
256 webServer.AddInternal(new VanityResource(this, webServer, Regex, Url));
257 }
258 }
259 break;
260
261 case "Redirections":
262 foreach (XmlNode N2 in E.ChildNodes)
263 {
264 if (N2.LocalName == "Redirection")
265 {
266 XmlElement E2 = (XmlElement)N2;
267 string Resource = XML.Attribute(E2, "resource");
268 string Location = XML.Attribute(E2, "location");
269 bool IncludeSubPaths = XML.Attribute(E2, "includeSubPaths", false);
270 bool Permanent = XML.Attribute(E2, "permanent", false);
271 webServer.AddInternal(new Redirection(this, webServer, Resource, Location, IncludeSubPaths, Permanent));
272 }
273 }
274 break;
275
276 case "ReverseProxy":
277 foreach (XmlNode N2 in E.ChildNodes)
278 {
279 if (!(N2 is XmlElement E2))
280 continue;
281
282 switch (E2.LocalName)
283 {
284 case "ProxyResource":
285 string LocalResource = XML.Attribute(E2, "localResource");
286 string RemoteDomain = XML.Attribute(E2, "remoteDomain");
287 string RemoteFolder = XML.Attribute(E2, "remoteFolder");
288 bool Encrypted = XML.Attribute(E2, "encrypted", false);
289 int RemotePort = XML.Attribute(E2, "remotePort", Encrypted ? HttpServer.DefaultHttpsPort : HttpServer.DefaultHttpPort);
290 bool UseSession = XML.Attribute(E2, "useSession", false);
291 int TimeoutMs = XML.Attribute(E2, "timeoutMs", 10000);
292 string Privilege = XML.Attribute(E2, "privilege", string.Empty);
293
295
296 foreach (HttpReverseProxyResource ReverseProxy in
297 Gateway.HttpServer.GetRegisteredResources<HttpReverseProxyResource>())
298 {
299 if (ReverseProxy.ResourceName == LocalResource &&
300 ReverseProxy.RemoteHost == RemoteDomain &&
301 ReverseProxy.RemoteFolder == RemoteFolder &&
302 ReverseProxy.RemotePort == RemotePort)
303 {
304 ProxyResource = ReverseProxy;
305 break;
306 }
307 }
308
309 webServer.AddInternal(new ProxyResource(this, webServer, LocalResource, RemoteDomain, RemoteFolder,
310 RemotePort, Encrypted, UseSession, TimeoutMs, Privilege, ProxyResource));
311 break;
312
313 case "ProxyDomain":
314 string LocalDomain = XML.Attribute(E2, "localDomain");
315 RemoteDomain = XML.Attribute(E2, "remoteDomain");
316 RemoteFolder = XML.Attribute(E2, "remoteFolder");
317 Encrypted = XML.Attribute(E2, "encrypted", false);
318 RemotePort = XML.Attribute(E2, "remotePort", Encrypted ? HttpServer.DefaultHttpsPort : HttpServer.DefaultHttpPort);
319 UseSession = XML.Attribute(E2, "useSession", false);
320 TimeoutMs = XML.Attribute(E2, "timeoutMs", 10000);
321 Privilege = XML.Attribute(E2, "privilege", string.Empty);
322
323 ProxyResource = null;
324
325 foreach (KeyValuePair<string, HttpReverseProxyResource> ReverseProxy in
327 {
328 if (ReverseProxy.Key == LocalDomain &&
329 ReverseProxy.Value.RemoteHost == RemoteDomain &&
330 ReverseProxy.Value.RemoteFolder == RemoteFolder &&
331 ReverseProxy.Value.RemotePort == RemotePort)
332 {
333 ProxyResource = ReverseProxy.Value;
334 break;
335 }
336 }
337 webServer.AddInternal(new ProxyDomain(this, webServer, LocalDomain, RemoteDomain, RemoteFolder,
338 RemotePort, Encrypted, UseSession, TimeoutMs, Privilege, ProxyResource));
339 break;
340 }
341 }
342 break;
343
344 case "LoginAuditor":
345 if (loginAuditor is null)
346 {
347 loginAuditor = new LoginAuditorNode(this);
348 Nodes.Add(loginAuditor);
349
350 foreach (XmlNode N2 in E.ChildNodes)
351 {
352 if (!(N2 is XmlElement E2))
353 continue;
354
355 switch (E2.LocalName)
356 {
357 case "Interval":
358 int NrAttempts = XML.Attribute(E2, "nrAttempts", 0);
359 Duration? Interval = XML.Attribute(E2, "interval", Duration.Zero);
360 if (Interval.Value <= Duration.Zero)
361 Interval = null;
362
363 loginAuditor.AddInternal(new IntervalNode(this, NrAttempts, Interval));
364 break;
365
366 case "Exception":
368 {
369 EndPoint = XML.Attribute(E2, "endpoint")
370 };
371
372 foreach (XmlNode N3 in E2.ChildNodes)
373 {
374 if (N3 is XmlElement E3 && E3.LocalName == "Interval")
375 {
376 NrAttempts = XML.Attribute(E3, "nrAttempts", 0);
377 Interval = XML.Attribute(E3, "interval", Duration.Zero);
378 if (Interval.Value <= Duration.Zero)
379 Interval = null;
380
381 ExceptionNode.AddInternal(new IntervalNode(this, NrAttempts, Interval));
382 }
383 }
384
385 loginAuditor.AddInternal(ExceptionNode);
386 break;
387 }
388 }
389 }
390 else
391 Log.Error("Only one LoginAuditor element permitted.", GatewayConfigFileName);
392 break;
393
394 case "EventSinks":
395 if (eventSinks is null)
396 {
397 eventSinks = new EventSinksNode(this);
398 Nodes.Add(eventSinks);
399
400 static EventSinkNode[] ParseSinks(XmlElement E, GatewayConfigSource Source, ConfigurationNode Parent)
401 {
403
404 foreach (XmlNode N2 in E.ChildNodes)
405 {
406 if (!(N2 is XmlElement E2) || E2.NamespaceURI != E.NamespaceURI)
407 continue;
408
409 try
410 {
411 switch (E2.LocalName)
412 {
413 case "TextFileEventSink":
414 string SinkId = XML.Attribute(E2, "id");
415 string FileName = XML.Attribute(E2, "fileName");
416 int DeleteAfterDays = XML.Attribute(E2, "deleteAfterDays", 7);
417
418 Sinks.Add(new TextFileEventSinkNode(Source, Parent, SinkId, FileName, DeleteAfterDays));
419 break;
420
421 case "XmlFileEventSink":
422 SinkId = XML.Attribute(E2, "id");
423 FileName = XML.Attribute(E2, "fileName");
424 DeleteAfterDays = XML.Attribute(E2, "deleteAfterDays", 7);
425 string TransformFileName = XML.Attribute(E2, "transformFileName");
426
427 Sinks.Add(new XmlFileEventSinkNode(Source, Parent, SinkId, FileName, TransformFileName, DeleteAfterDays));
428 break;
429
430 case "MqttEventSink":
431 SinkId = XML.Attribute(E2, "id");
432 string Broker = XML.Attribute(E2, "broker");
433 int Port = XML.Attribute(E2, "port", 1883);
434 bool Tls = XML.Attribute(E2, "tls", false);
435 string UserName = XML.Attribute(E2, "userName");
436 string Password = XML.Attribute(E2, "password");
437 string Topic = XML.Attribute(E2, "topic");
438
439 Sinks.Add(new MqttEventSinkNode(Source, Parent, SinkId, Broker, Port, Tls, UserName, Password, Topic));
440 break;
441
442 case "PipeEventSink":
443 SinkId = XML.Attribute(E2, "id");
444 string PipeName = XML.Attribute(E2, "pipeName");
445
446 Sinks.Add(new PipeEventSinkNode(Source, Parent, SinkId, PipeName));
447 break;
448
449 case "SocketEventSink":
450 SinkId = XML.Attribute(E2, "id");
451 string Host = XML.Attribute(E2, "host");
452 Port = XML.Attribute(E2, "port", 0);
453 Tls = XML.Attribute(E2, "tls", false);
454
455 Sinks.Add(new SocketEventSinkNode(Source, Parent, SinkId, Host, Port, Tls));
456 break;
457
458 case "SyslogEventSink":
459 SinkId = XML.Attribute(E2, "id");
460 string Name = XML.Attribute(E2, "name");
461 Host = XML.Attribute(E2, "host");
462 Port = XML.Attribute(E2, "port", 514);
463 Tls = XML.Attribute(E2, "tls", false);
464 SyslogEventSeparation Separation = XML.Attribute(E2, "separation", SyslogEventSeparation.OctetCounting);
465
466 Sinks.Add(new SyslogEventSinkNode(Source, Parent, SinkId, Host, Port, Tls, Name, Separation));
467 break;
468
469 case "WebHookEventSink":
470 SinkId = XML.Attribute(E2, "id");
471 string Url = XML.Attribute(E2, "url");
472 int MaxSecondsUsed = XML.Attribute(E2, "maxSecondsUsed", 0);
473 int MaxSecondsUnused = XML.Attribute(E2, "maxSecondsUnused", 0);
474 bool CollectOnType = XML.Attribute(E2, "collectOnType", false);
475 bool CollectOnLevel = XML.Attribute(E2, "collectOnLevel", false);
476 bool CollectOnEventId = XML.Attribute(E2, "collectOnEventId", false);
477 bool CollectOnObject = XML.Attribute(E2, "collectOnObject", false);
478 bool CollectOnActor = XML.Attribute(E2, "collectOnActor", false);
479 bool CollectOnFacility = XML.Attribute(E2, "collectOnFacility", false);
480 bool CollectOnModule = XML.Attribute(E2, "collectOnModule", false);
481
482 Sinks.Add(new WebHookEventSinkNode(Source, Parent, SinkId, Url,
483 MaxSecondsUsed, MaxSecondsUnused, CollectOnType, CollectOnLevel,
484 CollectOnEventId, CollectOnObject, CollectOnActor,
485 CollectOnFacility, CollectOnModule));
486 break;
487
488 case "XmppEventSink":
489 SinkId = XML.Attribute(E2, "id");
490 string Jid = XML.Attribute(E2, "jid");
491
492 Sinks.Add(new XmppEventSinkNode(Source, Parent, SinkId, Jid));
493 break;
494
495 case "EventFilter":
496 SinkId = XML.Attribute(E2, "id");
497 FromEventLevel Debug = XML.Attribute(E2, "debug", FromEventLevel.None);
498 FromEventLevel Informational = XML.Attribute(E2, "informational", FromEventLevel.None);
499 FromEventLevel Notice = XML.Attribute(E2, "notice", FromEventLevel.None);
500 FromEventLevel Warning = XML.Attribute(E2, "warning", FromEventLevel.None);
501 FromEventLevel Error = XML.Attribute(E2, "error", FromEventLevel.None);
502 FromEventLevel Critical = XML.Attribute(E2, "critical", FromEventLevel.None);
503 FromEventLevel Alert = XML.Attribute(E2, "alert", FromEventLevel.None);
504 FromEventLevel Emergency = XML.Attribute(E2, "emergency", FromEventLevel.None);
505 string EventIdsString = XML.Attribute(E2, "eventIds").Trim();
506 string[] EventIds;
507
508 if (string.IsNullOrEmpty(EventIdsString))
509 EventIds = null;
510 else
511 EventIds = EventIdsString.Split(',', StringSplitOptions.RemoveEmptyEntries);
512
513 EventFilterNode EventFilter = new EventFilterNode(Source, Parent, SinkId,
514 Debug, Informational, Notice, Warning, Error, Critical, Alert, Emergency,
515 EventIds);
516
517 Sinks.Add(EventFilter);
518
519 foreach (EventSinkNode ChildSink in ParseSinks(E2, Source, EventFilter))
520 EventFilter.AddInternal(ChildSink);
521
522 break;
523
524 case "EventQueue":
525 SinkId = XML.Attribute(E2, "id");
526 string QueueName = XML.Attribute(E2, "name");
527 DeleteAfterDays = XML.Attribute(E2, "deleteAfterDays", 7);
528
529 Sinks.Add(new EventQueueEventSinkNode(Source, Parent, SinkId, QueueName, DeleteAfterDays));
530 break;
531 }
532 }
533 catch (Exception ex)
534 {
536 }
537 }
538
539 return Sinks.ToArray();
540 }
541
542 foreach (EventSinkNode EventSink in ParseSinks(E, this, eventSinks))
543 eventSinks.AddInternal(EventSink);
544 }
545 else
546 Log.Error("Only one EventSinks element permitted.", GatewayConfigFileName);
547 break;
548 }
549 }
550 }
551
552 if (loginAuditor is null)
553 {
554 loginAuditor = new LoginAuditorNode(this);
555 Nodes.Add(loginAuditor);
556 }
557
558 if (eventSinks is null)
559 {
560 eventSinks = new EventSinksNode(this);
561 Nodes.Add(eventSinks);
562 }
563
564 foreach (Type T in Types.GetTypesImplementingInterface(typeof(IContentEncoding)))
565 {
566 IContentEncoding Encoding;
567
568 try
569 {
570 ConstructorInfo CI = Types.GetDefaultConstructor(T);
571 if (CI is null)
572 continue;
573
574 Encoding = (IContentEncoding)CI.Invoke(Types.NoParameters);
575 }
576 catch (Exception)
577 {
578 continue; // Ignore
579 }
580
581 if (ContentEncodingsFound.ContainsKey(Encoding.Label))
582 continue;
583
584 ContentEncodingsFound[Encoding.Label] = true;
585
586 webServer.AddInternal(new ContentEncoding(this, webServer, Encoding.Label, Encoding.SupportsDynamicEncoding,
587 Encoding.SupportsStaticEncoding));
588 }
589
590 lock (nodesById)
591 {
592 nodes = Nodes.ToArray();
593 nodesTimestamp = this.LastChanged;
594
595 nodesById.Clear();
596
597 foreach (INode Node in nodes)
598 {
599 nodesById[Node.NodeId] = Node;
600
603 {
604 foreach (ConfigurationNode Child in ConfigurationNode.Children)
605 nodesById[Child.NodeId] = Child;
606 }
607 }
608 }
609 }
610 catch (Exception ex)
611 {
612 Log.Exception(ex);
613 }
614 }
615
619 string IDataSource.SourceID => SourceID;
620
624 public bool HasChildren => false;
625
629 public DateTime LastChanged => File.GetLastWriteTimeUtc(Gateway.ConfigFilePath);
630
634 public IEnumerable<IDataSource> ChildSources => null;
635
639 public IEnumerable<INode> RootNodes
640 {
641 get
642 {
643 this.CheckLoadConfiguration();
644 return nodes;
645 }
646 }
647
651 public event EventHandlerAsync<SourceEvent> OnEvent;
652
658 public Task<bool> CanViewAsync(RequestOrigin Caller)
659 {
660 return Task.FromResult(Caller.HasPrivilege("Source." + SourceID + ".View"));
661 }
662
668 public Task<string> GetNameAsync(Language Language)
669 {
670 return Language.GetStringAsync(typeof(GatewayConfigSource), 1, "Gateway configuration");
671 }
672
678 public Task<INode> GetNodeAsync(IThingReference NodeRef)
679 {
680 if (NodeRef is null ||
681 NodeRef.SourceId != SourceID ||
682 !string.IsNullOrEmpty(NodeRef.Partition))
683 {
684 return Task.FromResult<INode>(null);
685 }
686
687 lock (nodesById)
688 {
689 if (nodesById.TryGetValue(NodeRef.NodeId, out INode Node))
690 return Task.FromResult(Node);
691 else
692 return Task.FromResult<INode>(null);
693 }
694 }
695
696 private Task RaiseSourceEvent(SourceEvent Event)
697 {
698 return this.OnEvent.Raise(this, Event);
699 }
700
701 internal async Task NodeAdded(INode Node, bool External)
702 {
703 if (!External)
704 ScheduleSave();
705
706 await this.RaiseSourceEvent(await Things.SourceEvents.NodeAdded.FromNode(Node, await Translator.GetDefaultLanguageAsync(),
707 RequestOrigin.Empty, false));
708
709 lock (nodesById)
710 {
711 nodesById[Node.NodeId] = Node;
712 }
713 }
714
715 internal async Task NodeUpdated(INode Node, bool External)
716 {
717 if (!External)
718 ScheduleSave();
719
720 await this.RaiseSourceEvent(await Things.SourceEvents.NodeUpdated.FromNode(Node, await Translator.GetDefaultLanguageAsync(),
722
723 lock (nodesById)
724 {
725 if (nodesById.TryGetValue(Node.NodeId, out INode Node2) && Node == Node2)
726 return;
727
728 foreach (KeyValuePair<string, INode> P in nodesById)
729 {
730 if (P.Value == Node)
731 {
732 nodesById.Remove(P.Key);
733 break;
734 }
735 }
736
737 nodesById[Node.NodeId] = Node;
738 }
739 }
740
741 internal async Task NodeDeleted(INode Node, bool External)
742 {
743 if (!External)
744 ScheduleSave();
745
746 await this.RaiseSourceEvent(NodeRemoved.FromNode(Node));
747
748 lock (nodesById)
749 {
750 if (nodesById.TryGetValue(Node.NodeId, out INode Node2) && Node == Node2)
751 nodesById.Remove(Node.NodeId);
752 }
753 }
754
755 private static void ScheduleSave()
756 {
757 if (writeTime > DateTime.MinValue)
758 {
759 Gateway.CancelScheduledEvent(writeTime);
760 writeTime = DateTime.MinValue;
761 }
762
763 writeTime = Gateway.ScheduleEvent(SaveFile, DateTime.Now.AddSeconds(5), null);
764 }
765
766 private static async Task SaveFile(object _)
767 {
768 try
769 {
770 string ConfigFileName = Path.Combine(Gateway.AppDataFolder, Gateway.GatewayConfigLocalFileName);
771 string BakFileName = Path.Combine(Gateway.AppDataFolder, Gateway.GatewayConfigLocalFileName + ".bak");
772
773 if (File.Exists(BakFileName))
774 File.Delete(BakFileName);
775
776 if (File.Exists(ConfigFileName))
777 {
778 string OldConfig = await Files.ReadAllTextAsync(ConfigFileName);
779
780 Log.Notice("Gateway.config file updated.\r\n\r\nOld Config file:\r\n\r\n```\r\n" + OldConfig + "\r\n```",
781 ConfigFileName, string.Empty, "GatewayConfigUpdated");
782
783 File.Move(ConfigFileName, BakFileName);
784 }
785
786 using (FileStream fs = File.Create(ConfigFileName))
787 {
788 using XmlWriter Xml = XmlWriter.Create(fs, XML.WriterSettings(true, false, Encoding.UTF8));
789
790 Xml.WriteStartDocument();
792
793 Xml.WriteComment("The configuration file in the program data folder, will have precedence over the configuration file in the installation folder.");
794 Xml.WriteComment("When upgrading, the configuration file in the installation folder will be updated, but the configuration file in the program data");
795 Xml.WriteComment("folder will be maintained. If you make changes to the configuration file, make a copy and place it in the program data folder, and");
796 Xml.WriteComment("edit it there. This will make sure you don't lose any changes when you update the software.");
797
798 Xml.WriteElementString("ApplicationName", generalInformation.ApplicationName);
799
800 if (webServer.HasChildren)
801 {
802 foreach (INode Node in await webServer.ChildNodes)
803 {
804 if (Node is DefaultPage DefaultPage)
805 {
806 Xml.WriteStartElement("DefaultPage");
807
808 if (!string.IsNullOrEmpty(DefaultPage.Host))
809 Xml.WriteAttributeString("host", DefaultPage.Host);
810
811 Xml.WriteValue(DefaultPage.Page);
812 Xml.WriteEndElement();
813 }
814 }
815 }
816
817 Xml.WriteStartElement("MutualTls");
818 Xml.WriteAttributeString("clientCertificates", webServer.ClientCertificates.ToString());
819 Xml.WriteAttributeString("trustCertificates", CommonTypes.Encode(webServer.TrustClientCertificates));
820
821 foreach (INode Node in await webServer.ChildNodes)
822 {
823 if (Node is MTlsPort MTlsPort)
824 {
825 Xml.WriteStartElement("Port");
826 Xml.WriteAttributeString("clientCertificates", MTlsPort.ClientCertificates.ToString());
827 Xml.WriteAttributeString("trustCertificates", CommonTypes.Encode(MTlsPort.TrustClientCertificates));
828 Xml.WriteValue(MTlsPort.PortNumber.ToString());
829 Xml.WriteEndElement();
830 }
831 }
832
833 Xml.WriteEndElement();
834
835 if (webServer.HasChildren)
836 {
837 Dictionary<string, bool> Found = new Dictionary<string, bool>();
838
839 Xml.WriteStartElement("ContentEncodings");
840
841 foreach (INode Node in await webServer.ChildNodes)
842 {
844 {
845 Xml.WriteStartElement("ContentEncoding");
846 Xml.WriteAttributeString("method", ContentEncoding.Method);
847 Xml.WriteAttributeString("dynamic", CommonTypes.Encode(ContentEncoding.Dynamic));
848 Xml.WriteAttributeString("static", CommonTypes.Encode(ContentEncoding.Static));
849 Xml.WriteEndElement();
850
851 Found[ContentEncoding.Method] = true;
852 }
853 }
854
855 foreach (Type T in Types.GetTypesImplementingInterface(typeof(IContentEncoding)))
856 {
857 IContentEncoding Encoding;
858
859 try
860 {
861 ConstructorInfo CI = Types.GetDefaultConstructor(T);
862 if (CI is null)
863 continue;
864
865 Encoding = (IContentEncoding)CI.Invoke(Types.NoParameters);
866 }
867 catch (Exception)
868 {
869 continue; // Ignore
870 }
871
872 if (Found.ContainsKey(Encoding.Label))
873 continue;
874
875 Found[Encoding.Label] = true;
876
877 Xml.WriteStartElement("ContentEncoding");
878 Xml.WriteAttributeString("method", Encoding.Label);
879 Xml.WriteAttributeString("dynamic", CommonTypes.Encode(Encoding.SupportsDynamicEncoding));
880 Xml.WriteAttributeString("static", CommonTypes.Encode(Encoding.SupportsStaticEncoding));
881 Xml.WriteEndElement();
882 }
883
884 Xml.WriteEndElement();
885 }
886
887 Xml.WriteStartElement("Http2Settings");
888 Xml.WriteAttributeString("enabled", CommonTypes.Encode(webServer.Http2Enabled));
889 Xml.WriteAttributeString("initialWindowSize", webServer.Http2InitialStreamWindowSize.ToString());
890 Xml.WriteAttributeString("initialConnectionWindowSize", webServer.Http2InitialConnectionWindowSize.ToString());
891 Xml.WriteAttributeString("maxFrameSize", webServer.Http2MaxFrameSize.ToString());
892 Xml.WriteAttributeString("maxConcurrentStreams", webServer.Http2MaxConcurrentStreams.ToString());
893 Xml.WriteAttributeString("headerTableSize", webServer.Http2HeaderTableSize.ToString());
894 Xml.WriteAttributeString("noRfc7540Priorities", CommonTypes.Encode(webServer.Http2NoRfc7540Priorities));
895 Xml.WriteAttributeString("profiling", CommonTypes.Encode(webServer.Http2Profiling));
896 Xml.WriteAttributeString("sniffersPerEndpoint", CommonTypes.Encode(webServer.HttpSniffersPerEndpoint));
897 Xml.WriteEndElement();
898
899 Xml.WriteStartElement("Database");
900 Xml.WriteAttributeString("folder", databaseDefinition.Folder);
901 Xml.WriteAttributeString("defaultCollectionName", databaseDefinition.DefaultCollectionName);
902 Xml.WriteAttributeString("blockSize", databaseDefinition.BlockSize.ToString());
903 Xml.WriteAttributeString("blocksInCache", databaseDefinition.BlocksInCache.ToString());
904 Xml.WriteAttributeString("blobBlockSize", databaseDefinition.BlobBlockSize.ToString());
905 Xml.WriteAttributeString("timeoutMs", databaseDefinition.TimeoutMs.ToString());
906 Xml.WriteAttributeString("encrypted", CommonTypes.Encode(databaseDefinition.Encrypted));
907 Xml.WriteAttributeString("compiled", CommonTypes.Encode(databaseDefinition.Compiled));
908 Xml.WriteEndElement();
909
910 Xml.WriteStartElement("Ports");
911
912 if (ports.HasChildren)
913 {
914 foreach (INode Node in await ports.ChildNodes)
915 {
916 if (Node is Port Port)
917 {
918 Xml.WriteStartElement("Port");
919 Xml.WriteAttributeString("protocol", Port.Protocol);
920 Xml.WriteValue(Port.PortNumber.ToString());
921 Xml.WriteEndElement();
922 }
923 }
924 }
925
926 Xml.WriteEndElement();
927
928 if (webServer.HasChildren)
929 {
930 Xml.WriteStartElement("DefaultHttpResponseHeaders");
931
932 foreach (INode Node in await webServer.ChildNodes)
933 {
935 {
936 Xml.WriteStartElement("DefaultHttpResponseHeader");
937 Xml.WriteAttributeString("key", DefaultHttpResponseHeader.Name);
938 Xml.WriteAttributeString("value", DefaultHttpResponseHeader.Value);
939 Xml.WriteEndElement();
940 }
941 }
942
943 Xml.WriteEndElement();
944 Xml.WriteStartElement("FileFolders");
945
946 Xml.WriteComment("Add a sequence of FileFolder elements. Each FileFolder element creates a web folder defined by the webFolder attribute. These folder resources are absolute");
947 Xml.WriteComment("resources. Each web folder will be mapped to a corresponding folder on the local machine or in the network, defined by the folderPath attribute. ");
948 Xml.WriteComment("");
949 Xml.WriteComment("Example:");
950 Xml.WriteComment("");
951 Xml.WriteComment("<FileFolder webFolder=\"/Folder\" folderPath=\"\\\\Server\\Path\"/>");
952
953 foreach (INode Node in await webServer.ChildNodes)
954 {
955 if (Node is FileFolder FileFolder)
956 {
957 Xml.WriteStartElement("FileFolder");
958 Xml.WriteAttributeString("webFolder", FileFolder.WebFolder);
959 Xml.WriteAttributeString("folderPath", FileFolder.FolderPath);
960 Xml.WriteEndElement();
961 }
962 }
963
964 Xml.WriteEndElement();
965 }
966
967 if (webServer.HasChildren)
968 {
969 Xml.WriteStartElement("VanityResources");
970
971 foreach (INode Node in await webServer.ChildNodes)
972 {
973 if (Node is VanityResource VanityResource)
974 {
975 Xml.WriteStartElement("VanityResource");
976 Xml.WriteAttributeString("regex", VanityResource.Regex);
977 Xml.WriteAttributeString("url", VanityResource.Url);
978 Xml.WriteEndElement();
979 }
980 }
981
982 Xml.WriteEndElement();
983
984 Xml.WriteStartElement("Redirections");
985
986 foreach (INode Node in await webServer.ChildNodes)
987 {
988 if (Node is Redirection Redirection)
989 {
990 Xml.WriteStartElement("Redirection");
991 Xml.WriteAttributeString("resource", Redirection.Resource);
992 Xml.WriteAttributeString("location", Redirection.Location);
993 Xml.WriteAttributeString("includeSubPaths", CommonTypes.Encode(Redirection.IncludeSubPaths));
994 Xml.WriteAttributeString("permanent", CommonTypes.Encode(Redirection.Permanent));
995 Xml.WriteEndElement();
996 }
997 }
998
999 Xml.WriteEndElement();
1000
1001 Xml.WriteStartElement("ReverseProxy");
1002
1003 foreach (INode Node in await webServer.ChildNodes)
1004 {
1005 if (Node is ProxyResource ProxyResource)
1006 {
1007 Xml.WriteStartElement("ProxyResource");
1008 Xml.WriteAttributeString("localResource", ProxyResource.LocalResource);
1009 Xml.WriteAttributeString("remoteDomain", ProxyResource.RemoteDomain);
1010 Xml.WriteAttributeString("remoteFolder", ProxyResource.RemoteFolder);
1011 Xml.WriteAttributeString("remotePort", ProxyResource.RemotePort.ToString());
1012 Xml.WriteAttributeString("encrypted", CommonTypes.Encode(ProxyResource.Encrypted));
1013 Xml.WriteAttributeString("useSession", CommonTypes.Encode(ProxyResource.UseSession));
1014 Xml.WriteAttributeString("timeoutMs", ProxyResource.TimeoutMs.ToString());
1015
1016 if (!string.IsNullOrEmpty(ProxyResource.Privilege))
1017 Xml.WriteAttributeString("privilege", ProxyResource.Privilege);
1018
1019 Xml.WriteEndElement();
1020 }
1021 else if (Node is ProxyDomain ProxyDomain)
1022 {
1023 Xml.WriteStartElement("ProxyDomain");
1024 Xml.WriteAttributeString("localDomain", ProxyDomain.LocalDomain);
1025 Xml.WriteAttributeString("remoteDomain", ProxyDomain.RemoteDomain);
1026 Xml.WriteAttributeString("remoteFolder", ProxyDomain.RemoteFolder);
1027 Xml.WriteAttributeString("remotePort", ProxyDomain.RemotePort.ToString());
1028 Xml.WriteAttributeString("encrypted", CommonTypes.Encode(ProxyDomain.Encrypted));
1029 Xml.WriteAttributeString("useSession", CommonTypes.Encode(ProxyDomain.UseSession));
1030 Xml.WriteAttributeString("timeoutMs", ProxyDomain.TimeoutMs.ToString());
1031
1032 if (!string.IsNullOrEmpty(ProxyDomain.Privilege))
1033 Xml.WriteAttributeString("privilege", ProxyDomain.Privilege);
1034
1035 Xml.WriteEndElement();
1036 }
1037 }
1038
1039 Xml.WriteEndElement();
1040 }
1041
1042 if (!string.IsNullOrEmpty(generalInformation.ExceptionFolder))
1043 {
1044 Xml.WriteStartElement("ExportExceptions");
1045 Xml.WriteAttributeString("folder", generalInformation.ExceptionFolder);
1046 Xml.WriteEndElement();
1047 }
1048
1049 if (!(loginAuditor is null))
1050 {
1051 IEnumerable<INode> Intervals = await loginAuditor.ChildNodes;
1052 bool Empty = true;
1053
1054 foreach (INode _2 in Intervals)
1055 {
1056 Empty = false;
1057 break;
1058 }
1059
1060 if (!Empty)
1061 {
1062 Xml.WriteStartElement("LoginAuditor");
1063
1064 int NrIntervals = 0;
1065
1066 foreach (INode Node in Intervals)
1067 {
1068 if (Node is IntervalNode Interval)
1069 {
1070 Xml.WriteStartElement("Interval");
1071 Xml.WriteAttributeString("nrAttempts", Interval.NrAttempts.ToString());
1072
1073 if (Interval.Interval.HasValue)
1074 Xml.WriteAttributeString("interval", Interval.Interval.Value.ToString());
1075
1076 Xml.WriteEndElement();
1077 NrIntervals++;
1078 }
1079 else if (Node is LoginAuditorExceptionNode ExceptionNode)
1080 {
1081 Xml.WriteStartElement("Exception");
1082 Xml.WriteAttributeString("endpoint", ExceptionNode.EndPoint);
1083
1084 int NrIntervals2 = 0;
1085
1086 foreach (INode Node2 in await ExceptionNode.ChildNodes)
1087 {
1088 if (Node2 is IntervalNode Interval2)
1089 {
1090 Xml.WriteStartElement("Interval");
1091 Xml.WriteAttributeString("nrAttempts", Interval2.NrAttempts.ToString());
1092
1093 if (Interval2.Interval.HasValue)
1094 Xml.WriteAttributeString("interval", Interval2.Interval.Value.ToString());
1095
1096 Xml.WriteEndElement();
1097 NrIntervals2++;
1098 }
1099
1100 if (NrIntervals2 == 0) // Write default interval to avoid creating XML file that is not valid.
1101 {
1102 Xml.WriteStartElement("Interval");
1103 Xml.WriteAttributeString("nrAttempts", "1");
1104 Xml.WriteAttributeString("interval", "PT1H");
1105 Xml.WriteEndElement();
1106 }
1107 }
1108
1109 Xml.WriteEndElement();
1110 }
1111 }
1112
1113 if (NrIntervals == 0) // Write default interval to avoid creating XML file that is not valid.
1114 {
1115 Xml.WriteStartElement("Interval");
1116 Xml.WriteAttributeString("nrAttempts", "1");
1117 Xml.WriteAttributeString("interval", "PT1H");
1118 Xml.WriteEndElement();
1119 }
1120
1121 Xml.WriteEndElement();
1122 }
1123 }
1124
1125 if (!(eventSinks is null))
1126 {
1127 Xml.WriteStartElement("EventSinks");
1128
1129 foreach (ConfigurationNode Node in eventSinks.Children)
1130 {
1131 if (Node is EventSinkNode Sink)
1132 Sink.Export(Xml);
1133 }
1134
1135 Xml.WriteEndElement();
1136 }
1137
1138 Xml.WriteEndElement();
1139 Xml.WriteEndDocument();
1140
1141 Xml.Flush();
1142 }
1143
1144 await Task.Delay(5000);
1145 }
1146 catch (Exception ex)
1147 {
1148 Log.Exception(ex);
1149 }
1150 finally
1151 {
1152 writeTime = DateTime.MinValue;
1153 }
1154 }
1155
1160 internal static async Task FileUpdated()
1161 {
1162 try
1163 {
1164 if (writeTime > DateTime.MinValue)
1165 return;
1166
1167 Log.Notice("Gateway.config changed outside of the system. Loading configuration.");
1168
1169 Dictionary<string, INode> OldNodes = new Dictionary<string, INode>();
1170 List<INode> Updated = new List<INode>();
1171 List<INode> Added = new List<INode>();
1172
1173 lock (nodesById)
1174 {
1175 foreach (KeyValuePair<string, INode> P in nodesById)
1176 OldNodes[P.Key] = P.Value;
1177 }
1178
1179 instance.LoadConfiguration();
1180
1181 lock (nodesById)
1182 {
1183 foreach (KeyValuePair<string, INode> P in nodesById)
1184 {
1185 if (OldNodes.Remove(P.Key))
1186 Updated.Add(P.Value);
1187 else
1188 Added.Add(P.Value);
1189 }
1190 }
1191
1192 foreach (INode Node in OldNodes.Values)
1193 await instance.NodeDeleted(Node, true);
1194
1195 foreach (INode Node in Added)
1196 await instance.NodeAdded(Node, true);
1197
1198 foreach (INode Node in Updated)
1199 await instance.NodeUpdated(Node, true);
1200 }
1201 catch (Exception ex)
1202 {
1203 Log.Exception(ex);
1204 }
1205 }
1206 }
1207}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:596
Helps with common XML-related tasks.
Definition: XML.cs:21
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:1062
static XmlDocument LoadFromFile(string FileName)
Loads an XML document from a file.
Definition: XML.cs:1808
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
Definition: XML.cs:1351
Static class managing loading of XSL resources stored as embedded resources or in content files.
Definition: XSL.cs:16
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
Definition: XSL.cs:24
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Definition: XSL.cs:134
Class representing an event.
Definition: Event.cs:11
Base class for event sinks.
Definition: EventSink.cs:9
Filters incoming events and passes remaining events to a secondary event sink.
Definition: EventFilter.cs:11
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
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.
Definition: Log.cs:1657
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
Definition: Log.cs:692
static void Notice(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a notice event.
Definition: Log.cs:460
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:147
static HttpServer HttpServer
HTTP Server
Definition: Gateway.cs:4118
static string ConfigFilePath
Full path to Gateway.config file.
Definition: Gateway.cs:3181
const string GatewayConfigNamespace
http://waher.se/Schema/GatewayConfiguration.xsd
Definition: Gateway.cs:166
static string AppDataFolder
Application data folder.
Definition: Gateway.cs:3132
static DateTime ScheduleEvent(Action< object > Callback, DateTime When, object State)
Schedules a one-time event.
Definition: Gateway.cs:4253
const string GatewayConfigLocalName
GatewayConfiguration
Definition: Gateway.cs:161
static bool CancelScheduledEvent(DateTime When)
Cancels a scheduled event.
Definition: Gateway.cs:4275
const string GatewayConfigLocalFileName
Gateway.config
Definition: Gateway.cs:151
Accept-Encoding HTTP Field header. (RFC 2616, §14.3)
static void ContentEncodingsReconfigured()
If Content-Encodings have been reconfigured.
string ResourceName
Name of resource.
An HTTP Reverse proxy resource. Incoming requests are reverted to a another web server for processing...
int RemotePort
Port number of remote web server.
string RemoteFolder
Optional remote folder where remote content is hosted.
Implements an HTTP server.
Definition: HttpServer.cs:41
int Http2HeaderTableSize
HTTP/2: Header table size.
Definition: HttpServer.cs:1027
int Http2InitialConnectionWindowSize
HTTP/2: Initial connection window size.
Definition: HttpServer.cs:1012
bool Http2Enabled
HTTP/2: Enabled or not.
Definition: HttpServer.cs:1002
int Http2InitialStreamWindowSize
HTTP/2: Initial stream window size.
Definition: HttpServer.cs:1007
const int DefaultHttpPort
Default HTTP Port (80).
Definition: HttpServer.cs:45
int Http2MaxConcurrentStreams
HTTP/2: Maximum number of concurrent streams.
Definition: HttpServer.cs:1022
KeyValuePair< string, HttpReverseProxyResource >[] GetDomainProxies()
Gets all registered domain proxy resources.
Definition: HttpServer.cs:1993
const int DefaultHttpsPort
Default HTTPS port (443).
Definition: HttpServer.cs:50
int Http2MaxFrameSize
HTTP/2: Maximum frame size.
Definition: HttpServer.cs:1017
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
T[] ToArray()
Returns an array containing all elements of the collection.
Contains static methods
Definition: Files.cs:14
static async Task< string > ReadAllTextAsync(string FileName)
Reads a text file asynchronously.
Definition: Files.cs:84
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
static object[] NoParameters
Contains an empty array of parameter values.
Definition: Types.cs:572
static Type[] GetTypesImplementingInterface(string InterfaceFullName)
Gets all types implementing a given interface.
Definition: Types.cs:85
static ConstructorInfo GetDefaultConstructor(Type Type)
Gets the default constructor of a type, if one exists.
Definition: Types.cs:1742
Contains information about a language.
Definition: Language.cs:17
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 ...
Definition: Language.cs:209
Contains information about a namespace in a language.
Definition: Namespace.cs:17
Basic access point for runtime language localization.
Definition: Translator.cs:16
static async Task< Language > GetDefaultLanguageAsync()
Gets the default language.
Definition: Translator.cs:223
Abstract base class for gateway configuration nodes.
virtual Task< IEnumerable< INode > > ChildNodes
Child nodes. If no child nodes are available, null is returned.
virtual bool HasChildren
If the source has any child sources.
Configures a Content-Encoding in the web server.
bool Static
If dynamically generated content can be compressed using this method.
bool Dynamic
If dynamically generated content can be compressed using this method.
int TimeoutMs
Timeout of database operations, in milliseconds.
int BlockSize
Number of bytes of each B-Tree block in the database.
int BlocksInCache
Number of blocks to maintain in internal memory.
string Folder
Folder, relative to the application data folder, where object database files will be stored.
bool Compiled
If object serializers should be compiled or not.
int BlobBlockSize
Number of bytes of each BLOB block in the database.
string DefaultCollectionName
Name of the collection to use, if the class definition lacks a collection definition.
Abstract base class for event sink nodes.
Contains configuration of custom event sinks.
string FolderPath
Path to folder with contents.
Definition: FileFolder.cs:56
string WebFolder
Local resource that will be mapped to the file folder.
Definition: FileFolder.cs:46
IEnumerable< IDataSource > ChildSources
Child sources. If no child sources are available, null is returned.
Task< string > GetNameAsync(Language Language)
Gets the name of data source.
Task< bool > CanViewAsync(RequestOrigin Caller)
If the data source is visible to the caller.
GatewayConfigSource()
Data source mirroring the Gateway.config file.
Task< INode > GetNodeAsync(IThingReference NodeRef)
Gets the node, given a reference to it.
EventHandlerAsync< SourceEvent > OnEvent
Event raised when a data source event has been raised.
IEnumerable< INode > RootNodes
Root node references. If no root nodes are available, null is returned.
const string SourceID
Source ID for the reports data source.
Represents an interval in a LoginAuditor configuration.
Definition: IntervalNode.cs:16
Contains configuration of the Login Auditor.
mTLS-configuration for a specific port number.
Definition: MTlsPort.cs:15
bool TrustClientCertificates
If certificates are to be trusted, or if they are required to be valid.
Definition: MTlsPort.cs:72
ClientCertificates ClientCertificates
mTLS-configuration
Definition: MTlsPort.cs:64
Root node of port numbers to use.
Definition: Ports.cs:11
Defines a proxy domain to act as a reverse proxy for a specific domain name.
Definition: ProxyDomain.cs:19
string RemoteDomain
Location client is redirected to.
Definition: ProxyDomain.cs:83
string RemoteFolder
If sub-paths should be included in the redirection.
Definition: ProxyDomain.cs:91
int TimeoutMs
If redirection is permanent (true) or temporary (false).
Definition: ProxyDomain.cs:129
int RemotePort
If redirection is permanent (true) or temporary (false).
Definition: ProxyDomain.cs:101
bool UseSession
If forwarded requests are encrypted (HTTPS) or not (HTTP).
Definition: ProxyDomain.cs:119
bool Encrypted
If forwarded requests are encrypted (HTTPS) or not (HTTP).
Definition: ProxyDomain.cs:110
string Privilege
Required privilege to access the resource. If not specified, the resource is public.
Definition: ProxyDomain.cs:137
Defines a proxy resource to act as a reverse proxy.
bool Encrypted
If forwarded requests are encrypted (HTTPS) or not (HTTP).
string RemoteDomain
Location client is redirected to.
bool UseSession
If forwarded requests are encrypted (HTTPS) or not (HTTP).
string RemoteFolder
If sub-paths should be included in the redirection.
int TimeoutMs
If redirection is permanent (true) or temporary (false).
int RemotePort
If redirection is permanent (true) or temporary (false).
string Privilege
Required privilege to access the resource. If not specified, the resource is public.
bool IncludeSubPaths
If sub-paths should be included in the redirection.
Definition: Redirection.cs:69
bool Permanent
If redirection is permanent (true) or temporary (false).
Definition: Redirection.cs:78
string Location
Location client is redirected to.
Definition: Redirection.cs:61
string Url
URL the resource points to. Can include references to named group in the regular expression.
string Regex
Regular expression defining a vanity resource or set of vanity resources.
bool Http2Profiling
Maximum Frame Size, in bytes.
Definition: WebServer.cs:109
int Http2InitialConnectionWindowSize
Initial Connection Window Size, in bytes.
Definition: WebServer.cs:69
ClientCertificates ClientCertificates
mTLS-configuration
Definition: WebServer.cs:37
int Http2InitialStreamWindowSize
Initial Window Size, in bytes.
Definition: WebServer.cs:61
int Http2HeaderTableSize
Dynamic Header Table Size, in bytes.
Definition: WebServer.cs:93
int Http2MaxConcurrentStreams
Maximum number of concurrent streams.
Definition: WebServer.cs:85
int Http2MaxFrameSize
Maximum Frame Size, in bytes.
Definition: WebServer.cs:77
bool TrustClientCertificates
If certificates are to be trusted, or if they are required to be valid.
Definition: WebServer.cs:45
bool Http2Enabled
If HTTP/2 is enabled or not.
Definition: WebServer.cs:53
bool HttpSniffersPerEndpoint
Separate sniffers by remote endpoint.
Definition: WebServer.cs:117
bool Http2NoRfc7540Priorities
Maximum Frame Size, in bytes.
Definition: WebServer.cs:101
Tokens available in request.
Definition: RequestOrigin.cs:9
static readonly RequestOrigin Empty
Empty request origin.
bool HasPrivilege(string Privilege)
If the origin has a given privilege.
static NodeRemoved FromNode(INode Node)
Creates an event object from a node object.
Definition: NodeRemoved.cs:30
Abstract base class for all data source events.
Definition: SourceEvent.cs:13
Interface for content encodings in HTTP transfers.
bool SupportsStaticEncoding
If encoding can be used for static encoding.
void ConfigureSupport(bool Dynamic, bool Static)
Configures support for the algorithm.
bool SupportsDynamicEncoding
If encoding can be used for dynamic encoding.
string Label
Label identifying the Content-Encoding
Interface for datasources that are published through the concentrator interface.
Definition: IDataSource.cs:14
Interface for nodes that are published through the concentrator interface.
Definition: INode.cs:49
Task< IEnumerable< INode > > ChildNodes
Child nodes. If no child nodes are available, null is returned.
Definition: INode.cs:140
Interface for thing references.
string Partition
Optional partition in which the Node ID is unique.
string SourceId
Optional ID of source containing node.
Definition: ImplTypes.g.cs:58
FromEventLevel
Allows events from a certain level.
SyslogEventSeparation
How events are separated in the Syslog event stream.
ClientCertificates
Client Certificate Options
Represents a duration value, as defined by the xsd:duration data type: http://www....
Definition: Duration.cs:14
static readonly Duration Zero
Zero value
Definition: Duration.cs:577