using Open.Nat;
using System;
using System.Collections.Generic;
using System.Threading;
namespace Pulsar.Server.Networking
{
public class UPnPService
{
///
/// Used to keep track of all created mappings.
///
private readonly Dictionary _mappings = new Dictionary();
///
/// The discovered UPnP device.
///
private NatDevice _device;
///
/// The NAT discoverer used to discover NAT-UPnP devices.
///
private NatDiscoverer _discoverer;
///
/// Initializes the discovery of new UPnP devices.
///
public UPnPService()
{
_discoverer = new NatDiscoverer();
}
///
/// Creates a new port mapping on the UPnP device.
///
/// The port to map.
public async void CreatePortMapAsync(int port)
{
try
{
var cts = new CancellationTokenSource(10000);
_device = await _discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);
Mapping mapping = new Mapping(Protocol.Tcp, port, port);
await _device.CreatePortMapAsync(mapping);
if (_mappings.ContainsKey(mapping.PrivatePort))
_mappings[mapping.PrivatePort] = mapping;
else
_mappings.Add(mapping.PrivatePort, mapping);
}
catch (Exception ex) when (ex is MappingException || ex is NatDeviceNotFoundException)
{
}
}
///
/// Deletes an existing port mapping.
///
/// The port mapping to delete.
public async void DeletePortMapAsync(int port)
{
if (_mappings.TryGetValue(port, out var mapping))
{
try
{
await _device.DeletePortMapAsync(mapping);
_mappings.Remove(mapping.PrivatePort);
}
catch (Exception ex) when (ex is MappingException || ex is NatDeviceNotFoundException)
{
}
}
}
}
}