From 6d250c4050ceb0bda33aad6a484fd05e508c4e27 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 4 Nov 2016 04:31:05 -0400 Subject: make dlna project portable --- RSSDP/ISocketFactory.cs | 33 ----- RSSDP/ISsdpCommunicationsServer.cs | 5 +- RSSDP/IUdpSocket.cs | 28 ---- RSSDP/Properties/AssemblyInfo.cs | 31 +++-- RSSDP/RSSDP.csproj | 85 ++++++++++++ RSSDP/RSSDP.xproj | 21 --- RSSDP/ReceivedUdpData.cs | 29 ----- RSSDP/RequestReceivedEventArgs.cs | 7 +- RSSDP/ResponseReceivedEventArgs.cs | 9 +- RSSDP/Rssdp.Portable.csproj | 110 ---------------- RSSDP/SocketFactory.cs | 114 ---------------- RSSDP/SsdpCommunicationsServer.cs | 15 ++- RSSDP/SsdpDeviceLocator.cs | 13 +- RSSDP/SsdpDeviceLocatorBase.cs | 10 +- RSSDP/SsdpDevicePublisher.cs | 72 +---------- RSSDP/SsdpDevicePublisherBase.cs | 23 ++-- RSSDP/UdpEndPoint.cs | 37 ------ RSSDP/UdpSocket.cs | 259 ------------------------------------- RSSDP/project.json | 48 ------- 19 files changed, 150 insertions(+), 799 deletions(-) delete mode 100644 RSSDP/ISocketFactory.cs delete mode 100644 RSSDP/IUdpSocket.cs create mode 100644 RSSDP/RSSDP.csproj delete mode 100644 RSSDP/RSSDP.xproj delete mode 100644 RSSDP/ReceivedUdpData.cs delete mode 100644 RSSDP/Rssdp.Portable.csproj delete mode 100644 RSSDP/SocketFactory.cs delete mode 100644 RSSDP/UdpEndPoint.cs delete mode 100644 RSSDP/UdpSocket.cs delete mode 100644 RSSDP/project.json (limited to 'RSSDP') diff --git a/RSSDP/ISocketFactory.cs b/RSSDP/ISocketFactory.cs deleted file mode 100644 index 3e7d7facb9..0000000000 --- a/RSSDP/ISocketFactory.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rssdp.Infrastructure -{ - /// - /// Implemented by components that can create a platform specific UDP socket implementation, and wrap it in the cross platform interface. - /// - public interface ISocketFactory - { - - /// - /// Createa a new unicast socket using the specified local port number. - /// - /// The local port to bind to. - /// A implementation. - IUdpSocket CreateUdpSocket(int localPort); - - /// - /// Createa a new multicast socket using the specified multicast IP address, multicast time to live and local port. - /// - /// The multicast IP address to bind to. - /// The multicast time to live value. Actually a maximum number of network hops for UDP packets. - /// The local port to bind to. - /// A implementation. - [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); - - } -} diff --git a/RSSDP/ISsdpCommunicationsServer.cs b/RSSDP/ISsdpCommunicationsServer.cs index 990b21d05e..b1e84dc9f5 100644 --- a/RSSDP/ISsdpCommunicationsServer.cs +++ b/RSSDP/ISsdpCommunicationsServer.cs @@ -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. /// /// A byte array containing the data to send. - /// A representing the destination address for the data. Can be either a multicast or unicast destination. - Task SendMessage(byte[] messageData, UdpEndPoint destination); + /// A representing the destination address for the data. Can be either a multicast or unicast destination. + Task SendMessage(byte[] messageData, IpEndPointInfo destination); /// /// Sends a message to the SSDP multicast address and port. diff --git a/RSSDP/IUdpSocket.cs b/RSSDP/IUdpSocket.cs deleted file mode 100644 index bcab4ecf12..0000000000 --- a/RSSDP/IUdpSocket.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rssdp.Infrastructure -{ - /// - /// Provides a common interface across platforms for UDP sockets used by this SSDP implementation. - /// - public interface IUdpSocket : IDisposable - { - /// - /// Waits for and returns the next UDP message sent to this socket (uni or multicast). - /// - /// - System.Threading.Tasks.Task ReceiveAsync(); - - /// - /// Sends a UDP message to a particular end point (uni or multicast). - /// - /// The data to send. - /// The providing the address and port to send to. - Task SendTo(byte[] messageData, UdpEndPoint endPoint); - - } -} \ No newline at end of file diff --git a/RSSDP/Properties/AssemblyInfo.cs b/RSSDP/Properties/AssemblyInfo.cs index 63f3af0832..1ce64b159d 100644 --- a/RSSDP/Properties/AssemblyInfo.cs +++ b/RSSDP/Properties/AssemblyInfo.cs @@ -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")] diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj new file mode 100644 index 0000000000..fb4d67e1ab --- /dev/null +++ b/RSSDP/RSSDP.csproj @@ -0,0 +1,85 @@ + + + + + 11.0 + Debug + AnyCPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F} + Library + Properties + RSSDP + RSSDP + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile7 + v4.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} + MediaBrowser.Model + + + + + \ No newline at end of file diff --git a/RSSDP/RSSDP.xproj b/RSSDP/RSSDP.xproj deleted file mode 100644 index d0b2b2cbfc..0000000000 --- a/RSSDP/RSSDP.xproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - c227adb7-e256-4e70-a8b9-22b9e0cf4f55 - RSSDP - .\obj - .\bin\ - v4.5.2 - - - - 2.0 - - - diff --git a/RSSDP/ReceivedUdpData.cs b/RSSDP/ReceivedUdpData.cs deleted file mode 100644 index d1c2ca3c9e..0000000000 --- a/RSSDP/ReceivedUdpData.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rssdp.Infrastructure -{ - /// - /// Used by the sockets wrapper to hold raw data received from a UDP socket. - /// - public sealed class ReceivedUdpData - { - /// - /// The buffer to place received data into. - /// - public byte[] Buffer { get; set; } - - /// - /// The number of bytes received. - /// - public int ReceivedBytes { get; set; } - - /// - /// The the data was received from. - /// - public UdpEndPoint ReceivedFrom { get; set; } - } -} diff --git a/RSSDP/RequestReceivedEventArgs.cs b/RSSDP/RequestReceivedEventArgs.cs index a78f1b91d6..fb4fac8714 100644 --- a/RSSDP/RequestReceivedEventArgs.cs +++ b/RSSDP/RequestReceivedEventArgs.cs @@ -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 /// /// The that was received. /// A representing the sender's address (sometimes used for replies). - public RequestReceivedEventArgs(HttpRequestMessage message, UdpEndPoint receivedFrom) + public RequestReceivedEventArgs(HttpRequestMessage message, IpEndPointInfo receivedFrom) { _Message = message; _ReceivedFrom = receivedFrom; @@ -49,7 +50,7 @@ namespace Rssdp.Infrastructure /// /// The the request came from. /// - public UdpEndPoint ReceivedFrom + public IpEndPointInfo ReceivedFrom { get { return _ReceivedFrom; } } diff --git a/RSSDP/ResponseReceivedEventArgs.cs b/RSSDP/ResponseReceivedEventArgs.cs index f883308023..f7dc5813d9 100644 --- a/RSSDP/ResponseReceivedEventArgs.cs +++ b/RSSDP/ResponseReceivedEventArgs.cs @@ -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 /// /// Full constructor. /// - /// The that was received. - /// A representing the sender's address (sometimes used for replies). - public ResponseReceivedEventArgs(HttpResponseMessage message, UdpEndPoint receivedFrom) + public ResponseReceivedEventArgs(HttpResponseMessage message, IpEndPointInfo receivedFrom) { _Message = message; _ReceivedFrom = receivedFrom; @@ -49,7 +48,7 @@ namespace Rssdp.Infrastructure /// /// The the response came from. /// - public UdpEndPoint ReceivedFrom + public IpEndPointInfo ReceivedFrom { get { return _ReceivedFrom; } } diff --git a/RSSDP/Rssdp.Portable.csproj b/RSSDP/Rssdp.Portable.csproj deleted file mode 100644 index a8169f4b30..0000000000 --- a/RSSDP/Rssdp.Portable.csproj +++ /dev/null @@ -1,110 +0,0 @@ - - - - - 12.0 - Debug - AnyCPU - {67F9D3A8-F71E-4428-913F-C37AE82CDB24} - Library - Properties - Rssdp - Rssdp.Portable - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile44 - v4.6 - 512 - 1c5b2aa5 - ..\ - true - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - ..\RssdpRuleset.ruleset - bin\Debug\Rssdp.Portable.XML - - - pdbonly - true - ..\lib\portable-net45+win+wpa81+wp80\ - TRACE - prompt - 4 - ..\RssdpRuleset.ruleset - ..\lib\portable-net45+win+wpa81+wp80\Rssdp.Portable.XML - true - - - - Properties\AssemblyInfoCommon.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Properties\CodeAnalysisDictionary.xml - Designer - - - - - - 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}. - - - - - - \ No newline at end of file diff --git a/RSSDP/SocketFactory.cs b/RSSDP/SocketFactory.cs deleted file mode 100644 index 1a9c981d01..0000000000 --- a/RSSDP/SocketFactory.cs +++ /dev/null @@ -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. - - /// - /// Used by RSSDP components to create implementations of the interface, to perform platform agnostic socket communications. - /// - public sealed class SocketFactory : ISocketFactory - { - private IPAddress _LocalIP; - - /// - /// Default constructor. - /// - /// A string containing the IP address of the local network adapter to bind sockets to. Null or empty string will use . - public SocketFactory(string localIP) - { - if (String.IsNullOrEmpty(localIP)) - _LocalIP = IPAddress.Any; - else - _LocalIP = IPAddress.Parse(localIP); - } - - #region ISocketFactory Members - - /// - /// Creates a new UDP socket that is a member of the SSDP multicast local admin group and binds it to the specified local port. - /// - /// An integer specifying the local port to bind the socket to. - /// An implementation of the interface used by RSSDP components to perform socket operations. - [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; - } - } - - /// - /// Creates a new UDP socket that is a member of the specified multicast IP address, and binds it to the specified local port. - /// - /// The multicast IP address to make the socket a member of. - /// The multicast time to live value for the socket. - /// The number of the local port to bind to. - /// - [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 - } -} \ No newline at end of file diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index df23cae507..64278fe4e5 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -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. /// /// A byte array containing the data to send. - /// A representing the destination address for the data. Can be either a multicast or unicast destination. + /// A representing the destination address for the data. Can be either a multicast or unicast destination. /// Thrown if the argument is null. /// Thrown if the property is true (because has been called previously). - 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); } /// @@ -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) diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index 42d20d3320..01c96463fe 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -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 and implementations for this platform. /// [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. } - - /// - /// Full constructor. Constructs a new instance using the provided implementation. - /// - public SsdpDeviceLocator(ISsdpCommunicationsServer communicationsServer) - : base(communicationsServer) - { - } - } } \ No newline at end of file diff --git a/RSSDP/SsdpDeviceLocatorBase.cs b/RSSDP/SsdpDeviceLocatorBase.cs index 0c5166eecb..ed4c087cda 100644 --- a/RSSDP/SsdpDeviceLocatorBase.cs +++ b/RSSDP/SsdpDeviceLocatorBase.cs @@ -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 _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} /// /// Default constructor. /// - /// The implementation to use for network communications. - 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); } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 9667ed8095..56f27b3a29 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -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 /// Uses the default implementation and network settings for Windows and the SSDP specification. /// [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) { } - /// - /// Full constructor. - /// - /// - /// Allows the caller to specify their own implementation for full control over the networking, or for mocking/testing purposes.. - /// - public SsdpDevicePublisher(ISsdpCommunicationsServer communicationsServer) - : base(communicationsServer, GetOSName(), GetOSVersion()) - { - - } - - /// - /// Partial constructor. - /// - /// The local port to use for socket communications, specify 0 to have the system choose it's own. - /// - /// Uses the default 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. - /// - [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)) - { - - } - - /// - /// Partial constructor. - /// - /// The local port to use for socket communications, specify 0 to have the system choose it's own. - /// The number of hops a multicast packet can make before it expires. Must be 1 or greater. - /// - /// Uses the default 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. - /// Specify 0 for the argument to indicate the system should choose it's own port. - /// The is actually a number of 'hops' on the network and not a time based argument. - /// - [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 - } } \ No newline at end of file diff --git a/RSSDP/SsdpDevicePublisherBase.cs b/RSSDP/SsdpDevicePublisherBase.cs index ecf1ac1329..b3c28aab71 100644 --- a/RSSDP/SsdpDevicePublisherBase.cs +++ b/RSSDP/SsdpDevicePublisherBase.cs @@ -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 _Devices; private ReadOnlyEnumerable _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 /// /// Default constructor. /// - /// The implementation, used to send and receive SSDP network messages. - /// Then name of the operating system running the server. - /// The version of the operating system running the server. - 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(); _ReadOnlyDevices = new ReadOnlyEnumerable(_Devices); _RecentSearchRequests = new Dictionary(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((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; } diff --git a/RSSDP/UdpEndPoint.cs b/RSSDP/UdpEndPoint.cs deleted file mode 100644 index 617769cf44..0000000000 --- a/RSSDP/UdpEndPoint.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rssdp.Infrastructure -{ - /// - /// Cross platform representation of a UDP end point, being an IP address (either IPv4 or IPv6) and a port. - /// - public sealed class UdpEndPoint - { - - /// - /// The IP Address of the end point. - /// - /// - /// Can be either IPv4 or IPv6, up to the code using this instance to determine which was provided. - /// - public string IPAddress { get; set; } - - /// - /// The port of the end point. - /// - public int Port { get; set; } - - /// - /// Returns the and values separated by a colon. - /// - /// A string containing :. - public override string ToString() - { - return (this.IPAddress ?? String.Empty) + ":" + this.Port.ToString(); - } - } -} diff --git a/RSSDP/UdpSocket.cs b/RSSDP/UdpSocket.cs deleted file mode 100644 index ea5d6ae977..0000000000 --- a/RSSDP/UdpSocket.cs +++ /dev/null @@ -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 ReceiveAsync() - { - ThrowIfDisposed(); - - var tcs = new TaskCompletionSource(); - - 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(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(); - - 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 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 TaskCompletionSource { get; set; } - - } - - #endregion - - } -} \ No newline at end of file diff --git a/RSSDP/project.json b/RSSDP/project.json deleted file mode 100644 index 0ec2f45d6a..0000000000 --- a/RSSDP/project.json +++ /dev/null @@ -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" - } - } - } -} -- cgit v1.2.3