diff options
| author | stefan <stefan@hegedues.at> | 2018-09-12 19:26:21 +0200 |
|---|---|---|
| committer | stefan <stefan@hegedues.at> | 2018-09-12 19:26:21 +0200 |
| commit | 48facb797ed912e4ea6b04b17d1ff190ac2daac4 (patch) | |
| tree | 8dae77a31670a888d733484cb17dd4077d5444e8 /Mono.Nat | |
| parent | c32d8656382a0eacb301692e0084377fc433ae9b (diff) | |
Update to 3.5.2 and .net core 2.1
Diffstat (limited to 'Mono.Nat')
| -rw-r--r-- | Mono.Nat/AsyncResults/AsyncResult.cs | 71 | ||||
| -rw-r--r-- | Mono.Nat/Enums/MapState.cs | 36 | ||||
| -rw-r--r-- | Mono.Nat/Exceptions/MappingException.cs | 68 | ||||
| -rw-r--r-- | Mono.Nat/ISearcher.cs | 6 | ||||
| -rw-r--r-- | Mono.Nat/Mono.Nat.csproj | 106 | ||||
| -rw-r--r-- | Mono.Nat/NatManager.cs | 86 | ||||
| -rw-r--r-- | Mono.Nat/NatUtility.cs | 233 | ||||
| -rw-r--r-- | Mono.Nat/Pmp/AsyncResults/PortMapAsyncResult.cs | 52 | ||||
| -rw-r--r-- | Mono.Nat/Pmp/PmpNatDevice.cs | 22 | ||||
| -rw-r--r-- | Mono.Nat/Pmp/PmpSearcher.cs (renamed from Mono.Nat/Pmp/Searchers/PmpSearcher.cs) | 49 | ||||
| -rw-r--r-- | Mono.Nat/Upnp/Messages/DiscoverDeviceMessage.cs | 60 | ||||
| -rw-r--r-- | Mono.Nat/Upnp/Messages/ErrorMessage.cs | 63 | ||||
| -rw-r--r-- | Mono.Nat/Upnp/Messages/Responses/CreatePortMappingResponseMessage.cs | 48 | ||||
| -rw-r--r-- | Mono.Nat/Upnp/Messages/UpnpMessage.cs | 6 | ||||
| -rw-r--r-- | Mono.Nat/Upnp/Searchers/UpnpSearcher.cs | 9 | ||||
| -rw-r--r-- | Mono.Nat/Upnp/UpnpNatDevice.cs | 48 |
16 files changed, 175 insertions, 788 deletions
diff --git a/Mono.Nat/AsyncResults/AsyncResult.cs b/Mono.Nat/AsyncResults/AsyncResult.cs deleted file mode 100644 index e98e7d7ca..000000000 --- a/Mono.Nat/AsyncResults/AsyncResult.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; - -namespace Mono.Nat -{ - internal class AsyncResult : IAsyncResult - { - private object asyncState; - private AsyncCallback callback; - private bool completedSynchronously; - private bool isCompleted; - private Exception storedException; - private ManualResetEvent waitHandle; - - public AsyncResult(AsyncCallback callback, object asyncState) - { - this.callback = callback; - this.asyncState = asyncState; - waitHandle = new ManualResetEvent(false); - } - - public object AsyncState - { - get { return asyncState; } - } - - public ManualResetEvent AsyncWaitHandle - { - get { return waitHandle; } - } - - WaitHandle IAsyncResult.AsyncWaitHandle - { - get { return waitHandle; } - } - - public bool CompletedSynchronously - { - get { return completedSynchronously; } - protected internal set { completedSynchronously = value; } - } - - public bool IsCompleted - { - get { return isCompleted; } - protected internal set { isCompleted = value; } - } - - public Exception StoredException - { - get { return storedException; } - } - - public void Complete() - { - Complete(storedException); - } - - public void Complete(Exception ex) - { - storedException = ex; - isCompleted = true; - waitHandle.Set(); - - if (callback != null) - callback(this); - } - } -} diff --git a/Mono.Nat/Enums/MapState.cs b/Mono.Nat/Enums/MapState.cs deleted file mode 100644 index 5ed2abd8f..000000000 --- a/Mono.Nat/Enums/MapState.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// 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; - -namespace Mono.Nat -{ - public enum MapState - { - AlreadyMapped, - Available - } -}
\ No newline at end of file diff --git a/Mono.Nat/Exceptions/MappingException.cs b/Mono.Nat/Exceptions/MappingException.cs deleted file mode 100644 index 9c0c4f122..000000000 --- a/Mono.Nat/Exceptions/MappingException.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// 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; - -namespace Mono.Nat -{ - public class MappingException : Exception - { - private int errorCode; - private string errorText; - - public int ErrorCode - { - get { return this.errorCode; } - } - - public string ErrorText - { - get { return this.errorText; } - } - - public MappingException() - : base() - { - } - - public MappingException(string message) - : base(message) - { - } - - public MappingException(int errorCode, string errorText) - : base (string.Format ("Error {0}: {1}", errorCode, errorText)) - { - this.errorCode = errorCode; - this.errorText = errorText; - } - - public MappingException(string message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/Mono.Nat/ISearcher.cs b/Mono.Nat/ISearcher.cs index 51042bf27..fff7e8d75 100644 --- a/Mono.Nat/ISearcher.cs +++ b/Mono.Nat/ISearcher.cs @@ -33,20 +33,14 @@ using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.Net; -using System.Threading.Tasks; namespace Mono.Nat { - public delegate void NatDeviceCallback(INatDevice device); - internal interface ISearcher { event EventHandler<DeviceEventArgs> DeviceFound; - event EventHandler<DeviceEventArgs> DeviceLost; void Search(); void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint); - DateTime NextSearch { get; } - NatProtocol Protocol { get; } } } diff --git a/Mono.Nat/Mono.Nat.csproj b/Mono.Nat/Mono.Nat.csproj index 426824f0d..4de89290e 100644 --- a/Mono.Nat/Mono.Nat.csproj +++ b/Mono.Nat/Mono.Nat.csproj @@ -1,97 +1,17 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{CB7F2326-6497-4A3D-BA03-48513B17A7BE}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>Mono.Nat</RootNamespace> - <AssemblyName>Mono.Nat</AssemblyName> - <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <TargetFrameworkProfile /> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Data" /> - <Reference Include="System.Net.Http" /> - <Reference Include="System.Xml" /> - </ItemGroup> - <ItemGroup> - <Compile Include="..\SharedVersion.cs"> - <Link>Properties\SharedVersion.cs</Link> - </Compile> - <Compile Include="AbstractNatDevice.cs" /> - <Compile Include="AsyncResults\AsyncResult.cs" /> - <Compile Include="Enums\MapState.cs" /> - <Compile Include="Enums\ProtocolType.cs" /> - <Compile Include="EventArgs\DeviceEventArgs.cs" /> - <Compile Include="Exceptions\MappingException.cs" /> - <Compile Include="INatDevice.cs" /> - <Compile Include="ISearcher.cs" /> - <Compile Include="Mapping.cs" /> - <Compile Include="NatProtocol.cs" /> - <Compile Include="NatUtility.cs" /> - <Compile Include="Pmp\AsyncResults\PortMapAsyncResult.cs" /> - <Compile Include="Pmp\PmpConstants.cs" /> - <Compile Include="Pmp\PmpNatDevice.cs" /> - <Compile Include="Pmp\Searchers\PmpSearcher.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Upnp\Messages\DiscoverDeviceMessage.cs" /> - <Compile Include="Upnp\Messages\ErrorMessage.cs" /> - <Compile Include="Upnp\Messages\GetServicesMessage.cs" /> - <Compile Include="Upnp\Messages\Requests\CreatePortMappingMessage.cs" /> - <Compile Include="Upnp\Messages\Responses\CreatePortMappingResponseMessage.cs" /> - <Compile Include="Upnp\Messages\UpnpMessage.cs" /> - <Compile Include="Upnp\Searchers\UpnpSearcher.cs" /> - <Compile Include="Upnp\UpnpNatDevice.cs" /> - </ItemGroup> +<Project Sdk="Microsoft.NET.Sdk"> + <ItemGroup> - <Folder Include="Upnp\AsyncResults\" /> + <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> + <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> </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> - </ProjectReference> - <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> - <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> - <Name>MediaBrowser.Model</Name> - </ProjectReference> + <Compile Include="..\SharedVersion.cs"/> </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project>
\ No newline at end of file + + <PropertyGroup> + <TargetFramework>netcoreapp2.1</TargetFramework> + <GenerateAssemblyInfo>false</GenerateAssemblyInfo> + </PropertyGroup> + +</Project> diff --git a/Mono.Nat/NatManager.cs b/Mono.Nat/NatManager.cs new file mode 100644 index 000000000..752fd0416 --- /dev/null +++ b/Mono.Nat/NatManager.cs @@ -0,0 +1,86 @@ +using System; +using System.Net; +using System.Collections.Generic; +using System.Threading.Tasks; +using MediaBrowser.Common.Net; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Logging; +using System.Linq; + +namespace Mono.Nat +{ + public class NatManager : IDisposable + { + public event EventHandler<DeviceEventArgs> DeviceFound; + + private List<ISearcher> controllers = new List<ISearcher>(); + + private ILogger Logger; + private IHttpClient HttpClient; + + public NatManager(ILogger logger, IHttpClient httpClient) + { + Logger = logger; + HttpClient = httpClient; + } + + private object _runSyncLock = new object(); + public void StartDiscovery() + { + lock (_runSyncLock) + { + if (controllers.Count > 0) + { + return; + } + + controllers.Add(new PmpSearcher(Logger)); + + foreach (var searcher in controllers) + { + searcher.DeviceFound += Searcher_DeviceFound; + } + } + } + + public void StopDiscovery() + { + lock (_runSyncLock) + { + var disposables = controllers.OfType<IDisposable>().ToList(); + controllers.Clear(); + + foreach (var disposable in disposables) + { + disposable.Dispose(); + } + } + } + + public void Dispose() + { + StopDiscovery(); + } + + public Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol) + { + switch (protocol) + { + case NatProtocol.Upnp: + var searcher = new UpnpSearcher(Logger, HttpClient); + searcher.DeviceFound += Searcher_DeviceFound; + return searcher.Handle(localAddress, deviceInfo, endpoint); + default: + throw new ArgumentException("Unexpected protocol: " + protocol); + } + } + + private void Searcher_DeviceFound(object sender, DeviceEventArgs e) + { + if (DeviceFound != null) + { + DeviceFound(sender, e); + } + } + } +} diff --git a/Mono.Nat/NatUtility.cs b/Mono.Nat/NatUtility.cs deleted file mode 100644 index bf703e399..000000000 --- a/Mono.Nat/NatUtility.cs +++ /dev/null @@ -1,233 +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.Net; -using System.Net.Sockets; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using System.Net.NetworkInformation; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Logging; - -namespace Mono.Nat -{ - public static class NatUtility - { - public static event EventHandler<DeviceEventArgs> DeviceFound; - public static event EventHandler<DeviceEventArgs> DeviceLost; - - private static List<ISearcher> controllers; - private static bool verbose; - - public static List<NatProtocol> EnabledProtocols { get; set; } - - public static ILogger Logger { get; set; } - public static IHttpClient HttpClient { get; set; } - - public static bool Verbose - { - get { return verbose; } - set { verbose = value; } - } - - static NatUtility() - { - EnabledProtocols = new List<NatProtocol> - { - NatProtocol.Pmp - }; - - controllers = new List<ISearcher>(); - controllers.Add(PmpSearcher.Instance); - - controllers.ForEach(searcher => - { - searcher.DeviceFound += (sender, args) => - { - if (DeviceFound != null) - DeviceFound(sender, args); - }; - searcher.DeviceLost += (sender, args) => - { - if (DeviceLost != null) - DeviceLost(sender, args); - }; - }); - } - - internal static void Log(string format, params object[] args) - { - var logger = Logger; - if (logger != null) - logger.Debug(format, args); - } - - private static async Task SearchAndListen(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - try - { - if (EnabledProtocols.Contains(PmpSearcher.Instance.Protocol)) - { - await Receive(PmpSearcher.Instance, PmpSearcher.sockets).ConfigureAwait(false); - } - - foreach (ISearcher s in controllers) - { - if (s.NextSearch < DateTime.Now && EnabledProtocols.Contains(s.Protocol)) - { - Log("Searching for: {0}", s.GetType().Name); - s.Search(); - } - } - } - catch (Exception e) - { - - } - await Task.Delay(100).ConfigureAwait(false); - } - } - - static async Task Receive(ISearcher searcher, List<UdpClient> clients) - { - foreach (UdpClient client in clients) - { - if (client.Available > 0) - { - IPAddress localAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address; - var result = await client.ReceiveAsync().ConfigureAwait(false); - var data = result.Buffer; - var received = result.RemoteEndPoint; - searcher.Handle(localAddress, data, received); - } - } - } - - private static CancellationTokenSource _currentCancellationTokenSource; - private static object _runSyncLock = new object(); - public static void StartDiscovery() - { - lock (_runSyncLock) - { - if (_currentCancellationTokenSource == null) - { - return; - } - - var tokenSource = new CancellationTokenSource(); - - _currentCancellationTokenSource = tokenSource; - //Task.Factory.StartNew(() => SearchAndListen(tokenSource.Token), tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); - } - } - - public static void StopDiscovery() - { - lock (_runSyncLock) - { - var tokenSource = _currentCancellationTokenSource; - - if (tokenSource != null) - { - try - { - tokenSource.Cancel(); - tokenSource.Dispose(); - } - catch - { - - } - - _currentCancellationTokenSource = null; - } - } - } - - //checks if an IP address is a private address space as defined by RFC 1918 - public static bool IsPrivateAddressSpace(IPAddress address) - { - byte[] ba = address.GetAddressBytes(); - - switch ((int)ba[0]) - { - case 10: - return true; //10.x.x.x - case 172: - return ((int)ba[1] & 16) != 0; //172.16-31.x.x - case 192: - return (int)ba[1] == 168; //192.168.x.x - default: - return false; - } - } - - public static void Handle(IPAddress localAddress, byte[] response, IPEndPoint endpoint, NatProtocol protocol) - { - switch (protocol) - { - case NatProtocol.Upnp: - //UpnpSearcher.Instance.Handle(localAddress, response, endpoint); - break; - case NatProtocol.Pmp: - PmpSearcher.Instance.Handle(localAddress, response, endpoint); - break; - default: - throw new ArgumentException("Unexpected protocol: " + protocol); - } - } - - public static async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint endpoint, NatProtocol protocol) - { - switch (protocol) - { - case NatProtocol.Upnp: - var searcher = new UpnpSearcher(Logger, HttpClient); - searcher.DeviceFound += Searcher_DeviceFound; - await searcher.Handle(localAddress, deviceInfo, endpoint).ConfigureAwait(false); - break; - default: - throw new ArgumentException("Unexpected protocol: " + protocol); - } - } - - private static void Searcher_DeviceFound(object sender, DeviceEventArgs e) - { - if (DeviceFound != null) - { - DeviceFound(sender, e); - } - } - } -} diff --git a/Mono.Nat/Pmp/AsyncResults/PortMapAsyncResult.cs b/Mono.Nat/Pmp/AsyncResults/PortMapAsyncResult.cs deleted file mode 100644 index c8ccf5435..000000000 --- a/Mono.Nat/Pmp/AsyncResults/PortMapAsyncResult.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Authors: -// Ben Motmans <ben.motmans@gmail.com> -// -// Copyright (C) 2007 Ben Motmans -// -// 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; - -namespace Mono.Nat.Pmp -{ - internal class PortMapAsyncResult : AsyncResult - { - private Mapping mapping; - - internal PortMapAsyncResult (Mapping mapping, AsyncCallback callback, object asyncState) - : base (callback, asyncState) - { - this.mapping = mapping; - } - - internal PortMapAsyncResult (Protocol protocol, int port, int lifetime, AsyncCallback callback, object asyncState) - : base (callback, asyncState) - { - this.mapping = new Mapping (protocol, port, port, lifetime); - } - - internal Mapping Mapping - { - get { return mapping; } - } - } -} diff --git a/Mono.Nat/Pmp/PmpNatDevice.cs b/Mono.Nat/Pmp/PmpNatDevice.cs index fb45b365b..2ef66fdbb 100644 --- a/Mono.Nat/Pmp/PmpNatDevice.cs +++ b/Mono.Nat/Pmp/PmpNatDevice.cs @@ -32,6 +32,7 @@ using System.Threading; using System.Collections.Generic; using System.Threading.Tasks; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Logging; namespace Mono.Nat.Pmp { @@ -39,11 +40,18 @@ namespace Mono.Nat.Pmp { private IPAddress localAddress; private IPAddress publicAddress; + private ILogger _logger; - internal PmpNatDevice(IPAddress localAddress, IPAddress publicAddress) + internal PmpNatDevice(IPAddress localAddress, IPAddress publicAddress, ILogger logger) { + if (localAddress == null) + { + throw new ArgumentNullException("localAddress"); + } + this.localAddress = localAddress; this.publicAddress = publicAddress; + _logger = logger; } public override IPAddress LocalAddress @@ -97,8 +105,7 @@ namespace Mono.Nat.Pmp while (attempt < PmpConstants.RetryAttempts) { - await udpClient.SendAsync(buffer, buffer.Length, - new IPEndPoint(LocalAddress, PmpConstants.ServerPort)); + await udpClient.SendAsync(buffer, buffer.Length, new IPEndPoint(LocalAddress, PmpConstants.ServerPort)); if (attempt == 0) { @@ -125,9 +132,8 @@ namespace Mono.Nat.Pmp mapping.Protocol, mapping.PrivatePort, e.Message); - NatUtility.Log(message); - var pmpException = e as MappingException; - throw new MappingException(message, pmpException); + _logger.Debug(message); + throw e; } return mapping; @@ -177,7 +183,7 @@ namespace Mono.Nat.Pmp }; var errorMsg = errors[resultCode]; - NatUtility.Log("Error in CreatePortMapListen: " + errorMsg); + _logger.Debug("Error in CreatePortMapListen: " + errorMsg); return; } @@ -192,7 +198,7 @@ namespace Mono.Nat.Pmp } catch (Exception ex) { - NatUtility.Logger.ErrorException("Error in CreatePortMapListen", ex); + _logger.ErrorException("Error in CreatePortMapListen", ex); return; } } diff --git a/Mono.Nat/Pmp/Searchers/PmpSearcher.cs b/Mono.Nat/Pmp/PmpSearcher.cs index 2836071d0..180fb48d7 100644 --- a/Mono.Nat/Pmp/Searchers/PmpSearcher.cs +++ b/Mono.Nat/Pmp/PmpSearcher.cs @@ -37,33 +37,44 @@ using Mono.Nat.Pmp; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using System.Linq; namespace Mono.Nat { - internal class PmpSearcher : ISearcher + internal class PmpSearcher : ISearcher, IDisposable { - static PmpSearcher instance = new PmpSearcher(); + private ILogger _logger; - - public static PmpSearcher Instance - { - get { return instance; } - } - - private int timeout; + private int timeout = 250; private DateTime nextSearch; public event EventHandler<DeviceEventArgs> DeviceFound; - public event EventHandler<DeviceEventArgs> DeviceLost; - static PmpSearcher() + public PmpSearcher(ILogger logger) { + _logger = logger; + CreateSocketsAndAddGateways(); } - public static List<UdpClient> sockets; - protected static Dictionary<UdpClient, List<IPEndPoint>> gatewayLists; + public void Dispose() + { + var list = sockets.ToList(); + sockets.Clear(); + + foreach (var s in list) + { + using (s) + { + s.Close(); + } + } + } + + private List<UdpClient> sockets; + private Dictionary<UdpClient, List<IPEndPoint>> gatewayLists; - internal static void CreateSocketsAndAddGateways() + private void CreateSocketsAndAddGateways() { sockets = new List<UdpClient>(); gatewayLists = new Dictionary<UdpClient, List<IPEndPoint>>(); @@ -137,11 +148,6 @@ namespace Mono.Nat } } - PmpSearcher() - { - timeout = 250; - } - public async void Search() { foreach (UdpClient s in sockets) @@ -202,12 +208,13 @@ namespace Mono.Nat return; int errorcode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(response, 2)); if (errorcode != 0) - NatUtility.Log("Non zero error: {0}", errorcode); + _logger.Debug("Non zero error: {0}", errorcode); IPAddress publicIp = new IPAddress(new byte[] { response[8], response[9], response[10], response[11] }); nextSearch = DateTime.Now.AddMinutes(5); timeout = 250; - OnDeviceFound(new DeviceEventArgs(new PmpNatDevice(endpoint.Address, publicIp))); + + OnDeviceFound(new DeviceEventArgs(new PmpNatDevice(endpoint.Address, publicIp, _logger))); } public DateTime NextSearch diff --git a/Mono.Nat/Upnp/Messages/DiscoverDeviceMessage.cs b/Mono.Nat/Upnp/Messages/DiscoverDeviceMessage.cs deleted file mode 100644 index 87f5835a6..000000000 --- a/Mono.Nat/Upnp/Messages/DiscoverDeviceMessage.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// 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.Net; -using System.Text; - -namespace Mono.Nat.Upnp -{ - internal static class DiscoverDeviceMessage - { - /// <summary> - /// The message sent to discover all uPnP devices on the network - /// </summary> - /// <returns></returns> - public static byte[] EncodeSSDP() - { - string s = "M-SEARCH * HTTP/1.1\r\n" - + "HOST: 239.255.255.250:1900\r\n" - + "MAN: \"ssdp:discover\"\r\n" - + "MX: 3\r\n" - + "ST: ssdp:all\r\n\r\n"; - return UTF8Encoding.ASCII.GetBytes(s); - } - - public static byte[] EncodeUnicast(IPAddress gatewayAddress) - { - //Format obtained from http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf pg 31 - //This method only works with upnp 1.1 routers... unfortunately - string s = "M-SEARCH * HTTP/1.1\r\n" - + "HOST: " + gatewayAddress + ":1900\r\n" - + "MAN: \"ssdp:discover\"\r\n" - + "ST: ssdp:all\r\n\r\n"; - //+ "USER-AGENT: unix/5.1 UPnP/1.1 MyProduct/1.0\r\n\r\n"; - return UTF8Encoding.ASCII.GetBytes(s); - } - } -} diff --git a/Mono.Nat/Upnp/Messages/ErrorMessage.cs b/Mono.Nat/Upnp/Messages/ErrorMessage.cs deleted file mode 100644 index 7c0c44d8e..000000000 --- a/Mono.Nat/Upnp/Messages/ErrorMessage.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// 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 MediaBrowser.Common.Net; - -namespace Mono.Nat.Upnp -{ - internal class ErrorMessage : MessageBase - { - #region Member Variables - public string Description - { - get { return this.description; } - } - private string description; - - public int ErrorCode - { - get { return this.errorCode; } - } - private int errorCode; - #endregion - - - #region Constructors - public ErrorMessage(int errorCode, string description) - :base(null) - { - this.description = description; - this.errorCode = errorCode; - } - #endregion - - public override HttpRequestOptions Encode() - { - throw new NotImplementedException(); - } - } -} diff --git a/Mono.Nat/Upnp/Messages/Responses/CreatePortMappingResponseMessage.cs b/Mono.Nat/Upnp/Messages/Responses/CreatePortMappingResponseMessage.cs deleted file mode 100644 index 48776dd6f..000000000 --- a/Mono.Nat/Upnp/Messages/Responses/CreatePortMappingResponseMessage.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Authors: -// Alan McGovern alan.mcgovern@gmail.com -// -// Copyright (C) 2006 Alan McGovern -// -// 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 MediaBrowser.Common.Net; - -namespace Mono.Nat.Upnp -{ - internal class CreatePortMappingResponseMessage : MessageBase - { - #region Constructors - public CreatePortMappingResponseMessage() - :base(null) - { - } - #endregion - - public override HttpRequestOptions Encode() - { - throw new NotImplementedException(); - } - } -} diff --git a/Mono.Nat/Upnp/Messages/UpnpMessage.cs b/Mono.Nat/Upnp/Messages/UpnpMessage.cs index b0264fc4a..37a46e47d 100644 --- a/Mono.Nat/Upnp/Messages/UpnpMessage.cs +++ b/Mono.Nat/Upnp/Messages/UpnpMessage.cs @@ -37,7 +37,6 @@ namespace Mono.Nat.Upnp { internal abstract class MessageBase { - internal static readonly CultureInfo Culture = CultureInfo.InvariantCulture; protected UpnpNatDevice device; protected MessageBase(UpnpNatDevice device) @@ -48,7 +47,6 @@ namespace Mono.Nat.Upnp 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.LogErrors = false; @@ -84,14 +82,14 @@ namespace Mono.Nat.Upnp get { return "POST"; } } - internal static void WriteFullElement(XmlWriter writer, string element, string value) + protected void WriteFullElement(XmlWriter writer, string element, string value) { writer.WriteStartElement(element); writer.WriteString(value); writer.WriteEndElement(); } - internal static XmlWriter CreateWriter(StringBuilder sb) + protected XmlWriter CreateWriter(StringBuilder sb) { XmlWriterSettings settings = new XmlWriterSettings(); settings.ConformanceLevel = ConformanceLevel.Fragment; diff --git a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs index d9b16dd81..7c1e89d3b 100644 --- a/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs +++ b/Mono.Nat/Upnp/Searchers/UpnpSearcher.cs @@ -46,7 +46,6 @@ namespace Mono.Nat internal class UpnpSearcher : ISearcher { public event EventHandler<DeviceEventArgs> DeviceFound; - public event EventHandler<DeviceEventArgs> DeviceLost; private DateTime nextSearch; private readonly ILogger _logger; @@ -64,8 +63,11 @@ namespace Mono.Nat public async Task Handle(IPAddress localAddress, UpnpDeviceInfo deviceInfo, 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. + if (localAddress == null) + { + throw new ArgumentNullException("localAddress"); + } + try { /* For UPnP Port Mapping we need ot find either WANPPPConnection or WANIPConnection. @@ -82,7 +84,6 @@ namespace Mono.Nat // We have an internet gateway device now UpnpNatDevice d = new UpnpNatDevice(localAddress, deviceInfo, endpoint, string.Empty, _logger, _httpClient); - NatUtility.Log("Fetching service list: {0}", d.HostEndPoint); await d.GetServicesList().ConfigureAwait(false); OnDeviceFound(new DeviceEventArgs(d)); diff --git a/Mono.Nat/Upnp/UpnpNatDevice.cs b/Mono.Nat/Upnp/UpnpNatDevice.cs index fda990fa8..cae7f5fc8 100644 --- a/Mono.Nat/Upnp/UpnpNatDevice.cs +++ b/Mono.Nat/Upnp/UpnpNatDevice.cs @@ -56,6 +56,11 @@ namespace Mono.Nat.Upnp internal UpnpNatDevice(IPAddress localAddress, UpnpDeviceInfo deviceInfo, IPEndPoint hostEndPoint, string serviceType, ILogger logger, IHttpClient httpClient) { + if (localAddress == null) + { + throw new ArgumentNullException("localAddress"); + } + this.LastSeen = DateTime.Now; this.localAddress = localAddress; @@ -72,21 +77,19 @@ namespace Mono.Nat.Upnp // Are we going to get addresses with the "http://" attached? if (locationDetails.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) { - NatUtility.Log("Found device at: {0}", locationDetails); + _logger.Debug("Found device at: {0}", locationDetails); // This bit strings out the "http://" from the string locationDetails = locationDetails.Substring(7); this.hostEndPoint = hostEndPoint; - NatUtility.Log("Parsed device as: {0}", this.hostEndPoint.ToString()); - // The service description URL is the remainder of the "locationDetails" string. The bit that was originally after the ip // and port information this.serviceDescriptionUrl = locationDetails.Substring(locationDetails.IndexOf('/')); } else { - NatUtility.Log("Couldn't decode address. Please send following string to the developer: "); + _logger.Debug("Couldn't decode address. Please send following string to the developer: "); } } @@ -113,7 +116,7 @@ namespace Mono.Nat.Upnp { if (response.StatusCode != HttpStatusCode.OK) { - NatUtility.Log("{0}: Couldn't get services list: {1}", HostEndPoint, response.StatusCode); + _logger.Debug("{0}: Couldn't get services list: {1}", HostEndPoint, response.StatusCode); return; // FIXME: This the best thing to do?? } @@ -136,12 +139,11 @@ namespace Mono.Nat.Upnp { return; } - NatUtility.Log("{0}: Couldn't parse services list", HostEndPoint); + _logger.Debug("{0}: Couldn't parse services list", HostEndPoint); System.Threading.Thread.Sleep(10); } } - NatUtility.Log("{0}: Parsed services list", HostEndPoint); XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable); ns.AddNamespace("ns", "urn:schemas-upnp-org:device-1-0"); XmlNodeList nodes = xmldoc.SelectNodes("//*/ns:serviceList", ns); @@ -153,31 +155,35 @@ namespace Mono.Nat.Upnp { //If the service is a WANIPConnection, then we have what we want string type = service["serviceType"].InnerText; - NatUtility.Log("{0}: Found service: {1}", HostEndPoint, type); - StringComparison c = StringComparison.OrdinalIgnoreCase; + _logger.Debug("{0}: Found service: {1}", HostEndPoint, type); + // TODO: Add support for version 2 of UPnP. - if (type.Equals("urn:schemas-upnp-org:service:WANPPPConnection:1", c) || - type.Equals("urn:schemas-upnp-org:service:WANIPConnection:1", c)) + if (string.Equals(type, "urn:schemas-upnp-org:service:WANPPPConnection:1", StringComparison.OrdinalIgnoreCase) || + string.Equals(type, "urn:schemas-upnp-org:service:WANIPConnection:1", StringComparison.OrdinalIgnoreCase)) { this.controlUrl = service["controlURL"].InnerText; - NatUtility.Log("{0}: Found upnp service at: {1}", HostEndPoint, controlUrl); - try + _logger.Debug("{0}: Found upnp service at: {1}", HostEndPoint, controlUrl); + + Uri u; + if (Uri.TryCreate(controlUrl, UriKind.RelativeOrAbsolute, out u)) { - Uri u = new Uri(controlUrl); if (u.IsAbsoluteUri) { EndPoint old = hostEndPoint; - this.hostEndPoint = new IPEndPoint(IPAddress.Parse(u.Host), u.Port); - NatUtility.Log("{0}: Absolute URI detected. Host address is now: {1}", old, HostEndPoint); - this.controlUrl = controlUrl.Substring(u.GetLeftPart(UriPartial.Authority).Length); - NatUtility.Log("{0}: New control url: {1}", HostEndPoint, controlUrl); + IPAddress parsedHostIpAddress; + if (IPAddress.TryParse(u.Host, out parsedHostIpAddress)) + { + this.hostEndPoint = new IPEndPoint(parsedHostIpAddress, u.Port); + //_logger.Debug("{0}: Absolute URI detected. Host address is now: {1}", old, HostEndPoint); + this.controlUrl = controlUrl.Substring(u.GetLeftPart(UriPartial.Authority).Length); + //_logger.Debug("{0}: New control url: {1}", HostEndPoint, controlUrl); + } } } - catch + else { - NatUtility.Log("{0}: Assuming control Uri is relative: {1}", HostEndPoint, controlUrl); + _logger.Debug("{0}: Assuming control Uri is relative: {1}", HostEndPoint, controlUrl); } - NatUtility.Log("{0}: Handshake Complete", HostEndPoint); return; } } |
