mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-24 11:05:08 +01:00
Merge branch 'master' into fix-resharper-warnings
# Conflicts: # Emby.Server.Implementations/Net/SocketFactory.cs # RSSDP/SsdpCommunicationsServer.cs # RSSDP/SsdpDeviceLocator.cs # RSSDP/SsdpDevicePublisher.cs
This commit is contained in:
@@ -32,10 +32,10 @@ namespace Rssdp.Infrastructure
|
||||
* 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 object _BroadcastListenSocketSynchroniser = new();
|
||||
private List<Socket> _MulticastListenSockets;
|
||||
|
||||
private object _SendSocketSynchroniser = new object();
|
||||
private object _SendSocketSynchroniser = new();
|
||||
private List<Socket> _sendSockets;
|
||||
|
||||
private HttpRequestParser _RequestParser;
|
||||
@@ -48,7 +48,6 @@ namespace Rssdp.Infrastructure
|
||||
private int _MulticastTtl;
|
||||
|
||||
private bool _IsShared;
|
||||
private readonly bool _enableMultiSocketBinding;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a HTTPU request message is received by a socket (unicast or multicast).
|
||||
@@ -64,9 +63,11 @@ namespace Rssdp.Infrastructure
|
||||
/// Minimum constructor.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="socketFactory"/> argument is null.</exception>
|
||||
public SsdpCommunicationsServer(ISocketFactory socketFactory,
|
||||
INetworkManager networkManager, ILogger logger, bool enableMultiSocketBinding)
|
||||
: this(socketFactory, 0, SsdpConstants.SsdpDefaultMulticastTimeToLive, networkManager, logger, enableMultiSocketBinding)
|
||||
public SsdpCommunicationsServer(
|
||||
ISocketFactory socketFactory,
|
||||
INetworkManager networkManager,
|
||||
ILogger logger)
|
||||
: this(socketFactory, 0, SsdpConstants.SsdpDefaultMulticastTimeToLive, networkManager, logger)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -76,7 +77,12 @@ namespace Rssdp.Infrastructure
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="socketFactory"/> argument is null.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The <paramref name="multicastTimeToLive"/> argument is less than or equal to zero.</exception>
|
||||
public SsdpCommunicationsServer(ISocketFactory socketFactory, int localPort, int multicastTimeToLive, INetworkManager networkManager, ILogger logger, bool enableMultiSocketBinding)
|
||||
public SsdpCommunicationsServer(
|
||||
ISocketFactory socketFactory,
|
||||
int localPort,
|
||||
int multicastTimeToLive,
|
||||
INetworkManager networkManager,
|
||||
ILogger logger)
|
||||
{
|
||||
if (socketFactory is null)
|
||||
{
|
||||
@@ -88,19 +94,18 @@ namespace Rssdp.Infrastructure
|
||||
throw new ArgumentOutOfRangeException(nameof(multicastTimeToLive), "multicastTimeToLive must be greater than zero.");
|
||||
}
|
||||
|
||||
_BroadcastListenSocketSynchroniser = new object();
|
||||
_SendSocketSynchroniser = new object();
|
||||
_BroadcastListenSocketSynchroniser = new();
|
||||
_SendSocketSynchroniser = new();
|
||||
|
||||
_LocalPort = localPort;
|
||||
_SocketFactory = socketFactory;
|
||||
|
||||
_RequestParser = new HttpRequestParser();
|
||||
_ResponseParser = new HttpResponseParser();
|
||||
_RequestParser = new();
|
||||
_ResponseParser = new();
|
||||
|
||||
_MulticastTtl = multicastTimeToLive;
|
||||
_networkManager = networkManager;
|
||||
_logger = logger;
|
||||
_enableMultiSocketBinding = enableMultiSocketBinding;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -335,7 +340,7 @@ namespace Rssdp.Infrastructure
|
||||
{
|
||||
sockets = sockets.ToList();
|
||||
|
||||
var tasks = sockets.Where(s => (fromlocalIPAddress is null || fromlocalIPAddress.Equals(((IPEndPoint)s.LocalEndPoint).Address)))
|
||||
var tasks = sockets.Where(s => fromlocalIPAddress is null || fromlocalIPAddress.Equals(((IPEndPoint)s.LocalEndPoint).Address))
|
||||
.Select(s => SendFromSocket(s, messageData, destination, cancellationToken));
|
||||
return Task.WhenAll(tasks);
|
||||
}
|
||||
@@ -347,33 +352,26 @@ namespace Rssdp.Infrastructure
|
||||
{
|
||||
var sockets = new List<Socket>();
|
||||
var multicastGroupAddress = IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress);
|
||||
if (_enableMultiSocketBinding)
|
||||
{
|
||||
// IPv6 is currently unsupported
|
||||
var validInterfaces = _networkManager.GetInternalBindAddresses()
|
||||
.Where(x => x.Address is not null)
|
||||
.Where(x => x.AddressFamily == AddressFamily.InterNetwork)
|
||||
.DistinctBy(x => x.Index);
|
||||
|
||||
foreach (var intf in validInterfaces)
|
||||
{
|
||||
try
|
||||
{
|
||||
var socket = _SocketFactory.CreateUdpMulticastSocket(multicastGroupAddress, intf, _MulticastTtl, SsdpConstants.MulticastPort);
|
||||
_ = ListenToSocketInternal(socket);
|
||||
sockets.Add(socket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in CreateMulticastSocketsAndListen. IP address: {0}", intf.Address);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
// IPv6 is currently unsupported
|
||||
var validInterfaces = _networkManager.GetInternalBindAddresses()
|
||||
.Where(x => x.Address is not null)
|
||||
.Where(x => x.SupportsMulticast)
|
||||
.Where(x => x.AddressFamily == AddressFamily.InterNetwork)
|
||||
.DistinctBy(x => x.Index);
|
||||
|
||||
foreach (var intf in validInterfaces)
|
||||
{
|
||||
var socket = _SocketFactory.CreateUdpMulticastSocket(multicastGroupAddress, new IPData(IPAddress.Any, null), _MulticastTtl, SsdpConstants.MulticastPort);
|
||||
_ = ListenToSocketInternal(socket);
|
||||
sockets.Add(socket);
|
||||
try
|
||||
{
|
||||
var socket = _SocketFactory.CreateUdpMulticastSocket(multicastGroupAddress, intf, _MulticastTtl, SsdpConstants.MulticastPort);
|
||||
_ = ListenToSocketInternal(socket);
|
||||
sockets.Add(socket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to create SSDP UDP multicast socket for {0} on interface {1} (index {2})", intf.Address, intf.Name, intf.Index);
|
||||
}
|
||||
}
|
||||
|
||||
return sockets;
|
||||
@@ -382,34 +380,32 @@ namespace Rssdp.Infrastructure
|
||||
private List<Socket> CreateSendSockets()
|
||||
{
|
||||
var sockets = new List<Socket>();
|
||||
if (_enableMultiSocketBinding)
|
||||
{
|
||||
// IPv6 is currently unsupported
|
||||
var validInterfaces = _networkManager.GetInternalBindAddresses()
|
||||
.Where(x => x.Address is not null)
|
||||
.Where(x => x.AddressFamily == AddressFamily.InterNetwork);
|
||||
|
||||
foreach (var intf in validInterfaces)
|
||||
// IPv6 is currently unsupported
|
||||
var validInterfaces = _networkManager.GetInternalBindAddresses()
|
||||
.Where(x => x.Address is not null)
|
||||
.Where(x => x.SupportsMulticast)
|
||||
.Where(x => x.AddressFamily == AddressFamily.InterNetwork);
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
// Manually remove loopback on macOS due to https://github.com/dotnet/runtime/issues/24340
|
||||
validInterfaces = validInterfaces.Where(x => !x.Address.Equals(IPAddress.Loopback));
|
||||
}
|
||||
|
||||
foreach (var intf in validInterfaces)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
var socket = _SocketFactory.CreateSsdpUdpSocket(intf, _LocalPort);
|
||||
_ = ListenToSocketInternal(socket);
|
||||
sockets.Add(socket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error in CreateSsdpUdpSocket. IPAddress: {0}", intf.Address);
|
||||
}
|
||||
var socket = _SocketFactory.CreateSsdpUdpSocket(intf, _LocalPort);
|
||||
_ = ListenToSocketInternal(socket);
|
||||
sockets.Add(socket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to create SSDP UDP sender socket for {0} on interface {1} (index {2})", intf.Address, intf.Name, intf.Index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var socket = _SocketFactory.CreateSsdpUdpSocket(new IPData(IPAddress.Any, null), _LocalPort);
|
||||
_ = ListenToSocketInternal(socket);
|
||||
sockets.Add(socket);
|
||||
}
|
||||
|
||||
|
||||
return sockets;
|
||||
}
|
||||
@@ -423,7 +419,7 @@ namespace Rssdp.Infrastructure
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await socket.ReceiveMessageFromAsync(receiveBuffer, SocketFlags.None, new IPEndPoint(IPAddress.Any, 0), CancellationToken.None).ConfigureAwait(false);
|
||||
var result = await socket.ReceiveMessageFromAsync(receiveBuffer, new IPEndPoint(IPAddress.Any, _LocalPort), CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (result.ReceivedBytes > 0)
|
||||
{
|
||||
@@ -431,7 +427,7 @@ namespace Rssdp.Infrastructure
|
||||
var localEndpointAdapter = _networkManager.GetAllBindInterfaces().First(a => a.Index == result.PacketInformation.Interface);
|
||||
|
||||
ProcessMessage(
|
||||
UTF8Encoding.UTF8.GetString(receiveBuffer, 0, result.ReceivedBytes),
|
||||
Encoding.UTF8.GetString(receiveBuffer, 0, result.ReceivedBytes),
|
||||
remoteEndpoint,
|
||||
localEndpointAdapter.Address);
|
||||
}
|
||||
@@ -511,13 +507,13 @@ namespace Rssdp.Infrastructure
|
||||
return;
|
||||
}
|
||||
|
||||
var handlers = this.RequestReceived;
|
||||
var handlers = RequestReceived;
|
||||
handlers?.Invoke(this, new RequestReceivedEventArgs(data, remoteEndPoint, receivedOnlocalIPAddress));
|
||||
}
|
||||
|
||||
private void OnResponseReceived(HttpResponseMessage data, IPEndPoint endPoint, IPAddress localIPAddress)
|
||||
{
|
||||
var handlers = this.ResponseReceived;
|
||||
var handlers = ResponseReceived;
|
||||
handlers?.Invoke(this, new ResponseReceivedEventArgs(data, endPoint)
|
||||
{
|
||||
LocalIPAddress = localIPAddress
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Rssdp.Infrastructure
|
||||
private ISsdpCommunicationsServer _CommunicationsServer;
|
||||
|
||||
private Timer _BroadcastTimer;
|
||||
private object _timerLock = new object();
|
||||
private object _timerLock = new();
|
||||
|
||||
private string _OSName;
|
||||
|
||||
@@ -221,12 +221,12 @@ namespace Rssdp.Infrastructure
|
||||
/// <seealso cref="DeviceAvailable"/>
|
||||
protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress IPAddress)
|
||||
{
|
||||
if (this.IsDisposed)
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var handlers = this.DeviceAvailable;
|
||||
var handlers = DeviceAvailable;
|
||||
handlers?.Invoke(this, new DeviceAvailableEventArgs(device, isNewDevice)
|
||||
{
|
||||
RemoteIPAddress = IPAddress
|
||||
@@ -241,12 +241,12 @@ namespace Rssdp.Infrastructure
|
||||
/// <seealso cref="DeviceUnavailable"/>
|
||||
protected virtual void OnDeviceUnavailable(DiscoveredSsdpDevice device, bool expired)
|
||||
{
|
||||
if (this.IsDisposed)
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var handlers = this.DeviceUnavailable;
|
||||
var handlers = DeviceUnavailable;
|
||||
handlers?.Invoke(this, new DeviceUnavailableEventArgs(device, expired));
|
||||
}
|
||||
|
||||
@@ -285,8 +285,8 @@ namespace Rssdp.Infrastructure
|
||||
_CommunicationsServer = null;
|
||||
if (commsServer is not null)
|
||||
{
|
||||
commsServer.ResponseReceived -= this.CommsServer_ResponseReceived;
|
||||
commsServer.RequestReceived -= this.CommsServer_RequestReceived;
|
||||
commsServer.ResponseReceived -= CommsServer_ResponseReceived;
|
||||
commsServer.RequestReceived -= CommsServer_RequestReceived;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -335,7 +335,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
values["HOST"] = "239.255.255.250:1900";
|
||||
values["HOST"] = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", SsdpConstants.MulticastLocalAdminAddress, SsdpConstants.MulticastPort);
|
||||
values["USER-AGENT"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion);
|
||||
values["MAN"] = "\"ssdp:discover\"";
|
||||
|
||||
@@ -376,17 +376,17 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
private void ProcessNotificationMessage(HttpRequestMessage message, IPAddress IPAddress)
|
||||
{
|
||||
if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0)
|
||||
if (string.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var notificationType = GetFirstHeaderStringValue("NTS", message);
|
||||
if (String.Compare(notificationType, SsdpConstants.SsdpKeepAliveNotification, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
if (string.Compare(notificationType, SsdpConstants.SsdpKeepAliveNotification, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
ProcessAliveNotification(message, IPAddress);
|
||||
}
|
||||
else if (String.Compare(notificationType, SsdpConstants.SsdpByeByeNotification, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
else if (string.Compare(notificationType, SsdpConstants.SsdpByeByeNotification, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
ProcessByeByeNotification(message);
|
||||
}
|
||||
@@ -414,7 +414,7 @@ namespace Rssdp.Infrastructure
|
||||
private void ProcessByeByeNotification(HttpRequestMessage message)
|
||||
{
|
||||
var notficationType = GetFirstHeaderStringValue("NT", message);
|
||||
if (!String.IsNullOrEmpty(notficationType))
|
||||
if (!string.IsNullOrEmpty(notficationType))
|
||||
{
|
||||
var usn = GetFirstHeaderStringValue("USN", message);
|
||||
|
||||
@@ -519,7 +519,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
foreach (var device in expiredDevices)
|
||||
{
|
||||
if (this.IsDisposed)
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -533,7 +533,7 @@ namespace Rssdp.Infrastructure
|
||||
// problems.
|
||||
foreach (var expiredUsn in (from expiredDevice in expiredDevices select expiredDevice.Usn).Distinct())
|
||||
{
|
||||
if (this.IsDisposed)
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -550,7 +550,7 @@ namespace Rssdp.Infrastructure
|
||||
existingDevices = FindExistingDeviceNotifications(_Devices, deviceUsn);
|
||||
foreach (var existingDevice in existingDevices)
|
||||
{
|
||||
if (this.IsDisposed)
|
||||
if (IsDisposed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -206,9 +206,9 @@ namespace Rssdp.Infrastructure
|
||||
IPAddress receivedOnlocalIPAddress,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (String.IsNullOrEmpty(searchTarget))
|
||||
if (string.IsNullOrEmpty(searchTarget))
|
||||
{
|
||||
WriteTrace(String.Format(CultureInfo.InvariantCulture, "Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString()));
|
||||
WriteTrace(string.Format(CultureInfo.InvariantCulture, "Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace Rssdp.Infrastructure
|
||||
// return;
|
||||
}
|
||||
|
||||
if (!Int32.TryParse(mx, out var maxWaitInterval) || maxWaitInterval <= 0)
|
||||
if (!int.TryParse(mx, out var maxWaitInterval) || maxWaitInterval <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -243,27 +243,27 @@ namespace Rssdp.Infrastructure
|
||||
}
|
||||
|
||||
// Do not block synchronously as that may tie up a threadpool thread for several seconds.
|
||||
Task.Delay(_Random.Next(16, (maxWaitInterval * 1000)), cancellationToken).ContinueWith((parentTask) =>
|
||||
Task.Delay(_Random.Next(16, maxWaitInterval * 1000), cancellationToken).ContinueWith((parentTask) =>
|
||||
{
|
||||
// Copying devices to local array here to avoid threading issues/enumerator exceptions.
|
||||
IEnumerable<SsdpDevice> devices = null;
|
||||
lock (_Devices)
|
||||
{
|
||||
if (String.Compare(SsdpConstants.SsdpDiscoverAllSTHeader, searchTarget, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
if (string.Compare(SsdpConstants.SsdpDiscoverAllSTHeader, searchTarget, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
devices = GetAllDevicesAsFlatEnumerable().ToArray();
|
||||
}
|
||||
else if (String.Compare(SsdpConstants.UpnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0 || (this.SupportPnpRootDevice && String.Compare(SsdpConstants.PnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0))
|
||||
else if (string.Compare(SsdpConstants.UpnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0 || (SupportPnpRootDevice && String.Compare(SsdpConstants.PnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0))
|
||||
{
|
||||
devices = _Devices.ToArray();
|
||||
}
|
||||
else if (searchTarget.Trim().StartsWith("uuid:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
devices = GetAllDevicesAsFlatEnumerable().Where(d => String.Compare(d.Uuid, searchTarget.Substring(5), StringComparison.OrdinalIgnoreCase) == 0).ToArray();
|
||||
devices = GetAllDevicesAsFlatEnumerable().Where(d => string.Compare(d.Uuid, searchTarget.Substring(5), StringComparison.OrdinalIgnoreCase) == 0).ToArray();
|
||||
}
|
||||
else if (searchTarget.StartsWith("urn:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
devices = GetAllDevicesAsFlatEnumerable().Where(d => String.Compare(d.FullDeviceType, searchTarget, StringComparison.OrdinalIgnoreCase) == 0).ToArray();
|
||||
devices = GetAllDevicesAsFlatEnumerable().Where(d => string.Compare(d.FullDeviceType, searchTarget, StringComparison.OrdinalIgnoreCase) == 0).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ namespace Rssdp.Infrastructure
|
||||
if (isRootDevice)
|
||||
{
|
||||
SendSearchResponse(SsdpConstants.UpnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), endPoint, receivedOnlocalIPAddress, cancellationToken);
|
||||
if (this.SupportPnpRootDevice)
|
||||
if (SupportPnpRootDevice)
|
||||
{
|
||||
SendSearchResponse(SsdpConstants.PnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), endPoint, receivedOnlocalIPAddress, cancellationToken);
|
||||
}
|
||||
@@ -312,7 +312,7 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
private string GetUsn(string udn, string fullDeviceType)
|
||||
{
|
||||
return String.Format(CultureInfo.InvariantCulture, "{0}::{1}", udn, fullDeviceType);
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0}::{1}", udn, fullDeviceType);
|
||||
}
|
||||
|
||||
private async void SendSearchResponse(
|
||||
@@ -326,16 +326,17 @@ namespace Rssdp.Infrastructure
|
||||
const string header = "HTTP/1.1 200 OK";
|
||||
|
||||
var rootDevice = device.ToRootDevice();
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
values["EXT"] = "";
|
||||
values["DATE"] = DateTime.UtcNow.ToString("r");
|
||||
values["HOST"] = "239.255.255.250:1900";
|
||||
values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds;
|
||||
values["ST"] = searchTarget;
|
||||
values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion);
|
||||
values["USN"] = uniqueServiceName;
|
||||
values["LOCATION"] = rootDevice.Location.ToString();
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["EXT"] = "",
|
||||
["DATE"] = DateTime.UtcNow.ToString("r"),
|
||||
["HOST"] = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", SsdpConstants.MulticastLocalAdminAddress, SsdpConstants.MulticastPort),
|
||||
["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds,
|
||||
["ST"] = searchTarget,
|
||||
["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion),
|
||||
["USN"] = uniqueServiceName,
|
||||
["LOCATION"] = rootDevice.Location.ToString()
|
||||
};
|
||||
|
||||
var message = BuildMessage(header, values);
|
||||
|
||||
@@ -439,7 +440,7 @@ namespace Rssdp.Infrastructure
|
||||
if (isRoot)
|
||||
{
|
||||
SendAliveNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken);
|
||||
if (this.SupportPnpRootDevice)
|
||||
if (SupportPnpRootDevice)
|
||||
{
|
||||
SendAliveNotification(device, SsdpConstants.PnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), cancellationToken);
|
||||
}
|
||||
@@ -460,17 +461,18 @@ namespace Rssdp.Infrastructure
|
||||
|
||||
const string header = "NOTIFY * HTTP/1.1";
|
||||
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// 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;
|
||||
values["LOCATION"] = rootDevice.Location.ToString();
|
||||
values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion);
|
||||
values["NTS"] = "ssdp:alive";
|
||||
values["NT"] = notificationType;
|
||||
values["USN"] = uniqueServiceName;
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
// If needed later for non-server devices, these headers will need to be dynamic
|
||||
["HOST"] = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", SsdpConstants.MulticastLocalAdminAddress, SsdpConstants.MulticastPort),
|
||||
["DATE"] = DateTime.UtcNow.ToString("r"),
|
||||
["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds,
|
||||
["LOCATION"] = rootDevice.Location.ToString(),
|
||||
["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion),
|
||||
["NTS"] = "ssdp:alive",
|
||||
["NT"] = notificationType,
|
||||
["USN"] = uniqueServiceName
|
||||
};
|
||||
|
||||
var message = BuildMessage(header, values);
|
||||
|
||||
@@ -485,7 +487,7 @@ namespace Rssdp.Infrastructure
|
||||
if (isRoot)
|
||||
{
|
||||
tasks.Add(SendByeByeNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken));
|
||||
if (this.SupportPnpRootDevice)
|
||||
if (SupportPnpRootDevice)
|
||||
{
|
||||
tasks.Add(SendByeByeNotification(device, "pnp:rootdevice", GetUsn(device.Udn, "pnp:rootdevice"), cancellationToken));
|
||||
}
|
||||
@@ -506,20 +508,21 @@ namespace Rssdp.Infrastructure
|
||||
{
|
||||
const string header = "NOTIFY * HTTP/1.1";
|
||||
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// 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(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion);
|
||||
values["NTS"] = "ssdp:byebye";
|
||||
values["NT"] = notificationType;
|
||||
values["USN"] = uniqueServiceName;
|
||||
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
// If needed later for non-server devices, these headers will need to be dynamic
|
||||
["HOST"] = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", SsdpConstants.MulticastLocalAdminAddress, SsdpConstants.MulticastPort),
|
||||
["DATE"] = DateTime.UtcNow.ToString("r"),
|
||||
["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, SsdpConstants.ServerVersion),
|
||||
["NTS"] = "ssdp:byebye",
|
||||
["NT"] = notificationType,
|
||||
["USN"] = uniqueServiceName
|
||||
};
|
||||
|
||||
var message = BuildMessage(header, values);
|
||||
|
||||
var sendCount = IsDisposed ? 1 : 3;
|
||||
WriteTrace(String.Format(CultureInfo.InvariantCulture, "Sent byebye notification"), device);
|
||||
WriteTrace(string.Format(CultureInfo.InvariantCulture, "Sent byebye notification"), device);
|
||||
return _CommsServer.SendMulticastMessage(message, sendCount, _sendOnlyMatchedHost ? device.ToRootDevice().Address : null, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user