mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 19:37:55 +02:00
commit
a10d94b747
12 changed files with 92 additions and 116 deletions
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Common.Implementations.Networking;
|
using Emby.Common.Implementations.Networking;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
@ -56,7 +57,7 @@ namespace Emby.Common.Implementations.Net
|
||||||
state.TaskCompletionSource = tcs;
|
state.TaskCompletionSource = tcs;
|
||||||
|
|
||||||
#if NETSTANDARD1_6
|
#if NETSTANDARD1_6
|
||||||
_Socket.ReceiveFromAsync(new ArraySegment<Byte>(state.Buffer),SocketFlags.None, state.RemoteEndPoint)
|
_Socket.ReceiveFromAsync(new ArraySegment<Byte>(state.Buffer), SocketFlags.None, state.RemoteEndPoint)
|
||||||
.ContinueWith((task, asyncState) =>
|
.ContinueWith((task, asyncState) =>
|
||||||
{
|
{
|
||||||
if (task.Status != TaskStatus.Faulted)
|
if (task.Status != TaskStatus.Faulted)
|
||||||
|
@ -73,7 +74,7 @@ namespace Emby.Common.Implementations.Net
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendAsync(byte[] buffer, int size, IpEndPointInfo endPoint)
|
public Task SendAsync(byte[] buffer, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
|
@ -91,6 +92,8 @@ namespace Emby.Common.Implementations.Net
|
||||||
buffer = copy;
|
buffer = copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
_Socket.SendTo(buffer, ipEndPoint);
|
_Socket.SendTo(buffer, ipEndPoint);
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
#else
|
#else
|
||||||
|
@ -100,6 +103,11 @@ namespace Emby.Common.Implementations.Net
|
||||||
{
|
{
|
||||||
_Socket.BeginSendTo(buffer, 0, size, SocketFlags.None, ipEndPoint, result =>
|
_Socket.BeginSendTo(buffer, 0, size, SocketFlags.None, ipEndPoint, result =>
|
||||||
{
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
taskSource.TrySetCanceled();
|
||||||
|
return;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_Socket.EndSend(result);
|
_Socket.EndSend(result);
|
||||||
|
|
|
@ -75,16 +75,20 @@ namespace Emby.Dlna.Ssdp
|
||||||
// Enable listening for notifications (optional)
|
// Enable listening for notifications (optional)
|
||||||
_deviceLocator.StartListeningForNotifications();
|
_deviceLocator.StartListeningForNotifications();
|
||||||
|
|
||||||
await _deviceLocator.SearchAsync().ConfigureAwait(false);
|
await _deviceLocator.SearchAsync(_tokenSource.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var delay = _config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds * 1000;
|
||||||
|
|
||||||
|
await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error searching for devices", ex);
|
_logger.ErrorException("Error searching for devices", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var delay = _config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds * 1000;
|
|
||||||
|
|
||||||
await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}, CancellationToken.None, TaskCreationOptions.LongRunning);
|
}, CancellationToken.None, TaskCreationOptions.LongRunning);
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
@ -246,7 +247,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _udpClient.SendAsync(bytes, bytes.Length, remoteEndPoint).ConfigureAwait(false);
|
await _udpClient.SendAsync(bytes, bytes.Length, remoteEndPoint, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
_logger.Info("Udp message sent to {0}", remoteEndPoint);
|
_logger.Info("Udp message sent to {0}", remoteEndPoint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net
|
namespace MediaBrowser.Model.Net
|
||||||
|
@ -22,6 +23,6 @@ namespace MediaBrowser.Model.Net
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a UDP message to a particular end point (uni or multicast).
|
/// Sends a UDP message to a particular end point (uni or multicast).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SendAsync(byte[] buffer, int bytes, IpEndPointInfo endPoint);
|
Task SendAsync(byte[] buffer, int bytes, IpEndPointInfo endPoint, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -124,7 +124,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami", ".txt" };
|
return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
{
|
{
|
||||||
var mode = request.Mode;
|
var mode = request.Mode;
|
||||||
|
|
||||||
var path = string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ?
|
var path = !string.IsNullOrWhiteSpace(mode) ?
|
||||||
Path.Combine(_serverConfigurationManager.ApplicationPaths.ProgramDataPath, "webclient-dump")
|
Path.Combine(_serverConfigurationManager.ApplicationPaths.ProgramDataPath, "webclient-dump")
|
||||||
: "C:\\dev\\emby-web-mobile\\src";
|
: "C:\\dev\\emby-web-mobile\\src";
|
||||||
|
|
||||||
|
@ -364,14 +364,11 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
// Try to trim the output size a bit
|
// Try to trim the output size a bit
|
||||||
var bowerPath = Path.Combine(path, "bower_components");
|
var bowerPath = Path.Combine(path, "bower_components");
|
||||||
|
|
||||||
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrWhiteSpace(mode))
|
||||||
{
|
|
||||||
DeleteFoldersByName(Path.Combine(bowerPath, "emby-webcomponents", "fonts"), "roboto");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
// Delete things that are unneeded in an attempt to keep the output as trim as possible
|
// Delete things that are unneeded in an attempt to keep the output as trim as possible
|
||||||
|
|
||||||
|
DeleteFoldersByName(Path.Combine(bowerPath, "emby-webcomponents", "fonts"), "roboto");
|
||||||
_fileSystem.DeleteDirectory(Path.Combine(path, "css", "images", "tour"), true);
|
_fileSystem.DeleteDirectory(Path.Combine(path, "css", "images", "tour"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
|
|
||||||
html = Encoding.UTF8.GetString(originalBytes, 0, originalBytes.Length);
|
html = Encoding.UTF8.GetString(originalBytes, 0, originalBytes.Length);
|
||||||
|
|
||||||
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrWhiteSpace(mode))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrWhiteSpace(path) && !string.Equals(path, "index.html", StringComparison.OrdinalIgnoreCase))
|
else if (!string.IsNullOrWhiteSpace(path) && !string.Equals(path, "index.html", StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -208,7 +208,8 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(mode, "android", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: file: filesystem: ws: wss:;\">");
|
sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: file: filesystem: ws: wss:;\">");
|
||||||
}
|
}
|
||||||
|
@ -257,7 +258,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
private string GetCommonCss(string mode, string version)
|
private string GetCommonCss(string mode, string version)
|
||||||
{
|
{
|
||||||
var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + version : string.Empty;
|
var versionString = string.IsNullOrWhiteSpace(mode) ? "?v=" + version : string.Empty;
|
||||||
|
|
||||||
var files = new[]
|
var files = new[]
|
||||||
{
|
{
|
||||||
|
@ -288,14 +289,14 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
builder.AppendFormat("window.appMode='{0}';", mode);
|
builder.AppendFormat("window.appMode='{0}';", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
if (string.IsNullOrWhiteSpace(mode))
|
||||||
{
|
{
|
||||||
builder.AppendFormat("window.dashboardVersion='{0}';", version);
|
builder.AppendFormat("window.dashboardVersion='{0}';", version);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append("</script>");
|
builder.Append("</script>");
|
||||||
|
|
||||||
var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + version : string.Empty;
|
var versionString = string.IsNullOrWhiteSpace(mode) ? "?v=" + version : string.Empty;
|
||||||
|
|
||||||
var files = new List<string>();
|
var files = new List<string>();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
|
||||||
|
@ -44,15 +45,12 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to a particular address (uni or multicast) and port.
|
/// Sends a message to a particular address (uni or multicast) and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="messageData">A byte array containing the data to send.</param>
|
Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken);
|
||||||
/// <param name="destination">A <see cref="IpEndPointInfo"/> representing the destination address for the data. Can be either a multicast or unicast destination.</param>
|
|
||||||
/// <param name="fromLocalIpAddress">A <see cref="IpEndPointInfo"/> The local ip address to send from, or .Any if sending from all available</param>
|
|
||||||
Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to the SSDP multicast address and port.
|
/// Sends a message to the SSDP multicast address and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SendMulticastMessage(string message);
|
Task SendMulticastMessage(string message, CancellationToken cancellationToken);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -58,11 +58,6 @@ namespace Rssdp.Infrastructure
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a boolean indicating whether or not a search is currently active.
|
|
||||||
/// </summary>
|
|
||||||
bool IsSearching { get; }
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
@ -149,12 +150,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to a particular address (uni or multicast) and port.
|
/// Sends a message to a particular address (uni or multicast) and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="messageData">A byte array containing the data to send.</param>
|
public async Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken)
|
||||||
/// <param name="destination">A <see cref="IpEndPointInfo"/> representing the destination address for the data. Can be either a multicast or unicast destination.</param>
|
|
||||||
/// <param name="fromLocalIpAddress">A <see cref="IpEndPointInfo"/> The local ip address to send from, or .Any if sending from all available</param>
|
|
||||||
/// <exception cref="System.ArgumentNullException">Thrown if the <paramref name="messageData"/> argument is null.</exception>
|
|
||||||
/// <exception cref="System.ObjectDisposedException">Thrown if the <see cref="DisposableManagedObjectBase.IsDisposed"/> property is true (because <seealso cref="DisposableManagedObjectBase.Dispose()" /> has been called previously).</exception>
|
|
||||||
public async Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress)
|
|
||||||
{
|
{
|
||||||
if (messageData == null) throw new ArgumentNullException("messageData");
|
if (messageData == null) throw new ArgumentNullException("messageData");
|
||||||
|
|
||||||
|
@ -170,18 +166,18 @@ namespace Rssdp.Infrastructure
|
||||||
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
||||||
for (var i = 0; i < SsdpConstants.UdpResendCount; i++)
|
for (var i = 0; i < SsdpConstants.UdpResendCount; i++)
|
||||||
{
|
{
|
||||||
var tasks = sockets.Select(s => SendFromSocket(s, messageData, destination)).ToArray();
|
var tasks = sockets.Select(s => SendFromSocket(s, messageData, destination, cancellationToken)).ToArray();
|
||||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.Delay(100).ConfigureAwait(false);
|
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SendFromSocket(IUdpSocket socket, byte[] messageData, IpEndPointInfo destination)
|
private async Task SendFromSocket(IUdpSocket socket, byte[] messageData, IpEndPointInfo destination, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await socket.SendAsync(messageData, messageData.Length, destination).ConfigureAwait(false);
|
await socket.SendAsync(messageData, messageData.Length, destination, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
|
@ -230,7 +226,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to the SSDP multicast address and port.
|
/// Sends a message to the SSDP multicast address and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task SendMulticastMessage(string message)
|
public async Task SendMulticastMessage(string message, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (message == null) throw new ArgumentNullException("messageData");
|
if (message == null) throw new ArgumentNullException("messageData");
|
||||||
|
|
||||||
|
@ -238,6 +234,8 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
EnsureSendSocketCreated();
|
EnsureSendSocketCreated();
|
||||||
|
|
||||||
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
||||||
|
@ -251,9 +249,9 @@ namespace Rssdp.Infrastructure
|
||||||
},
|
},
|
||||||
Port = SsdpConstants.MulticastPort
|
Port = SsdpConstants.MulticastPort
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.Delay(100).ConfigureAwait(false);
|
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +332,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private async Task SendMessageIfSocketNotDisposed(byte[] messageData, IpEndPointInfo destination)
|
private async Task SendMessageIfSocketNotDisposed(byte[] messageData, IpEndPointInfo destination, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var sockets = _sendSockets;
|
var sockets = _sendSockets;
|
||||||
if (sockets != null)
|
if (sockets != null)
|
||||||
|
@ -343,7 +341,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
foreach (var socket in sockets)
|
foreach (var socket in sockets)
|
||||||
{
|
{
|
||||||
await socket.SendAsync(messageData, messageData.Length, destination).ConfigureAwait(false);
|
await socket.SendAsync(messageData, messageData.Length, destination, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to search the network for a particular device, device types, or UPnP service types. Also listenings for broadcast notifications of device availability and raises events to indicate changes in status.
|
/// Allows you to search the network for a particular device, device types, or UPnP service types. Also listenings for broadcast notifications of device availability and raises events to indicate changes in status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class SsdpDeviceLocatorBase : DisposableManagedObjectBase, ISsdpDeviceLocator
|
public abstract class SsdpDeviceLocatorBase : DisposableManagedObjectBase
|
||||||
{
|
{
|
||||||
|
|
||||||
#region Fields & Constants
|
#region Fields & Constants
|
||||||
|
@ -96,9 +96,9 @@ namespace Rssdp.Infrastructure
|
||||||
/// Performs a search for all devices using the default search timeout.
|
/// Performs a search for all devices using the default search timeout.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
/// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
||||||
public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync()
|
public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return SearchAsync(SsdpConstants.SsdpDiscoverAllSTHeader, DefaultSearchWaitTime);
|
return SearchAsync(SsdpConstants.SsdpDiscoverAllSTHeader, DefaultSearchWaitTime, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -114,7 +114,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
/// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
||||||
public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget)
|
public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget)
|
||||||
{
|
{
|
||||||
return SearchAsync(searchTarget, DefaultSearchWaitTime);
|
return SearchAsync(searchTarget, DefaultSearchWaitTime, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -124,27 +124,10 @@ namespace Rssdp.Infrastructure
|
||||||
/// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
/// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
||||||
public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(TimeSpan searchWaitTime)
|
public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(TimeSpan searchWaitTime)
|
||||||
{
|
{
|
||||||
return SearchAsync(SsdpConstants.SsdpDiscoverAllSTHeader, searchWaitTime);
|
return SearchAsync(SsdpConstants.SsdpDiscoverAllSTHeader, searchWaitTime, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public async Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget, TimeSpan searchWaitTime, CancellationToken cancellationToken)
|
||||||
/// 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 seconds is recommended by the UPnP 1.1 specification, this method requires the value be greater 1 second if it is not zero. 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="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns>
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "expireTask", Justification = "Task is not actually required, but capturing to local variable suppresses compiler warning")]
|
|
||||||
public async Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget, TimeSpan searchWaitTime)
|
|
||||||
{
|
{
|
||||||
if (searchTarget == null) throw new ArgumentNullException("searchTarget");
|
if (searchTarget == null) throw new ArgumentNullException("searchTarget");
|
||||||
if (searchTarget.Length == 0) throw new ArgumentException("searchTarget cannot be an empty string.", "searchTarget");
|
if (searchTarget.Length == 0) throw new ArgumentException("searchTarget cannot be an empty string.", "searchTarget");
|
||||||
|
@ -158,7 +141,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
// If searchWaitTime == 0 then we are only going to report unexpired cached items, not actually do a search.
|
// If searchWaitTime == 0 then we are only going to report unexpired cached items, not actually do a search.
|
||||||
if (searchWaitTime > TimeSpan.Zero)
|
if (searchWaitTime > TimeSpan.Zero)
|
||||||
await BroadcastDiscoverMessage(searchTarget, SearchTimeToMXValue(searchWaitTime)).ConfigureAwait(false);
|
await BroadcastDiscoverMessage(searchTarget, SearchTimeToMXValue(searchWaitTime), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
lock (_SearchResultsSynchroniser)
|
lock (_SearchResultsSynchroniser)
|
||||||
{
|
{
|
||||||
|
@ -169,7 +152,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchWaitTime != TimeSpan.Zero)
|
if (searchWaitTime != TimeSpan.Zero)
|
||||||
await Task.Delay(searchWaitTime).ConfigureAwait(false);
|
await Task.Delay(searchWaitTime, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
IEnumerable<DiscoveredSsdpDevice> retVal = null;
|
IEnumerable<DiscoveredSsdpDevice> retVal = null;
|
||||||
|
|
||||||
|
@ -270,17 +253,6 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a boolean indicating whether or not a search is currently in progress.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Only one search can be performed at a time, per <see cref="SsdpDeviceLocatorBase"/> instance.</para>
|
|
||||||
/// </remarks>
|
|
||||||
public bool IsSearching
|
|
||||||
{
|
|
||||||
get { return _SearchResults != null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// 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>
|
/// </summary>
|
||||||
|
@ -407,7 +379,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region Network Message Processing
|
#region Network Message Processing
|
||||||
|
|
||||||
private Task BroadcastDiscoverMessage(string serviceType, TimeSpan mxValue)
|
private Task BroadcastDiscoverMessage(string serviceType, TimeSpan mxValue, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
@ -427,7 +399,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
var message = SsdpHelper.BuildMessage(header, values);
|
var message = SsdpHelper.BuildMessage(header, values);
|
||||||
|
|
||||||
return _CommunicationsServer.SendMulticastMessage(message);
|
return _CommunicationsServer.SendMulticastMessage(message, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessSearchResponseMessage(HttpResponseMessage message, IpAddressInfo localIpAddress)
|
private void ProcessSearchResponseMessage(HttpResponseMessage message, IpAddressInfo localIpAddress)
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
@ -122,7 +123,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
SetRebroadcastAliveNotificationsTimer(minCacheTime);
|
SetRebroadcastAliveNotificationsTimer(minCacheTime);
|
||||||
|
|
||||||
SendAliveNotifications(device, true);
|
SendAliveNotifications(device, true, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
WriteTrace("Device Removed", device);
|
WriteTrace("Device Removed", device);
|
||||||
|
|
||||||
await SendByeByeNotifications(device, true).ConfigureAwait(false);
|
await SendByeByeNotifications(device, true, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
SetRebroadcastAliveNotificationsTimer(minCacheTime);
|
SetRebroadcastAliveNotificationsTimer(minCacheTime);
|
||||||
}
|
}
|
||||||
|
@ -237,7 +238,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region Search Related Methods
|
#region Search Related Methods
|
||||||
|
|
||||||
private void ProcessSearchRequest(string mx, string searchTarget, IpEndPointInfo remoteEndPoint, IpAddressInfo receivedOnlocalIpAddress)
|
private void ProcessSearchRequest(string mx, string searchTarget, IpEndPointInfo remoteEndPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(searchTarget))
|
if (String.IsNullOrEmpty(searchTarget))
|
||||||
{
|
{
|
||||||
|
@ -295,7 +296,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
foreach (var device in deviceList)
|
foreach (var device in deviceList)
|
||||||
{
|
{
|
||||||
SendDeviceSearchResponses(device, remoteEndPoint, receivedOnlocalIpAddress);
|
SendDeviceSearchResponses(device, remoteEndPoint, receivedOnlocalIpAddress, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -310,19 +311,19 @@ namespace Rssdp.Infrastructure
|
||||||
return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices));
|
return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendDeviceSearchResponses(SsdpDevice device, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress)
|
private void SendDeviceSearchResponses(SsdpDevice device, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
bool isRootDevice = (device as SsdpRootDevice) != null;
|
bool isRootDevice = (device as SsdpRootDevice) != null;
|
||||||
if (isRootDevice)
|
if (isRootDevice)
|
||||||
{
|
{
|
||||||
SendSearchResponse(SsdpConstants.UpnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress);
|
SendSearchResponse(SsdpConstants.UpnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress, cancellationToken);
|
||||||
if (this.SupportPnpRootDevice)
|
if (this.SupportPnpRootDevice)
|
||||||
SendSearchResponse(SsdpConstants.PnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress);
|
SendSearchResponse(SsdpConstants.PnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendSearchResponse(device.Udn, device, device.Udn, endPoint, receivedOnlocalIpAddress);
|
SendSearchResponse(device.Udn, device, device.Udn, endPoint, receivedOnlocalIpAddress, cancellationToken);
|
||||||
|
|
||||||
SendSearchResponse(device.FullDeviceType, device, GetUsn(device.Udn, device.FullDeviceType), endPoint, receivedOnlocalIpAddress);
|
SendSearchResponse(device.FullDeviceType, device, GetUsn(device.Udn, device.FullDeviceType), endPoint, receivedOnlocalIpAddress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetUsn(string udn, string fullDeviceType)
|
private static string GetUsn(string udn, string fullDeviceType)
|
||||||
|
@ -330,7 +331,7 @@ namespace Rssdp.Infrastructure
|
||||||
return String.Format("{0}::{1}", udn, fullDeviceType);
|
return String.Format("{0}::{1}", udn, fullDeviceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SendSearchResponse(string searchTarget, SsdpDevice device, string uniqueServiceName, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress)
|
private async void SendSearchResponse(string searchTarget, SsdpDevice device, string uniqueServiceName, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var rootDevice = device.ToRootDevice();
|
var rootDevice = device.ToRootDevice();
|
||||||
|
|
||||||
|
@ -352,7 +353,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _CommsServer.SendMessage(System.Text.Encoding.UTF8.GetBytes(message), endPoint, receivedOnlocalIpAddress).ConfigureAwait(false);
|
await _CommsServer.SendMessage(System.Text.Encoding.UTF8.GetBytes(message), endPoint, receivedOnlocalIpAddress, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -427,7 +428,7 @@ namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
if (IsDisposed) return;
|
if (IsDisposed) return;
|
||||||
|
|
||||||
SendAliveNotifications(device, true);
|
SendAliveNotifications(device, true, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
//WriteTrace("Completed Sending Alive Notifications For All Devices");
|
//WriteTrace("Completed Sending Alive Notifications For All Devices");
|
||||||
|
@ -445,25 +446,25 @@ namespace Rssdp.Infrastructure
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendAliveNotifications(SsdpDevice device, bool isRoot)
|
private void SendAliveNotifications(SsdpDevice device, bool isRoot, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (isRoot)
|
if (isRoot)
|
||||||
{
|
{
|
||||||
SendAliveNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice));
|
SendAliveNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken);
|
||||||
if (this.SupportPnpRootDevice)
|
if (this.SupportPnpRootDevice)
|
||||||
SendAliveNotification(device, SsdpConstants.PnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice));
|
SendAliveNotification(device, SsdpConstants.PnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendAliveNotification(device, device.Udn, device.Udn);
|
SendAliveNotification(device, device.Udn, device.Udn, cancellationToken);
|
||||||
SendAliveNotification(device, device.FullDeviceType, GetUsn(device.Udn, device.FullDeviceType));
|
SendAliveNotification(device, device.FullDeviceType, GetUsn(device.Udn, device.FullDeviceType), cancellationToken);
|
||||||
|
|
||||||
foreach (var childDevice in device.Devices)
|
foreach (var childDevice in device.Devices)
|
||||||
{
|
{
|
||||||
SendAliveNotifications(childDevice, false);
|
SendAliveNotifications(childDevice, false, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendAliveNotification(SsdpDevice device, string notificationType, string uniqueServiceName)
|
private void SendAliveNotification(SsdpDevice device, string notificationType, string uniqueServiceName, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var rootDevice = device.ToRootDevice();
|
var rootDevice = device.ToRootDevice();
|
||||||
|
|
||||||
|
@ -483,7 +484,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
var message = SsdpHelper.BuildMessage(header, values);
|
var message = SsdpHelper.BuildMessage(header, values);
|
||||||
|
|
||||||
_CommsServer.SendMulticastMessage(message);
|
_CommsServer.SendMulticastMessage(message, cancellationToken);
|
||||||
|
|
||||||
//WriteTrace(String.Format("Sent alive notification"), device);
|
//WriteTrace(String.Format("Sent alive notification"), device);
|
||||||
}
|
}
|
||||||
|
@ -492,26 +493,26 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region ByeBye
|
#region ByeBye
|
||||||
|
|
||||||
private async Task SendByeByeNotifications(SsdpDevice device, bool isRoot)
|
private async Task SendByeByeNotifications(SsdpDevice device, bool isRoot, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (isRoot)
|
if (isRoot)
|
||||||
{
|
{
|
||||||
await SendByeByeNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice)).ConfigureAwait(false);
|
await SendByeByeNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken).ConfigureAwait(false);
|
||||||
if (this.SupportPnpRootDevice)
|
if (this.SupportPnpRootDevice)
|
||||||
await SendByeByeNotification(device, "pnp:rootdevice", GetUsn(device.Udn, "pnp:rootdevice")).ConfigureAwait(false); ;
|
await SendByeByeNotification(device, "pnp:rootdevice", GetUsn(device.Udn, "pnp:rootdevice"), cancellationToken).ConfigureAwait(false); ;
|
||||||
}
|
}
|
||||||
|
|
||||||
await SendByeByeNotification(device, device.Udn, device.Udn).ConfigureAwait(false); ;
|
await SendByeByeNotification(device, device.Udn, device.Udn, cancellationToken).ConfigureAwait(false); ;
|
||||||
await SendByeByeNotification(device, String.Format("urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType)).ConfigureAwait(false); ;
|
await SendByeByeNotification(device, String.Format("urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken).ConfigureAwait(false); ;
|
||||||
|
|
||||||
foreach (var childDevice in device.Devices)
|
foreach (var childDevice in device.Devices)
|
||||||
{
|
{
|
||||||
await SendByeByeNotifications(childDevice, false).ConfigureAwait(false); ;
|
await SendByeByeNotifications(childDevice, false, cancellationToken).ConfigureAwait(false); ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "byebye", Justification = "Correct value for this type of notification in SSDP.")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "byebye", Justification = "Correct value for this type of notification in SSDP.")]
|
||||||
private Task SendByeByeNotification(SsdpDevice device, string notificationType, string uniqueServiceName)
|
private Task SendByeByeNotification(SsdpDevice device, string notificationType, string uniqueServiceName, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
const string header = "NOTIFY * HTTP/1.1";
|
const string header = "NOTIFY * HTTP/1.1";
|
||||||
|
|
||||||
|
@ -527,7 +528,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
var message = SsdpHelper.BuildMessage(header, values);
|
var message = SsdpHelper.BuildMessage(header, values);
|
||||||
|
|
||||||
return _CommsServer.SendMulticastMessage(message);
|
return _CommsServer.SendMulticastMessage(message, cancellationToken);
|
||||||
|
|
||||||
//WriteTrace(String.Format("Sent byebye notification"), device);
|
//WriteTrace(String.Format("Sent byebye notification"), device);
|
||||||
}
|
}
|
||||||
|
@ -653,13 +654,13 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
private void device_DeviceAdded(object sender, DeviceEventArgs e)
|
private void device_DeviceAdded(object sender, DeviceEventArgs e)
|
||||||
{
|
{
|
||||||
SendAliveNotifications(e.Device, false);
|
SendAliveNotifications(e.Device, false, CancellationToken.None);
|
||||||
ConnectToDeviceEvents(e.Device);
|
ConnectToDeviceEvents(e.Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void device_DeviceRemoved(object sender, DeviceEventArgs e)
|
private void device_DeviceRemoved(object sender, DeviceEventArgs e)
|
||||||
{
|
{
|
||||||
var task = SendByeByeNotifications(e.Device, false);
|
var task = SendByeByeNotifications(e.Device, false, CancellationToken.None);
|
||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
DisconnectFromDeviceEvents(e.Device);
|
DisconnectFromDeviceEvents(e.Device);
|
||||||
}
|
}
|
||||||
|
@ -677,7 +678,7 @@ namespace Rssdp.Infrastructure
|
||||||
//else if (!e.Message.Headers.Contains("MAN"))
|
//else if (!e.Message.Headers.Contains("MAN"))
|
||||||
// WriteTrace("Ignoring search request - missing MAN header.");
|
// WriteTrace("Ignoring search request - missing MAN header.");
|
||||||
//else
|
//else
|
||||||
ProcessSearchRequest(GetFirstHeaderValue(e.Message.Headers, "MX"), GetFirstHeaderValue(e.Message.Headers, "ST"), e.ReceivedFrom, e.LocalIpAddress);
|
ProcessSearchRequest(GetFirstHeaderValue(e.Message.Headers, "MX"), GetFirstHeaderValue(e.Message.Headers, "ST"), e.ReceivedFrom, e.LocalIpAddress, CancellationToken.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue