Hush – Rev 2
?pathlinks?
using System;
using System.Threading;
using System.Threading.Tasks;
using Open.Nat;
namespace Hush.Discovery
{
public class Discovery : IDisposable
{
public delegate void PortMapFailed(object sender, DiscoveryFailedEventArgs args);
public Discovery()
{
NatDiscoverer = new NatDiscoverer();
}
public Discovery(string mappingName, CancellationToken cancellationToken,
TaskScheduler taskScheduler) : this()
{
MappingName = mappingName;
CancellationToken = cancellationToken;
TaskScheduler = taskScheduler;
}
private static string MappingName { get; set; }
private static CancellationToken CancellationToken { get; set; }
private static NatDiscoverer NatDiscoverer { get; set; }
private static TaskScheduler TaskScheduler { get; set; }
private static CancellationTokenSource UpnPCancellationTokenSource { get; set; }
private static CancellationTokenSource PmpCancellationTokenSource { get; set; }
public void Dispose()
{
PmpCancellationTokenSource?.Dispose();
PmpCancellationTokenSource = null;
PmpCancellationTokenSource?.Dispose();
PmpCancellationTokenSource = null;
}
public event PortMapFailed OnPortMapFailed;
public async Task<bool> CreateMapping(DiscoveryType type, int port)
{
switch (type)
{
case DiscoveryType.Upnp:
return await CreateUpnPMapping(port);
case DiscoveryType.Pmp:
return await CreatePmpPortMapping(port);
default:
throw new ArgumentException("Unknown discovery type");
}
}
public async Task<bool> DeleteMapping(DiscoveryType type, int port)
{
switch (type)
{
case DiscoveryType.Upnp:
return await DeleteUpnPMapping(port);
case DiscoveryType.Pmp:
return await DeletePmpPortMapping(port);
default:
throw new ArgumentException("Unknown discovery type");
}
}
private async Task<bool> DeleteUpnPMapping(int port)
{
try
{
UpnPCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(UpnPCancellationTokenSource.Token,
CancellationToken);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Upnp, linkedCancellationTokenSource);
await device.DeletePortMapAsync(new Mapping(Protocol.Tcp, port, port, MappingName));
return true;
}
catch
{
return false;
}
}
private async Task<bool> CreateUpnPMapping(int port)
{
try
{
UpnPCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource =
CancellationTokenSource.CreateLinkedTokenSource(UpnPCancellationTokenSource.Token,
CancellationToken);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Upnp, linkedCancellationTokenSource);
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port, MappingName));
return true;
}
catch (Exception ex)
{
await Task.Delay(0, CancellationToken).ContinueWith(_ =>
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.Upnp, ex)),
CancellationToken, TaskContinuationOptions.None, TaskScheduler);
return false;
}
}
private async Task<bool> DeletePmpPortMapping(int port)
{
try
{
PmpCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
PmpCancellationTokenSource.Token,
CancellationToken);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Pmp, linkedCancellationTokenSource);
await device.DeletePortMapAsync(new Mapping(Protocol.Tcp, port, port, MappingName));
return true;
}
catch
{
return false;
}
}
private async Task<bool> CreatePmpPortMapping(int port)
{
try
{
PmpCancellationTokenSource = new CancellationTokenSource();
var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
PmpCancellationTokenSource.Token,
CancellationToken);
var device = await NatDiscoverer.DiscoverDeviceAsync(PortMapper.Pmp, linkedCancellationTokenSource);
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port, MappingName));
return true;
}
catch (Exception ex)
{
await Task.Delay(0, CancellationToken).ContinueWith(_ =>
OnPortMapFailed?.Invoke(this, new DiscoveryFailedEventArgs(DiscoveryType.Pmp, ex)),
CancellationToken, TaskContinuationOptions.None, TaskScheduler);
return false;
}
}
}
}
Generated by GNU Enscript 1.6.5.90.