aboutsummaryrefslogtreecommitdiff
path: root/RSSDP
diff options
context:
space:
mode:
Diffstat (limited to 'RSSDP')
-rw-r--r--RSSDP/DeviceAvailableEventArgs.cs18
-rw-r--r--RSSDP/DeviceEventArgs.cs18
-rw-r--r--RSSDP/DeviceUnavailableEventArgs.cs19
-rw-r--r--RSSDP/DiscoveredSsdpDevice.cs17
-rw-r--r--RSSDP/DisposableManagedObjectBase.cs18
-rw-r--r--RSSDP/HttpParserBase.cs59
-rw-r--r--RSSDP/HttpRequestParser.cs41
-rw-r--r--RSSDP/HttpResponseParser.cs39
-rw-r--r--RSSDP/IEnumerableExtensions.cs11
-rw-r--r--RSSDP/ISsdpCommunicationsServer.cs13
-rw-r--r--RSSDP/ISsdpDeviceLocator.cs18
-rw-r--r--RSSDP/RequestReceivedEventArgs.cs13
-rw-r--r--RSSDP/ResponseReceivedEventArgs.cs14
-rw-r--r--RSSDP/SsdpCommunicationsServer.cs55
-rw-r--r--RSSDP/SsdpDevice.cs61
-rw-r--r--RSSDP/SsdpDeviceLocator.cs155
-rw-r--r--RSSDP/SsdpDevicePublisher.cs110
-rw-r--r--RSSDP/SsdpEmbeddedDevice.cs12
-rw-r--r--RSSDP/SsdpRootDevice.cs12
19 files changed, 345 insertions, 358 deletions
diff --git a/RSSDP/DeviceAvailableEventArgs.cs b/RSSDP/DeviceAvailableEventArgs.cs
index 439cee467..b7d22a7df 100644
--- a/RSSDP/DeviceAvailableEventArgs.cs
+++ b/RSSDP/DeviceAvailableEventArgs.cs
@@ -10,14 +10,9 @@ namespace Rssdp
{
public IPAddress LocalIpAddress { get; set; }
- #region Fields
-
private readonly DiscoveredSsdpDevice _DiscoveredDevice;
- private readonly bool _IsNewlyDiscovered;
- #endregion
-
- #region Constructors
+ private readonly bool _IsNewlyDiscovered;
/// <summary>
/// Full constructor.
@@ -27,16 +22,15 @@ namespace Rssdp
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception>
public DeviceAvailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool isNewlyDiscovered)
{
- if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice));
+ if (discoveredDevice == null)
+ {
+ throw new ArgumentNullException(nameof(discoveredDevice));
+ }
_DiscoveredDevice = discoveredDevice;
_IsNewlyDiscovered = isNewlyDiscovered;
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Returns true if the device was discovered due to an alive notification, or a search and was not already in the cache. Returns false if the item came from the cache but matched the current search request.
/// </summary>
@@ -52,7 +46,5 @@ namespace Rssdp
{
get { return _DiscoveredDevice; }
}
-
- #endregion
}
}
diff --git a/RSSDP/DeviceEventArgs.cs b/RSSDP/DeviceEventArgs.cs
index faeff8347..2455ccbfa 100644
--- a/RSSDP/DeviceEventArgs.cs
+++ b/RSSDP/DeviceEventArgs.cs
@@ -7,15 +7,8 @@ namespace Rssdp
/// </summary>
public sealed class DeviceEventArgs : EventArgs
{
-
- #region Fields
-
private readonly SsdpDevice _Device;
- #endregion
-
- #region Constructors
-
/// <summary>
/// Constructs a new instance for the specified <see cref="SsdpDevice"/>.
/// </summary>
@@ -23,15 +16,14 @@ namespace Rssdp
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="device"/> argument is null.</exception>
public DeviceEventArgs(SsdpDevice device)
{
- if (device == null) throw new ArgumentNullException(nameof(device));
+ if (device == null)
+ {
+ throw new ArgumentNullException(nameof(device));
+ }
_Device = device;
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Returns the <see cref="SsdpDevice"/> instance the event being raised for.
/// </summary>
@@ -39,7 +31,5 @@ namespace Rssdp
{
get { return _Device; }
}
-
- #endregion
}
}
diff --git a/RSSDP/DeviceUnavailableEventArgs.cs b/RSSDP/DeviceUnavailableEventArgs.cs
index ef04904bd..94248f39f 100644
--- a/RSSDP/DeviceUnavailableEventArgs.cs
+++ b/RSSDP/DeviceUnavailableEventArgs.cs
@@ -7,15 +7,9 @@ namespace Rssdp
/// </summary>
public sealed class DeviceUnavailableEventArgs : EventArgs
{
-
- #region Fields
-
private readonly DiscoveredSsdpDevice _DiscoveredDevice;
- private readonly bool _Expired;
-
- #endregion
- #region Constructors
+ private readonly bool _Expired;
/// <summary>
/// Full constructor.
@@ -25,16 +19,15 @@ namespace Rssdp
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception>
public DeviceUnavailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool expired)
{
- if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice));
+ if (discoveredDevice == null)
+ {
+ throw new ArgumentNullException(nameof(discoveredDevice));
+ }
_DiscoveredDevice = discoveredDevice;
_Expired = expired;
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Returns true if the device is considered unavailable because it's cached information expired before a new alive notification or search result was received. Returns false if the device is unavailable because it sent an explicit notification of it's unavailability.
/// </summary>
@@ -50,7 +43,5 @@ namespace Rssdp
{
get { return _DiscoveredDevice; }
}
-
- #endregion
}
}
diff --git a/RSSDP/DiscoveredSsdpDevice.cs b/RSSDP/DiscoveredSsdpDevice.cs
index fb323c1fb..322bd55e5 100644
--- a/RSSDP/DiscoveredSsdpDevice.cs
+++ b/RSSDP/DiscoveredSsdpDevice.cs
@@ -10,15 +10,8 @@ namespace Rssdp
/// <seealso cref="Infrastructure.ISsdpDeviceLocator"/>
public sealed class DiscoveredSsdpDevice
{
-
- #region Fields
-
private DateTimeOffset _AsAt;
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Sets or returns the type of notification, being either a uuid, device type, service type or upnp:rootdevice.
/// </summary>
@@ -60,10 +53,6 @@ namespace Rssdp
/// </summary>
public HttpHeaders ResponseHeaders { get; set; }
- #endregion
-
- #region Public Methods
-
/// <summary>
/// Returns true if this device information has expired, based on the current date/time, and the <see cref="CacheLifetime"/> &amp; <see cref="AsAt"/> properties.
/// </summary>
@@ -73,10 +62,6 @@ namespace Rssdp
return this.CacheLifetime == TimeSpan.Zero || this.AsAt.Add(this.CacheLifetime) <= DateTimeOffset.Now;
}
- #endregion
-
- #region Overrides
-
/// <summary>
/// Returns the device's <see cref="Usn"/> value.
/// </summary>
@@ -85,7 +70,5 @@ namespace Rssdp
{
return this.Usn;
}
-
- #endregion
}
}
diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs
index 39589f022..66a0c5ec4 100644
--- a/RSSDP/DisposableManagedObjectBase.cs
+++ b/RSSDP/DisposableManagedObjectBase.cs
@@ -9,9 +9,6 @@ namespace Rssdp.Infrastructure
/// </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>
@@ -26,13 +23,12 @@ namespace Rssdp.Infrastructure
/// <seealso cref="Dispose()"/>
protected virtual void ThrowIfDisposed()
{
- if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().FullName);
+ 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>
@@ -43,8 +39,6 @@ namespace Rssdp.Infrastructure
private set;
}
- #endregion
-
public string BuildMessage(string header, Dictionary<string, string> values)
{
var builder = new StringBuilder();
@@ -63,8 +57,6 @@ namespace Rssdp.Infrastructure
return builder.ToString();
}
- #region IDisposable Members
-
/// <summary>
/// Disposes this object instance and all internally managed resources.
/// </summary>
@@ -79,7 +71,5 @@ namespace Rssdp.Infrastructure
Dispose(true);
}
-
- #endregion
}
}
diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs
index e7172cb1c..a40612bc2 100644
--- a/RSSDP/HttpParserBase.cs
+++ b/RSSDP/HttpParserBase.cs
@@ -11,16 +11,9 @@ namespace Rssdp.Infrastructure
/// <typeparam name="T"></typeparam>
public abstract class HttpParserBase<T> where T : new()
{
-
- #region Fields
-
private readonly string[] LineTerminators = new string[] { "\r\n", "\n" };
private readonly char[] SeparatorCharacters = new char[] { ',', ';' };
- #endregion
-
- #region Public Methods
-
/// <summary>
/// Parses the <paramref name="data"/> provided into either a <see cref="HttpRequestMessage"/> or <see cref="HttpResponseMessage"/> object.
/// </summary>
@@ -38,9 +31,20 @@ namespace Rssdp.Infrastructure
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Honestly, it's fine. MemoryStream doesn't mind.")]
protected virtual void Parse(T message, System.Net.Http.Headers.HttpHeaders headers, string data)
{
- if (data == null) throw new ArgumentNullException(nameof(data));
- if (data.Length == 0) throw new ArgumentException("data cannot be an empty string.", nameof(data));
- if (!LineTerminators.Any(data.Contains)) throw new ArgumentException("data is not a valid request, it does not contain any CRLF/LF terminators.", nameof(data));
+ if (data == null)
+ {
+ throw new ArgumentNullException(nameof(data));
+ }
+
+ if (data.Length == 0)
+ {
+ throw new ArgumentException("data cannot be an empty string.", nameof(data));
+ }
+
+ if (!LineTerminators.Any(data.Contains))
+ {
+ throw new ArgumentException("data is not a valid request, it does not contain any CRLF/LF terminators.", nameof(data));
+ }
using (var retVal = new ByteArrayContent(Array.Empty<byte>()))
{
@@ -73,18 +77,20 @@ namespace Rssdp.Infrastructure
/// <returns>A <see cref="Version"/> object containing the parsed version data.</returns>
protected Version ParseHttpVersion(string versionData)
{
- if (versionData == null) throw new ArgumentNullException(nameof(versionData));
+ if (versionData == null)
+ {
+ throw new ArgumentNullException(nameof(versionData));
+ }
var versionSeparatorIndex = versionData.IndexOf('/');
- if (versionSeparatorIndex <= 0 || versionSeparatorIndex == versionData.Length) throw new ArgumentException("request header line is invalid. Http Version not supplied or incorrect format.", nameof(versionData));
+ if (versionSeparatorIndex <= 0 || versionSeparatorIndex == versionData.Length)
+ {
+ throw new ArgumentException("request header line is invalid. Http Version not supplied or incorrect format.", nameof(versionData));
+ }
return Version.Parse(versionData.Substring(versionSeparatorIndex + 1));
}
- #endregion
-
- #region Private Methods
-
/// <summary>
/// Parses a line from an HTTP request or response message containing a header name and value pair.
/// </summary>
@@ -108,9 +114,13 @@ namespace Rssdp.Infrastructure
var headersToAddTo = IsContentHeader(headerName) ? contentHeaders : headers;
if (values.Count > 1)
+ {
headersToAddTo.TryAddWithoutValidation(headerName, values);
+ }
else
+ {
headersToAddTo.TryAddWithoutValidation(headerName, values.First());
+ }
}
private int ParseHeaders(System.Net.Http.Headers.HttpHeaders headers, System.Net.Http.Headers.HttpHeaders contentHeaders, string[] lines)
@@ -130,7 +140,9 @@ namespace Rssdp.Infrastructure
lineIndex++;
}
else
+ {
break;
+ }
}
ParseHeader(line, headers, contentHeaders);
@@ -154,7 +166,9 @@ namespace Rssdp.Infrastructure
var indexOfSeparator = headerValue.IndexOfAny(SeparatorCharacters);
if (indexOfSeparator <= 0)
+ {
values.Add(headerValue);
+ }
else
{
var segments = headerValue.Split(SeparatorCharacters);
@@ -164,13 +178,17 @@ namespace Rssdp.Infrastructure
{
var segment = segments[segmentIndex];
if (segment.Trim().StartsWith("\"", StringComparison.OrdinalIgnoreCase))
+ {
segment = CombineQuotedSegments(segments, ref segmentIndex, segment);
+ }
values.Add(segment);
}
}
else
+ {
values.AddRange(segments);
+ }
}
return values;
@@ -193,17 +211,20 @@ namespace Rssdp.Infrastructure
}
if (index + 1 < segments.Length)
+ {
trimmedSegment += "," + segments[index + 1].TrimEnd();
+ }
}
segmentIndex = segments.Length;
if (trimmedSegment.StartsWith("\"", StringComparison.OrdinalIgnoreCase) && trimmedSegment.EndsWith("\"", StringComparison.OrdinalIgnoreCase))
+ {
return trimmedSegment.Substring(1, trimmedSegment.Length - 2);
+ }
else
+ {
return trimmedSegment;
+ }
}
-
- #endregion
-
}
}
diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs
index 3fc328b8c..4114195a6 100644
--- a/RSSDP/HttpRequestParser.cs
+++ b/RSSDP/HttpRequestParser.cs
@@ -9,17 +9,10 @@ namespace Rssdp.Infrastructure
/// </summary>
public sealed class HttpRequestParser : HttpParserBase<HttpRequestMessage>
{
-
- #region Fields & Constants
-
private readonly string[] ContentHeaderNames = new string[]
- {
- "Allow", "Content-Disposition", "Content-Encoding", "Content-Language", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type", "Expires", "Last-Modified"
- };
-
- #endregion
-
- #region Public Methods
+ {
+ "Allow", "Content-Disposition", "Content-Encoding", "Content-Language", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type", "Expires", "Last-Modified"
+ };
/// <summary>
/// Parses the specified data into a <see cref="HttpRequestMessage"/> instance.
@@ -41,14 +34,12 @@ namespace Rssdp.Infrastructure
finally
{
if (retVal != null)
+ {
retVal.Dispose();
+ }
}
}
- #endregion
-
- #region Overrides
-
/// <summary>
/// Used to parse the first line of an HTTP request or response and assign the values to the appropriate properties on the <paramref name="message"/>.
/// </summary>
@@ -56,18 +47,32 @@ namespace Rssdp.Infrastructure
/// <param name="message">Either a <see cref="HttpResponseMessage"/> or <see cref="HttpRequestMessage"/> to assign the parsed values to.</param>
protected override void ParseStatusLine(string data, HttpRequestMessage message)
{
- if (data == null) throw new ArgumentNullException(nameof(data));
- if (message == null) throw new ArgumentNullException(nameof(message));
+ if (data == null)
+ {
+ throw new ArgumentNullException(nameof(data));
+ }
+
+ if (message == null)
+ {
+ throw new ArgumentNullException(nameof(message));
+ }
var parts = data.Split(' ');
- if (parts.Length < 2) throw new ArgumentException("Status line is invalid. Insufficient status parts.", nameof(data));
+ if (parts.Length < 2)
+ {
+ throw new ArgumentException("Status line is invalid. Insufficient status parts.", nameof(data));
+ }
message.Method = new HttpMethod(parts[0].Trim());
Uri requestUri;
if (Uri.TryCreate(parts[1].Trim(), UriKind.RelativeOrAbsolute, out requestUri))
+ {
message.RequestUri = requestUri;
+ }
else
+ {
System.Diagnostics.Debug.WriteLine(parts[1]);
+ }
if (parts.Length >= 3)
{
@@ -83,7 +88,5 @@ namespace Rssdp.Infrastructure
{
return ContentHeaderNames.Contains(headerName, StringComparer.OrdinalIgnoreCase);
}
-
- #endregion
}
}
diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs
index b96eaf625..0dd4bb45a 100644
--- a/RSSDP/HttpResponseParser.cs
+++ b/RSSDP/HttpResponseParser.cs
@@ -10,17 +10,10 @@ namespace Rssdp.Infrastructure
/// </summary>
public sealed class HttpResponseParser : HttpParserBase<HttpResponseMessage>
{
-
- #region Fields & Constants
-
private readonly string[] ContentHeaderNames = new string[]
- {
- "Allow", "Content-Disposition", "Content-Encoding", "Content-Language", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type", "Expires", "Last-Modified"
- };
-
- #endregion
-
- #region Public Methods
+ {
+ "Allow", "Content-Disposition", "Content-Encoding", "Content-Language", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Type", "Expires", "Last-Modified"
+ };
/// <summary>
/// Parses the specified data into a <see cref="HttpResponseMessage"/> instance.
@@ -41,16 +34,14 @@ namespace Rssdp.Infrastructure
catch
{
if (retVal != null)
+ {
retVal.Dispose();
+ }
throw;
}
}
- #endregion
-
- #region Overrides Methods
-
/// <summary>
/// Returns a boolean indicating whether the specified HTTP header name represents a content header (true), or a message header (false).
/// </summary>
@@ -68,17 +59,29 @@ namespace Rssdp.Infrastructure
/// <param name="message">Either a <see cref="HttpResponseMessage"/> or <see cref="HttpRequestMessage"/> to assign the parsed values to.</param>
protected override void ParseStatusLine(string data, HttpResponseMessage message)
{
- if (data == null) throw new ArgumentNullException(nameof(data));
- if (message == null) throw new ArgumentNullException(nameof(message));
+ if (data == null)
+ {
+ throw new ArgumentNullException(nameof(data));
+ }
+
+ if (message == null)
+ {
+ throw new ArgumentNullException(nameof(message));
+ }
var parts = data.Split(' ');
- if (parts.Length < 2) throw new ArgumentException("data status line is invalid. Insufficient status parts.", nameof(data));
+ if (parts.Length < 2)
+ {
+ throw new ArgumentException("data status line is invalid. Insufficient status parts.", nameof(data));
+ }
message.Version = ParseHttpVersion(parts[0].Trim());
int statusCode = -1;
if (!Int32.TryParse(parts[1].Trim(), out statusCode))
+ {
throw new ArgumentException("data status line is invalid. Status code is not a valid integer.", nameof(data));
+ }
message.StatusCode = (HttpStatusCode)statusCode;
@@ -87,7 +90,5 @@ namespace Rssdp.Infrastructure
message.ReasonPhrase = parts[2].Trim();
}
}
-
- #endregion
}
}
diff --git a/RSSDP/IEnumerableExtensions.cs b/RSSDP/IEnumerableExtensions.cs
index 371454893..1f0daad3e 100644
--- a/RSSDP/IEnumerableExtensions.cs
+++ b/RSSDP/IEnumerableExtensions.cs
@@ -8,8 +8,15 @@ namespace Rssdp.Infrastructure
{
public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
{
- if (source == null) throw new ArgumentNullException(nameof(source));
- if (selector == null) throw new ArgumentNullException(nameof(selector));
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ if (selector == null)
+ {
+ throw new ArgumentNullException(nameof(selector));
+ }
return !source.Any() ? source :
source.Concat(
diff --git a/RSSDP/ISsdpCommunicationsServer.cs b/RSSDP/ISsdpCommunicationsServer.cs
index 02c3af0e5..aa35811ef 100644
--- a/RSSDP/ISsdpCommunicationsServer.cs
+++ b/RSSDP/ISsdpCommunicationsServer.cs
@@ -10,9 +10,6 @@ namespace Rssdp.Infrastructure
/// </summary>
public interface ISsdpCommunicationsServer : IDisposable
{
-
- #region Events
-
/// <summary>
/// Raised when a HTTPU request message is received by a socket (unicast or multicast).
/// </summary>
@@ -23,10 +20,6 @@ namespace Rssdp.Infrastructure
/// </summary>
event EventHandler<ResponseReceivedEventArgs> ResponseReceived;
- #endregion
-
- #region Methods
-
/// <summary>
/// Causes the server to begin listening for multicast messages, being SSDP search requests and notifications.
/// </summary>
@@ -48,10 +41,6 @@ namespace Rssdp.Infrastructure
Task SendMulticastMessage(string message, IPAddress fromLocalIpAddress, CancellationToken cancellationToken);
Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken);
- #endregion
-
- #region Properties
-
/// <summary>
/// Gets or sets a boolean value indicating whether or not this instance is shared amongst multiple <see cref="SsdpDeviceLocatorBase"/> and/or <see cref="ISsdpDevicePublisher"/> instances.
/// </summary>
@@ -59,7 +48,5 @@ namespace Rssdp.Infrastructure
/// <para>If true, disposing an instance of a <see cref="SsdpDeviceLocatorBase"/>or a <see cref="ISsdpDevicePublisher"/> will not dispose this comms server instance. The calling code is responsible for managing the lifetime of the server.</para>
/// </remarks>
bool IsShared { get; set; }
-
- #endregion
}
}
diff --git a/RSSDP/ISsdpDeviceLocator.cs b/RSSDP/ISsdpDeviceLocator.cs
index 8f0d39e75..413055643 100644
--- a/RSSDP/ISsdpDeviceLocator.cs
+++ b/RSSDP/ISsdpDeviceLocator.cs
@@ -13,9 +13,6 @@ namespace Rssdp.Infrastructure
/// <seealso cref="ISsdpDevicePublisher"/>
public interface ISsdpDeviceLocator
{
-
- #region Events
-
/// <summary>
/// Event raised when a device becomes available or is found by a search request.
/// </summary>
@@ -34,10 +31,6 @@ namespace Rssdp.Infrastructure
/// <seealso cref="StopListeningForNotifications"/>
event EventHandler<DeviceUnavailableEventArgs> DeviceUnavailable;
- #endregion
-
- #region Properties
-
/// <summary>
/// Sets or returns a string containing the filter for notifications. Notifications not matching the filter will not raise the <see cref="DeviceAvailable"/> or <see cref="DeviceUnavailable"/> events.
/// </summary>
@@ -58,12 +51,6 @@ namespace Rssdp.Infrastructure
set;
}
- #endregion
-
- #region Methods
-
- #region SearchAsync Overloads
-
/// <summary>
/// Aynchronously performs a search for all devices using the default search timeout, and returns an awaitable task that can be used to retrieve the results.
/// </summary>
@@ -108,8 +95,6 @@ namespace Rssdp.Infrastructure
/// <returns>A task whose result is an <see cref="System.Collections.Generic.IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<DiscoveredSsdpDevice>> SearchAsync(TimeSpan searchWaitTime);
- #endregion
-
/// <summary>
/// Starts listening for broadcast notifications of service availability.
/// </summary>
@@ -134,8 +119,5 @@ namespace Rssdp.Infrastructure
/// <seealso cref="DeviceUnavailable"/>
/// <seealso cref="NotificationFilter"/>
void StopListeningForNotifications();
-
- #endregion
-
}
}
diff --git a/RSSDP/RequestReceivedEventArgs.cs b/RSSDP/RequestReceivedEventArgs.cs
index b753950f0..025c4d2e0 100644
--- a/RSSDP/RequestReceivedEventArgs.cs
+++ b/RSSDP/RequestReceivedEventArgs.cs
@@ -9,17 +9,12 @@ namespace Rssdp.Infrastructure
/// </summary>
public sealed class RequestReceivedEventArgs : EventArgs
{
- #region Fields
-
private readonly HttpRequestMessage _Message;
- private readonly IPEndPoint _ReceivedFrom;
- #endregion
+ private readonly IPEndPoint _ReceivedFrom;
public IPAddress LocalIpAddress { get; private set; }
- #region Constructors
-
/// <summary>
/// Full constructor.
/// </summary>
@@ -30,10 +25,6 @@ namespace Rssdp.Infrastructure
LocalIpAddress = localIpAddress;
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// The <see cref="HttpRequestMessage"/> that was received.
/// </summary>
@@ -49,7 +40,5 @@ namespace Rssdp.Infrastructure
{
get { return _ReceivedFrom; }
}
-
- #endregion
}
}
diff --git a/RSSDP/ResponseReceivedEventArgs.cs b/RSSDP/ResponseReceivedEventArgs.cs
index f9f9c3040..708113da1 100644
--- a/RSSDP/ResponseReceivedEventArgs.cs
+++ b/RSSDP/ResponseReceivedEventArgs.cs
@@ -9,17 +9,11 @@ namespace Rssdp.Infrastructure
/// </summary>
public sealed class ResponseReceivedEventArgs : EventArgs
{
-
public IPAddress LocalIpAddress { get; set; }
- #region Fields
-
private readonly HttpResponseMessage _Message;
- private readonly IPEndPoint _ReceivedFrom;
-
- #endregion
- #region Constructors
+ private readonly IPEndPoint _ReceivedFrom;
/// <summary>
/// Full constructor.
@@ -30,10 +24,6 @@ namespace Rssdp.Infrastructure
_ReceivedFrom = receivedFrom;
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// The <see cref="HttpResponseMessage"/> that was received.
/// </summary>
@@ -49,7 +39,5 @@ namespace Rssdp.Infrastructure
{
get { return _ReceivedFrom; }
}
-
- #endregion
}
}
diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs
index fe49fb7d3..e4c4a2017 100644
--- a/RSSDP/SsdpCommunicationsServer.cs
+++ b/RSSDP/SsdpCommunicationsServer.cs
@@ -19,9 +19,6 @@ namespace Rssdp.Infrastructure
/// </summary>
public sealed class SsdpCommunicationsServer : DisposableManagedObjectBase, ISsdpCommunicationsServer
{
-
- #region Fields
-
/* We could technically use one socket listening on port 1900 for everything.
* This should get both multicast (notifications) and unicast (search response) messages, however
* this often doesn't work under Windows because the MS SSDP service is running. If that service
@@ -55,10 +52,6 @@ namespace Rssdp.Infrastructure
private bool _IsShared;
private readonly bool _enableMultiSocketBinding;
- #endregion
-
- #region Events
-
/// <summary>
/// Raised when a HTTPU request message is received by a socket (unicast or multicast).
/// </summary>
@@ -69,10 +62,6 @@ namespace Rssdp.Infrastructure
/// </summary>
public event EventHandler<ResponseReceivedEventArgs> ResponseReceived;
- #endregion
-
- #region Constructors
-
/// <summary>
/// Minimum constructor.
/// </summary>
@@ -91,8 +80,15 @@ namespace Rssdp.Infrastructure
/// <exception cref="ArgumentOutOfRangeException">The <paramref name="multicastTimeToLive"/> argument is less than or equal to zero.</exception>
public SsdpCommunicationsServer(ISocketFactory socketFactory, int localPort, int multicastTimeToLive, INetworkManager networkManager, ILogger logger, bool enableMultiSocketBinding)
{
- if (socketFactory == null) throw new ArgumentNullException(nameof(socketFactory));
- if (multicastTimeToLive <= 0) throw new ArgumentOutOfRangeException(nameof(multicastTimeToLive), "multicastTimeToLive must be greater than zero.");
+ if (socketFactory == null)
+ {
+ throw new ArgumentNullException(nameof(socketFactory));
+ }
+
+ if (multicastTimeToLive <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(multicastTimeToLive), "multicastTimeToLive must be greater than zero.");
+ }
_BroadcastListenSocketSynchroniser = new object();
_SendSocketSynchroniser = new object();
@@ -109,10 +105,6 @@ namespace Rssdp.Infrastructure
_enableMultiSocketBinding = enableMultiSocketBinding;
}
- #endregion
-
- #region Public Methods
-
/// <summary>
/// Causes the server to begin listening for multicast messages, being SSDP search requests and notifications.
/// </summary>
@@ -166,7 +158,10 @@ namespace Rssdp.Infrastructure
/// </summary>
public async Task SendMessage(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
{
- if (messageData == null) throw new ArgumentNullException(nameof(messageData));
+ if (messageData == null)
+ {
+ throw new ArgumentNullException(nameof(messageData));
+ }
ThrowIfDisposed();
@@ -249,7 +244,10 @@ namespace Rssdp.Infrastructure
/// </summary>
public async Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
{
- if (message == null) throw new ArgumentNullException(nameof(message));
+ if (message == null)
+ {
+ throw new ArgumentNullException(nameof(message));
+ }
byte[] messageData = Encoding.UTF8.GetBytes(message);
@@ -298,10 +296,6 @@ namespace Rssdp.Infrastructure
}
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Gets or sets a boolean value indicating whether or not this instance is shared amongst multiple <see cref="SsdpDeviceLocatorBase"/> and/or <see cref="ISsdpDevicePublisher"/> instances.
/// </summary>
@@ -315,10 +309,6 @@ namespace Rssdp.Infrastructure
set { _IsShared = value; }
}
- #endregion
-
- #region Overrides
-
/// <summary>
/// Stops listening for requests, disposes this instance and all internal resources.
/// </summary>
@@ -333,10 +323,6 @@ namespace Rssdp.Infrastructure
}
}
- #endregion
-
- #region Private Methods
-
private Task SendMessageIfSocketNotDisposed(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
{
var sockets = _sendSockets;
@@ -494,20 +480,21 @@ namespace Rssdp.Infrastructure
var handlers = this.RequestReceived;
if (handlers != null)
+ {
handlers(this, new RequestReceivedEventArgs(data, remoteEndPoint, receivedOnLocalIpAddress));
+ }
}
private void OnResponseReceived(HttpResponseMessage data, IPEndPoint endPoint, IPAddress localIpAddress)
{
var handlers = this.ResponseReceived;
if (handlers != null)
+ {
handlers(this, new ResponseReceivedEventArgs(data, endPoint)
{
LocalIpAddress = localIpAddress
});
+ }
}
-
- #endregion
-
}
}
diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs
index f89bafb19..4005d836d 100644
--- a/RSSDP/SsdpDevice.cs
+++ b/RSSDP/SsdpDevice.cs
@@ -15,9 +15,6 @@ namespace Rssdp
/// <seealso cref="SsdpEmbeddedDevice"/>
public abstract class SsdpDevice
{
-
- #region Fields
-
private string _Udn;
private string _DeviceType;
private string _DeviceTypeNamespace;
@@ -25,10 +22,6 @@ namespace Rssdp
private IList<SsdpDevice> _Devices;
- #endregion
-
- #region Events
-
/// <summary>
/// Raised when a new child device is added.
/// </summary>
@@ -43,10 +36,6 @@ namespace Rssdp
/// <seealso cref="DeviceRemoved"/>
public event EventHandler<DeviceEventArgs> DeviceRemoved;
- #endregion
-
- #region Constructors
-
/// <summary>
/// Derived type constructor, allows constructing a device with no parent. Should only be used from derived types that are or inherit from <see cref="SsdpRootDevice"/>.
/// </summary>
@@ -60,23 +49,19 @@ namespace Rssdp
this.Devices = new ReadOnlyCollection<SsdpDevice>(_Devices);
}
- #endregion
-
public SsdpRootDevice ToRootDevice()
{
var device = this;
var rootDevice = device as SsdpRootDevice;
if (rootDevice == null)
+ {
rootDevice = ((SsdpEmbeddedDevice)device).RootDevice;
+ }
return rootDevice;
}
- #region Public Properties
-
- #region UPnP Device Description Properties
-
/// <summary>
/// Sets or returns the core device type (not including namespace, version etc.). Required.
/// </summary>
@@ -180,9 +165,13 @@ namespace Rssdp
get
{
if (String.IsNullOrEmpty(_Udn) && !String.IsNullOrEmpty(this.Uuid))
+ {
return "uuid:" + this.Uuid;
+ }
else
+ {
return _Udn;
+ }
}
set
@@ -252,8 +241,6 @@ namespace Rssdp
/// </remarks>
public Uri PresentationUrl { get; set; }
- #endregion
-
/// <summary>
/// Returns a read-only enumerable set of <see cref="SsdpDevice"/> objects representing children of this device. Child devices are optional.
/// </summary>
@@ -265,10 +252,6 @@ namespace Rssdp
private set;
}
- #endregion
-
- #region Public Methods
-
/// <summary>
/// Adds a child device to the <see cref="Devices"/> collection.
/// </summary>
@@ -282,9 +265,20 @@ namespace Rssdp
/// <seealso cref="DeviceAdded"/>
public void AddDevice(SsdpEmbeddedDevice device)
{
- if (device == null) throw new ArgumentNullException(nameof(device));
- if (device.RootDevice != null && device.RootDevice != this.ToRootDevice()) throw new InvalidOperationException("This device is already associated with a different root device (has been added as a child in another branch).");
- if (device == this) throw new InvalidOperationException("Can't add device to itself.");
+ if (device == null)
+ {
+ throw new ArgumentNullException(nameof(device));
+ }
+
+ if (device.RootDevice != null && device.RootDevice != this.ToRootDevice())
+ {
+ throw new InvalidOperationException("This device is already associated with a different root device (has been added as a child in another branch).");
+ }
+
+ if (device == this)
+ {
+ throw new InvalidOperationException("Can't add device to itself.");
+ }
bool wasAdded = false;
lock (_Devices)
@@ -295,7 +289,9 @@ namespace Rssdp
}
if (wasAdded)
+ {
OnDeviceAdded(device);
+ }
}
/// <summary>
@@ -310,7 +306,10 @@ namespace Rssdp
/// <seealso cref="DeviceRemoved"/>
public void RemoveDevice(SsdpEmbeddedDevice device)
{
- if (device == null) throw new ArgumentNullException(nameof(device));
+ if (device == null)
+ {
+ throw new ArgumentNullException(nameof(device));
+ }
bool wasRemoved = false;
lock (_Devices)
@@ -323,7 +322,9 @@ namespace Rssdp
}
if (wasRemoved)
+ {
OnDeviceRemoved(device);
+ }
}
/// <summary>
@@ -336,7 +337,9 @@ namespace Rssdp
{
var handlers = this.DeviceAdded;
if (handlers != null)
+ {
handlers(this, new DeviceEventArgs(device));
+ }
}
/// <summary>
@@ -349,9 +352,9 @@ namespace Rssdp
{
var handlers = this.DeviceRemoved;
if (handlers != null)
+ {
handlers(this, new DeviceEventArgs(device));
+ }
}
-
- #endregion
}
}
diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs
index 9b48cf31c..38562ce49 100644
--- a/RSSDP/SsdpDeviceLocator.cs
+++ b/RSSDP/SsdpDeviceLocator.cs
@@ -13,9 +13,6 @@ namespace Rssdp.Infrastructure
/// </summary>
public class SsdpDeviceLocator : DisposableManagedObjectBase
{
-
- #region Fields & Constants
-
private List<DiscoveredSsdpDevice> _Devices;
private ISsdpCommunicationsServer _CommunicationsServer;
@@ -25,16 +22,15 @@ namespace Rssdp.Infrastructure
private readonly TimeSpan DefaultSearchWaitTime = TimeSpan.FromSeconds(4);
private readonly TimeSpan OneSecond = TimeSpan.FromSeconds(1);
- #endregion
-
- #region Constructors
-
/// <summary>
/// Default constructor.
/// </summary>
public SsdpDeviceLocator(ISsdpCommunicationsServer communicationsServer)
{
- if (communicationsServer == null) throw new ArgumentNullException(nameof(communicationsServer));
+ if (communicationsServer == null)
+ {
+ throw new ArgumentNullException(nameof(communicationsServer));
+ }
_CommunicationsServer = communicationsServer;
_CommunicationsServer.ResponseReceived += CommsServer_ResponseReceived;
@@ -42,10 +38,6 @@ namespace Rssdp.Infrastructure
_Devices = new List<DiscoveredSsdpDevice>();
}
- #endregion
-
- #region Events
-
/// <summary>
/// Raised for when
/// <list type="bullet">
@@ -76,12 +68,6 @@ namespace Rssdp.Infrastructure
/// <seealso cref="StopListeningForNotifications"/>
public event EventHandler<DeviceUnavailableEventArgs> DeviceUnavailable;
- #endregion
-
- #region Public Methods
-
- #region Search Overloads
-
public void RestartBroadcastTimer(TimeSpan dueTime, TimeSpan period)
{
lock (_timerLock)
@@ -157,18 +143,31 @@ namespace Rssdp.Infrastructure
private Task SearchAsync(string searchTarget, TimeSpan searchWaitTime, CancellationToken cancellationToken)
{
- if (searchTarget == null) throw new ArgumentNullException(nameof(searchTarget));
- if (searchTarget.Length == 0) throw new ArgumentException("searchTarget cannot be an empty string.", nameof(searchTarget));
- if (searchWaitTime.TotalSeconds < 0) throw new ArgumentException("searchWaitTime must be a positive time.");
- if (searchWaitTime.TotalSeconds > 0 && searchWaitTime.TotalSeconds <= 1) throw new ArgumentException("searchWaitTime must be zero (if you are not using the result and relying entirely in the events), or greater than one second.");
+ if (searchTarget == null)
+ {
+ throw new ArgumentNullException(nameof(searchTarget));
+ }
+
+ if (searchTarget.Length == 0)
+ {
+ throw new ArgumentException("searchTarget cannot be an empty string.", nameof(searchTarget));
+ }
+
+ if (searchWaitTime.TotalSeconds < 0)
+ {
+ throw new ArgumentException("searchWaitTime must be a positive time.");
+ }
+
+ if (searchWaitTime.TotalSeconds > 0 && searchWaitTime.TotalSeconds <= 1)
+ {
+ throw new ArgumentException("searchWaitTime must be zero (if you are not using the result and relying entirely in the events), or greater than one second.");
+ }
ThrowIfDisposed();
return BroadcastDiscoverMessage(searchTarget, SearchTimeToMXValue(searchWaitTime), cancellationToken);
}
- #endregion
-
/// <summary>
/// Starts listening for broadcast notifications of service availability.
/// </summary>
@@ -211,14 +210,19 @@ namespace Rssdp.Infrastructure
/// <seealso cref="DeviceAvailable"/>
protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress)
{
- if (this.IsDisposed) return;
+ if (this.IsDisposed)
+ {
+ return;
+ }
var handlers = this.DeviceAvailable;
if (handlers != null)
+ {
handlers(this, new DeviceAvailableEventArgs(device, isNewDevice)
{
LocalIpAddress = localIpAddress
});
+ }
}
/// <summary>
@@ -229,17 +233,18 @@ namespace Rssdp.Infrastructure
/// <seealso cref="DeviceUnavailable"/>
protected virtual void OnDeviceUnavailable(DiscoveredSsdpDevice device, bool expired)
{
- if (this.IsDisposed) return;
+ if (this.IsDisposed)
+ {
+ return;
+ }
var handlers = this.DeviceUnavailable;
if (handlers != null)
+ {
handlers(this, new DeviceUnavailableEventArgs(device, expired));
+ }
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Sets or returns a string containing the filter for notifications. Notifications not matching the filter will not raise the <see cref="ISsdpDeviceLocator.DeviceAvailable"/> or <see cref="ISsdpDeviceLocator.DeviceUnavailable"/> events.
/// </summary>
@@ -261,10 +266,6 @@ namespace Rssdp.Infrastructure
set;
}
- #endregion
-
- #region Overrides
-
/// <summary>
/// Disposes this object and all internal resources. Stops listening for all network messages.
/// </summary>
@@ -285,12 +286,6 @@ namespace Rssdp.Infrastructure
}
}
- #endregion
-
- #region Private Methods
-
- #region Discovery/Device Add
-
private void AddOrUpdateDiscoveredDevice(DiscoveredSsdpDevice device, IPAddress localIpAddress)
{
bool isNewDevice = false;
@@ -314,7 +309,10 @@ namespace Rssdp.Infrastructure
private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress)
{
- if (!NotificationTypeMatchesFilter(device)) return;
+ if (!NotificationTypeMatchesFilter(device))
+ {
+ return;
+ }
OnDeviceAvailable(device, isNewDevice, localIpAddress);
}
@@ -326,10 +324,6 @@ namespace Rssdp.Infrastructure
|| device.NotificationType == this.NotificationFilter;
}
- #endregion
-
- #region Network Message Processing
-
private Task BroadcastDiscoverMessage(string serviceType, TimeSpan mxValue, CancellationToken cancellationToken)
{
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@@ -355,7 +349,10 @@ namespace Rssdp.Infrastructure
private void ProcessSearchResponseMessage(HttpResponseMessage message, IPAddress localIpAddress)
{
- if (!message.IsSuccessStatusCode) return;
+ if (!message.IsSuccessStatusCode)
+ {
+ return;
+ }
var location = GetFirstHeaderUriValue("Location", message);
if (location != null)
@@ -376,13 +373,20 @@ namespace Rssdp.Infrastructure
private void ProcessNotificationMessage(HttpRequestMessage message, IPAddress localIpAddress)
{
- if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0) return;
+ if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0)
+ {
+ return;
+ }
var notificationType = GetFirstHeaderStringValue("NTS", message);
if (String.Compare(notificationType, SsdpConstants.SsdpKeepAliveNotification, StringComparison.OrdinalIgnoreCase) == 0)
+ {
ProcessAliveNotification(message, localIpAddress);
+ }
else if (String.Compare(notificationType, SsdpConstants.SsdpByeByeNotification, StringComparison.OrdinalIgnoreCase) == 0)
+ {
ProcessByeByeNotification(message);
+ }
}
private void ProcessAliveNotification(HttpRequestMessage message, IPAddress localIpAddress)
@@ -424,13 +428,13 @@ namespace Rssdp.Infrastructure
};
if (NotificationTypeMatchesFilter(deadDevice))
+ {
OnDeviceUnavailable(deadDevice, false);
+ }
}
}
}
- #region Header/Message Processing Utilities
-
private string GetFirstHeaderStringValue(string headerName, HttpResponseMessage message)
{
string retVal = null;
@@ -439,7 +443,9 @@ namespace Rssdp.Infrastructure
{
message.Headers.TryGetValues(headerName, out values);
if (values != null)
+ {
retVal = values.FirstOrDefault();
+ }
}
return retVal;
@@ -453,7 +459,9 @@ namespace Rssdp.Infrastructure
{
message.Headers.TryGetValues(headerName, out values);
if (values != null)
+ {
retVal = values.FirstOrDefault();
+ }
}
return retVal;
@@ -467,7 +475,9 @@ namespace Rssdp.Infrastructure
{
request.Headers.TryGetValues(headerName, out values);
if (values != null)
+ {
value = values.FirstOrDefault();
+ }
}
Uri retVal;
@@ -483,7 +493,9 @@ namespace Rssdp.Infrastructure
{
response.Headers.TryGetValues(headerName, out values);
if (values != null)
+ {
value = values.FirstOrDefault();
+ }
}
Uri retVal;
@@ -493,20 +505,20 @@ namespace Rssdp.Infrastructure
private TimeSpan CacheAgeFromHeader(System.Net.Http.Headers.CacheControlHeaderValue headerValue)
{
- if (headerValue == null) return TimeSpan.Zero;
+ if (headerValue == null)
+ {
+ return TimeSpan.Zero;
+ }
return (TimeSpan)(headerValue.MaxAge ?? headerValue.SharedMaxAge ?? TimeSpan.Zero);
}
- #endregion
-
- #endregion
-
- #region Expiry and Device Removal
-
private void RemoveExpiredDevicesFromCache()
{
- if (this.IsDisposed) return;
+ if (this.IsDisposed)
+ {
+ return;
+ }
DiscoveredSsdpDevice[] expiredDevices = null;
lock (_Devices)
@@ -515,7 +527,10 @@ namespace Rssdp.Infrastructure
foreach (var device in expiredDevices)
{
- if (this.IsDisposed) return;
+ if (this.IsDisposed)
+ {
+ return;
+ }
_Devices.Remove(device);
}
@@ -526,7 +541,10 @@ namespace Rssdp.Infrastructure
// problems.
foreach (var expiredUsn in (from expiredDevice in expiredDevices select expiredDevice.Usn).Distinct())
{
- if (this.IsDisposed) return;
+ if (this.IsDisposed)
+ {
+ return;
+ }
DeviceDied(expiredUsn, true);
}
@@ -540,7 +558,10 @@ namespace Rssdp.Infrastructure
existingDevices = FindExistingDeviceNotifications(_Devices, deviceUsn);
foreach (var existingDevice in existingDevices)
{
- if (this.IsDisposed) return true;
+ if (this.IsDisposed)
+ {
+ return true;
+ }
_Devices.Remove(existingDevice);
}
@@ -551,7 +572,9 @@ namespace Rssdp.Infrastructure
foreach (var removedDevice in existingDevices)
{
if (NotificationTypeMatchesFilter(removedDevice))
+ {
OnDeviceUnavailable(removedDevice, expired);
+ }
}
return true;
@@ -560,14 +583,16 @@ namespace Rssdp.Infrastructure
return false;
}
- #endregion
-
private TimeSpan SearchTimeToMXValue(TimeSpan searchWaitTime)
{
if (searchWaitTime.TotalSeconds < 2 || searchWaitTime == TimeSpan.Zero)
+ {
return OneSecond;
+ }
else
+ {
return searchWaitTime.Subtract(OneSecond);
+ }
}
private DiscoveredSsdpDevice FindExistingDeviceNotification(IEnumerable<DiscoveredSsdpDevice> devices, string notificationType, string usn)
@@ -598,10 +623,6 @@ namespace Rssdp.Infrastructure
return list;
}
- #endregion
-
- #region Event Handlers
-
private void CommsServer_ResponseReceived(object sender, ResponseReceivedEventArgs e)
{
ProcessSearchResponseMessage(e.Message, e.LocalIpAddress);
@@ -611,7 +632,5 @@ namespace Rssdp.Infrastructure
{
ProcessNotificationMessage(e.Message, e.LocalIpAddress);
}
-
- #endregion
}
}
diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs
index b4cf2fb48..1a8577d8d 100644
--- a/RSSDP/SsdpDevicePublisher.cs
+++ b/RSSDP/SsdpDevicePublisher.cs
@@ -40,12 +40,35 @@ namespace Rssdp.Infrastructure
public SsdpDevicePublisher(ISsdpCommunicationsServer communicationsServer, INetworkManager networkManager,
string osName, string osVersion, bool sendOnlyMatchedHost)
{
- if (communicationsServer == null) throw new ArgumentNullException(nameof(communicationsServer));
- if (networkManager == null) throw new ArgumentNullException(nameof(networkManager));
- if (osName == null) throw new ArgumentNullException(nameof(osName));
- if (osName.Length == 0) throw new ArgumentException("osName cannot be an empty string.", nameof(osName));
- if (osVersion == null) throw new ArgumentNullException(nameof(osVersion));
- if (osVersion.Length == 0) throw new ArgumentException("osVersion cannot be an empty string.", nameof(osName));
+ if (communicationsServer == null)
+ {
+ throw new ArgumentNullException(nameof(communicationsServer));
+ }
+
+ if (networkManager == null)
+ {
+ throw new ArgumentNullException(nameof(networkManager));
+ }
+
+ if (osName == null)
+ {
+ throw new ArgumentNullException(nameof(osName));
+ }
+
+ if (osName.Length == 0)
+ {
+ throw new ArgumentException("osName cannot be an empty string.", nameof(osName));
+ }
+
+ if (osVersion == null)
+ {
+ throw new ArgumentNullException(nameof(osVersion));
+ }
+
+ if (osVersion.Length == 0)
+ {
+ throw new ArgumentException("osVersion cannot be an empty string.", nameof(osName));
+ }
_SupportPnpRootDevice = true;
_Devices = new List<SsdpRootDevice>();
@@ -82,7 +105,10 @@ namespace Rssdp.Infrastructure
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "t", Justification = "Capture task to local variable supresses compiler warning, but task is not really needed.")]
public void AddDevice(SsdpRootDevice device)
{
- if (device == null) throw new ArgumentNullException(nameof(device));
+ if (device == null)
+ {
+ throw new ArgumentNullException(nameof(device));
+ }
ThrowIfDisposed();
@@ -115,7 +141,10 @@ namespace Rssdp.Infrastructure
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="device"/> argument is null.</exception>
public async Task RemoveDevice(SsdpRootDevice device)
{
- if (device == null) throw new ArgumentNullException(nameof(device));
+ if (device == null)
+ {
+ throw new ArgumentNullException(nameof(device));
+ }
bool wasRemoved = false;
lock (_Devices)
@@ -186,7 +215,9 @@ namespace Rssdp.Infrastructure
if (commsServer != null)
{
if (!commsServer.IsShared)
+ {
commsServer.Dispose();
+ }
}
_RecentSearchRequests = null;
@@ -227,10 +258,15 @@ namespace Rssdp.Infrastructure
// return;
}
- if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0) return;
+ if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0)
+ {
+ return;
+ }
if (maxWaitInterval > 120)
+ {
maxWaitInterval = _Random.Next(0, 120);
+ }
// Do not block synchronously as that may tie up a threadpool thread for several seconds.
Task.Delay(_Random.Next(16, (maxWaitInterval * 1000))).ContinueWith((parentTask) =>
@@ -240,13 +276,21 @@ namespace Rssdp.Infrastructure
lock (_Devices)
{
if (String.Compare(SsdpConstants.SsdpDiscoverAllSTHeader, searchTarget, StringComparison.OrdinalIgnoreCase) == 0)
+ {
devices = GetAllDevicesAsFlatEnumerable().ToArray();
+ }
else if (String.Compare(SsdpConstants.UpnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0 || (this.SupportPnpRootDevice && String.Compare(SsdpConstants.PnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0))
+ {
devices = _Devices.ToArray();
+ }
else if (searchTarget.Trim().StartsWith("uuid:", StringComparison.OrdinalIgnoreCase))
+ {
devices = (from device in GetAllDevicesAsFlatEnumerable() where String.Compare(device.Uuid, searchTarget.Substring(5), StringComparison.OrdinalIgnoreCase) == 0 select device).ToArray();
+ }
else if (searchTarget.StartsWith("urn:", StringComparison.OrdinalIgnoreCase))
+ {
devices = (from device in GetAllDevicesAsFlatEnumerable() where String.Compare(device.FullDeviceType, searchTarget, StringComparison.OrdinalIgnoreCase) == 0 select device).ToArray();
+ }
}
if (devices != null)
@@ -286,7 +330,9 @@ namespace Rssdp.Infrastructure
{
SendSearchResponse(SsdpConstants.UpnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress, cancellationToken);
if (this.SupportPnpRootDevice)
+ {
SendSearchResponse(SsdpConstants.PnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress, cancellationToken);
+ }
}
SendSearchResponse(device.Udn, device, device.Udn, endPoint, receivedOnlocalIpAddress, cancellationToken);
@@ -352,15 +398,21 @@ namespace Rssdp.Infrastructure
{
var lastRequest = _RecentSearchRequests[newRequest.Key];
if (lastRequest.IsOld())
+ {
_RecentSearchRequests[newRequest.Key] = newRequest;
+ }
else
+ {
isDuplicateRequest = true;
+ }
}
else
{
_RecentSearchRequests.Add(newRequest.Key, newRequest);
if (_RecentSearchRequests.Count > 10)
+ {
CleanUpRecentSearchRequestsAsync();
+ }
}
}
@@ -382,7 +434,10 @@ namespace Rssdp.Infrastructure
{
try
{
- if (IsDisposed) return;
+ if (IsDisposed)
+ {
+ return;
+ }
// WriteTrace("Begin Sending Alive Notifications For All Devices");
@@ -394,7 +449,10 @@ namespace Rssdp.Infrastructure
foreach (var device in devices)
{
- if (IsDisposed) return;
+ if (IsDisposed)
+ {
+ return;
+ }
SendAliveNotifications(device, true, CancellationToken.None);
}
@@ -414,7 +472,9 @@ namespace Rssdp.Infrastructure
{
SendAliveNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken);
if (this.SupportPnpRootDevice)
+ {
SendAliveNotification(device, SsdpConstants.PnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), cancellationToken);
+ }
}
SendAliveNotification(device, device.Udn, device.Udn, cancellationToken);
@@ -458,7 +518,9 @@ namespace Rssdp.Infrastructure
{
tasks.Add(SendByeByeNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken));
if (this.SupportPnpRootDevice)
+ {
tasks.Add(SendByeByeNotification(device, "pnp:rootdevice", GetUsn(device.Udn, "pnp:rootdevice"), cancellationToken));
+ }
}
tasks.Add(SendByeByeNotification(device, device.Udn, device.Udn, cancellationToken));
@@ -499,20 +561,27 @@ namespace Rssdp.Infrastructure
var timer = _RebroadcastAliveNotificationsTimer;
_RebroadcastAliveNotificationsTimer = null;
if (timer != null)
+ {
timer.Dispose();
+ }
}
private TimeSpan GetMinimumNonZeroCacheLifetime()
{
- var nonzeroCacheLifetimesQuery = (from device
- in _Devices
- where device.CacheLifetime != TimeSpan.Zero
- select device.CacheLifetime).ToList();
+ var nonzeroCacheLifetimesQuery = (
+ from device
+ in _Devices
+ where device.CacheLifetime != TimeSpan.Zero
+ select device.CacheLifetime).ToList();
if (nonzeroCacheLifetimesQuery.Any())
+ {
return nonzeroCacheLifetimesQuery.Min();
+ }
else
+ {
return TimeSpan.Zero;
+ }
}
private string GetFirstHeaderValue(System.Net.Http.Headers.HttpRequestHeaders httpRequestHeaders, string headerName)
@@ -520,7 +589,9 @@ namespace Rssdp.Infrastructure
string retVal = null;
IEnumerable<String> values = null;
if (httpRequestHeaders.TryGetValues(headerName, out values) && values != null)
+ {
retVal = values.FirstOrDefault();
+ }
return retVal;
}
@@ -540,14 +611,21 @@ namespace Rssdp.Infrastructure
{
var rootDevice = device as SsdpRootDevice;
if (rootDevice != null)
+ {
WriteTrace(text + " " + device.DeviceType + " - " + device.Uuid + " - " + rootDevice.Location);
+ }
else
+ {
WriteTrace(text + " " + device.DeviceType + " - " + device.Uuid);
+ }
}
private void CommsServer_RequestReceived(object sender, RequestReceivedEventArgs e)
{
- if (this.IsDisposed) return;
+ if (this.IsDisposed)
+ {
+ return;
+ }
if (string.Equals(e.Message.Method.Method, SsdpConstants.MSearchMethod, StringComparison.OrdinalIgnoreCase))
{
diff --git a/RSSDP/SsdpEmbeddedDevice.cs b/RSSDP/SsdpEmbeddedDevice.cs
index ff644993b..f1a598111 100644
--- a/RSSDP/SsdpEmbeddedDevice.cs
+++ b/RSSDP/SsdpEmbeddedDevice.cs
@@ -5,14 +5,8 @@ namespace Rssdp
/// </summary>
public class SsdpEmbeddedDevice : SsdpDevice
{
-
- #region Fields
private SsdpRootDevice _RootDevice;
- #endregion
-
- #region Constructors
-
/// <summary>
/// Default constructor.
/// </summary>
@@ -20,10 +14,6 @@ namespace Rssdp
{
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Returns the <see cref="SsdpRootDevice"/> that is this device's first ancestor. If this device is itself an <see cref="SsdpRootDevice"/>, then returns a reference to itself.
/// </summary>
@@ -46,7 +36,5 @@ namespace Rssdp
}
}
}
-
- #endregion
}
}
diff --git a/RSSDP/SsdpRootDevice.cs b/RSSDP/SsdpRootDevice.cs
index 0f2de7b15..8937ec331 100644
--- a/RSSDP/SsdpRootDevice.cs
+++ b/RSSDP/SsdpRootDevice.cs
@@ -12,14 +12,8 @@ namespace Rssdp
/// </remarks>
public class SsdpRootDevice : SsdpDevice
{
- #region Fields
-
private Uri _UrlBase;
- #endregion
-
- #region Constructors
-
/// <summary>
/// Default constructor.
/// </summary>
@@ -27,10 +21,6 @@ namespace Rssdp
{
}
- #endregion
-
- #region Public Properties
-
/// <summary>
/// Specifies how long clients can cache this device's details for. Optional but defaults to <see cref="TimeSpan.Zero"/> which means no-caching. Recommended value is half an hour.
/// </summary>
@@ -77,7 +67,5 @@ namespace Rssdp
_UrlBase = value;
}
}
-
- #endregion
}
}