3using System.Collections.Generic;
5using System.Net.NetworkInformation;
6using System.Net.Sockets;
7using System.Threading.Tasks;
21 internal IPAddress localAddress;
22 internal IPAddress externalAddress;
24 private readonly
ISniffer[] sniffers;
25 private Dictionary<IPAddress, bool> ipAddressesFound =
new Dictionary<IPAddress, bool>();
29 private ManualResetEvent ready =
new ManualResetEvent(
false);
30 private ManualResetEvent error =
new ManualResetEvent(
false);
31 private Timer searchTimer =
null;
32 internal bool disposed =
false;
42 this.sniffers = Sniffers;
44 NetworkChange.NetworkAddressChanged += this.NetworkChange_NetworkAddressChanged;
47 private async
void NetworkChange_NetworkAddressChanged(
object Sender, EventArgs e)
70 public virtual async Task
Start()
73 this.localAddress = this.externalAddress;
84 foreach (NetworkInterface Interface
in NetworkInterface.GetAllNetworkInterfaces())
86 if (Interface.OperationalStatus != OperationalStatus.Up)
89 IPInterfaceProperties Properties = Interface.GetIPProperties();
91 foreach (UnicastIPAddressInformation UnicastAddress
in Properties.UnicastAddresses)
96 this.externalAddress = UnicastAddress.Address;
111 if (Address.AddressFamily == AddressFamily.InterNetwork && Socket.OSSupportsIPv4)
113 byte[] Addr = Address.GetAddressBytes();
126 return (Addr[1] & 0xc0) != 64;
132 return Addr[1] != 254;
135 return (Addr[1] & 0xf0) != 16;
154 return Addr[2] != 99;
173 if (this.disposed || this.ipAddressesFound is
null)
178 this.searchTimer?.Dispose();
179 this.searchTimer =
null;
181 if (this.upnpClient is
null)
183 this.upnpClient =
new UPnPClient(this.sniffers);
184 this.upnpClient.OnDeviceFound += this.UpnpClient_OnDeviceFound;
187 lock (this.ipAddressesFound)
189 this.ipAddressesFound.Clear();
194 await this.upnpClient.
StartSearch(
"urn:schemas-upnp-org:service:WANIPConnection:1", 1);
195 await this.upnpClient.
StartSearch(
"urn:schemas-upnp-org:service:WANIPConnection:2", 1);
197 this.searchTimer =
new Timer(this.SearchTimeout,
null, 10000, Timeout.Infinite);
206 private async
void SearchTimeout(
object State)
210 this.searchTimer?.Dispose();
211 this.searchTimer =
null;
221 private void Reinitialize(
object State)
223 this.searchTimer?.Dispose();
224 this.searchTimer =
null;
226 this.NetworkChange_NetworkAddressChanged(
this, EventArgs.Empty);
233 lock (this.ipAddressesFound)
247 Service = Doc.
GetService(
"urn:schemas-upnp-org:service:WANIPConnection:2");
267 Dictionary<ushort, bool> TcpPortMapped =
new Dictionary<ushort, bool>();
268 Dictionary<ushort, bool> UdpPortMapped =
new Dictionary<ushort, bool>();
269 ushort PortMappingIndex;
275 this.externalAddress = IPAddress.Parse(NewExternalIPAddress);
281 Log.
Warning(
"External IP Address not a public IP address.");
285 PortMappingIndex = 0;
294 out ushort NewExternalPort, out
string NewProtocol, out ushort NewInternalPort, out
string NewInternalClient,
295 out
bool NewEnabled, out
string NewPortMappingDescription, out uint NewLeaseDuration);
305 foreach (InternetGatewayRegistration Registration
in this.ports)
307 if ((Registration.ExternalPort != 0 && NewExternalPort == Registration.ExternalPort) ||
308 (Registration.ExternalPort == 0 && NewPortMappingDescription == Registration.ApplicationName))
310 if (NewProtocol ==
"TCP")
313 Registration.TcpRegistered =
true;
316 else if (NewProtocol ==
"UDP")
319 Registration.UdpRegistered =
true;
323 Log.
Notice(
"Deleting Internet Gateway port mapping.",
324 new KeyValuePair<string, object>(
"Host", NewRemoteHost),
325 new KeyValuePair<string, object>(
"External Port", NewExternalPort),
326 new KeyValuePair<string, object>(
"Protocol", NewProtocol),
327 new KeyValuePair<string, object>(
"Local Port", NewInternalPort),
328 new KeyValuePair<string, object>(
"Local Address", NewInternalClient),
329 new KeyValuePair<string, object>(
"Application", NewPortMappingDescription));
331 this.serviceWANIPConnectionV1.
DeletePortMapping(NewRemoteHost, NewExternalPort, NewProtocol);
345 TcpPortMapped[NewExternalPort] =
true;
349 UdpPortMapped[NewExternalPort] =
true;
357 catch (AggregateException ex)
360 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
367 this.localAddress = LocalEndPoint.Address;
369 foreach (InternetGatewayRegistration Registration
in this.ports)
373 if ((Registration.TcpRegistered || !Registration.Tcp) &&
374 (Registration.UdpRegistered || !Registration.Udp))
379 if (Registration.Tcp && !Registration.TcpRegistered)
381 Log.
Notice(
"Adding Internet Gateway port mapping.",
382 new KeyValuePair<string, object>(
"Host",
string.Empty),
383 new KeyValuePair<string, object>(
"External Port", Registration.ExternalPort),
384 new KeyValuePair<string, object>(
"Protocol",
"TCP"),
385 new KeyValuePair<string, object>(
"Local Port", Registration.LocalPort),
386 new KeyValuePair<string, object>(
"Local Address",
this.LocalAddress.ToString()),
387 new KeyValuePair<string, object>(
"Application", Registration.ApplicationName));
391 this.serviceWANIPConnectionV1.
AddPortMapping(
string.Empty, Registration.ExternalPort,
392 "TCP", Registration.LocalPort,
this.LocalAddress.ToString(),
true, Registration.ApplicationName, 0);
394 Registration.TcpRegistered =
true;
398 Log.
Error(
"Unable to register port in Internet Gateway: " + ex.Message,
399 new KeyValuePair<string, object>(
"External Port", Registration.ExternalPort),
400 new KeyValuePair<string, object>(
"Protocol",
"TCP"),
401 new KeyValuePair<string, object>(
"Local Port", Registration.LocalPort),
402 new KeyValuePair<string, object>(
"Local Address",
this.LocalAddress.ToString()),
403 new KeyValuePair<string, object>(
"Application", Registration.ApplicationName));
407 if (Registration.Udp && !Registration.UdpRegistered)
409 Log.
Notice(
"Adding Internet Gateway port mapping.",
410 new KeyValuePair<string, object>(
"Host",
string.Empty),
411 new KeyValuePair<string, object>(
"External Port", Registration.ExternalPort),
412 new KeyValuePair<string, object>(
"Protocol",
"UDP"),
413 new KeyValuePair<string, object>(
"Local Port", Registration.LocalPort),
414 new KeyValuePair<string, object>(
"Local Address",
this.LocalAddress.ToString()),
415 new KeyValuePair<string, object>(
"Application", Registration.ApplicationName));
419 this.serviceWANIPConnectionV1.
AddPortMapping(
string.Empty, Registration.ExternalPort,
420 "UDP", Registration.LocalPort,
this.LocalAddress.ToString(),
true, Registration.ApplicationName, 0);
422 Registration.UdpRegistered =
true;
426 Log.
Error(
"Unable to register port in Internet Gateway: " + ex.Message,
427 new KeyValuePair<string, object>(
"External Port", Registration.ExternalPort),
428 new KeyValuePair<string, object>(
"Protocol",
"UDP"),
429 new KeyValuePair<string, object>(
"Local Port", Registration.LocalPort),
430 new KeyValuePair<string, object>(
"Local Address",
this.LocalAddress.ToString()),
431 new KeyValuePair<string, object>(
"Application", Registration.ApplicationName));
454 Dictionary<ushort, bool> TcpPortMapped, Dictionary<ushort, bool> UdpPortMapped)
456 return Task.CompletedTask;
466 if (this.state != NewState)
468 this.state = NewState;
473 this.searchTimer?.Dispose();
474 this.searchTimer =
null;
479 this.searchTimer?.Dispose();
480 this.searchTimer =
null;
483 this.searchTimer =
new Timer(this.Reinitialize,
null, 60000, Timeout.Infinite);
494 public event EventHandlerAsync<PeerToPeerNetworkState>
OnStateChange =
null;
517 return this.
Wait(10000);
525 public bool Wait(
int TimeoutMilliseconds)
527 switch (WaitHandle.WaitAny(
new WaitHandle[] { this.ready, this.error }, TimeoutMilliseconds))
541 [Obsolete(
"Use DisposeAsync() instead.")]
559 this.disposed =
true;
562 NetworkChange.NetworkAddressChanged -= this.NetworkChange_NetworkAddressChanged;
564 this.searchTimer?.Dispose();
565 this.searchTimer =
null;
569 if (Registration.TcpRegistered)
571 Registration.TcpRegistered =
false;
574 Log.
Notice(
"Deleting Internet Gateway port mapping.",
575 new KeyValuePair<string, object>(
"Host",
string.Empty),
576 new KeyValuePair<string, object>(
"External Port", Registration.
ExternalPort),
577 new KeyValuePair<string, object>(
"Protocol",
"TCP"),
578 new KeyValuePair<string, object>(
"Local Port", Registration.
LocalPort),
579 new KeyValuePair<string, object>(
"Application", Registration.
ApplicationName));
589 if (Registration.UdpRegistered)
591 Registration.UdpRegistered =
false;
594 Log.
Notice(
"Deleting Internet Gateway port mapping.",
595 new KeyValuePair<string, object>(
"Host",
string.Empty),
596 new KeyValuePair<string, object>(
"External Port", Registration.
ExternalPort),
597 new KeyValuePair<string, object>(
"Protocol",
"UDP"),
598 new KeyValuePair<string, object>(
"Local Port", Registration.
LocalPort),
599 new KeyValuePair<string, object>(
"Application", Registration.
ApplicationName));
610 this.serviceWANIPConnectionV1 =
null;
613 this.upnpClient =
null;
615 this.ipAddressesFound?.Clear();
616 this.ipAddressesFound =
null;
618 this.ready?.Dispose();
621 this.error?.Dispose();
633 if (IPAddress.Equals(RemoteEndPoint.Address,
this.externalAddress))
636 out ushort InternalPort, out
string InternalClient, out
bool _, out
string _, out uint _);
638 return new IPEndPoint(IPAddress.Parse(InternalClient), InternalPort);
641 return RemoteEndPoint;
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.
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.
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.
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.
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.
Represents a registraing in an UPnP-compatible Internet Gateway.
ushort LocalPort
Port on local machine.
ushort ExternalPort
Port on external side of gateway.
string ApplicationName
Name of application to be registered.
Manages registration of TCP and UDP ports in an Internet Gateway
IPAddress LocalAddress
Local IP Address.
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.
virtual async Task DisposeAsync()
IDisposable.Dispose
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.
IPAddress ExternalAddress
External IP Address.
void Dispose()
IDisposable.Dispose
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.
IPEndPoint LocalEndPoint
Local End Point
IPEndPoint RemoteEndPoint
Remote End Point
DeviceLocation Location
Device Location information.
Task< DeviceDescriptionDocument > GetDeviceAsync()
Gets a Device Description Document from a device.
Contains the information provided in a Service Description Document, downloaded from a service in the...
void GetSpecificPortMappingEntry(string NewRemoteHost, ushort NewExternalPort, string NewProtocol, out ushort NewInternalPort, out string NewInternalClient, out bool NewEnabled, out string NewPortMappingDescription, out uint NewLeaseDuration)
Generated from SCPD
void AddPortMapping(string NewRemoteHost, ushort NewExternalPort, string NewProtocol, ushort NewInternalPort, string NewInternalClient, bool NewEnabled, string NewPortMappingDescription, uint NewLeaseDuration)
Generated from SCPD
void GetGenericPortMappingEntry(ushort NewPortMappingIndex, out string NewRemoteHost, out ushort NewExternalPort, out string NewProtocol, out ushort NewInternalPort, out string NewInternalClient, out bool NewEnabled, out string NewPortMappingDescription, out uint NewLeaseDuration)
Generated from SCPD
void GetExternalIPAddress(out string NewExternalIPAddress)
Generated from SCPD
void DeletePortMapping(string NewRemoteHost, ushort NewExternalPort, string NewProtocol)
Generated from SCPD
Implements support for the UPnP protocol, as described in: http://upnp.org/specs/arch/UPnP-arch-Devic...
Task StartSearch()
Starts a search for devices on the network.
void Dispose()
IDisposable.Dispose
Contains information about a service.
Task< ServiceDescriptionDocument > GetServiceAsync()
Starts the retrieval of a Service Description Document.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
PeerToPeerNetworkState
State of Peer-to-peer network.