mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-21 17:44:43 +01:00
make dlna project portable
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Implemented by components that can create a platform specific UDP socket implementation, and wrap it in the cross platform <see cref="IUdpSocket"/> interface.
|
||||
/// </summary>
|
||||
public interface ISocketFactory
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Createa a new unicast socket using the specified local port number.
|
||||
/// </summary>
|
||||
/// <param name="localPort">The local port to bind to.</param>
|
||||
/// <returns>A <see cref="IUdpSocket"/> implementation.</returns>
|
||||
IUdpSocket CreateUdpSocket(int localPort);
|
||||
|
||||
/// <summary>
|
||||
/// Createa a new multicast socket using the specified multicast IP address, multicast time to live and local port.
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">The multicast IP address to bind to.</param>
|
||||
/// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param>
|
||||
/// <param name="localPort">The local port to bind to.</param>
|
||||
/// <returns>A <see cref="IUdpSocket"/> implementation.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "ip", Justification="IP is a well known and understood abbreviation and the full name is excessive.")]
|
||||
IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
@@ -44,8 +45,8 @@ namespace Rssdp.Infrastructure
|
||||
/// Sends a message to a particular address (uni or multicast) and port.
|
||||
/// </summary>
|
||||
/// <param name="messageData">A byte array containing the data to send.</param>
|
||||
/// <param name="destination">A <see cref="UdpEndPoint"/> representing the destination address for the data. Can be either a multicast or unicast destination.</param>
|
||||
Task SendMessage(byte[] messageData, UdpEndPoint destination);
|
||||
/// <param name="destination">A <see cref="IpEndPointInfo"/> representing the destination address for the data. Can be either a multicast or unicast destination.</param>
|
||||
Task SendMessage(byte[] messageData, IpEndPointInfo destination);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to the SSDP multicast address and port.
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a common interface across platforms for UDP sockets used by this SSDP implementation.
|
||||
/// </summary>
|
||||
public interface IUdpSocket : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for and returns the next UDP message sent to this socket (uni or multicast).
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
System.Threading.Tasks.Task<ReceivedUdpData> ReceiveAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Sends a UDP message to a particular end point (uni or multicast).
|
||||
/// </summary>
|
||||
/// <param name="messageData">The data to send.</param>
|
||||
/// <param name="endPoint">The <see cref="UdpEndPoint"/> providing the address and port to send to.</param>
|
||||
Task SendTo(byte[] messageData, UdpEndPoint endPoint);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,30 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("RSSDP2")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RSSDP")]
|
||||
[assembly: AssemblyProduct("RSSDP2")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("c227adb7-e256-4e70-a8b9-22b9e0cf4f55")]
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<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>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{67F9D3A8-F71E-4428-913F-C37AE82CDB24}</ProjectGuid>
|
||||
<ProjectGuid>{21002819-C39A-4D3E-BE83-2A276A77FB1F}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Rssdp</RootNamespace>
|
||||
<AssemblyName>Rssdp.Portable</AssemblyName>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile44</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<RootNamespace>RSSDP</RootNamespace>
|
||||
<AssemblyName>RSSDP</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>1c5b2aa5</NuGetPackageImportStamp>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -27,79 +24,57 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>..\RssdpRuleset.ruleset</CodeAnalysisRuleSet>
|
||||
<DocumentationFile>bin\Debug\Rssdp.Portable.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\lib\portable-net45+win+wpa81+wp80\</OutputPath>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>..\RssdpRuleset.ruleset</CodeAnalysisRuleSet>
|
||||
<DocumentationFile>..\lib\portable-net45+win+wpa81+wp80\Rssdp.Portable.XML</DocumentationFile>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\AssemblyInfoCommon.cs">
|
||||
<Link>Properties\AssemblyInfoCommon.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="CustomHttpHeaders.cs" />
|
||||
<Compile Include="DeviceAvailableEventArgs.cs" />
|
||||
<Compile Include="DeviceEventArgs.cs" />
|
||||
<Compile Include="DeviceUnavailableEventArgs.cs" />
|
||||
<Compile Include="DiscoveredSsdpDevice.cs" />
|
||||
<Compile Include="DisposableManagedObjectBase.cs" />
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="HttpParserBase.cs" />
|
||||
<Compile Include="HttpRequestParser.cs" />
|
||||
<Compile Include="HttpResponseParser.cs" />
|
||||
<Compile Include="IEnumerableExtensions.cs" />
|
||||
<Compile Include="ISsdpCommunicationsServer.cs" />
|
||||
<Compile Include="ISsdpDeviceLocator.cs" />
|
||||
<Compile Include="ISsdpDevicePublisher.cs" />
|
||||
<Compile Include="IUPnPDeviceValidator.cs" />
|
||||
<Compile Include="ReadOnlyEnumerable.cs" />
|
||||
<Compile Include="SsdpDeviceExtensions.cs" />
|
||||
<Compile Include="SsdpDeviceLocatorBase.cs" />
|
||||
<Compile Include="DiscoveredSsdpDevice.cs" />
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="HttpRequestParser.cs" />
|
||||
<Compile Include="HttpResponseParser.cs" />
|
||||
<Compile Include="ISocketFactory.cs" />
|
||||
<Compile Include="IUdpSocket.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReceivedUdpData.cs" />
|
||||
<Compile Include="ReadOnlyEnumerable.cs" />
|
||||
<Compile Include="RequestReceivedEventArgs.cs" />
|
||||
<Compile Include="ResponseReceivedEventArgs.cs" />
|
||||
<Compile Include="SsdpCommunicationsServer.cs" />
|
||||
<Compile Include="SsdpConstants.cs" />
|
||||
<Compile Include="SsdpDevice.cs" />
|
||||
<Compile Include="SsdpDeviceExtensions.cs" />
|
||||
<Compile Include="SsdpDeviceIcon.cs" />
|
||||
<Compile Include="SsdpDeviceLocator.cs" />
|
||||
<Compile Include="SsdpDeviceLocatorBase.cs" />
|
||||
<Compile Include="SsdpDeviceProperties.cs" />
|
||||
<Compile Include="SsdpDeviceProperty.cs" />
|
||||
<Compile Include="SsdpDevicePublisher.cs" />
|
||||
<Compile Include="SsdpDevicePublisherBase.cs" />
|
||||
<Compile Include="SsdpEmbeddedDevice.cs" />
|
||||
<Compile Include="SsdpRootDevice.cs" />
|
||||
<Compile Include="UdpEndPoint.cs" />
|
||||
<Compile Include="UPnP10DeviceValidator.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CodeAnalysisDictionary Include="..\Shared\CodeAnalysisDictionary.xml">
|
||||
<Link>Properties\CodeAnalysisDictionary.xml</Link>
|
||||
<SubType>Designer</SubType>
|
||||
</CodeAnalysisDictionary>
|
||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
|
||||
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
|
||||
<Name>MediaBrowser.Model</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.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">
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>c227adb7-e256-4e70-a8b9-22b9e0cf4f55</ProjectGuid>
|
||||
<RootNamespace>RSSDP</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the sockets wrapper to hold raw data received from a UDP socket.
|
||||
/// </summary>
|
||||
public sealed class ReceivedUdpData
|
||||
{
|
||||
/// <summary>
|
||||
/// The buffer to place received data into.
|
||||
/// </summary>
|
||||
public byte[] Buffer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes received.
|
||||
/// </summary>
|
||||
public int ReceivedBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="UdpEndPoint"/> the data was received from.
|
||||
/// </summary>
|
||||
public UdpEndPoint ReceivedFrom { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
@@ -17,7 +18,7 @@ namespace Rssdp.Infrastructure
|
||||
#region Fields
|
||||
|
||||
private readonly HttpRequestMessage _Message;
|
||||
private readonly UdpEndPoint _ReceivedFrom;
|
||||
private readonly IpEndPointInfo _ReceivedFrom;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -28,7 +29,7 @@ namespace Rssdp.Infrastructure
|
||||
/// </summary>
|
||||
/// <param name="message">The <see cref="HttpRequestMessage"/> that was received.</param>
|
||||
/// <param name="receivedFrom">A <see cref="UdpEndPoint"/> representing the sender's address (sometimes used for replies).</param>
|
||||
public RequestReceivedEventArgs(HttpRequestMessage message, UdpEndPoint receivedFrom)
|
||||
public RequestReceivedEventArgs(HttpRequestMessage message, IpEndPointInfo receivedFrom)
|
||||
{
|
||||
_Message = message;
|
||||
_ReceivedFrom = receivedFrom;
|
||||
@@ -49,7 +50,7 @@ namespace Rssdp.Infrastructure
|
||||
/// <summary>
|
||||
/// The <see cref="UdpEndPoint"/> the request came from.
|
||||
/// </summary>
|
||||
public UdpEndPoint ReceivedFrom
|
||||
public IpEndPointInfo ReceivedFrom
|
||||
{
|
||||
get { return _ReceivedFrom; }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
@@ -17,7 +18,7 @@ namespace Rssdp.Infrastructure
|
||||
#region Fields
|
||||
|
||||
private readonly HttpResponseMessage _Message;
|
||||
private readonly UdpEndPoint _ReceivedFrom;
|
||||
private readonly IpEndPointInfo _ReceivedFrom;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -26,9 +27,7 @@ namespace Rssdp.Infrastructure
|
||||
/// <summary>
|
||||
/// Full constructor.
|
||||
/// </summary>
|
||||
/// <param name="message">The <see cref="HttpResponseMessage"/> that was received.</param>
|
||||
/// <param name="receivedFrom">A <see cref="UdpEndPoint"/> representing the sender's address (sometimes used for replies).</param>
|
||||
public ResponseReceivedEventArgs(HttpResponseMessage message, UdpEndPoint receivedFrom)
|
||||
public ResponseReceivedEventArgs(HttpResponseMessage message, IpEndPointInfo receivedFrom)
|
||||
{
|
||||
_Message = message;
|
||||
_ReceivedFrom = receivedFrom;
|
||||
@@ -49,7 +48,7 @@ namespace Rssdp.Infrastructure
|
||||
/// <summary>
|
||||
/// The <see cref="UdpEndPoint"/> the response came from.
|
||||
/// </summary>
|
||||
public UdpEndPoint ReceivedFrom
|
||||
public IpEndPointInfo ReceivedFrom
|
||||
{
|
||||
get { return _ReceivedFrom; }
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using Rssdp.Infrastructure;
|
||||
|
||||
namespace Rssdp
|
||||
{
|
||||
// THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS
|
||||
// Be careful to check any changes compile and work for all platform projects it is shared in.
|
||||
|
||||
// Not entirely happy with this. Would have liked to have done something more generic/reusable,
|
||||
// but that wasn't really the point so kept to YAGNI principal for now, even if the
|
||||
// interfaces are a bit ugly, specific and make assumptions.
|
||||
|
||||
/// <summary>
|
||||
/// Used by RSSDP components to create implementations of the <see cref="IUdpSocket"/> interface, to perform platform agnostic socket communications.
|
||||
/// </summary>
|
||||
public sealed class SocketFactory : ISocketFactory
|
||||
{
|
||||
private IPAddress _LocalIP;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
/// <param name="localIP">A string containing the IP address of the local network adapter to bind sockets to. Null or empty string will use <see cref="IPAddress.Any"/>.</param>
|
||||
public SocketFactory(string localIP)
|
||||
{
|
||||
if (String.IsNullOrEmpty(localIP))
|
||||
_LocalIP = IPAddress.Any;
|
||||
else
|
||||
_LocalIP = IPAddress.Parse(localIP);
|
||||
}
|
||||
|
||||
#region ISocketFactory Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new UDP socket that is a member of the SSDP multicast local admin group and binds it to the specified local port.
|
||||
/// </summary>
|
||||
/// <param name="localPort">An integer specifying the local port to bind the socket to.</param>
|
||||
/// <returns>An implementation of the <see cref="IUdpSocket"/> interface used by RSSDP components to perform socket operations.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")]
|
||||
public IUdpSocket CreateUdpSocket(int localPort)
|
||||
{
|
||||
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
|
||||
|
||||
var retVal = new Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
|
||||
try
|
||||
{
|
||||
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, SsdpConstants.SsdpDefaultMulticastTimeToLive);
|
||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), _LocalIP));
|
||||
return new UdpSocket(retVal, localPort, _LocalIP.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (retVal != null)
|
||||
retVal.Dispose();
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new UDP socket that is a member of the specified multicast IP address, and binds it to the specified local port.
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">The multicast IP address to make the socket a member of.</param>
|
||||
/// <param name="multicastTimeToLive">The multicast time to live value for the socket.</param>
|
||||
/// <param name="localPort">The number of the local port to bind to.</param>
|
||||
/// <returns></returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "ip"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")]
|
||||
public IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort)
|
||||
{
|
||||
if (ipAddress == null) throw new ArgumentNullException("ipAddress");
|
||||
if (ipAddress.Length == 0) throw new ArgumentException("ipAddress cannot be an empty string.", "ipAddress");
|
||||
if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive");
|
||||
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
|
||||
|
||||
var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
|
||||
try
|
||||
{
|
||||
#if NETSTANDARD1_3
|
||||
// The ExclusiveAddressUse socket option is a Windows-specific option that, when set to "true," tells Windows not to allow another socket to use the same local address as this socket
|
||||
// See https://github.com/dotnet/corefx/pull/11509 for more details
|
||||
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
|
||||
{
|
||||
retVal.ExclusiveAddressUse = false;
|
||||
}
|
||||
#else
|
||||
retVal.ExclusiveAddressUse = false;
|
||||
#endif
|
||||
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
|
||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), _LocalIP));
|
||||
retVal.MulticastLoopback = true;
|
||||
|
||||
return new UdpSocket(retVal, localPort, _LocalIP.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (retVal != null)
|
||||
retVal.Dispose();
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Net;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
@@ -157,10 +158,10 @@ namespace Rssdp.Infrastructure
|
||||
/// Sends a message to a particular address (uni or multicast) and port.
|
||||
/// </summary>
|
||||
/// <param name="messageData">A byte array containing the data to send.</param>
|
||||
/// <param name="destination">A <see cref="UdpEndPoint"/> representing the destination address for the data. Can be either a multicast or unicast destination.</param>
|
||||
/// <param name="destination">A <see cref="IpEndPointInfo"/> representing the destination address for the data. Can be either a multicast or unicast destination.</param>
|
||||
/// <exception cref="System.ArgumentNullException">Thrown if the <paramref name="messageData"/> argument is null.</exception>
|
||||
/// <exception cref="System.ObjectDisposedException">Thrown if the <see cref="DisposableManagedObjectBase.IsDisposed"/> property is true (because <seealso cref="DisposableManagedObjectBase.Dispose()" /> has been called previously).</exception>
|
||||
public async Task SendMessage(byte[] messageData, UdpEndPoint destination)
|
||||
public async Task SendMessage(byte[] messageData, IpEndPointInfo destination)
|
||||
{
|
||||
if (messageData == null) throw new ArgumentNullException("messageData");
|
||||
|
||||
@@ -188,7 +189,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
||||
await Repeat(SsdpConstants.UdpResendCount, TimeSpan.FromMilliseconds(100),
|
||||
() => SendMessageIfSocketNotDisposed(messageData, new UdpEndPoint() { IPAddress = SsdpConstants.MulticastLocalAdminAddress, Port = SsdpConstants.MulticastPort })).ConfigureAwait(false);
|
||||
() => SendMessageIfSocketNotDisposed(messageData, new IpEndPointInfo() { IpAddress = new IpAddressInfo { Address = SsdpConstants.MulticastLocalAdminAddress }, Port = SsdpConstants.MulticastPort })).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -254,7 +255,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task SendMessageIfSocketNotDisposed(byte[] messageData, UdpEndPoint destination)
|
||||
private async Task SendMessageIfSocketNotDisposed(byte[] messageData, IpEndPointInfo destination)
|
||||
{
|
||||
var socket = _SendSocket;
|
||||
if (socket != null)
|
||||
@@ -343,7 +344,7 @@ namespace Rssdp.Infrastructure
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessMessage(string data, UdpEndPoint endPoint)
|
||||
private void ProcessMessage(string data, IpEndPointInfo endPoint)
|
||||
{
|
||||
//Responses start with the HTTP version, prefixed with HTTP/ while
|
||||
//requests start with a method which can vary and might be one we haven't
|
||||
@@ -375,7 +376,7 @@ namespace Rssdp.Infrastructure
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRequestReceived(HttpRequestMessage data, UdpEndPoint endPoint)
|
||||
private void OnRequestReceived(HttpRequestMessage data, IpEndPointInfo endPoint)
|
||||
{
|
||||
//SSDP specification says only * is currently used but other uri's might
|
||||
//be implemented in the future and should be ignored unless understood.
|
||||
@@ -387,7 +388,7 @@ namespace Rssdp.Infrastructure
|
||||
handlers(this, new RequestReceivedEventArgs(data, endPoint));
|
||||
}
|
||||
|
||||
private void OnResponseReceived(HttpResponseMessage data, UdpEndPoint endPoint)
|
||||
private void OnResponseReceived(HttpResponseMessage data, IpEndPointInfo endPoint)
|
||||
{
|
||||
var handlers = this.ResponseReceived;
|
||||
if (handlers != null)
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Threading;
|
||||
using Rssdp.Infrastructure;
|
||||
|
||||
namespace Rssdp
|
||||
@@ -19,7 +21,7 @@ namespace Rssdp
|
||||
/// Default constructor. Constructs a new instance using the default <see cref="ISsdpCommunicationsServer"/> and <see cref="ISocketFactory"/> implementations for this platform.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification="Can't expose along exception paths here (exceptions should be very rare anyway, and probably fatal too) and we shouldn't dipose the items we pass to base in any other case.")]
|
||||
public SsdpDeviceLocator() : base(new SsdpCommunicationsServer(new SocketFactory(null)))
|
||||
public SsdpDeviceLocator(ISocketFactory socketFactory, ITimerFactory timerFacatory) : base(new SsdpCommunicationsServer(socketFactory), timerFacatory)
|
||||
{
|
||||
// This is not the problem you are looking for;
|
||||
// Yes, this is poor man's dependency injection which some call an anti-pattern.
|
||||
@@ -30,14 +32,5 @@ namespace Rssdp
|
||||
// There is a constructor that takes a manually injected dependency anyway, so proper DI using
|
||||
// a container or whatever can be done anyway.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full constructor. Constructs a new instance using the provided <see cref="ISsdpCommunicationsServer"/> implementation.
|
||||
/// </summary>
|
||||
public SsdpDeviceLocator(ISsdpCommunicationsServer communicationsServer)
|
||||
: base(communicationsServer)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Threading;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
@@ -24,7 +25,8 @@ namespace Rssdp.Infrastructure
|
||||
private IList<DiscoveredSsdpDevice> _SearchResults;
|
||||
private object _SearchResultsSynchroniser;
|
||||
|
||||
private System.Threading.Timer _ExpireCachedDevicesTimer;
|
||||
private ITimer _ExpireCachedDevicesTimer;
|
||||
private ITimerFactory _timerFactory;
|
||||
|
||||
private const string HttpURequestMessageFormat = @"{0} * HTTP/1.1
|
||||
HOST: {1}:{2}
|
||||
@@ -44,12 +46,12 @@ ST: {4}
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
/// <param name="communicationsServer">The <see cref="ISsdpCommunicationsServer"/> implementation to use for network communications.</param>
|
||||
protected SsdpDeviceLocatorBase(ISsdpCommunicationsServer communicationsServer)
|
||||
protected SsdpDeviceLocatorBase(ISsdpCommunicationsServer communicationsServer, ITimerFactory timerFactory)
|
||||
{
|
||||
if (communicationsServer == null) throw new ArgumentNullException("communicationsServer");
|
||||
|
||||
_CommunicationsServer = communicationsServer;
|
||||
_timerFactory = timerFactory;
|
||||
_CommunicationsServer.ResponseReceived += CommsServer_ResponseReceived;
|
||||
|
||||
_SearchResultsSynchroniser = new object();
|
||||
@@ -521,7 +523,7 @@ ST: {4}
|
||||
if (IsDisposed) return;
|
||||
|
||||
if (_ExpireCachedDevicesTimer == null)
|
||||
_ExpireCachedDevicesTimer = new Timer(this.ExpireCachedDevices, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||
_ExpireCachedDevicesTimer = _timerFactory.Create(this.ExpireCachedDevices, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||
|
||||
_ExpireCachedDevicesTimer.Change(60000, System.Threading.Timeout.Infinite);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Threading;
|
||||
using Rssdp.Infrastructure;
|
||||
|
||||
namespace Rssdp
|
||||
@@ -24,79 +26,13 @@ namespace Rssdp
|
||||
/// <para>Uses the default <see cref="ISsdpCommunicationsServer"/> implementation and network settings for Windows and the SSDP specification.</para>
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No way to do this here, and we don't want to dispose it except in the (rare) case of an exception anyway.")]
|
||||
public SsdpDevicePublisher()
|
||||
: this(new SsdpCommunicationsServer(new SocketFactory(null)))
|
||||
public SsdpDevicePublisher(ISocketFactory socketFactory, ITimerFactory timerFactory, string osName, string osVersion)
|
||||
: base(new SsdpCommunicationsServer(socketFactory), timerFactory, osName, osVersion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full constructor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Allows the caller to specify their own <see cref="ISsdpCommunicationsServer"/> implementation for full control over the networking, or for mocking/testing purposes..</para>
|
||||
/// </remarks>
|
||||
public SsdpDevicePublisher(ISsdpCommunicationsServer communicationsServer)
|
||||
: base(communicationsServer, GetOSName(), GetOSVersion())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Partial constructor.
|
||||
/// </summary>
|
||||
/// <param name="localPort">The local port to use for socket communications, specify 0 to have the system choose it's own.</param>
|
||||
/// <remarks>
|
||||
/// <para>Uses the default <see cref="ISsdpCommunicationsServer"/> implementation and network settings for Windows and the SSDP specification, but specifies the local port to use for socket communications. Specify 0 to indicate the system should choose it's own port.</para>
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No way to do this here, and we don't want to dispose it except in the (rare) case of an exception anyway.")]
|
||||
public SsdpDevicePublisher(int localPort)
|
||||
: this(new SsdpCommunicationsServer(new SocketFactory(null), localPort))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Partial constructor.
|
||||
/// </summary>
|
||||
/// <param name="localPort">The local port to use for socket communications, specify 0 to have the system choose it's own.</param>
|
||||
/// <param name="multicastTimeToLive">The number of hops a multicast packet can make before it expires. Must be 1 or greater.</param>
|
||||
/// <remarks>
|
||||
/// <para>Uses the default <see cref="ISsdpCommunicationsServer"/> implementation and network settings for Windows and the SSDP specification, but specifies the local port to use and multicast time to live setting for socket communications.</para>
|
||||
/// <para>Specify 0 for the <paramref name="localPort"/> argument to indicate the system should choose it's own port.</para>
|
||||
/// <para>The <paramref name="multicastTimeToLive"/> is actually a number of 'hops' on the network and not a time based argument.</para>
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No way to do this here, and we don't want to dispose it except in the (rare) case of an exception anyway.")]
|
||||
public SsdpDevicePublisher(int localPort, int multicastTimeToLive)
|
||||
: this(new SsdpCommunicationsServer(new SocketFactory(null), localPort, multicastTimeToLive))
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static string GetOSName()
|
||||
{
|
||||
#if NET46
|
||||
return Environment.OSVersion.Platform.ToString();
|
||||
#elif NETSTANDARD1_6
|
||||
return System.Runtime.InteropServices.RuntimeInformation.OSDescription;
|
||||
#endif
|
||||
return "Operating System";
|
||||
}
|
||||
|
||||
private static string GetOSVersion()
|
||||
{
|
||||
#if NET46
|
||||
return Environment.OSVersion.Version.ToString() + " " + Environment.OSVersion.ServicePack.ToString();
|
||||
#elif NETSTANDARD1_6
|
||||
return System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
|
||||
#endif
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Threading;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
@@ -24,7 +26,8 @@ namespace Rssdp.Infrastructure
|
||||
private IList<SsdpRootDevice> _Devices;
|
||||
private ReadOnlyEnumerable<SsdpRootDevice> _ReadOnlyDevices;
|
||||
|
||||
private System.Threading.Timer _RebroadcastAliveNotificationsTimer;
|
||||
private ITimer _RebroadcastAliveNotificationsTimer;
|
||||
private ITimerFactory _timerFactory;
|
||||
//private TimeSpan _RebroadcastAliveNotificationsTimeSpan;
|
||||
private DateTime _LastNotificationTime;
|
||||
|
||||
@@ -47,10 +50,7 @@ namespace Rssdp.Infrastructure
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
/// <param name="communicationsServer">The <see cref="ISsdpCommunicationsServer"/> implementation, used to send and receive SSDP network messages.</param>
|
||||
/// <param name="osName">Then name of the operating system running the server.</param>
|
||||
/// <param name="osVersion">The version of the operating system running the server.</param>
|
||||
protected SsdpDevicePublisherBase(ISsdpCommunicationsServer communicationsServer, string osName, string osVersion)
|
||||
protected SsdpDevicePublisherBase(ISsdpCommunicationsServer communicationsServer, ITimerFactory timerFactory, string osName, string osVersion)
|
||||
{
|
||||
if (communicationsServer == null) throw new ArgumentNullException("communicationsServer");
|
||||
if (osName == null) throw new ArgumentNullException("osName");
|
||||
@@ -59,6 +59,7 @@ namespace Rssdp.Infrastructure
|
||||
if (osVersion.Length == 0) throw new ArgumentException("osVersion cannot be an empty string.", "osName");
|
||||
|
||||
_SupportPnpRootDevice = true;
|
||||
_timerFactory = timerFactory;
|
||||
_Devices = new List<SsdpRootDevice>();
|
||||
_ReadOnlyDevices = new ReadOnlyEnumerable<SsdpRootDevice>(_Devices);
|
||||
_RecentSearchRequests = new Dictionary<string, SearchRequest>(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -234,7 +235,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
#region Search Related Methods
|
||||
|
||||
private void ProcessSearchRequest(string mx, string searchTarget, UdpEndPoint endPoint)
|
||||
private void ProcessSearchRequest(string mx, string searchTarget, IpEndPointInfo endPoint)
|
||||
{
|
||||
if (String.IsNullOrEmpty(searchTarget))
|
||||
{
|
||||
@@ -305,7 +306,7 @@ namespace Rssdp.Infrastructure
|
||||
return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices));
|
||||
}
|
||||
|
||||
private void SendDeviceSearchResponses(SsdpDevice device, UdpEndPoint endPoint)
|
||||
private void SendDeviceSearchResponses(SsdpDevice device, IpEndPointInfo endPoint)
|
||||
{
|
||||
bool isRootDevice = (device as SsdpRootDevice) != null;
|
||||
if (isRootDevice)
|
||||
@@ -325,7 +326,7 @@ namespace Rssdp.Infrastructure
|
||||
return String.Format("{0}::{1}", udn, fullDeviceType);
|
||||
}
|
||||
|
||||
private async void SendSearchResponse(string searchTarget, SsdpDevice device, string uniqueServiceName, UdpEndPoint endPoint)
|
||||
private async void SendSearchResponse(string searchTarget, SsdpDevice device, string uniqueServiceName, IpEndPointInfo endPoint)
|
||||
{
|
||||
var rootDevice = device.ToRootDevice();
|
||||
|
||||
@@ -357,7 +358,7 @@ namespace Rssdp.Infrastructure
|
||||
WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device);
|
||||
}
|
||||
|
||||
private bool IsDuplicateSearchRequest(string searchTarget, UdpEndPoint endPoint)
|
||||
private bool IsDuplicateSearchRequest(string searchTarget, IpEndPointInfo endPoint)
|
||||
{
|
||||
var isDuplicateRequest = false;
|
||||
|
||||
@@ -590,7 +591,7 @@ namespace Rssdp.Infrastructure
|
||||
}
|
||||
|
||||
//_RebroadcastAliveNotificationsTimeSpan = rebroadCastInterval;
|
||||
_RebroadcastAliveNotificationsTimer = new System.Threading.Timer(SendAllAliveNotifications, null, nextBroadcastInterval, rebroadCastInterval);
|
||||
_RebroadcastAliveNotificationsTimer = _timerFactory.Create(SendAllAliveNotifications, null, nextBroadcastInterval, rebroadCastInterval);
|
||||
|
||||
WriteTrace(String.Format("Rebroadcast Interval = {0}, Next Broadcast At = {1}", rebroadCastInterval.ToString(), nextBroadcastInterval.ToString()));
|
||||
}
|
||||
@@ -704,7 +705,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
private class SearchRequest
|
||||
{
|
||||
public UdpEndPoint EndPoint { get; set; }
|
||||
public IpEndPointInfo EndPoint { get; set; }
|
||||
public DateTime Received { get; set; }
|
||||
public string SearchTarget { get; set; }
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rssdp.Infrastructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Cross platform representation of a UDP end point, being an IP address (either IPv4 or IPv6) and a port.
|
||||
/// </summary>
|
||||
public sealed class UdpEndPoint
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The IP Address of the end point.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Can be either IPv4 or IPv6, up to the code using this instance to determine which was provided.</para>
|
||||
/// </remarks>
|
||||
public string IPAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The port of the end point.
|
||||
/// </summary>
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="IPAddress"/> and <see cref="Port"/> values separated by a colon.
|
||||
/// </summary>
|
||||
/// <returns>A string containing <see cref="IPAddress"/>:<see cref="Port"/>.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return (this.IPAddress ?? String.Empty) + ":" + this.Port.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Rssdp.Infrastructure;
|
||||
|
||||
namespace Rssdp
|
||||
{
|
||||
// THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS
|
||||
// Be careful to check any changes compile and work for all platform projects it is shared in.
|
||||
|
||||
internal sealed class UdpSocket : DisposableManagedObjectBase, IUdpSocket
|
||||
{
|
||||
|
||||
#region Fields
|
||||
|
||||
private System.Net.Sockets.Socket _Socket;
|
||||
private int _LocalPort;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public UdpSocket(System.Net.Sockets.Socket socket, int localPort, string ipAddress)
|
||||
{
|
||||
if (socket == null) throw new ArgumentNullException("socket");
|
||||
|
||||
_Socket = socket;
|
||||
_LocalPort = localPort;
|
||||
|
||||
IPAddress ip = null;
|
||||
if (String.IsNullOrEmpty(ipAddress))
|
||||
ip = IPAddress.Any;
|
||||
else
|
||||
ip = IPAddress.Parse(ipAddress);
|
||||
|
||||
_Socket.Bind(new IPEndPoint(ip, _LocalPort));
|
||||
if (_LocalPort == 0)
|
||||
_LocalPort = (_Socket.LocalEndPoint as IPEndPoint).Port;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUdpSocket Members
|
||||
|
||||
public System.Threading.Tasks.Task<ReceivedUdpData> ReceiveAsync()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
var tcs = new TaskCompletionSource<ReceivedUdpData>();
|
||||
|
||||
System.Net.EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
||||
var state = new AsyncReceiveState(_Socket, receivedFromEndPoint);
|
||||
state.TaskCompletionSource = tcs;
|
||||
|
||||
#if NETSTANDARD1_6
|
||||
_Socket.ReceiveFromAsync(new System.ArraySegment<Byte>(state.Buffer), System.Net.Sockets.SocketFlags.None, state.EndPoint)
|
||||
.ContinueWith((task, asyncState) =>
|
||||
{
|
||||
if (task.Status != TaskStatus.Faulted)
|
||||
{
|
||||
var receiveState = asyncState as AsyncReceiveState;
|
||||
receiveState.EndPoint = task.Result.RemoteEndPoint;
|
||||
ProcessResponse(receiveState, () => task.Result.ReceivedBytes);
|
||||
}
|
||||
}, state);
|
||||
#else
|
||||
_Socket.BeginReceiveFrom(state.Buffer, 0, state.Buffer.Length, System.Net.Sockets.SocketFlags.None, ref state.EndPoint, new AsyncCallback(this.ProcessResponse), state);
|
||||
#endif
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public Task SendTo(byte[] messageData, UdpEndPoint endPoint)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
if (messageData == null) throw new ArgumentNullException("messageData");
|
||||
if (endPoint == null) throw new ArgumentNullException("endPoint");
|
||||
|
||||
#if NETSTANDARD1_6
|
||||
_Socket.SendTo(messageData, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IPAddress), endPoint.Port));
|
||||
return Task.FromResult(true);
|
||||
#else
|
||||
var taskSource = new TaskCompletionSource<bool>();
|
||||
|
||||
try
|
||||
{
|
||||
_Socket.BeginSendTo(messageData, 0, messageData.Length, SocketFlags.None, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IPAddress), endPoint.Port), result =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_Socket.EndSend(result);
|
||||
taskSource.TrySetResult(true);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
taskSource.TrySetException(ex);
|
||||
}
|
||||
|
||||
//_Socket.SendTo(messageData, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IPAddress), endPoint.Port));
|
||||
|
||||
return taskSource.Task;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
var socket = _Socket;
|
||||
if (socket != null)
|
||||
socket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions via task methods should be reported by task completion source, so this should be ok.")]
|
||||
private static void ProcessResponse(AsyncReceiveState state, Func<int> receiveData)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytesRead = receiveData();
|
||||
|
||||
var ipEndPoint = state.EndPoint as IPEndPoint;
|
||||
state.TaskCompletionSource.SetResult(
|
||||
new ReceivedUdpData()
|
||||
{
|
||||
Buffer = state.Buffer,
|
||||
ReceivedBytes = bytesRead,
|
||||
ReceivedFrom = new UdpEndPoint()
|
||||
{
|
||||
IPAddress = ipEndPoint.Address.ToString(),
|
||||
Port = ipEndPoint.Port
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
state.TaskCompletionSource.SetCanceled();
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
if (se.SocketErrorCode != SocketError.Interrupted && se.SocketErrorCode != SocketError.OperationAborted && se.SocketErrorCode != SocketError.Shutdown)
|
||||
state.TaskCompletionSource.SetException(se);
|
||||
else
|
||||
state.TaskCompletionSource.SetCanceled();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state.TaskCompletionSource.SetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions via task methods should be reported by task completion source, so this should be ok.")]
|
||||
private void ProcessResponse(IAsyncResult asyncResult)
|
||||
{
|
||||
#if NET46
|
||||
var state = asyncResult.AsyncState as AsyncReceiveState;
|
||||
try
|
||||
{
|
||||
var bytesRead = state.Socket.EndReceiveFrom(asyncResult, ref state.EndPoint);
|
||||
|
||||
var ipEndPoint = state.EndPoint as IPEndPoint;
|
||||
state.TaskCompletionSource.SetResult(
|
||||
new ReceivedUdpData()
|
||||
{
|
||||
Buffer = state.Buffer,
|
||||
ReceivedBytes = bytesRead,
|
||||
ReceivedFrom = new UdpEndPoint()
|
||||
{
|
||||
IPAddress = ipEndPoint.Address.ToString(),
|
||||
Port = ipEndPoint.Port
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
state.TaskCompletionSource.SetCanceled();
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
if (se.SocketErrorCode != SocketError.Interrupted && se.SocketErrorCode != SocketError.OperationAborted && se.SocketErrorCode != SocketError.Shutdown)
|
||||
state.TaskCompletionSource.SetException(se);
|
||||
else
|
||||
state.TaskCompletionSource.SetCanceled();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state.TaskCompletionSource.SetException(ex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Classes
|
||||
|
||||
private class AsyncReceiveState
|
||||
{
|
||||
public AsyncReceiveState(System.Net.Sockets.Socket socket, EndPoint endPoint)
|
||||
{
|
||||
this.Socket = socket;
|
||||
this.EndPoint = endPoint;
|
||||
}
|
||||
|
||||
public EndPoint EndPoint;
|
||||
public byte[] Buffer = new byte[SsdpConstants.DefaultUdpSocketBufferSize];
|
||||
|
||||
public System.Net.Sockets.Socket Socket { get; private set; }
|
||||
|
||||
public TaskCompletionSource<ReceivedUdpData> TaskCompletionSource { get; set; }
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"net46": {
|
||||
"frameworkAssemblies": {
|
||||
"System.Collections": "4.0.0.0",
|
||||
"System.Net": "4.0.0.0",
|
||||
"System.Net.Http": "4.0.0.0",
|
||||
"System.Runtime": "4.0.0.0",
|
||||
"System.Threading": "4.0.0.0",
|
||||
"System.Threading.Tasks": "4.0.0.0",
|
||||
"System.Xml": "4.0.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
}
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"imports": "dnxcore50",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.6.0",
|
||||
"System.Collections": "4.0.11",
|
||||
"System.Diagnostics.Debug": "4.0.11",
|
||||
"System.Diagnostics.Tools": "4.0.1",
|
||||
"System.IO": "4.1.0",
|
||||
"System.Linq": "4.1.0",
|
||||
"System.Net.Http": "4.1.0",
|
||||
"System.Net.Primitives": "4.0.11",
|
||||
"System.Net.Sockets": "4.1.0",
|
||||
"System.Resources.ResourceManager": "4.0.1",
|
||||
"System.Runtime": "4.1.0",
|
||||
"System.Runtime.Extensions": "4.1.0",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
|
||||
"System.Text.Encoding": "4.0.11",
|
||||
"System.Text.Encoding.Extensions": "4.0.11",
|
||||
"System.Threading": "4.0.11",
|
||||
"System.Threading.Tasks": "4.0.11",
|
||||
"System.Threading.Timer": "4.0.1",
|
||||
"System.Xml.ReaderWriter": "4.0.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user