-
Notifications
You must be signed in to change notification settings - Fork 820
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9e32b9d
commit cb087e1
Showing
57 changed files
with
1,310 additions
and
1,028 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
Emby.Common.Implementations/Net/DisposableManagedObjectBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace Emby.Common.Implementations.Net | ||
{ | ||
/// <summary> | ||
/// Correclty implements the <see cref="IDisposable"/> interface and pattern for an object containing only managed resources, and adds a few common niceities not on the interface such as an <see cref="IsDisposed"/> property. | ||
/// </summary> | ||
public abstract class DisposableManagedObjectBase : IDisposable | ||
{ | ||
|
||
#region Public Methods | ||
|
||
/// <summary> | ||
/// Override this method and dispose any objects you own the lifetime of if disposing is true; | ||
/// </summary> | ||
/// <param name="disposing">True if managed objects should be disposed, if false, only unmanaged resources should be released.</param> | ||
protected abstract void Dispose(bool disposing); | ||
|
||
/// <summary> | ||
/// Throws and <see cref="System.ObjectDisposedException"/> if the <see cref="IsDisposed"/> property is true. | ||
/// </summary> | ||
/// <seealso cref="IsDisposed"/> | ||
/// <exception cref="System.ObjectDisposedException">Thrown if the <see cref="IsDisposed"/> property is true.</exception> | ||
/// <seealso cref="Dispose()"/> | ||
protected virtual void ThrowIfDisposed() | ||
{ | ||
if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().FullName); | ||
} | ||
|
||
#endregion | ||
|
||
#region Public Properties | ||
|
||
/// <summary> | ||
/// Sets or returns a boolean indicating whether or not this instance has been disposed. | ||
/// </summary> | ||
/// <seealso cref="Dispose()"/> | ||
public bool IsDisposed | ||
{ | ||
get; | ||
private set; | ||
} | ||
|
||
#endregion | ||
|
||
#region IDisposable Members | ||
|
||
/// <summary> | ||
/// Disposes this object instance and all internally managed resources. | ||
/// </summary> | ||
/// <remarks> | ||
/// <para>Sets the <see cref="IsDisposed"/> property to true. Does not explicitly throw an exception if called multiple times, but makes no promises about behaviour of derived classes.</para> | ||
/// </remarks> | ||
/// <seealso cref="IsDisposed"/> | ||
public void Dispose() | ||
{ | ||
try | ||
{ | ||
IsDisposed = true; | ||
|
||
Dispose(true); | ||
} | ||
finally | ||
{ | ||
GC.SuppressFinalize(this); | ||
} | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Net.Sockets; | ||
using System.Threading.Tasks; | ||
using MediaBrowser.Model.Net; | ||
|
||
namespace Emby.Common.Implementations.Net | ||
{ | ||
public class SocketFactory : ISocketFactory | ||
{ | ||
// 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> | ||
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, 4); | ||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), _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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.