jellyfin/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs

143 lines
5.2 KiB
C#
Raw Normal View History

using MediaBrowser.Common.Events;
2014-09-16 20:04:10 -07:00
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
2015-04-29 11:48:34 -07:00
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
2016-01-06 20:54:26 -07:00
using MediaBrowser.Common.Net;
2016-09-11 00:33:53 -07:00
using MediaBrowser.Model.Events;
using Rssdp;
namespace MediaBrowser.Dlna.Ssdp
{
2015-07-23 09:32:34 -07:00
public class DeviceDiscovery : IDeviceDiscovery, IDisposable
{
private bool _disposed;
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
private readonly CancellationTokenSource _tokenSource;
2016-09-11 00:33:53 -07:00
public event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceDiscovered;
public event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceLeft;
2016-09-11 00:33:53 -07:00
private SsdpDeviceLocator _DeviceLocator;
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config)
{
_tokenSource = new CancellationTokenSource();
_logger = logger;
_config = config;
}
2015-07-23 09:32:34 -07:00
2016-09-11 00:33:53 -07:00
// Call this method from somewhere in your code to start the search.
public void BeginSearch()
{
2016-09-11 00:33:53 -07:00
_DeviceLocator = new SsdpDeviceLocator();
// (Optional) Set the filter so we only see notifications for devices we care about
// (can be any search target value i.e device type, uuid value etc - any value that appears in the
// DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method).
//_DeviceLocator.NotificationFilter = "upnp:rootdevice";
// Connect our event handler so we process devices as they are found
_DeviceLocator.DeviceAvailable += deviceLocator_DeviceAvailable;
_DeviceLocator.DeviceUnavailable += _DeviceLocator_DeviceUnavailable;
// Enable listening for notifications (optional)
_DeviceLocator.StartListeningForNotifications();
// Perform a search so we don't have to wait for devices to broadcast notifications
// again to get any results right away (notifications are broadcast periodically).
StartAsyncSearch();
}
2016-09-11 00:33:53 -07:00
private void StartAsyncSearch()
{
Task.Factory.StartNew(async (o) =>
{
try
{
while (true)
{
2016-09-11 00:33:53 -07:00
await _DeviceLocator.SearchAsync().ConfigureAwait(false);
var delay = _config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds * 1000;
await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
2016-09-11 00:33:53 -07:00
_logger.ErrorException("Error searching for devices", ex);
}
2016-09-11 00:33:53 -07:00
}, CancellationToken.None, TaskCreationOptions.LongRunning);
}
2016-09-11 00:33:53 -07:00
// Process each found device in the event handler
void deviceLocator_DeviceAvailable(object sender, DeviceAvailableEventArgs e)
{
2016-09-11 00:33:53 -07:00
var originalHeaders = e.DiscoveredDevice.ResponseHeaders;
2014-09-16 20:04:10 -07:00
2016-09-11 00:33:53 -07:00
var headerDict = originalHeaders == null ? new Dictionary<string, KeyValuePair<string, IEnumerable<string>>>() : originalHeaders.ToDictionary(i => i.Key, StringComparer.OrdinalIgnoreCase);
2015-07-23 09:32:34 -07:00
2016-09-11 00:33:53 -07:00
var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
2016-09-11 00:33:53 -07:00
var args = new GenericEventArgs<UpnpDeviceInfo>
2015-05-04 11:01:01 -07:00
{
2016-09-11 00:33:53 -07:00
Argument = new UpnpDeviceInfo
2015-05-04 11:01:01 -07:00
{
2016-09-11 00:33:53 -07:00
Location = e.DiscoveredDevice.DescriptionLocation,
Headers = headers
2015-05-04 11:01:01 -07:00
}
2016-09-11 00:33:53 -07:00
};
2015-05-04 11:01:01 -07:00
2016-09-11 00:33:53 -07:00
EventHelper.FireEventIfNotNull(DeviceDiscovered, this, args, _logger);
}
2015-05-04 11:01:01 -07:00
2016-09-11 00:33:53 -07:00
private void _DeviceLocator_DeviceUnavailable(object sender, DeviceUnavailableEventArgs e)
{
var originalHeaders = e.DiscoveredDevice.ResponseHeaders;
var headerDict = originalHeaders == null ? new Dictionary<string, KeyValuePair<string, IEnumerable<string>>>() : originalHeaders.ToDictionary(i => i.Key, StringComparer.OrdinalIgnoreCase);
2016-09-11 00:33:53 -07:00
var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
2016-09-11 00:33:53 -07:00
var args = new GenericEventArgs<UpnpDeviceInfo>
{
2016-09-11 00:33:53 -07:00
Argument = new UpnpDeviceInfo
{
Location = e.DiscoveredDevice.DescriptionLocation,
Headers = headers
}
};
2016-09-11 00:33:53 -07:00
EventHelper.FireEventIfNotNull(DeviceLeft, this, args, _logger);
}
2016-09-11 00:33:53 -07:00
public void Start()
{
2016-09-11 00:33:53 -07:00
BeginSearch();
}
2014-08-25 19:30:52 -07:00
2016-09-11 00:33:53 -07:00
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_tokenSource.Cancel();
}
}
}
}