mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-23 14:10:40 +02:00
update port mapper
This commit is contained in:
parent
8e57296f69
commit
ce043225c4
|
@ -8,6 +8,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Server.Implementations.Threading;
|
using MediaBrowser.Server.Implementations.Threading;
|
||||||
|
|
||||||
|
@ -17,18 +18,20 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
|
|
||||||
private PeriodicTimer _timer;
|
private PeriodicTimer _timer;
|
||||||
private bool _isStarted;
|
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");
|
_logger = logmanager.GetLogger("PortMapper");
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_config = config;
|
_config = config;
|
||||||
_deviceDiscovery = deviceDiscovery;
|
_deviceDiscovery = deviceDiscovery;
|
||||||
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _lastConfigIdentifier;
|
private string _lastConfigIdentifier;
|
||||||
|
@ -63,6 +66,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
NatUtility.Logger = _logger;
|
NatUtility.Logger = _logger;
|
||||||
|
NatUtility.HttpClient = _httpClient;
|
||||||
|
|
||||||
if (_config.Configuration.EnableUPnP)
|
if (_config.Configuration.EnableUPnP)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +140,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
_usnsHandled.Add(identifier);
|
_usnsHandled.Add(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Calling Nat.Handle on " + identifier);
|
_logger.Debug("Found NAT device: " + identifier);
|
||||||
|
|
||||||
IPAddress address;
|
IPAddress address;
|
||||||
if (IPAddress.TryParse(info.Location.Host, out 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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Calling Nat.Handle on " + identifier);
|
||||||
NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp);
|
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);
|
_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.
|
// 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.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Mono.Nat
|
namespace Mono.Nat
|
||||||
{
|
{
|
||||||
|
@ -50,11 +51,7 @@ namespace Mono.Nat
|
||||||
set { lastSeen = value; }
|
set { lastSeen = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void CreatePortMap (Mapping mapping)
|
public abstract Task CreatePortMap(Mapping mapping);
|
||||||
{
|
|
||||||
IAsyncResult result = BeginCreatePortMap (mapping, null, null);
|
|
||||||
EndCreatePortMap(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void DeletePortMap (Mapping mapping)
|
public virtual void DeletePortMap (Mapping mapping)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,12 +30,13 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Mono.Nat
|
namespace Mono.Nat
|
||||||
{
|
{
|
||||||
public interface INatDevice
|
public interface INatDevice
|
||||||
{
|
{
|
||||||
void CreatePortMap (Mapping mapping);
|
Task CreatePortMap (Mapping mapping);
|
||||||
void DeletePortMap (Mapping mapping);
|
void DeletePortMap (Mapping mapping);
|
||||||
|
|
||||||
IPAddress LocalAddress { get; }
|
IPAddress LocalAddress { get; }
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
<Compile Include="NatUtility.cs" />
|
<Compile Include="NatUtility.cs" />
|
||||||
<Compile Include="Pmp\AsyncResults\PortMapAsyncResult.cs" />
|
<Compile Include="Pmp\AsyncResults\PortMapAsyncResult.cs" />
|
||||||
<Compile Include="Pmp\Mappers\PmpMapper.cs" />
|
<Compile Include="Pmp\Mappers\PmpMapper.cs" />
|
||||||
<Compile Include="Pmp\Pmp.cs" />
|
|
||||||
<Compile Include="Pmp\PmpConstants.cs" />
|
<Compile Include="Pmp\PmpConstants.cs" />
|
||||||
<Compile Include="Pmp\PmpNatDevice.cs" />
|
<Compile Include="Pmp\PmpNatDevice.cs" />
|
||||||
<Compile Include="Pmp\Searchers\PmpSearcher.cs" />
|
<Compile Include="Pmp\Searchers\PmpSearcher.cs" />
|
||||||
|
@ -80,6 +79,10 @@
|
||||||
<Compile Include="Upnp\UpnpNatDevice.cs" />
|
<Compile Include="Upnp\UpnpNatDevice.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<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">
|
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
|
||||||
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
|
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
|
||||||
<Name>MediaBrowser.Controller</Name>
|
<Name>MediaBrowser.Controller</Name>
|
||||||
|
|
|
@ -34,9 +34,11 @@ using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using Mono.Nat.Pmp.Mappers;
|
using Mono.Nat.Pmp.Mappers;
|
||||||
|
using Mono.Nat.Upnp;
|
||||||
using Mono.Nat.Upnp.Mappers;
|
using Mono.Nat.Upnp.Mappers;
|
||||||
|
|
||||||
namespace Mono.Nat
|
namespace Mono.Nat
|
||||||
|
@ -55,8 +57,9 @@ namespace Mono.Nat
|
||||||
public static List<NatProtocol> EnabledProtocols { get; set; }
|
public static List<NatProtocol> EnabledProtocols { get; set; }
|
||||||
|
|
||||||
public static ILogger Logger { 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; }
|
get { return verbose; }
|
||||||
set { verbose = value; }
|
set { verbose = value; }
|
||||||
|
@ -153,32 +156,6 @@ namespace Mono.Nat
|
||||||
{
|
{
|
||||||
searching.Reset();
|
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
|
//checks if an IP address is a private address space as defined by RFC 1918
|
||||||
public static bool IsPrivateAddressSpace (IPAddress address)
|
public static bool IsPrivateAddressSpace (IPAddress address)
|
||||||
|
@ -217,11 +194,21 @@ namespace Mono.Nat
|
||||||
switch (protocol)
|
switch (protocol)
|
||||||
{
|
{
|
||||||
case NatProtocol.Upnp:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException("Unexpected protocol: " + protocol);
|
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
|
namespace Mono.Nat.Pmp.Mappers
|
||||||
{
|
{
|
||||||
internal class PmpMapper : Pmp, IMapper
|
internal class PmpMapper : IMapper
|
||||||
{
|
{
|
||||||
public event EventHandler<DeviceEventArgs> DeviceFound;
|
public event EventHandler<DeviceEventArgs> DeviceFound;
|
||||||
|
|
||||||
static PmpMapper()
|
|
||||||
{
|
|
||||||
CreateSocketsAndAddGateways();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Map(IPAddress gatewayAddress)
|
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)
|
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.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Mono.Nat.Pmp
|
namespace Mono.Nat.Pmp
|
||||||
{
|
{
|
||||||
|
@ -56,6 +57,12 @@ namespace Mono.Nat.Pmp
|
||||||
return publicAddress;
|
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)
|
public override IAsyncResult BeginCreatePortMap(Mapping mapping, AsyncCallback callback, object asyncState)
|
||||||
{
|
{
|
||||||
PortMapAsyncResult pmar = new PortMapAsyncResult (mapping.Protocol, mapping.PublicPort, PmpConstants.DefaultLeaseTime, callback, asyncState);
|
PortMapAsyncResult pmar = new PortMapAsyncResult (mapping.Protocol, mapping.PublicPort, PmpConstants.DefaultLeaseTime, callback, asyncState);
|
||||||
|
|
|
@ -40,7 +40,7 @@ using System.Linq;
|
||||||
|
|
||||||
namespace Mono.Nat
|
namespace Mono.Nat
|
||||||
{
|
{
|
||||||
internal class PmpSearcher : Pmp.Pmp, ISearcher
|
internal class PmpSearcher : ISearcher
|
||||||
{
|
{
|
||||||
static PmpSearcher instance = new PmpSearcher();
|
static PmpSearcher instance = new PmpSearcher();
|
||||||
|
|
||||||
|
@ -60,6 +60,83 @@ namespace Mono.Nat
|
||||||
CreateSocketsAndAddGateways();
|
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()
|
PmpSearcher()
|
||||||
{
|
{
|
||||||
timeout = 250;
|
timeout = 250;
|
||||||
|
|
|
@ -32,19 +32,20 @@ using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp.Mappers
|
namespace Mono.Nat.Upnp.Mappers
|
||||||
{
|
{
|
||||||
internal class UpnpMapper : Upnp, IMapper
|
internal class UpnpMapper : Upnp, IMapper
|
||||||
{
|
{
|
||||||
|
|
||||||
public event EventHandler<DeviceEventArgs> DeviceFound;
|
public event EventHandler<DeviceEventArgs> DeviceFound;
|
||||||
|
|
||||||
public UdpClient Client { get; set; }
|
public UdpClient Client { get; set; }
|
||||||
|
|
||||||
public UpnpMapper(ILogger logger)
|
public UpnpMapper(ILogger logger, IHttpClient httpClient)
|
||||||
: base(logger)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
//Bind to local port 1900 for ssdp responses
|
//Bind to local port 1900 for ssdp responses
|
||||||
Client = new UdpClient(1900);
|
Client = new UdpClient(1900);
|
||||||
|
@ -60,7 +61,7 @@ namespace Mono.Nat.Upnp.Mappers
|
||||||
new Thread(Receive).Start();
|
new Thread(Receive).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Receive()
|
public async void Receive()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -69,28 +70,36 @@ namespace Mono.Nat.Upnp.Mappers
|
||||||
{
|
{
|
||||||
IPAddress localAddress = ((IPEndPoint)Client.Client.LocalEndPoint).Address;
|
IPAddress localAddress = ((IPEndPoint)Client.Client.LocalEndPoint).Address;
|
||||||
byte[] data = Client.Receive(ref received);
|
byte[] data = Client.Receive(ref received);
|
||||||
Handle(localAddress, data, received);
|
|
||||||
|
await Handle(localAddress, data, received);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(IPAddress localAddres, byte[] response)
|
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
|
// 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.
|
// we should still be in a position to handle the next reply correctly.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UpnpNatDevice d = base.Handle(localAddress, response, endpoint);
|
var d = await base.Handle(localAddress, response, endpoint).ConfigureAwait(false);
|
||||||
d.GetServicesList(DeviceSetupComplete);
|
var result = await d.GetServicesList().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
DeviceSetupComplete(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error mapping port. Data string: {0}", ex, Encoding.UTF8.GetString(response));
|
Logger.ErrorException("Error mapping port. Data string: {0}", ex, Encoding.UTF8.GetString(response));
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -54,6 +55,10 @@ namespace Mono.Nat.Upnp
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public override HttpRequestOptions Encode()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public override System.Net.WebRequest Encode(out byte[] body)
|
public override System.Net.WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
|
@ -38,7 +39,7 @@ namespace Mono.Nat.Upnp
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public GetServicesMessage(string description, EndPoint hostAddress, ILogger logger)
|
public GetServicesMessage(string description, EndPoint hostAddress, ILogger logger)
|
||||||
:base(null)
|
: base(null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(description))
|
if (string.IsNullOrEmpty(description))
|
||||||
_logger.Warn("Description is null");
|
_logger.Warn("Description is null");
|
||||||
|
@ -51,6 +52,13 @@ namespace Mono.Nat.Upnp
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string Method
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "GET";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override WebRequest Encode(out byte[] body)
|
public override WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
|
@ -61,5 +69,16 @@ namespace Mono.Nat.Upnp
|
||||||
body = new byte[0];
|
body = new byte[0];
|
||||||
return req;
|
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.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -51,6 +52,25 @@ namespace Mono.Nat.Upnp
|
||||||
}
|
}
|
||||||
#endregion
|
#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)
|
public override WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ using System.Net;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -41,7 +42,20 @@ namespace Mono.Nat.Upnp
|
||||||
this.mapping = mapping;
|
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);
|
StringBuilder builder = new StringBuilder(256);
|
||||||
XmlWriter writer = CreateWriter(builder);
|
XmlWriter writer = CreateWriter(builder);
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -42,6 +43,10 @@ namespace Mono.Nat.Upnp
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public override HttpRequestOptions Encode()
|
||||||
|
{
|
||||||
|
return CreateRequest("GetExternalIPAddress", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
public override WebRequest Encode(out byte[] body)
|
public override WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -41,6 +42,17 @@ namespace Mono.Nat.Upnp
|
||||||
this.index = index;
|
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)
|
public override System.Net.WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder(128);
|
StringBuilder sb = new StringBuilder(128);
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -55,6 +56,19 @@ namespace Mono.Nat.Upnp
|
||||||
writer.Flush();
|
writer.Flush();
|
||||||
|
|
||||||
return CreateRequest("GetSpecificPortMappingEntry", sb.ToString(), out body);
|
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 System;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
internal class CreatePortMappingResponseMessage : MessageBase
|
internal class CreatePortMappingResponseMessage : MessageBase
|
||||||
|
@ -38,6 +40,11 @@ namespace Mono.Nat.Upnp
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public override HttpRequestOptions Encode()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public override System.Net.WebRequest Encode(out byte[] body)
|
public override System.Net.WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
internal class DeletePortMapResponseMessage : MessageBase
|
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)
|
public override System.Net.WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
|
|
|
@ -28,6 +28,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -45,6 +46,11 @@ namespace Mono.Nat.Upnp
|
||||||
this.externalIPAddress = IPAddress.Parse(ip);
|
this.externalIPAddress = IPAddress.Parse(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override HttpRequestOptions Encode()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public override WebRequest Encode(out byte[] body)
|
public override WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -28,6 +28,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -100,6 +101,11 @@ namespace Mono.Nat.Upnp
|
||||||
leaseDuration = Convert.ToInt32(data["NewLeaseDuration"].InnerText);
|
leaseDuration = Convert.ToInt32(data["NewLeaseDuration"].InnerText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override HttpRequestOptions Encode()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public override System.Net.WebRequest Encode(out byte[] body)
|
public override System.Net.WebRequest Encode(out byte[] body)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -31,6 +31,7 @@ using System.Net;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
{
|
{
|
||||||
|
@ -71,6 +72,32 @@ namespace Mono.Nat.Upnp
|
||||||
return req;
|
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)
|
public static MessageBase Decode(UpnpNatDevice device, string message)
|
||||||
{
|
{
|
||||||
XmlNode node;
|
XmlNode node;
|
||||||
|
@ -113,8 +140,14 @@ namespace Mono.Nat.Upnp
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract HttpRequestOptions Encode();
|
||||||
public abstract WebRequest Encode(out byte[] body);
|
public abstract WebRequest Encode(out byte[] body);
|
||||||
|
|
||||||
|
public virtual string Method
|
||||||
|
{
|
||||||
|
get { return "POST"; }
|
||||||
|
}
|
||||||
|
|
||||||
internal static void WriteFullElement(XmlWriter writer, string element, string value)
|
internal static void WriteFullElement(XmlWriter writer, string element, string value)
|
||||||
{
|
{
|
||||||
writer.WriteStartElement(element);
|
writer.WriteStartElement(element);
|
||||||
|
|
|
@ -36,6 +36,7 @@ using Mono.Nat.Upnp;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
|
@ -48,10 +49,12 @@ namespace Mono.Nat
|
||||||
|
|
||||||
private DateTime nextSearch;
|
private DateTime nextSearch;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly IHttpClient _httpClient;
|
||||||
|
|
||||||
public UpnpSearcher(ILogger logger)
|
public UpnpSearcher(ILogger logger, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Search()
|
public void Search()
|
||||||
|
@ -76,7 +79,7 @@ namespace Mono.Nat
|
||||||
prefix. */
|
prefix. */
|
||||||
|
|
||||||
// We have an internet gateway device now
|
// 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);
|
NatUtility.Log("Fetching service list: {0}", d.HostEndPoint);
|
||||||
OnDeviceFound(new DeviceEventArgs(d));
|
OnDeviceFound(new DeviceEventArgs(d));
|
||||||
|
|
|
@ -33,6 +33,8 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace Mono.Nat.Upnp
|
namespace Mono.Nat.Upnp
|
||||||
|
@ -40,13 +42,15 @@ namespace Mono.Nat.Upnp
|
||||||
internal class Upnp
|
internal class Upnp
|
||||||
{
|
{
|
||||||
protected readonly ILogger Logger;
|
protected readonly ILogger Logger;
|
||||||
|
protected readonly IHttpClient HttpClient;
|
||||||
|
|
||||||
public Upnp(ILogger logger)
|
public Upnp(ILogger logger, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
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
|
// Convert it to a string for easy parsing
|
||||||
string dataString = null;
|
string dataString = null;
|
||||||
|
@ -85,7 +89,8 @@ namespace Mono.Nat.Upnp
|
||||||
throw new NotSupportedException("Received non-supported device type");
|
throw new NotSupportedException("Received non-supported device type");
|
||||||
|
|
||||||
// We have an internet gateway device now
|
// 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 a new issue