update port mapper
This commit is contained in:
parent
8e57296f69
commit
ce043225c4
|
@ -8,6 +8,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Server.Implementations.Threading;
|
||||
|
||||
|
@ -17,18 +18,20 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||
{
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||
|
||||
private PeriodicTimer _timer;
|
||||
private bool _isStarted;
|
||||
|
||||
public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery)
|
||||
public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient)
|
||||
{
|
||||
_logger = logmanager.GetLogger("PortMapper");
|
||||
_appHost = appHost;
|
||||
_config = config;
|
||||
_deviceDiscovery = deviceDiscovery;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
private string _lastConfigIdentifier;
|
||||
|
@ -63,6 +66,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||
public void Run()
|
||||
{
|
||||
NatUtility.Logger = _logger;
|
||||
NatUtility.HttpClient = _httpClient;
|
||||
|
||||
if (_config.Configuration.EnableUPnP)
|
||||
{
|
||||
|
@ -136,7 +140,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||
_usnsHandled.Add(identifier);
|
||||
}
|
||||
|
||||
_logger.Debug("Calling Nat.Handle on " + identifier);
|
||||
_logger.Debug("Found NAT device: " + identifier);
|
||||
|
||||
IPAddress address;
|
||||
if (IPAddress.TryParse(info.Location.Host, out address))
|
||||
|
@ -150,16 +154,23 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||
{
|
||||
var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
|
||||
|
||||
if (!IPAddress.TryParse(localAddressString, out localAddress))
|
||||
Uri uri;
|
||||
if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri))
|
||||
{
|
||||
return;
|
||||
localAddressString = uri.Host;
|
||||
|
||||
if (!IPAddress.TryParse(localAddressString, out localAddress))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Debug("Calling Nat.Handle on " + identifier);
|
||||
NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp);
|
||||
}
|
||||
}
|
||||
|
@ -229,13 +240,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||
}
|
||||
}
|
||||
|
||||
private void CreatePortMap(INatDevice device, int privatePort, int publicPort)
|
||||
private async void CreatePortMap(INatDevice device, int privatePort, int publicPort)
|
||||
{
|
||||
_logger.Debug("Creating port map on port {0}", privatePort);
|
||||
device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort)
|
||||
|
||||
try
|
||||
{
|
||||
Description = _appHost.Name
|
||||
});
|
||||
await device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort)
|
||||
{
|
||||
Description = _appHost.Name
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error creating port map", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// As I said before, this method will be never invoked. You can remove it.
|
||||
|
|
|
@ -30,6 +30,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Nat
|
||||
{
|
||||
|
@ -50,11 +51,7 @@ namespace Mono.Nat
|
|||
set { lastSeen = value; }
|
||||
}
|
||||
|
||||
public virtual void CreatePortMap (Mapping mapping)
|
||||
{
|
||||
IAsyncResult result = BeginCreatePortMap (mapping, null, null);
|
||||
EndCreatePortMap(result);
|
||||
}
|
||||
public abstract Task CreatePortMap(Mapping mapping);
|
||||
|
||||
public virtual void DeletePortMap (Mapping mapping)
|
||||
{
|
||||
|
|
|
@ -30,12 +30,13 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Nat
|
||||
{
|
||||
public interface INatDevice
|
||||
{
|
||||
void CreatePortMap (Mapping mapping);
|
||||
Task CreatePortMap (Mapping mapping);
|
||||
void DeletePortMap (Mapping mapping);
|
||||
|
||||
IPAddress LocalAddress { get; }
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
<Compile Include="NatUtility.cs" />
|
||||
<Compile Include="Pmp\AsyncResults\PortMapAsyncResult.cs" />
|
||||
<Compile Include="Pmp\Mappers\PmpMapper.cs" />
|
||||
<Compile Include="Pmp\Pmp.cs" />
|
||||
<Compile Include="Pmp\PmpConstants.cs" />
|
||||
<Compile Include="Pmp\PmpNatDevice.cs" />
|
||||
<Compile Include="Pmp\Searchers\PmpSearcher.cs" />
|
||||
|
@ -80,6 +79,10 @@
|
|||
<Compile Include="Upnp\UpnpNatDevice.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
|
||||
<Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
|
||||
<Name>MediaBrowser.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
|
||||
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
|
||||
<Name>MediaBrowser.Controller</Name>
|
||||
|
|
|
@ -34,9 +34,11 @@ using System.Linq;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.NetworkInformation;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Dlna;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using Mono.Nat.Pmp.Mappers;
|
||||
using Mono.Nat.Upnp;
|
||||
using Mono.Nat.Upnp.Mappers;
|
||||
|
||||
namespace Mono.Nat
|
||||
|
@ -55,8 +57,9 @@ namespace Mono.Nat
|
|||
public static List<NatProtocol> EnabledProtocols { get; set; }
|
||||
|
||||
public static ILogger Logger { get; set; }
|
||||
public static IHttpClient HttpClient { get; set; }
|
||||
|
||||
public static bool Verbose
|
||||
public static bool Verbose
|
||||
{
|
||||
get { return verbose; }
|
||||
set { verbose = value; }
|
||||
|
@ -153,32 +156,6 @@ namespace Mono.Nat
|
|||
{
|
||||
searching.Reset();
|
||||
}
|
||||
|
||||
//This is for when you know the Gateway IP and want to skip the costly search...
|
||||
public static void DirectMap(IPAddress gatewayAddress, MapperType type)
|
||||
{
|
||||
IMapper mapper;
|
||||
switch (type)
|
||||
{
|
||||
case MapperType.Pmp:
|
||||
mapper = new PmpMapper();
|
||||
break;
|
||||
case MapperType.Upnp:
|
||||
mapper = new UpnpMapper(Logger);
|
||||
mapper.DeviceFound += (sender, args) =>
|
||||
{
|
||||
if (DeviceFound != null)
|
||||
DeviceFound(sender, args);
|
||||
};
|
||||
mapper.Map(gatewayAddress);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unsuported type given");
|
||||
|
||||
}
|
||||
searching.Reset();
|
||||
|
||||
}
|
||||
|
||||
//checks if an IP address is a private address space as defined by RFC 1918
|
||||
public static bool IsPrivateAddressSpace (IPAddress address)
|
||||
|
@ -217,11 +194,21 @@ namespace Mono.Nat
|
|||
switch (protocol)
|
||||
{
|
||||
case NatProtocol.Upnp:
|
||||
new UpnpSearcher(Logger).Handle(localAddress, deviceInfo, endpoint);
|
||||
var searcher = new UpnpSearcher(Logger, HttpClient);
|
||||
searcher.DeviceFound += Searcher_DeviceFound;
|
||||
searcher.Handle(localAddress, deviceInfo, endpoint);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unexpected protocol: " + protocol);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Searcher_DeviceFound(object sender, DeviceEventArgs e)
|
||||
{
|
||||
if (DeviceFound != null)
|
||||
{
|
||||
DeviceFound(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,26 +34,12 @@ using Mono.Nat.Pmp;
|
|||
|
||||
namespace Mono.Nat.Pmp.Mappers
|
||||
{
|
||||
internal class PmpMapper : Pmp, IMapper
|
||||
internal class PmpMapper : IMapper
|
||||
{
|
||||
public event EventHandler<DeviceEventArgs> DeviceFound;
|
||||
|
||||
static PmpMapper()
|
||||
{
|
||||
CreateSocketsAndAddGateways();
|
||||
}
|
||||
|
||||
public void Map(IPAddress gatewayAddress)
|
||||
{
|
||||
sockets.ForEach(x => Map(x, gatewayAddress));
|
||||
}
|
||||
|
||||
void Map(UdpClient client, IPAddress gatewayAddress)
|
||||
{
|
||||
// The nat-pmp search message. Must be sent to GatewayIP:53531
|
||||
byte[] buffer = new byte[] { PmpConstants.Version, PmpConstants.OperationCode };
|
||||
|
||||
client.Send(buffer, buffer.Length, new IPEndPoint(gatewayAddress, PmpConstants.ServerPort));
|
||||
}
|
||||
|
||||
public void Handle(IPAddress localAddres, byte[] response)
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
//
|
||||
// Authors:
|
||||
// Ben Motmans <ben.motmans@gmail.com>
|
||||
// Nicholas Terry <nick.i.terry@gmail.com>
|
||||
//
|
||||
// Copyright (C) 2007 Ben Motmans
|
||||
// Copyright (C) 2014 Nicholas Terry
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Nat.Pmp
|
||||
{
|
||||
internal abstract class Pmp
|
||||
{
|
||||
public static List<UdpClient> sockets;
|
||||
protected static Dictionary<UdpClient, List<IPEndPoint>> gatewayLists;
|
||||
|
||||
internal static void CreateSocketsAndAddGateways()
|
||||
{
|
||||
sockets = new List<UdpClient>();
|
||||
gatewayLists = new Dictionary<UdpClient, List<IPEndPoint>>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (NetworkInterface n in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (n.OperationalStatus != OperationalStatus.Up && n.OperationalStatus != OperationalStatus.Unknown)
|
||||
continue;
|
||||
IPInterfaceProperties properties = n.GetIPProperties();
|
||||
List<IPEndPoint> gatewayList = new List<IPEndPoint>();
|
||||
|
||||
foreach (GatewayIPAddressInformation gateway in properties.GatewayAddresses)
|
||||
{
|
||||
if (gateway.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
gatewayList.Add(new IPEndPoint(gateway.Address, PmpConstants.ServerPort));
|
||||
}
|
||||
}
|
||||
if (gatewayList.Count == 0)
|
||||
{
|
||||
/* Mono on OSX doesn't give any gateway addresses, so check DNS entries */
|
||||
foreach (var gw2 in properties.DnsAddresses)
|
||||
{
|
||||
if (gw2.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
gatewayList.Add(new IPEndPoint(gw2, PmpConstants.ServerPort));
|
||||
}
|
||||
}
|
||||
foreach (var unicast in properties.UnicastAddresses)
|
||||
{
|
||||
if (/*unicast.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred
|
||||
&& unicast.AddressPreferredLifetime != UInt32.MaxValue
|
||||
&& */unicast.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
var bytes = unicast.Address.GetAddressBytes();
|
||||
bytes[3] = 1;
|
||||
gatewayList.Add(new IPEndPoint(new IPAddress(bytes), PmpConstants.ServerPort));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gatewayList.Count > 0)
|
||||
{
|
||||
foreach (UnicastIPAddressInformation address in properties.UnicastAddresses)
|
||||
{
|
||||
if (address.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
UdpClient client;
|
||||
|
||||
try
|
||||
{
|
||||
client = new UdpClient(new IPEndPoint(address.Address, 0));
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
continue; // Move on to the next address.
|
||||
}
|
||||
|
||||
gatewayLists.Add(client, gatewayList);
|
||||
sockets.Add(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// NAT-PMP does not use multicast, so there isn't really a good fallback.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ using System.Net;
|
|||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Nat.Pmp
|
||||
{
|
||||
|
@ -56,6 +57,12 @@ namespace Mono.Nat.Pmp
|
|||
return publicAddress;
|
||||
}
|
||||
|
||||
public override Task CreatePortMap(Mapping mapping)
|
||||
{
|
||||
CreatePortMap(mapping, true);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public override IAsyncResult BeginCreatePortMap(Mapping mapping, AsyncCallback callback, object asyncState)
|
||||
{
|
||||
PortMapAsyncResult pmar = new PortMapAsyncResult (mapping.Protocol, mapping.PublicPort, PmpConstants.DefaultLeaseTime, callback, asyncState);
|
||||
|
|
|
@ -40,7 +40,7 @@ using System.Linq;
|
|||
|
||||
namespace Mono.Nat
|
||||
{
|
||||
internal class PmpSearcher : Pmp.Pmp, ISearcher
|
||||
internal class PmpSearcher : ISearcher
|
||||
{
|
||||
static PmpSearcher instance = new PmpSearcher();
|
||||
|
||||
|
@ -60,6 +60,83 @@ namespace Mono.Nat
|
|||
CreateSocketsAndAddGateways();
|
||||
}
|
||||
|
||||
public static List<UdpClient> sockets;
|
||||
protected static Dictionary<UdpClient, List<IPEndPoint>> gatewayLists;
|
||||
|
||||
internal static void CreateSocketsAndAddGateways()
|
||||
{
|
||||
sockets = new List<UdpClient>();
|
||||
gatewayLists = new Dictionary<UdpClient, List<IPEndPoint>>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (NetworkInterface n in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (n.OperationalStatus != OperationalStatus.Up && n.OperationalStatus != OperationalStatus.Unknown)
|
||||
continue;
|
||||
IPInterfaceProperties properties = n.GetIPProperties();
|
||||
List<IPEndPoint> gatewayList = new List<IPEndPoint>();
|
||||
|
||||
foreach (GatewayIPAddressInformation gateway in properties.GatewayAddresses)
|
||||
{
|
||||
if (gateway.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
gatewayList.Add(new IPEndPoint(gateway.Address, PmpConstants.ServerPort));
|
||||
}
|
||||
}
|
||||
if (gatewayList.Count == 0)
|
||||
{
|
||||
/* Mono on OSX doesn't give any gateway addresses, so check DNS entries */
|
||||
foreach (var gw2 in properties.DnsAddresses)
|
||||
{
|
||||
if (gw2.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
gatewayList.Add(new IPEndPoint(gw2, PmpConstants.ServerPort));
|
||||
}
|
||||
}
|
||||
foreach (var unicast in properties.UnicastAddresses)
|
||||
{
|
||||
if (/*unicast.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred
|
||||
&& unicast.AddressPreferredLifetime != UInt32.MaxValue
|
||||
&& */unicast.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
var bytes = unicast.Address.GetAddressBytes();
|
||||
bytes[3] = 1;
|
||||
gatewayList.Add(new IPEndPoint(new IPAddress(bytes), PmpConstants.ServerPort));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gatewayList.Count > 0)
|
||||
{
|
||||
foreach (UnicastIPAddressInformation address in properties.UnicastAddresses)
|
||||
{
|
||||
if (address.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
UdpClient client;
|
||||
|
||||
try
|
||||
{
|
||||
client = new UdpClient(new IPEndPoint(address.Address, 0));
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
continue; // Move on to the next address.
|
||||
}
|
||||
|
||||
gatewayLists.Add(client, gatewayList);
|
||||
sockets.Add(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// NAT-PMP does not use multicast, so there isn't really a good fallback.
|
||||
}
|
||||
}
|
||||
|
||||
PmpSearcher()
|
||||
{
|
||||
timeout = 250;
|
||||
|
|
|
@ -32,19 +32,20 @@ using System.Net;
|
|||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
namespace Mono.Nat.Upnp.Mappers
|
||||
{
|
||||
internal class UpnpMapper : Upnp, IMapper
|
||||
{
|
||||
|
||||
public event EventHandler<DeviceEventArgs> DeviceFound;
|
||||
|
||||
public UdpClient Client { get; set; }
|
||||
|
||||
public UpnpMapper(ILogger logger)
|
||||
: base(logger)
|
||||
public UpnpMapper(ILogger logger, IHttpClient httpClient)
|
||||
: base(logger, httpClient)
|
||||
{
|
||||
//Bind to local port 1900 for ssdp responses
|
||||
Client = new UdpClient(1900);
|
||||
|
@ -60,7 +61,7 @@ namespace Mono.Nat.Upnp.Mappers
|
|||
new Thread(Receive).Start();
|
||||
}
|
||||
|
||||
public void Receive()
|
||||
public async void Receive()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
@ -69,28 +70,36 @@ namespace Mono.Nat.Upnp.Mappers
|
|||
{
|
||||
IPAddress localAddress = ((IPEndPoint)Client.Client.LocalEndPoint).Address;
|
||||
byte[] data = Client.Receive(ref received);
|
||||
Handle(localAddress, data, received);
|
||||
|
||||
await Handle(localAddress, data, received);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(IPAddress localAddres, byte[] response)
|
||||
{
|
||||
Handle(localAddres, response, null);
|
||||
}
|
||||
|
||||
public void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
public override async Task<UpnpNatDevice> Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
{
|
||||
// No matter what, this method should never throw an exception. If something goes wrong
|
||||
// we should still be in a position to handle the next reply correctly.
|
||||
try
|
||||
{
|
||||
UpnpNatDevice d = base.Handle(localAddress, response, endpoint);
|
||||
d.GetServicesList(DeviceSetupComplete);
|
||||
var d = await base.Handle(localAddress, response, endpoint).ConfigureAwait(false);
|
||||
var result = await d.GetServicesList().ConfigureAwait(false);
|
||||
|
||||
if (result)
|
||||
{
|
||||
DeviceSetupComplete(d);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error mapping port. Data string: {0}", ex, Encoding.UTF8.GetString(response));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
//
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -54,6 +55,10 @@ namespace Mono.Nat.Upnp
|
|||
}
|
||||
#endregion
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override System.Net.WebRequest Encode(out byte[] body)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
|
@ -38,7 +39,7 @@ namespace Mono.Nat.Upnp
|
|||
private readonly ILogger _logger;
|
||||
|
||||
public GetServicesMessage(string description, EndPoint hostAddress, ILogger logger)
|
||||
:base(null)
|
||||
: base(null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(description))
|
||||
_logger.Warn("Description is null");
|
||||
|
@ -51,6 +52,13 @@ namespace Mono.Nat.Upnp
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string Method
|
||||
{
|
||||
get
|
||||
{
|
||||
return "GET";
|
||||
}
|
||||
}
|
||||
|
||||
public override WebRequest Encode(out byte[] body)
|
||||
{
|
||||
|
@ -61,5 +69,16 @@ namespace Mono.Nat.Upnp
|
|||
body = new byte[0];
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
var req = new HttpRequestOptions();
|
||||
|
||||
req.Url = "http://" + this.hostAddress.ToString() + this.servicesDescriptionUrl;
|
||||
req.RequestHeaders.Add("ACCEPT-LANGUAGE", "en");
|
||||
|
||||
return req;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ using System.IO;
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -51,6 +52,25 @@ namespace Mono.Nat.Upnp
|
|||
}
|
||||
#endregion
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
CultureInfo culture = CultureInfo.InvariantCulture;
|
||||
|
||||
StringBuilder builder = new StringBuilder(256);
|
||||
XmlWriter writer = CreateWriter(builder);
|
||||
|
||||
WriteFullElement(writer, "NewRemoteHost", string.Empty);
|
||||
WriteFullElement(writer, "NewExternalPort", this.mapping.PublicPort.ToString(culture));
|
||||
WriteFullElement(writer, "NewProtocol", this.mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP");
|
||||
WriteFullElement(writer, "NewInternalPort", this.mapping.PrivatePort.ToString(culture));
|
||||
WriteFullElement(writer, "NewInternalClient", this.localIpAddress.ToString());
|
||||
WriteFullElement(writer, "NewEnabled", "1");
|
||||
WriteFullElement(writer, "NewPortMappingDescription", string.IsNullOrEmpty(mapping.Description) ? "Mono.Nat" : mapping.Description);
|
||||
WriteFullElement(writer, "NewLeaseDuration", mapping.Lifetime.ToString());
|
||||
|
||||
writer.Flush();
|
||||
return CreateRequest("AddPortMapping", builder.ToString());
|
||||
}
|
||||
|
||||
public override WebRequest Encode(out byte[] body)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@ using System.Net;
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -41,7 +42,20 @@ namespace Mono.Nat.Upnp
|
|||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public override WebRequest Encode(out byte[] body)
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(256);
|
||||
XmlWriter writer = CreateWriter(builder);
|
||||
|
||||
WriteFullElement(writer, "NewRemoteHost", string.Empty);
|
||||
WriteFullElement(writer, "NewExternalPort", mapping.PublicPort.ToString(MessageBase.Culture));
|
||||
WriteFullElement(writer, "NewProtocol", mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP");
|
||||
|
||||
writer.Flush();
|
||||
return CreateRequest("DeletePortMapping", builder.ToString());
|
||||
}
|
||||
|
||||
public override WebRequest Encode(out byte[] body)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(256);
|
||||
XmlWriter writer = CreateWriter(builder);
|
||||
|
|
|
@ -29,6 +29,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -42,6 +43,10 @@ namespace Mono.Nat.Upnp
|
|||
}
|
||||
#endregion
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
return CreateRequest("GetExternalIPAddress", string.Empty);
|
||||
}
|
||||
|
||||
public override WebRequest Encode(out byte[] body)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -41,6 +42,17 @@ namespace Mono.Nat.Upnp
|
|||
this.index = index;
|
||||
}
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
XmlWriter writer = CreateWriter(sb);
|
||||
|
||||
WriteFullElement(writer, "NewPortMappingIndex", index.ToString());
|
||||
|
||||
writer.Flush();
|
||||
return CreateRequest("GetGenericPortMappingEntry", sb.ToString());
|
||||
}
|
||||
|
||||
public override System.Net.WebRequest Encode(out byte[] body)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
|
|
|
@ -29,6 +29,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -55,6 +56,19 @@ namespace Mono.Nat.Upnp
|
|||
writer.Flush();
|
||||
|
||||
return CreateRequest("GetSpecificPortMappingEntry", sb.ToString(), out body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
XmlWriter writer = CreateWriter(sb);
|
||||
|
||||
WriteFullElement(writer, "NewRemoteHost", string.Empty);
|
||||
WriteFullElement(writer, "NewExternalPort", externalPort.ToString());
|
||||
WriteFullElement(writer, "NewProtocol", protocol == Protocol.Tcp ? "TCP" : "UDP");
|
||||
writer.Flush();
|
||||
|
||||
return CreateRequest("GetSpecificPortMappingEntry", sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
internal class CreatePortMappingResponseMessage : MessageBase
|
||||
|
@ -38,6 +40,11 @@ namespace Mono.Nat.Upnp
|
|||
}
|
||||
#endregion
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override System.Net.WebRequest Encode(out byte[] body)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
internal class DeletePortMapResponseMessage : MessageBase
|
||||
|
@ -36,6 +38,11 @@ namespace Mono.Nat.Upnp
|
|||
{
|
||||
}
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override System.Net.WebRequest Encode(out byte[] body)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
|
|
|
@ -28,6 +28,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -45,6 +46,11 @@ namespace Mono.Nat.Upnp
|
|||
this.externalIPAddress = IPAddress.Parse(ip);
|
||||
}
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override WebRequest Encode(out byte[] body)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
@ -28,6 +28,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -100,6 +101,11 @@ namespace Mono.Nat.Upnp
|
|||
leaseDuration = Convert.ToInt32(data["NewLeaseDuration"].InnerText);
|
||||
}
|
||||
|
||||
public override HttpRequestOptions Encode()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override System.Net.WebRequest Encode(out byte[] body)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
@ -31,6 +31,7 @@ using System.Net;
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Common.Net;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
{
|
||||
|
@ -71,6 +72,32 @@ namespace Mono.Nat.Upnp
|
|||
return req;
|
||||
}
|
||||
|
||||
protected HttpRequestOptions CreateRequest(string upnpMethod, string methodParameters)
|
||||
{
|
||||
string ss = "http://" + this.device.HostEndPoint.ToString() + this.device.ControlUrl;
|
||||
NatUtility.Log("Initiating request to: {0}", ss);
|
||||
|
||||
var req = new HttpRequestOptions();
|
||||
req.Url = ss;
|
||||
req.EnableKeepAlive = false;
|
||||
req.RequestContentType = "text/xml; charset=\"utf-8\"";
|
||||
req.RequestHeaders.Add("SOAPACTION", "\"" + device.ServiceType + "#" + upnpMethod + "\"");
|
||||
|
||||
string bodyString = "<s:Envelope "
|
||||
+ "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
+ "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
+ "<s:Body>"
|
||||
+ "<u:" + upnpMethod + " "
|
||||
+ "xmlns:u=\"" + device.ServiceType + "\">"
|
||||
+ methodParameters
|
||||
+ "</u:" + upnpMethod + ">"
|
||||
+ "</s:Body>"
|
||||
+ "</s:Envelope>\r\n\r\n";
|
||||
|
||||
req.RequestContentBytes = System.Text.Encoding.UTF8.GetBytes(bodyString);
|
||||
return req;
|
||||
}
|
||||
|
||||
public static MessageBase Decode(UpnpNatDevice device, string message)
|
||||
{
|
||||
XmlNode node;
|
||||
|
@ -113,8 +140,14 @@ namespace Mono.Nat.Upnp
|
|||
return null;
|
||||
}
|
||||
|
||||
public abstract HttpRequestOptions Encode();
|
||||
public abstract WebRequest Encode(out byte[] body);
|
||||
|
||||
public virtual string Method
|
||||
{
|
||||
get { return "POST"; }
|
||||
}
|
||||
|
||||
internal static void WriteFullElement(XmlWriter writer, string element, string value)
|
||||
{
|
||||
writer.WriteStartElement(element);
|
||||
|
|
|
@ -36,6 +36,7 @@ using Mono.Nat.Upnp;
|
|||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.NetworkInformation;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Dlna;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
|
@ -48,10 +49,12 @@ namespace Mono.Nat
|
|||
|
||||
private DateTime nextSearch;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IHttpClient _httpClient;
|
||||
|
||||
public UpnpSearcher(ILogger logger)
|
||||
public UpnpSearcher(ILogger logger, IHttpClient httpClient)
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public void Search()
|
||||
|
@ -76,7 +79,7 @@ namespace Mono.Nat
|
|||
prefix. */
|
||||
|
||||
// We have an internet gateway device now
|
||||
UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger);
|
||||
UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger, _httpClient);
|
||||
|
||||
NatUtility.Log("Fetching service list: {0}", d.HostEndPoint);
|
||||
OnDeviceFound(new DeviceEventArgs(d));
|
||||
|
|
|
@ -33,6 +33,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
||||
namespace Mono.Nat.Upnp
|
||||
|
@ -40,13 +42,15 @@ namespace Mono.Nat.Upnp
|
|||
internal class Upnp
|
||||
{
|
||||
protected readonly ILogger Logger;
|
||||
protected readonly IHttpClient HttpClient;
|
||||
|
||||
public Upnp(ILogger logger)
|
||||
public Upnp(ILogger logger, IHttpClient httpClient)
|
||||
{
|
||||
Logger = logger;
|
||||
HttpClient = httpClient;
|
||||
}
|
||||
|
||||
public UpnpNatDevice Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
public virtual Task<UpnpNatDevice> Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
|
||||
{
|
||||
// Convert it to a string for easy parsing
|
||||
string dataString = null;
|
||||
|
@ -85,7 +89,8 @@ namespace Mono.Nat.Upnp
|
|||
throw new NotSupportedException("Received non-supported device type");
|
||||
|
||||
// We have an internet gateway device now
|
||||
return new UpnpNatDevice(localAddress, dataString, urn, Logger);
|
||||
var device = new UpnpNatDevice(localAddress, dataString, urn, Logger, HttpClient);
|
||||
return Task.FromResult(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user