diff options
| author | Erwin de Haan <EraYaN@users.noreply.github.com> | 2019-01-11 12:50:36 +0100 |
|---|---|---|
| committer | Erwin de Haan <EraYaN@users.noreply.github.com> | 2019-01-11 12:50:36 +0100 |
| commit | e2751d42e8775596b7c4b929fd004d879f980947 (patch) | |
| tree | da1d6e703abbb6a47cd64730603f06dc4b51df8f /RSSDP | |
| parent | ec1f5dc317182582ebff843c9e8a4d5277405469 (diff) | |
| parent | e5c2dbdf23267006ef151d6ee8ab1cea147123d7 (diff) | |
Merge branch 'dev' into code-cleanup
Diffstat (limited to 'RSSDP')
| -rw-r--r-- | RSSDP/DeviceAvailableEventArgs.cs | 10 | ||||
| -rw-r--r-- | RSSDP/DeviceEventArgs.cs | 46 | ||||
| -rw-r--r-- | RSSDP/DiscoveredSsdpDevice.cs | 168 | ||||
| -rw-r--r-- | RSSDP/DisposableManagedObjectBase.cs | 84 | ||||
| -rw-r--r-- | RSSDP/HttpRequestParser.cs | 22 | ||||
| -rw-r--r-- | RSSDP/HttpResponseParser.cs | 7 | ||||
| -rw-r--r-- | RSSDP/IEnumerableExtensions.cs | 24 | ||||
| -rw-r--r-- | RSSDP/ISsdpDeviceLocator.cs | 274 | ||||
| -rw-r--r-- | RSSDP/ISsdpDevicePublisher.cs | 57 | ||||
| -rw-r--r-- | RSSDP/Properties/AssemblyInfo.cs | 2 | ||||
| -rw-r--r-- | RSSDP/RequestReceivedEventArgs.cs | 100 | ||||
| -rw-r--r-- | RSSDP/ResponseReceivedEventArgs.cs | 85 | ||||
| -rw-r--r-- | RSSDP/SsdpCommunicationsServer.cs | 31 | ||||
| -rw-r--r-- | RSSDP/SsdpConstants.cs | 100 | ||||
| -rw-r--r-- | RSSDP/SsdpDevice.cs | 4 | ||||
| -rw-r--r-- | RSSDP/SsdpDeviceLocator.cs | 2 | ||||
| -rw-r--r-- | RSSDP/SsdpDevicePublisher.cs | 8 | ||||
| -rw-r--r-- | RSSDP/SsdpEmbeddedDevice.cs | 100 | ||||
| -rw-r--r-- | RSSDP/SsdpRootDevice.cs | 114 |
19 files changed, 613 insertions, 625 deletions
diff --git a/RSSDP/DeviceAvailableEventArgs.cs b/RSSDP/DeviceAvailableEventArgs.cs index d69407b41..edc8687e9 100644 --- a/RSSDP/DeviceAvailableEventArgs.cs +++ b/RSSDP/DeviceAvailableEventArgs.cs @@ -6,11 +6,11 @@ using MediaBrowser.Model.Net; namespace Rssdp { - /// <summary> - /// Event arguments for the <see cref="Rssdp.Infrastructure.SsdpDeviceLocatorBase.DeviceAvailable"/> event. - /// </summary> - public sealed class DeviceAvailableEventArgs : EventArgs - { + /// <summary> + /// Event arguments for the <see cref="Rssdp.Infrastructure.SsdpDeviceLocatorBase.DeviceAvailable"/> event. + /// </summary> + public sealed class DeviceAvailableEventArgs : EventArgs + { public IpAddressInfo LocalIpAddress { get; set; } #region Fields diff --git a/RSSDP/DeviceEventArgs.cs b/RSSDP/DeviceEventArgs.cs index a49ef0736..0212d1d7c 100644 --- a/RSSDP/DeviceEventArgs.cs +++ b/RSSDP/DeviceEventArgs.cs @@ -4,19 +4,19 @@ using System.Text; namespace Rssdp { - /// <summary> - /// Event arguments for the <see cref="SsdpDevice.DeviceAdded"/> and <see cref="SsdpDevice.DeviceRemoved"/> events. - /// </summary> - public sealed class DeviceEventArgs : EventArgs - { + /// <summary> + /// Event arguments for the <see cref="SsdpDevice.DeviceAdded"/> and <see cref="SsdpDevice.DeviceRemoved"/> events. + /// </summary> + public sealed class DeviceEventArgs : EventArgs + { - #region Fields + #region Fields - private readonly SsdpDevice _Device; + private readonly SsdpDevice _Device; - #endregion + #endregion - #region Constructors + #region Constructors /// <summary> /// Constructs a new instance for the specified <see cref="SsdpDevice"/>. @@ -27,22 +27,22 @@ namespace Rssdp { if (device == null) throw new ArgumentNullException(nameof(device)); - _Device = device; - } + _Device = device; + } - #endregion + #endregion - #region Public Properties + #region Public Properties - /// <summary> - /// Returns the <see cref="SsdpDevice"/> instance the event being raised for. - /// </summary> - public SsdpDevice Device - { - get { return _Device; } - } + /// <summary> + /// Returns the <see cref="SsdpDevice"/> instance the event being raised for. + /// </summary> + public SsdpDevice Device + { + get { return _Device; } + } - #endregion + #endregion - } -}
\ No newline at end of file + } +} diff --git a/RSSDP/DiscoveredSsdpDevice.cs b/RSSDP/DiscoveredSsdpDevice.cs index 7e70817dd..0c5701d29 100644 --- a/RSSDP/DiscoveredSsdpDevice.cs +++ b/RSSDP/DiscoveredSsdpDevice.cs @@ -7,88 +7,88 @@ using System.Net.Http.Headers; namespace Rssdp { - /// <summary> - /// Represents a discovered device, containing basic information about the device and the location of it's full device description document. Also provides convenience methods for retrieving the device description document. - /// </summary> - /// <seealso cref="SsdpDevice"/> - /// <seealso cref="Rssdp.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> - public string NotificationType { get; set; } - - /// <summary> - /// Sets or returns the universal service name (USN) of the device. - /// </summary> - public string Usn { get; set; } - - /// <summary> - /// Sets or returns a URL pointing to the device description document for this device. - /// </summary> - public Uri DescriptionLocation { get; set; } - - /// <summary> - /// Sets or returns the length of time this information is valid for (from the <see cref="AsAt"/> time). - /// </summary> - public TimeSpan CacheLifetime { get; set; } - - /// <summary> - /// Sets or returns the date and time this information was received. - /// </summary> - public DateTimeOffset AsAt - { - get { return _AsAt; } - set - { - if (_AsAt != value) - { - _AsAt = value; - } - } - } - - /// <summary> - /// Returns the headers from the SSDP device response message - /// </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"/> & <see cref="AsAt"/> properties. - /// </summary> - /// <returns></returns> - public bool IsExpired() - { - 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> - /// <returns>A string containing the device's universal service name.</returns> - public override string ToString() - { - return this.Usn; - } - - #endregion - } + /// <summary> + /// Represents a discovered device, containing basic information about the device and the location of it's full device description document. Also provides convenience methods for retrieving the device description document. + /// </summary> + /// <seealso cref="SsdpDevice"/> + /// <seealso cref="Rssdp.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> + public string NotificationType { get; set; } + + /// <summary> + /// Sets or returns the universal service name (USN) of the device. + /// </summary> + public string Usn { get; set; } + + /// <summary> + /// Sets or returns a URL pointing to the device description document for this device. + /// </summary> + public Uri DescriptionLocation { get; set; } + + /// <summary> + /// Sets or returns the length of time this information is valid for (from the <see cref="AsAt"/> time). + /// </summary> + public TimeSpan CacheLifetime { get; set; } + + /// <summary> + /// Sets or returns the date and time this information was received. + /// </summary> + public DateTimeOffset AsAt + { + get { return _AsAt; } + set + { + if (_AsAt != value) + { + _AsAt = value; + } + } + } + + /// <summary> + /// Returns the headers from the SSDP device response message + /// </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"/> & <see cref="AsAt"/> properties. + /// </summary> + /// <returns></returns> + public bool IsExpired() + { + 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> + /// <returns>A string containing the device's universal service name.</returns> + public override string ToString() + { + return this.Usn; + } + + #endregion + } } diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 7a0fdd45a..c1349dd5c 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -5,44 +5,44 @@ using System.Threading.Tasks; namespace Rssdp.Infrastructure { - /// <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; - } + /// <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 @@ -63,7 +63,7 @@ namespace Rssdp.Infrastructure return builder.ToString(); } - + #region IDisposable Members /// <summary> @@ -74,8 +74,8 @@ namespace Rssdp.Infrastructure /// </remarks> /// <seealso cref="IsDisposed"/> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification="We do exactly as asked, but CA doesn't seem to like us also setting the IsDisposed property. Too bad, it's a good idea and shouldn't cause an exception or anything likely to interfer with the dispose process.")] - public void Dispose() - { + public void Dispose() + { IsDisposed = true; Dispose(true); @@ -83,4 +83,4 @@ namespace Rssdp.Infrastructure #endregion } -}
\ No newline at end of file +} diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index c3106fbce..7d611dea8 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -79,16 +79,16 @@ namespace Rssdp.Infrastructure } } - /// <summary> - /// Returns a boolean indicating whether the specified HTTP header name represents a content header (true), or a message header (false). - /// </summary> - /// <param name="headerName">A string containing the name of the header to return the type of.</param> - protected override bool IsContentHeader(string headerName) - { - return ContentHeaderNames.Contains(headerName, StringComparer.OrdinalIgnoreCase); - } + /// <summary> + /// Returns a boolean indicating whether the specified HTTP header name represents a content header (true), or a message header (false). + /// </summary> + /// <param name="headerName">A string containing the name of the header to return the type of.</param> + protected override bool IsContentHeader(string headerName) + { + return ContentHeaderNames.Contains(headerName, StringComparer.OrdinalIgnoreCase); + } - #endregion + #endregion - } -}
\ No newline at end of file + } +} diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs index eb170ea24..9c1373f74 100644 --- a/RSSDP/HttpResponseParser.cs +++ b/RSSDP/HttpResponseParser.cs @@ -91,7 +91,6 @@ namespace Rssdp.Infrastructure } } - #endregion - - } -}
\ No newline at end of file + #endregion + } +} diff --git a/RSSDP/IEnumerableExtensions.cs b/RSSDP/IEnumerableExtensions.cs index 9608cb479..950d561b0 100644 --- a/RSSDP/IEnumerableExtensions.cs +++ b/RSSDP/IEnumerableExtensions.cs @@ -12,17 +12,17 @@ namespace Rssdp.Infrastructure if (source == null) throw new ArgumentNullException(nameof(source)); if (selector == null) throw new ArgumentNullException(nameof(selector)); - return !source.Any() ? source : - source.Concat( - source - .SelectMany(i => selector(i).EmptyIfNull()) - .SelectManyRecursive(selector) - ); - } + return !source.Any() ? source : + source.Concat( + source + .SelectMany(i => selector(i).EmptyIfNull()) + .SelectManyRecursive(selector) + ); + } - public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source) - { - return source ?? Enumerable.Empty<T>(); - } - } + public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source) + { + return source ?? Enumerable.Empty<T>(); + } + } } diff --git a/RSSDP/ISsdpDeviceLocator.cs b/RSSDP/ISsdpDeviceLocator.cs index 3ab271836..32235c095 100644 --- a/RSSDP/ISsdpDeviceLocator.cs +++ b/RSSDP/ISsdpDeviceLocator.cs @@ -2,140 +2,140 @@ namespace Rssdp.Infrastructure { - /// <summary> - /// Interface for components that discover the existence of SSDP devices. - /// </summary> - /// <remarks> - /// <para>Discovering devices includes explicit search requests as well as listening for broadcast status notifications.</para> - /// </remarks> - /// <seealso cref="DiscoveredSsdpDevice"/> - /// <seealso cref="SsdpDevice"/> - /// <seealso cref="ISsdpDevicePublisher"/> - public interface ISsdpDeviceLocator - { - - #region Events - - /// <summary> - /// Event raised when a device becomes available or is found by a search request. - /// </summary> - /// <seealso cref="NotificationFilter"/> - /// <seealso cref="DeviceUnavailable"/> - /// <seealso cref="StartListeningForNotifications"/> - /// <seealso cref="StopListeningForNotifications"/> - event EventHandler<DeviceAvailableEventArgs> DeviceAvailable; - - /// <summary> - /// Event raised when a device explicitly notifies of shutdown or a device expires from the cache. - /// </summary> - /// <seeseealso cref="NotificationFilter"/> - /// <seealso cref="DeviceAvailable"/> - /// <seealso cref="StartListeningForNotifications"/> - /// <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> - /// <remarks> - /// <para>Device alive/byebye notifications whose NT header does not match this filter value will still be captured and cached internally, but will not raise events about device availability. Usually used with either a device type of uuid NT header value.</para> - /// <para>Example filters follow;</para> - /// <example>upnp:rootdevice</example> - /// <example>urn:schemas-upnp-org:device:WANDevice:1</example> - /// <example>"uuid:9F15356CC-95FA-572E-0E99-85B456BD3012"</example> - /// </remarks> - /// <seealso cref="DeviceAvailable"/> - /// <seealso cref="DeviceUnavailable"/> - /// <seealso cref="StartListeningForNotifications"/> - /// <seealso cref="StopListeningForNotifications"/> - string NotificationFilter - { - get; - 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> - /// <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(); - - /// <summary> - /// Performs a search for the specified search target (criteria) and default search timeout. - /// </summary> - /// <param name="searchTarget">The criteria for the search. Value can be; - /// <list type="table"> - /// <item><term>Root devices</term><description>upnp:rootdevice</description></item> - /// <item><term>Specific device by UUID</term><description>uuid:<device uuid></description></item> - /// <item><term>Device type</term><description>Fully qualified device type starting with urn: i.e urn:schemas-upnp-org:Basic:1</description></item> - /// </list> - /// </param> - /// <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(string searchTarget); - - /// <summary> - /// Performs a search for the specified search target (criteria) and search timeout. - /// </summary> - /// <param name="searchTarget">The criteria for the search. Value can be; - /// <list type="table"> - /// <item><term>Root devices</term><description>upnp:rootdevice</description></item> - /// <item><term>Specific device by UUID</term><description>uuid:<device uuid></description></item> - /// <item><term>Device type</term><description>A device namespace and type in format of urn:<device namespace>:device:<device type>:<device version> i.e urn:schemas-upnp-org:device:Basic:1</description></item> - /// <item><term>Service type</term><description>A service namespace and type in format of urn:<service namespace>:service:<servicetype>:<service version> i.e urn:my-namespace:service:MyCustomService:1</description></item> - /// </list> - /// </param> - /// <param name="searchWaitTime">The amount of time to wait for network responses to the search request. Longer values will likely return more devices, but increase search time. A value between 1 and 5 is recommended by the UPnP 1.1 specification. Specify TimeSpan.Zero to return only devices already in the cache.</param> - /// <remarks> - /// <para>By design RSSDP does not support 'publishing services' as it is intended for use with non-standard UPnP devices that don't publish UPnP style services. However, it is still possible to use RSSDP to search for devices implemetning these services if you know the service type.</para> - /// </remarks> - /// <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(string searchTarget, TimeSpan searchWaitTime); - - /// <summary> - /// Performs a search for all devices using the specified search timeout. - /// </summary> - /// <param name="searchWaitTime">The amount of time to wait for network responses to the search request. Longer values will likely return more devices, but increase search time. A value between 1 and 5 is recommended by the UPnP 1.1 specification. Specify TimeSpan.Zero to return only devices already in the cache.</param> - /// <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> - /// <remarks> - /// <para>When called the system will listen for 'alive' and 'byebye' notifications. This can speed up searching, as well as provide dynamic notification of new devices appearing on the network, and previously discovered devices disappearing.</para> - /// </remarks> - /// <seealso cref="StopListeningForNotifications"/> - /// <seealso cref="DeviceAvailable"/> - /// <seealso cref="DeviceUnavailable"/> - /// <seealso cref="NotificationFilter"/> - void StartListeningForNotifications(); - - /// <summary> - /// Stops listening for broadcast notifications of service availability. - /// </summary> - /// <remarks> - /// <para>Does nothing if this instance is not already listening for notifications.</para> - /// </remarks> - /// <exception cref="System.ObjectDisposedException">Throw if the <see cref="DisposableManagedObjectBase.IsDisposed"/> property is true.</exception> - /// <seealso cref="StartListeningForNotifications"/> - /// <seealso cref="DeviceAvailable"/> - /// <seealso cref="DeviceUnavailable"/> - /// <seealso cref="NotificationFilter"/> - void StopListeningForNotifications(); - - #endregion - - } -}
\ No newline at end of file + /// <summary> + /// Interface for components that discover the existence of SSDP devices. + /// </summary> + /// <remarks> + /// <para>Discovering devices includes explicit search requests as well as listening for broadcast status notifications.</para> + /// </remarks> + /// <seealso cref="DiscoveredSsdpDevice"/> + /// <seealso cref="SsdpDevice"/> + /// <seealso cref="ISsdpDevicePublisher"/> + public interface ISsdpDeviceLocator + { + + #region Events + + /// <summary> + /// Event raised when a device becomes available or is found by a search request. + /// </summary> + /// <seealso cref="NotificationFilter"/> + /// <seealso cref="DeviceUnavailable"/> + /// <seealso cref="StartListeningForNotifications"/> + /// <seealso cref="StopListeningForNotifications"/> + event EventHandler<DeviceAvailableEventArgs> DeviceAvailable; + + /// <summary> + /// Event raised when a device explicitly notifies of shutdown or a device expires from the cache. + /// </summary> + /// <seeseealso cref="NotificationFilter"/> + /// <seealso cref="DeviceAvailable"/> + /// <seealso cref="StartListeningForNotifications"/> + /// <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> + /// <remarks> + /// <para>Device alive/byebye notifications whose NT header does not match this filter value will still be captured and cached internally, but will not raise events about device availability. Usually used with either a device type of uuid NT header value.</para> + /// <para>Example filters follow;</para> + /// <example>upnp:rootdevice</example> + /// <example>urn:schemas-upnp-org:device:WANDevice:1</example> + /// <example>"uuid:9F15356CC-95FA-572E-0E99-85B456BD3012"</example> + /// </remarks> + /// <seealso cref="DeviceAvailable"/> + /// <seealso cref="DeviceUnavailable"/> + /// <seealso cref="StartListeningForNotifications"/> + /// <seealso cref="StopListeningForNotifications"/> + string NotificationFilter + { + get; + 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> + /// <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(); + + /// <summary> + /// Performs a search for the specified search target (criteria) and default search timeout. + /// </summary> + /// <param name="searchTarget">The criteria for the search. Value can be; + /// <list type="table"> + /// <item><term>Root devices</term><description>upnp:rootdevice</description></item> + /// <item><term>Specific device by UUID</term><description>uuid:<device uuid></description></item> + /// <item><term>Device type</term><description>Fully qualified device type starting with urn: i.e urn:schemas-upnp-org:Basic:1</description></item> + /// </list> + /// </param> + /// <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(string searchTarget); + + /// <summary> + /// Performs a search for the specified search target (criteria) and search timeout. + /// </summary> + /// <param name="searchTarget">The criteria for the search. Value can be; + /// <list type="table"> + /// <item><term>Root devices</term><description>upnp:rootdevice</description></item> + /// <item><term>Specific device by UUID</term><description>uuid:<device uuid></description></item> + /// <item><term>Device type</term><description>A device namespace and type in format of urn:<device namespace>:device:<device type>:<device version> i.e urn:schemas-upnp-org:device:Basic:1</description></item> + /// <item><term>Service type</term><description>A service namespace and type in format of urn:<service namespace>:service:<servicetype>:<service version> i.e urn:my-namespace:service:MyCustomService:1</description></item> + /// </list> + /// </param> + /// <param name="searchWaitTime">The amount of time to wait for network responses to the search request. Longer values will likely return more devices, but increase search time. A value between 1 and 5 is recommended by the UPnP 1.1 specification. Specify TimeSpan.Zero to return only devices already in the cache.</param> + /// <remarks> + /// <para>By design RSSDP does not support 'publishing services' as it is intended for use with non-standard UPnP devices that don't publish UPnP style services. However, it is still possible to use RSSDP to search for devices implemetning these services if you know the service type.</para> + /// </remarks> + /// <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(string searchTarget, TimeSpan searchWaitTime); + + /// <summary> + /// Performs a search for all devices using the specified search timeout. + /// </summary> + /// <param name="searchWaitTime">The amount of time to wait for network responses to the search request. Longer values will likely return more devices, but increase search time. A value between 1 and 5 is recommended by the UPnP 1.1 specification. Specify TimeSpan.Zero to return only devices already in the cache.</param> + /// <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> + /// <remarks> + /// <para>When called the system will listen for 'alive' and 'byebye' notifications. This can speed up searching, as well as provide dynamic notification of new devices appearing on the network, and previously discovered devices disappearing.</para> + /// </remarks> + /// <seealso cref="StopListeningForNotifications"/> + /// <seealso cref="DeviceAvailable"/> + /// <seealso cref="DeviceUnavailable"/> + /// <seealso cref="NotificationFilter"/> + void StartListeningForNotifications(); + + /// <summary> + /// Stops listening for broadcast notifications of service availability. + /// </summary> + /// <remarks> + /// <para>Does nothing if this instance is not already listening for notifications.</para> + /// </remarks> + /// <exception cref="System.ObjectDisposedException">Throw if the <see cref="DisposableManagedObjectBase.IsDisposed"/> property is true.</exception> + /// <seealso cref="StartListeningForNotifications"/> + /// <seealso cref="DeviceAvailable"/> + /// <seealso cref="DeviceUnavailable"/> + /// <seealso cref="NotificationFilter"/> + void StopListeningForNotifications(); + + #endregion + + } +} diff --git a/RSSDP/ISsdpDevicePublisher.cs b/RSSDP/ISsdpDevicePublisher.cs index b6ebc4176..b0924701f 100644 --- a/RSSDP/ISsdpDevicePublisher.cs +++ b/RSSDP/ISsdpDevicePublisher.cs @@ -3,35 +3,34 @@ using System.Threading.Tasks; namespace Rssdp.Infrastructure { - /// <summary> - /// Interface for components that publish the existence of SSDP devices. - /// </summary> - /// <remarks> - /// <para>Publishing a device includes sending notifications (alive and byebye) as well as responding to search requests when appropriate.</para> - /// </remarks> - /// <seealso cref="SsdpRootDevice"/> - /// <seealso cref="ISsdpDeviceLocator"/> - public interface ISsdpDevicePublisher - { - /// <summary> - /// Adds a device (and it's children) to the list of devices being published by this server, making them discoverable to SSDP clients. - /// </summary> - /// <param name="device">The <see cref="SsdpRootDevice"/> instance to add.</param> - /// <returns>An awaitable <see cref="System.Threading.Tasks.Task"/>.</returns> - void AddDevice(SsdpRootDevice device); + /// <summary> + /// Interface for components that publish the existence of SSDP devices. + /// </summary> + /// <remarks> + /// <para>Publishing a device includes sending notifications (alive and byebye) as well as responding to search requests when appropriate.</para> + /// </remarks> + /// <seealso cref="SsdpRootDevice"/> + /// <seealso cref="ISsdpDeviceLocator"/> + public interface ISsdpDevicePublisher + { + /// <summary> + /// Adds a device (and it's children) to the list of devices being published by this server, making them discoverable to SSDP clients. + /// </summary> + /// <param name="device">The <see cref="SsdpRootDevice"/> instance to add.</param> + /// <returns>An awaitable <see cref="System.Threading.Tasks.Task"/>.</returns> + void AddDevice(SsdpRootDevice device); - /// <summary> - /// Removes a device (and it's children) from the list of devices being published by this server, making them undiscoverable. - /// </summary> - /// <param name="device">The <see cref="SsdpRootDevice"/> instance to add.</param> - /// <returns>An awaitable <see cref="System.Threading.Tasks.Task"/>.</returns> - Task RemoveDevice(SsdpRootDevice device); + /// <summary> + /// Removes a device (and it's children) from the list of devices being published by this server, making them undiscoverable. + /// </summary> + /// <param name="device">The <see cref="SsdpRootDevice"/> instance to add.</param> + /// <returns>An awaitable <see cref="System.Threading.Tasks.Task"/>.</returns> + Task RemoveDevice(SsdpRootDevice device); - /// <summary> - /// Returns a read only list of devices being published by this instance. - /// </summary> - /// <seealso cref="SsdpDevice"/> - System.Collections.Generic.IEnumerable<SsdpRootDevice> Devices { get; } - - } + /// <summary> + /// Returns a read only list of devices being published by this instance. + /// </summary> + /// <seealso cref="SsdpDevice"/> + System.Collections.Generic.IEnumerable<SsdpRootDevice> Devices { get; } + } } diff --git a/RSSDP/Properties/AssemblyInfo.cs b/RSSDP/Properties/AssemblyInfo.cs index a60820520..7098279b4 100644 --- a/RSSDP/Properties/AssemblyInfo.cs +++ b/RSSDP/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ using System.Reflection; using System.Resources; 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("RSSDP")] diff --git a/RSSDP/RequestReceivedEventArgs.cs b/RSSDP/RequestReceivedEventArgs.cs index f4e367760..6a5b0f086 100644 --- a/RSSDP/RequestReceivedEventArgs.cs +++ b/RSSDP/RequestReceivedEventArgs.cs @@ -8,54 +8,52 @@ using MediaBrowser.Model.Net; namespace Rssdp.Infrastructure { - /// <summary> - /// Provides arguments for the <see cref="ISsdpCommunicationsServer.RequestReceived"/> event. - /// </summary> - public sealed class RequestReceivedEventArgs : EventArgs - { - - #region Fields - - private readonly HttpRequestMessage _Message; - private readonly IpEndPointInfo _ReceivedFrom; - - #endregion - - public IpAddressInfo LocalIpAddress { get; private set; } - - #region Constructors - - /// <summary> - /// Full constructor. - /// </summary> - public RequestReceivedEventArgs(HttpRequestMessage message, IpEndPointInfo receivedFrom, IpAddressInfo localIpAddress) - { - _Message = message; - _ReceivedFrom = receivedFrom; - LocalIpAddress = localIpAddress; - } - - #endregion - - #region Public Properties - - /// <summary> - /// The <see cref="HttpRequestMessage"/> that was received. - /// </summary> - public HttpRequestMessage Message - { - get { return _Message; } - } - - /// <summary> - /// The <see cref="UdpEndPoint"/> the request came from. - /// </summary> - public IpEndPointInfo ReceivedFrom - { - get { return _ReceivedFrom; } - } - - #endregion - - } -}
\ No newline at end of file + /// <summary> + /// Provides arguments for the <see cref="ISsdpCommunicationsServer.RequestReceived"/> event. + /// </summary> + public sealed class RequestReceivedEventArgs : EventArgs + { + #region Fields + + private readonly HttpRequestMessage _Message; + private readonly IpEndPointInfo _ReceivedFrom; + + #endregion + + public IpAddressInfo LocalIpAddress { get; private set; } + + #region Constructors + + /// <summary> + /// Full constructor. + /// </summary> + public RequestReceivedEventArgs(HttpRequestMessage message, IpEndPointInfo receivedFrom, IpAddressInfo localIpAddress) + { + _Message = message; + _ReceivedFrom = receivedFrom; + LocalIpAddress = localIpAddress; + } + + #endregion + + #region Public Properties + + /// <summary> + /// The <see cref="HttpRequestMessage"/> that was received. + /// </summary> + public HttpRequestMessage Message + { + get { return _Message; } + } + + /// <summary> + /// The <see cref="UdpEndPoint"/> the request came from. + /// </summary> + public IpEndPointInfo ReceivedFrom + { + get { return _ReceivedFrom; } + } + + #endregion + } +} diff --git a/RSSDP/ResponseReceivedEventArgs.cs b/RSSDP/ResponseReceivedEventArgs.cs index f67d5da90..5ec5376df 100644 --- a/RSSDP/ResponseReceivedEventArgs.cs +++ b/RSSDP/ResponseReceivedEventArgs.cs @@ -8,53 +8,52 @@ using MediaBrowser.Model.Net; namespace Rssdp.Infrastructure { - /// <summary> - /// Provides arguments for the <see cref="ISsdpCommunicationsServer.ResponseReceived"/> event. - /// </summary> - public sealed class ResponseReceivedEventArgs : EventArgs - { + /// <summary> + /// Provides arguments for the <see cref="ISsdpCommunicationsServer.ResponseReceived"/> event. + /// </summary> + public sealed class ResponseReceivedEventArgs : EventArgs + { public IpAddressInfo LocalIpAddress { get; set; } #region Fields private readonly HttpResponseMessage _Message; - private readonly IpEndPointInfo _ReceivedFrom; - - #endregion - - #region Constructors - - /// <summary> - /// Full constructor. - /// </summary> - public ResponseReceivedEventArgs(HttpResponseMessage message, IpEndPointInfo receivedFrom) - { - _Message = message; - _ReceivedFrom = receivedFrom; - } - - #endregion - - #region Public Properties - - /// <summary> - /// The <see cref="HttpResponseMessage"/> that was received. - /// </summary> - public HttpResponseMessage Message - { - get { return _Message; } - } - - /// <summary> - /// The <see cref="UdpEndPoint"/> the response came from. - /// </summary> - public IpEndPointInfo ReceivedFrom - { - get { return _ReceivedFrom; } - } - - #endregion - - } + private readonly IpEndPointInfo _ReceivedFrom; + + #endregion + + #region Constructors + + /// <summary> + /// Full constructor. + /// </summary> + public ResponseReceivedEventArgs(HttpResponseMessage message, IpEndPointInfo receivedFrom) + { + _Message = message; + _ReceivedFrom = receivedFrom; + } + + #endregion + + #region Public Properties + + /// <summary> + /// The <see cref="HttpResponseMessage"/> that was received. + /// </summary> + public HttpResponseMessage Message + { + get { return _Message; } + } + + /// <summary> + /// The <see cref="UdpEndPoint"/> the response came from. + /// </summary> + public IpEndPointInfo ReceivedFrom + { + get { return _ReceivedFrom; } + } + + #endregion + } } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 5ce3683eb..5fc524428 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -20,22 +20,19 @@ namespace Rssdp.Infrastructure #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 - is running then it will steal the unicast messages and we will never see search responses. - Since stopping the service would be a bad idea (might not be allowed security wise and might - break other apps running on the system) the only other work around is to use two sockets. - - We use one socket to listen for/receive notifications and search requests (_BroadcastListenSocket). - We use a second socket, bound to a different local port, to send search requests and listen for - responses (_SendSocket). The responses are sent to the local port this socket is bound to, - which isn't port 1900 so the MS service doesn't steal them. While the caller can specify a local - port to use, we will default to 0 which allows the underlying system to auto-assign a free port. - - */ + /* 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 + * is running then it will steal the unicast messages and we will never see search responses. + * Since stopping the service would be a bad idea (might not be allowed security wise and might + * break other apps running on the system) the only other work around is to use two sockets. + * + * We use one socket to listen for/receive notifications and search requests (_BroadcastListenSocket). + * We use a second socket, bound to a different local port, to send search requests and listen for + * responses (_SendSocket). The responses are sent to the local port this socket is bound to, + * which isn't port 1900 so the MS service doesn't steal them. While the caller can specify a local + * port to use, we will default to 0 which allows the underlying system to auto-assign a free port. + */ private object _BroadcastListenSocketSynchroniser = new object(); private ISocket _BroadcastListenSocket; @@ -443,7 +440,7 @@ namespace Rssdp.Infrastructure private void ProcessMessage(string data, IpEndPointInfo endPoint, IpAddressInfo receivedOnLocalIpAddress) { //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 + //requests start with a method which can vary and might be one we haven't //seen/don't know. We'll check if this message is a request or a response //by checking for the HTTP/ prefix on the start of the message. if (data.StartsWith("HTTP/", StringComparison.OrdinalIgnoreCase)) diff --git a/RSSDP/SsdpConstants.cs b/RSSDP/SsdpConstants.cs index 87f01f9e0..ab0ecb0f7 100644 --- a/RSSDP/SsdpConstants.cs +++ b/RSSDP/SsdpConstants.cs @@ -5,63 +5,63 @@ using System.Threading.Tasks; namespace Rssdp.Infrastructure { - /// <summary> - /// Provides constants for common values related to the SSDP protocols. - /// </summary> - public static class SsdpConstants - { + /// <summary> + /// Provides constants for common values related to the SSDP protocols. + /// </summary> + public static class SsdpConstants + { - /// <summary> - /// Multicast IP Address used for SSDP multicast messages. Values is 239.255.255.250. - /// </summary> - public const string MulticastLocalAdminAddress = "239.255.255.250"; - /// <summary> - /// The UDP port used for SSDP multicast messages. Values is 1900. - /// </summary> - public const int MulticastPort = 1900; - /// <summary> - /// The default multicase TTL for SSDP multicast messages. Value is 4. - /// </summary> - public const int SsdpDefaultMulticastTimeToLive = 4; + /// <summary> + /// Multicast IP Address used for SSDP multicast messages. Values is 239.255.255.250. + /// </summary> + public const string MulticastLocalAdminAddress = "239.255.255.250"; + /// <summary> + /// The UDP port used for SSDP multicast messages. Values is 1900. + /// </summary> + public const int MulticastPort = 1900; + /// <summary> + /// The default multicase TTL for SSDP multicast messages. Value is 4. + /// </summary> + public const int SsdpDefaultMulticastTimeToLive = 4; - internal const string MSearchMethod = "M-SEARCH"; + internal const string MSearchMethod = "M-SEARCH"; - internal const string SsdpDiscoverMessage = "ssdp:discover"; - internal const string SsdpDiscoverAllSTHeader = "ssdp:all"; + internal const string SsdpDiscoverMessage = "ssdp:discover"; + internal const string SsdpDiscoverAllSTHeader = "ssdp:all"; - internal const string SsdpDeviceDescriptionXmlNamespace = "urn:schemas-upnp-org:device-1-0"; + internal const string SsdpDeviceDescriptionXmlNamespace = "urn:schemas-upnp-org:device-1-0"; - /// <summary> - /// Default buffer size for receiving SSDP broadcasts. Value is 8192 (bytes). - /// </summary> - public const int DefaultUdpSocketBufferSize = 8192; - /// <summary> - /// The maximum possible buffer size for a UDP message. Value is 65507 (bytes). - /// </summary> - public const int MaxUdpSocketBufferSize = 65507; // Max possible UDP packet size on IPv4 without using 'jumbograms'. + /// <summary> + /// Default buffer size for receiving SSDP broadcasts. Value is 8192 (bytes). + /// </summary> + public const int DefaultUdpSocketBufferSize = 8192; + /// <summary> + /// The maximum possible buffer size for a UDP message. Value is 65507 (bytes). + /// </summary> + public const int MaxUdpSocketBufferSize = 65507; // Max possible UDP packet size on IPv4 without using 'jumbograms'. - /// <summary> - /// Namespace/prefix for UPnP device types. Values is schemas-upnp-org. - /// </summary> - public const string UpnpDeviceTypeNamespace = "schemas-upnp-org"; - /// <summary> - /// UPnP Root Device type. Value is upnp:rootdevice. - /// </summary> - public const string UpnpDeviceTypeRootDevice = "upnp:rootdevice"; - /// <summary> - /// The value is used by Windows Explorer for device searches instead of the UPNPDeviceTypeRootDevice constant. - /// Not sure why (different spec, bug, alternate protocol etc). Used to enable Windows Explorer support. - /// </summary> - public const string PnpDeviceTypeRootDevice = "pnp:rootdevice"; - /// <summary> - /// UPnP Basic Device type. Value is Basic. - /// </summary> - public const string UpnpDeviceTypeBasicDevice = "Basic"; + /// <summary> + /// Namespace/prefix for UPnP device types. Values is schemas-upnp-org. + /// </summary> + public const string UpnpDeviceTypeNamespace = "schemas-upnp-org"; + /// <summary> + /// UPnP Root Device type. Value is upnp:rootdevice. + /// </summary> + public const string UpnpDeviceTypeRootDevice = "upnp:rootdevice"; + /// <summary> + /// The value is used by Windows Explorer for device searches instead of the UPNPDeviceTypeRootDevice constant. + /// Not sure why (different spec, bug, alternate protocol etc). Used to enable Windows Explorer support. + /// </summary> + public const string PnpDeviceTypeRootDevice = "pnp:rootdevice"; + /// <summary> + /// UPnP Basic Device type. Value is Basic. + /// </summary> + public const string UpnpDeviceTypeBasicDevice = "Basic"; - internal const string SsdpKeepAliveNotification = "ssdp:alive"; - internal const string SsdpByeByeNotification = "ssdp:byebye"; + internal const string SsdpKeepAliveNotification = "ssdp:alive"; + internal const string SsdpByeByeNotification = "ssdp:byebye"; - internal const int UdpResendCount = 3; + internal const int UdpResendCount = 3; - } + } } diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 4913ea0cf..4508e4f34 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -75,7 +75,7 @@ namespace Rssdp return rootDevice; } - + #region Public Properties #region UPnP Device Description Properties @@ -330,7 +330,7 @@ namespace Rssdp /// </summary> /// <param name="device">The <see cref="SsdpEmbeddedDevice"/> instance added to the <see cref="Devices"/> collection.</param> /// <seealso cref="AddDevice"/> - /// <seealso cref="DeviceAdded"/> + /// <seealso cref="DeviceAdded"/> protected virtual void OnDeviceAdded(SsdpEmbeddedDevice device) { var handlers = this.DeviceAdded; diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index d36b306a0..0a092e6b0 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -53,7 +53,7 @@ namespace Rssdp.Infrastructure #region Events /// <summary> - /// Raised for when + /// Raised for when /// <list type="bullet"> /// <item>An 'alive' notification is received that a device, regardless of whether or not that device is not already in the cache or has previously raised this event.</item> /// <item>For each item found during a device <see cref="SearchAsync()"/> (cached or not), allowing clients to respond to found devices before the entire search is complete.</item> diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 11aaf4641..a44dd0c0c 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -418,7 +418,7 @@ namespace Rssdp.Infrastructure var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - // If needed later for non-server devices, these headers will need to be dynamic + // If needed later for non-server devices, these headers will need to be dynamic values["HOST"] = "239.255.255.250:1900"; values["DATE"] = DateTime.UtcNow.ToString("r"); values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds; @@ -463,7 +463,7 @@ namespace Rssdp.Infrastructure var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - // If needed later for non-server devices, these headers will need to be dynamic + // If needed later for non-server devices, these headers will need to be dynamic values["HOST"] = "239.255.255.250:1900"; values["DATE"] = DateTime.UtcNow.ToString("r"); values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); @@ -538,9 +538,9 @@ namespace Rssdp.Infrastructure //According to SSDP/UPnP spec, ignore message if missing these headers. // Edit: But some devices do it anyway //if (!e.Message.Headers.Contains("MX")) - // WriteTrace("Ignoring search request - missing MX header."); + // WriteTrace("Ignoring search request - missing MX header."); //else if (!e.Message.Headers.Contains("MAN")) - // WriteTrace("Ignoring search request - missing MAN header."); + // WriteTrace("Ignoring search request - missing MAN header."); //else ProcessSearchRequest(GetFirstHeaderValue(e.Message.Headers, "MX"), GetFirstHeaderValue(e.Message.Headers, "ST"), e.ReceivedFrom, e.LocalIpAddress, CancellationToken.None); } diff --git a/RSSDP/SsdpEmbeddedDevice.cs b/RSSDP/SsdpEmbeddedDevice.cs index dca1ff5e3..0e02ce33c 100644 --- a/RSSDP/SsdpEmbeddedDevice.cs +++ b/RSSDP/SsdpEmbeddedDevice.cs @@ -4,54 +4,52 @@ using System.Text; namespace Rssdp { - /// <summary> - /// Represents a device that is a descendant of a <see cref="SsdpRootDevice"/> instance. - /// </summary> - public class SsdpEmbeddedDevice : SsdpDevice - { - - #region Fields - - private SsdpRootDevice _RootDevice; - - #endregion - - #region Constructors - - /// <summary> - /// Default constructor. - /// </summary> - public SsdpEmbeddedDevice() - { - } - - #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> - public SsdpRootDevice RootDevice - { - get - { - return _RootDevice; - } - internal set - { - _RootDevice = value; - lock (this.Devices) - { - foreach (var embeddedDevice in this.Devices) - { - ((SsdpEmbeddedDevice)embeddedDevice).RootDevice = _RootDevice; - } - } - } - } - - #endregion - - } -}
\ No newline at end of file + /// <summary> + /// Represents a device that is a descendant of a <see cref="SsdpRootDevice"/> instance. + /// </summary> + public class SsdpEmbeddedDevice : SsdpDevice + { + + #region Fields + private SsdpRootDevice _RootDevice; + + #endregion + + #region Constructors + + /// <summary> + /// Default constructor. + /// </summary> + public SsdpEmbeddedDevice() + { + } + + #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> + public SsdpRootDevice RootDevice + { + get + { + return _RootDevice; + } + internal set + { + _RootDevice = value; + lock (this.Devices) + { + foreach (var embeddedDevice in this.Devices) + { + ((SsdpEmbeddedDevice)embeddedDevice).RootDevice = _RootDevice; + } + } + } + } + + #endregion + } +} diff --git a/RSSDP/SsdpRootDevice.cs b/RSSDP/SsdpRootDevice.cs index eaf3f6a38..20644535a 100644 --- a/RSSDP/SsdpRootDevice.cs +++ b/RSSDP/SsdpRootDevice.cs @@ -6,74 +6,72 @@ using Rssdp.Infrastructure; namespace Rssdp { - /// <summary> - /// Represents a 'root' device, a device that has no parent. Used for publishing devices and for the root device in a tree of discovered devices. - /// </summary> - /// <remarks> - /// <para>Child (embedded) devices are represented by the <see cref="SsdpDevice"/> in the <see cref="SsdpDevice.Devices"/> property.</para> - /// <para>Root devices contain some information that applies to the whole device tree and is therefore not present on child devices, such as <see cref="CacheLifetime"/> and <see cref="Location"/>.</para> - /// </remarks> - public class SsdpRootDevice : SsdpDevice - { - - #region Fields + /// <summary> + /// Represents a 'root' device, a device that has no parent. Used for publishing devices and for the root device in a tree of discovered devices. + /// </summary> + /// <remarks> + /// <para>Child (embedded) devices are represented by the <see cref="SsdpDevice"/> in the <see cref="SsdpDevice.Devices"/> property.</para> + /// <para>Root devices contain some information that applies to the whole device tree and is therefore not present on child devices, such as <see cref="CacheLifetime"/> and <see cref="Location"/>.</para> + /// </remarks> + public class SsdpRootDevice : SsdpDevice + { + #region Fields - private Uri _UrlBase; + private Uri _UrlBase; - #endregion + #endregion - #region Constructors + #region Constructors - /// <summary> - /// Default constructor. - /// </summary> - public SsdpRootDevice() : base() - { - } + /// <summary> + /// Default constructor. + /// </summary> + public SsdpRootDevice() : base() + { + } - #endregion + #endregion - #region Public Properties + #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> - /// <remarks> - /// <para>Specifiy <see cref="TimeSpan.Zero"/> to indicate no caching allowed.</para> - /// <para>Also used to specify how often to rebroadcast alive notifications.</para> - /// <para>The UPnP/SSDP specifications indicate this should not be less than 1800 seconds (half an hour), but this is not enforced by this library.</para> - /// </remarks> - public TimeSpan CacheLifetime - { - get; set; - } + /// <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> + /// <remarks> + /// <para>Specifiy <see cref="TimeSpan.Zero"/> to indicate no caching allowed.</para> + /// <para>Also used to specify how often to rebroadcast alive notifications.</para> + /// <para>The UPnP/SSDP specifications indicate this should not be less than 1800 seconds (half an hour), but this is not enforced by this library.</para> + /// </remarks> + public TimeSpan CacheLifetime + { + get; set; + } - /// <summary> - /// Gets or sets the URL used to retrieve the description document for this device/tree. Required. - /// </summary> - public Uri Location { get; set; } + /// <summary> + /// Gets or sets the URL used to retrieve the description document for this device/tree. Required. + /// </summary> + public Uri Location { get; set; } - /// <summary> - /// The base URL to use for all relative url's provided in other propertise (and those of child devices). Optional. - /// </summary> - /// <remarks> - /// <para>Defines the base URL. Used to construct fully-qualified URLs. All relative URLs that appear elsewhere in the description are combined with this base URL. If URLBase is empty or not given, the base URL is the URL from which the device description was retrieved (which is the preferred implementation; use of URLBase is no longer recommended). Specified by UPnP vendor. Single URL.</para> - /// </remarks> - public Uri UrlBase - { - get - { - return _UrlBase ?? this.Location; - } + /// <summary> + /// The base URL to use for all relative url's provided in other propertise (and those of child devices). Optional. + /// </summary> + /// <remarks> + /// <para>Defines the base URL. Used to construct fully-qualified URLs. All relative URLs that appear elsewhere in the description are combined with this base URL. If URLBase is empty or not given, the base URL is the URL from which the device description was retrieved (which is the preferred implementation; use of URLBase is no longer recommended). Specified by UPnP vendor. Single URL.</para> + /// </remarks> + public Uri UrlBase + { + get + { + return _UrlBase ?? this.Location; + } - set - { - _UrlBase = value; - } - } + set + { + _UrlBase = value; + } + } - #endregion - - } + #endregion + } } |
