Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
InternetGatewayRegistrator.cs
1using System;
2using System.Threading;
4using System.Net;
5using System.Net.NetworkInformation;
7using System.Threading.Tasks;
8using Waher.Events;
12
14{
19 {
20 private static readonly object upnpClientLock = new object();
21 private static UPnPClient upnpClient = null;
22 private static int upnpClientRefCount = 0;
23
24 internal readonly InternetGatewayRegistration[] ports;
25 internal IPAddress localAddress;
26 internal IPAddress externalAddress;
27 internal Exception exception = null;
28 private readonly ISniffer[] sniffers;
29 private HashSet<string> deviceUrlsProcessed = new HashSet<string>();
30 private IInternetGateway internetGateway;
31 private PeerToPeerNetworkState state = PeerToPeerNetworkState.Created;
32 private ManualResetEvent ready = new ManualResetEvent(false);
33 private ManualResetEvent error = new ManualResetEvent(false);
34 private Timer searchTimer = null;
35 private bool upnpHandlerRegistered = false;
36 internal bool disposed = false;
37
44 {
45 this.ports = Ports;
46 this.sniffers = Sniffers;
47
48 NetworkChange.NetworkAddressChanged += this.NetworkChange_NetworkAddressChanged;
49 }
50
51 private async void NetworkChange_NetworkAddressChanged(object Sender, EventArgs e)
52 {
53 try
54 {
55 if (!this.disposed && this.State != PeerToPeerNetworkState.SearchingForGateway) // Multiple events might get fired one after the other. Just start one search.
56 {
57 await this.SetState(PeerToPeerNetworkState.Reinitializing);
58
59 this.ready?.Reset();
60 this.error?.Reset();
61
62 await this.Start();
63 }
64 }
65 catch (Exception ex)
66 {
67 Log.Exception(ex);
68 }
69 }
70
74 public virtual async Task Start()
75 {
76 if (this.OnPublicNetwork())
77 this.localAddress = this.externalAddress;
78 else
79 await this.SearchGateways();
80 }
81
86 public bool OnPublicNetwork()
87 {
88 foreach (NetworkInterface Interface in NetworkInterface.GetAllNetworkInterfaces())
89 {
90 if (Interface.OperationalStatus != OperationalStatus.Up)
91 continue;
92
93 IPInterfaceProperties Properties = Interface.GetIPProperties();
94
95 foreach (UnicastIPAddressInformation UnicastAddress in Properties.UnicastAddresses)
96 {
97 if (!IsPublicAddress(UnicastAddress.Address))
98 continue;
99
100 this.externalAddress = UnicastAddress.Address;
101 return true;
102 }
103 }
104
105 return false;
106 }
107
113 public static bool IsPublicAddress(IPAddress Address)
114 {
115 if (Address.AddressFamily == AddressFamily.InterNetwork && Socket.OSSupportsIPv4)
116 {
117 byte[] Addr = Address.GetAddressBytes();
118
119 // https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
120
121 switch (Addr[0])
122 {
123 case 0:
124 return false; // 000.X.X.X/8: Reserved for self-identification [RFC1122]
125
126 case 10:
127 return false; // 010.X.X.X/8: Reserved for Private-Use Networks [RFC1918]
128
129 case 100: // 100.64.X.X/10 reserved for Shared Address Space [RFC6598].
130 return (Addr[1] & 0xc0) != 64;
131
132 case 127: // 127.X.X.X/8 reserved for Loopback [RFC1122]
133 return false;
134
135 case 169: // 169.254.X.X/16 reserved for Link Local
136 return Addr[1] != 254;
137
138 case 172: // 172.16.0.0/12 reserved for Private-Use Networks
139 return (Addr[1] & 0xf0) != 16;
140
141 case 192:
142 switch (Addr[1])
143 {
144 case 0:
145 switch (Addr[2])
146 {
147 case 0: // 192.0.0.0/24 reserved for IANA IPv4 Special Purpose Address Registry
148 return false;
149
150 case 2: // 192.0.2.X/24 reserved for TEST-NET-1
151 return false;
152
153 default:
154 return true;
155 }
156
157 case 88:
158 return Addr[2] != 99; // 192.88.99.X/24 reserved for 6to4 Relay Anycast
159
160 case 168:
161 return false; // 192.168.0.0/16 reserved for Private-Use Networks
162 }
163 break;
164 }
165
166 return true;
167 }
168 else
169 return false;
170 }
171
175 public async Task SearchGateways()
176 {
177 if (this.disposed || this.deviceUrlsProcessed is null)
178 return;
179
180 try
181 {
182 this.searchTimer?.Dispose();
183 this.searchTimer = null;
184
185 if (!this.upnpHandlerRegistered)
186 {
187 lock (upnpClientLock)
188 {
189 upnpClientRefCount++;
190 upnpClient ??= new UPnPClient(this.sniffers);
191
192 upnpClient.OnDeviceFound += this.UpnpClient_OnDeviceFound;
193 this.upnpHandlerRegistered = true;
194 }
195 }
196
197 lock (this.deviceUrlsProcessed)
198 {
199 this.deviceUrlsProcessed.Clear();
200 }
201
202 await this.SetState(PeerToPeerNetworkState.SearchingForGateway);
203
204 await upnpClient.StartSearch("urn:schemas-upnp-org:service:WANIPConnection:1", 1);
205 await upnpClient.StartSearch("urn:schemas-upnp-org:service:WANIPConnection:2", 1);
206 await upnpClient.StartSearch("urn:schemas-upnp-org:service:WANPPPConnection:1", 1);
207
208 this.searchTimer = new Timer(this.SearchTimeout, null, 10000, Timeout.Infinite);
209 }
210 catch (Exception ex)
211 {
212 this.exception = ex;
213 await this.SetState(PeerToPeerNetworkState.Error);
214 }
215 }
216
217 private async void SearchTimeout(object State)
218 {
219 try
220 {
221 this.searchTimer?.Dispose();
222 this.searchTimer = null;
223
224 await this.UnregisterUPnPClient();
225 await this.SetState(PeerToPeerNetworkState.Error);
226 }
227 catch (Exception ex)
228 {
229 Log.Exception(ex);
230 }
231 }
232
233 private async Task UnregisterUPnPClient()
234 {
235 UPnPClient ToDispose = null;
236
237 lock (upnpClientLock)
238 {
239 if (this.upnpHandlerRegistered)
240 {
241 upnpClient.OnDeviceFound -= this.UpnpClient_OnDeviceFound;
242 this.upnpHandlerRegistered = false;
243
244 if (--upnpClientRefCount == 0)
245 {
246 ToDispose = upnpClient;
247 upnpClient = null;
248 }
249 }
250 }
251
252 if (!(ToDispose is null))
253 await ToDispose.DisposeAsync();
254 }
255
256 private void Reinitialize(object State)
257 {
258 this.searchTimer?.Dispose();
259 this.searchTimer = null;
260
261 this.NetworkChange_NetworkAddressChanged(this, EventArgs.Empty);
262 }
263
264 private async Task UpnpClient_OnDeviceFound(object Sender, DeviceLocationEventArgs e)
265 {
266 try
267 {
268 lock (this.deviceUrlsProcessed)
269 {
270 if (this.deviceUrlsProcessed.Contains(e.Location.Location))
271 return;
272
273 this.deviceUrlsProcessed.Add(e.Location.Location);
274 }
275
277 if (!(Doc is null))
278 {
279 UPnPService Service = Doc.GetService("urn:schemas-upnp-org:service:WANIPConnection:1");
280 if (!(Service is null))
281 {
282 ServiceDescriptionDocument Scpd = await Service.GetServiceAsync();
283 await this.ServiceRetrieved(new WANIPConnectionV1(Scpd), e.LocalEndPoint);
284 return;
285
286 }
287
288 Service = Doc.GetService("urn:schemas-upnp-org:service:WANIPConnection:2");
289 if (!(Service is null))
290 {
291 ServiceDescriptionDocument Scpd = await Service.GetServiceAsync();
292 await this.ServiceRetrieved(new WANIPConnectionV2(Scpd), e.LocalEndPoint);
293 return;
294 }
295
296 Service = Doc.GetService("urn:schemas-upnp-org:service:WANPPPConnection:1");
297 if (!(Service is null))
298 {
299 ServiceDescriptionDocument Scpd = await Service.GetServiceAsync();
300 await this.ServiceRetrieved(new WANPPPConnectionV1(Scpd), e.LocalEndPoint);
301 return;
302 }
303 }
304 }
305 catch (Exception ex)
306 {
307 this.exception = ex;
308 await this.SetState(PeerToPeerNetworkState.Error);
309 }
310 }
311
312 private async Task ServiceRetrieved(IInternetGateway Gateway, IPEndPoint LocalEndPoint)
313 {
314 try
315 {
316 Dictionary<ushort, bool> TcpPortMapped = new Dictionary<ushort, bool>();
317 Dictionary<ushort, bool> UdpPortMapped = new Dictionary<ushort, bool>();
318 ushort PortMappingIndex;
319
320 this.internetGateway = Gateway;
321 await this.SetState(PeerToPeerNetworkState.RegisteringApplicationInGateway);
322
323 this.internetGateway.GetExternalIPAddress(out string NewExternalIPAddress);
324 this.externalAddress = IPAddress.Parse(NewExternalIPAddress);
325
326 Log.Informational("External IP Address: " + NewExternalIPAddress);
327
328 if (!IsPublicAddress(this.externalAddress))
329 {
330 Log.Warning("External IP Address not a public IP address.");
331 return; // TODO: Handle multiple layers of gateways.
332 }
333
334 PortMappingIndex = 0;
335
336 try
337 {
338 string LocalAddress = LocalEndPoint.Address.ToString();
339
340 while (true)
341 {
342 this.internetGateway.GetGenericPortMappingEntry(PortMappingIndex, out string NewRemoteHost,
343 out ushort NewExternalPort, out string NewProtocol, out ushort NewInternalPort, out string NewInternalClient,
344 out bool NewEnabled, out string NewPortMappingDescription, out uint NewLeaseDuration);
345
346 if (NewInternalClient != LocalAddress)
347 {
348 PortMappingIndex++;
349 continue;
350 }
351
352 bool Found = false;
353
354 foreach (InternetGatewayRegistration Registration in this.ports)
355 {
356 if ((Registration.ExternalPort != 0 && NewExternalPort == Registration.ExternalPort) ||
357 (Registration.ExternalPort == 0 && NewPortMappingDescription == Registration.ApplicationName))
358 {
359 if (NewProtocol == "TCP")
360 {
361 Found = true;
362 Registration.TcpRegistered = true;
363 break;
364 }
365 else if (NewProtocol == "UDP")
366 {
367 Found = true;
368 Registration.UdpRegistered = true;
369 break;
370 }
371
372 Log.Notice("Deleting Internet Gateway port mapping.",
373 new KeyValuePair<string, object>("Host", NewRemoteHost),
374 new KeyValuePair<string, object>("External Port", NewExternalPort),
375 new KeyValuePair<string, object>("Protocol", NewProtocol),
376 new KeyValuePair<string, object>("Local Port", NewInternalPort),
377 new KeyValuePair<string, object>("Local Address", NewInternalClient),
378 new KeyValuePair<string, object>("Application", NewPortMappingDescription));
379
380 this.internetGateway.DeletePortMapping(NewRemoteHost, NewExternalPort, NewProtocol);
381 }
382 }
383
384 if (Found)
385 {
386 PortMappingIndex++;
387 continue;
388 }
389 else
390 {
391 switch (NewProtocol)
392 {
393 case "TCP":
394 TcpPortMapped[NewExternalPort] = true;
395 break;
396
397 case "UDP":
398 UdpPortMapped[NewExternalPort] = true;
399 break;
400 }
401
402 PortMappingIndex++;
403 }
404 }
405 }
406 catch (AggregateException ex)
407 {
408 if (!(ex.InnerException is UPnPException))
409 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
410 }
411 catch (UPnPException)
412 {
413 // No more entries.
414 }
415
416 this.localAddress = LocalEndPoint.Address;
417
418 foreach (InternetGatewayRegistration Registration in this.ports)
419 {
420 await this.BeforeRegistration(Registration, TcpPortMapped, UdpPortMapped);
421
422 if ((Registration.TcpRegistered || !Registration.Tcp) &&
423 (Registration.UdpRegistered || !Registration.Udp))
424 {
425 continue;
426 }
427
428 if (Registration.Tcp && !Registration.TcpRegistered)
429 {
430 Log.Notice("Adding Internet Gateway port mapping.",
431 new KeyValuePair<string, object>("Host", string.Empty),
432 new KeyValuePair<string, object>("External Port", Registration.ExternalPort),
433 new KeyValuePair<string, object>("Protocol", "TCP"),
434 new KeyValuePair<string, object>("Local Port", Registration.LocalPort),
435 new KeyValuePair<string, object>("Local Address", this.LocalAddress.ToString()),
436 new KeyValuePair<string, object>("Application", Registration.ApplicationName));
437
438 try
439 {
440 this.internetGateway.AddPortMapping(string.Empty, Registration.ExternalPort,
441 "TCP", Registration.LocalPort, this.LocalAddress.ToString(), true, Registration.ApplicationName, 0);
442
443 Registration.TcpRegistered = true;
444 }
445 catch (Exception ex)
446 {
447 Log.Error("Unable to register port in Internet Gateway: " + ex.Message,
448 new KeyValuePair<string, object>("External Port", Registration.ExternalPort),
449 new KeyValuePair<string, object>("Protocol", "TCP"),
450 new KeyValuePair<string, object>("Local Port", Registration.LocalPort),
451 new KeyValuePair<string, object>("Local Address", this.LocalAddress.ToString()),
452 new KeyValuePair<string, object>("Application", Registration.ApplicationName));
453 }
454 }
455
456 if (Registration.Udp && !Registration.UdpRegistered)
457 {
458 Log.Notice("Adding Internet Gateway port mapping.",
459 new KeyValuePair<string, object>("Host", string.Empty),
460 new KeyValuePair<string, object>("External Port", Registration.ExternalPort),
461 new KeyValuePair<string, object>("Protocol", "UDP"),
462 new KeyValuePair<string, object>("Local Port", Registration.LocalPort),
463 new KeyValuePair<string, object>("Local Address", this.LocalAddress.ToString()),
464 new KeyValuePair<string, object>("Application", Registration.ApplicationName));
465
466 try
467 {
468 this.internetGateway.AddPortMapping(string.Empty, Registration.ExternalPort,
469 "UDP", Registration.LocalPort, this.LocalAddress.ToString(), true, Registration.ApplicationName, 0);
470
471 Registration.UdpRegistered = true;
472 }
473 catch (Exception ex)
474 {
475 Log.Error("Unable to register port in Internet Gateway: " + ex.Message,
476 new KeyValuePair<string, object>("External Port", Registration.ExternalPort),
477 new KeyValuePair<string, object>("Protocol", "UDP"),
478 new KeyValuePair<string, object>("Local Port", Registration.LocalPort),
479 new KeyValuePair<string, object>("Local Address", this.LocalAddress.ToString()),
480 new KeyValuePair<string, object>("Application", Registration.ApplicationName));
481 }
482 }
483 }
484
485 await this.SetState(PeerToPeerNetworkState.Ready);
486 }
487 catch (Exception ex)
488 {
489 Log.Exception(ex);
490
491 this.exception = ex;
492 await this.SetState(PeerToPeerNetworkState.Error);
493 }
494 }
495
502 protected virtual Task BeforeRegistration(InternetGatewayRegistration Registration,
503 Dictionary<ushort, bool> TcpPortMapped, Dictionary<ushort, bool> UdpPortMapped)
504 {
505 return Task.CompletedTask; // Do nothing by default.
506 }
507
511 public PeerToPeerNetworkState State => this.state;
512
513 internal async Task SetState(PeerToPeerNetworkState NewState)
514 {
515 if (this.state != NewState)
516 {
517 this.state = NewState;
518
519 switch (NewState)
520 {
521 case PeerToPeerNetworkState.Ready:
522 this.searchTimer?.Dispose();
523 this.searchTimer = null;
524 this.ready?.Set();
525 break;
526
527 case PeerToPeerNetworkState.Error:
528 this.searchTimer?.Dispose();
529 this.searchTimer = null;
530 this.error?.Set();
531
532 this.searchTimer = new Timer(this.Reinitialize, null, 60000, Timeout.Infinite);
533 break;
534 }
535
536 await this.OnStateChange.Raise(this, NewState);
537 }
538 }
539
543 public event EventHandlerAsync<PeerToPeerNetworkState> OnStateChange = null;
544
548 public IPAddress ExternalAddress => this.externalAddress;
549
553 public IPAddress LocalAddress => this.localAddress;
554
558 public Exception Exception => this.exception;
559
564 public bool Wait()
565 {
566 return this.Wait(10000);
567 }
568
574 public bool Wait(int TimeoutMilliseconds)
575 {
576 switch (WaitHandle.WaitAny(new WaitHandle[] { this.ready, this.error }, TimeoutMilliseconds))
577 {
578 case 0:
579 return true;
580
581 case 1:
582 default:
583 return false;
584 }
585 }
586
590 [Obsolete("Use DisposeAsync() instead.")]
591 public void Dispose()
592 {
593 try
594 {
595 this.DisposeAsync().Wait();
596 }
597 catch (Exception ex)
598 {
599 Log.Exception(ex);
600 }
601 }
602
606 public virtual async Task DisposeAsync()
607 {
608 this.disposed = true;
609 await this.SetState(PeerToPeerNetworkState.Closed);
610
611 NetworkChange.NetworkAddressChanged -= this.NetworkChange_NetworkAddressChanged;
612
613 this.searchTimer?.Dispose();
614 this.searchTimer = null;
615
616 await this.UnregisterUPnPClient();
617
618 foreach (InternetGatewayRegistration Registration in this.ports)
619 {
620 if (Registration.TcpRegistered)
621 {
622 Registration.TcpRegistered = false;
623 try
624 {
625 Log.Notice("Deleting Internet Gateway port mapping.",
626 new KeyValuePair<string, object>("Host", string.Empty),
627 new KeyValuePair<string, object>("External Port", Registration.ExternalPort),
628 new KeyValuePair<string, object>("Protocol", "TCP"),
629 new KeyValuePair<string, object>("Local Port", Registration.LocalPort),
630 new KeyValuePair<string, object>("Application", Registration.ApplicationName));
631
632 this.internetGateway.DeletePortMapping(string.Empty, Registration.LocalPort, "TCP");
633 }
634 catch (Exception)
635 {
636 // Ignore
637 }
638 }
639
640 if (Registration.UdpRegistered)
641 {
642 Registration.UdpRegistered = false;
643 try
644 {
645 Log.Notice("Deleting Internet Gateway port mapping.",
646 new KeyValuePair<string, object>("Host", string.Empty),
647 new KeyValuePair<string, object>("External Port", Registration.ExternalPort),
648 new KeyValuePair<string, object>("Protocol", "UDP"),
649 new KeyValuePair<string, object>("Local Port", Registration.LocalPort),
650 new KeyValuePair<string, object>("Application", Registration.ApplicationName));
651
652 this.internetGateway.DeletePortMapping(string.Empty, Registration.LocalPort, "UDP");
653 }
654 catch (Exception)
655 {
656 // Ignore
657 }
658 }
659 }
660
661 this.internetGateway = null;
662
663 this.deviceUrlsProcessed?.Clear();
664 this.deviceUrlsProcessed = null;
665
666 this.ready?.Dispose();
667 this.ready = null;
668
669 this.error?.Dispose();
670 this.error = null;
671 }
672
679 public IPEndPoint CheckLocalRemoteEndpoint(IPEndPoint RemoteEndPoint)
680 {
681 if (IPAddress.Equals(RemoteEndPoint.Address, this.externalAddress))
682 {
683 this.internetGateway.GetSpecificPortMappingEntry(string.Empty, (ushort)RemoteEndPoint.Port, "TCP",
684 out ushort InternalPort, out string InternalClient, out bool _, out string _, out uint _);
685
686 return new IPEndPoint(IPAddress.Parse(InternalClient), InternalPort);
687 }
688 else
689 return RemoteEndPoint;
690 }
691
692 }
693}
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 Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
Definition: Log.cs:576
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 Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Definition: Log.cs:344
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
Represents a registraing in an UPnP-compatible Internet Gateway.
string ApplicationName
Name of application to be registered.
Manages registration of TCP and UDP ports in an Internet Gateway
async Task SearchGateways()
Searches for Internet Gateways in the network.
virtual async Task Start()
Starts the registration.
Exception Exception
In case State=PeerToPeerNetworkState.Error, this exception object contains details about the error.
static bool IsPublicAddress(IPAddress Address)
Checks if an IPv4 address is public.
EventHandlerAsync< PeerToPeerNetworkState > OnStateChange
Event raised when the state of the peer-to-peer network changes.
IPEndPoint CheckLocalRemoteEndpoint(IPEndPoint RemoteEndPoint)
Checks if a remote endpoint resides in the internal network, and if so, replaces it with the correspo...
bool Wait(int TimeoutMilliseconds)
Waits for the peer-to-peer network object to be ready to receive connections.
bool Wait()
Waits for the peer-to-peer network object to be ready to receive connections.
bool OnPublicNetwork()
If the machine is on a public network.
InternetGatewayRegistrator(InternetGatewayRegistration[] Ports, params ISniffer[] Sniffers)
Manages registration of TCP and UDP ports in an Internet Gateway
PeerToPeerNetworkState State
Current state of the peer-to-peer network object.
virtual Task BeforeRegistration(InternetGatewayRegistration Registration, Dictionary< ushort, bool > TcpPortMapped, Dictionary< ushort, bool > UdpPortMapped)
is called before performing a registration.
Contains the information provided in a Device Description Document, downloaded from a device in the n...
UPnPService GetService(string ServiceType)
Gets a service, given its service type.
Event arguments for completion events when downloading device description documents.
DeviceLocation Location
Device Location information.
Task< DeviceDescriptionDocument > GetDeviceAsync()
Gets a Device Description Document from a device.
string Location
Location of device information
Contains the information provided in a Service Description Document, downloaded from a service in the...
Implements support for the UPnP protocol, as described in: http://upnp.org/specs/arch/UPnP-arch-Devic...
Definition: UPnPClient.cs:21
Task StartSearch()
Starts a search for devices on the network.
Definition: UPnPClient.cs:284
async Task DisposeAsync()
IDisposableAsync.DisposeAsync
Definition: UPnPClient.cs:411
Contains information about a service.
Definition: UPnPService.cs:11
Task< ServiceDescriptionDocument > GetServiceAsync()
Starts the retrieval of a Service Description Document.
Definition: UPnPService.cs:165
Interface for asynchronously disposable objects.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
Definition: ISniffer.cs:10
Interface for Internet Gateway Services.
void GetExternalIPAddress(out string NewExternalIPAddress)
Gets the external public IP address.
void DeletePortMapping(string NewRemoteHost, ushort NewExternalPort, string NewProtocol)
Deletes a port mapping entry.
void GetGenericPortMappingEntry(ushort PortMappingIndex, out string NewRemoteHost, out ushort NewExternalPort, out string NewProtocol, out ushort NewInternalPort, out string NewInternalClient, out bool NewEnabled, out string NewPortMappingDescription, out uint NewLeaseDuration)
Gets a port mapping entry.
void AddPortMapping(string NewRemoteHost, ushort NewExternalPort, string NewProtocol, ushort NewInternalPort, string NewInternalClient, bool NewEnabled, string NewPortMappingDescription, uint NewLeaseDuration)
Adds a port mapping entry.
void GetSpecificPortMappingEntry(string NewRemoteHost, ushort NewExternalPort, string NewProtocol, out ushort NewInternalPort, out string NewInternalClient, out bool NewEnabled, out string NewPortMappingDescription, out uint NewLeaseDuration)
Gets a specific port mapping entry.
Definition: ImplTypes.g.cs:58
PeerToPeerNetworkState
State of Peer-to-peer network.