|
|
@ -86,8 +86,15 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
|
|
|
|
|
|
|
|
public event EventHandler<SsdpMessageEventArgs> MessageReceived;
|
|
|
|
public event EventHandler<SsdpMessageEventArgs> MessageReceived;
|
|
|
|
|
|
|
|
|
|
|
|
private async void OnMessageReceived(SsdpMessageEventArgs args)
|
|
|
|
private async void OnMessageReceived(SsdpMessageEventArgs args, bool isMulticast)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (IgnoreMessage(args, isMulticast))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LogMessageReceived(args, isMulticast);
|
|
|
|
|
|
|
|
|
|
|
|
var headers = args.Headers;
|
|
|
|
var headers = args.Headers;
|
|
|
|
string st;
|
|
|
|
string st;
|
|
|
|
|
|
|
|
|
|
|
@ -108,6 +115,59 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger);
|
|
|
|
EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal void LogMessageReceived(SsdpMessageEventArgs args, bool isMulticast)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLog;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (enableDebugLogging)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
|
|
|
|
|
|
|
|
var headerText = string.Join(",", headerTexts.ToArray());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var protocol = isMulticast ? "Multicast" : "Unicast";
|
|
|
|
|
|
|
|
var localEndPointString = args.LocalEndPoint == null ? "null" : args.LocalEndPoint.ToString();
|
|
|
|
|
|
|
|
_logger.Debug("{0} message received from {1} on {3}. Protocol: {4} Headers: {2}", args.Method, args.EndPoint, headerText, localEndPointString, protocol);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal bool IgnoreMessage(SsdpMessageEventArgs args, bool isMulticast)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
string usn;
|
|
|
|
|
|
|
|
if (args.Headers.TryGetValue("USN", out usn))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// USN=uuid:b67df29b5c379445fde78c3774ab518d::urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1
|
|
|
|
|
|
|
|
if (RegisteredDevices.Select(i => i.USN).Contains(usn, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
|
|
|
|
|
|
|
|
//var headerText = string.Join(",", headerTexts.ToArray());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//var protocol = isMulticast ? "Multicast" : "Unicast";
|
|
|
|
|
|
|
|
//var localEndPointString = args.LocalEndPoint == null ? "null" : args.LocalEndPoint.ToString();
|
|
|
|
|
|
|
|
//_logger.Debug("IGNORING {0} message received from {1} on {3}. Protocol: {4} Headers: {2}", args.Method, args.EndPoint, headerText, localEndPointString, protocol);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string serverId;
|
|
|
|
|
|
|
|
if (args.Headers.TryGetValue("X-EMBY-SERVERID", out serverId))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (string.Equals(serverId, _appHost.SystemId, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
|
|
|
|
|
|
|
|
//var headerText = string.Join(",", headerTexts.ToArray());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//var protocol = isMulticast ? "Multicast" : "Unicast";
|
|
|
|
|
|
|
|
//var localEndPointString = args.LocalEndPoint == null ? "null" : args.LocalEndPoint.ToString();
|
|
|
|
|
|
|
|
//_logger.Debug("IGNORING {0} message received from {1} on {3}. Protocol: {4} Headers: {2}", args.Method, args.EndPoint, headerText, localEndPointString, protocol);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public IEnumerable<UpnpDevice> RegisteredDevices
|
|
|
|
public IEnumerable<UpnpDevice> RegisteredDevices
|
|
|
|
{
|
|
|
|
{
|
|
|
|
get
|
|
|
|
get
|
|
|
@ -126,7 +186,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
RestartSocketListener();
|
|
|
|
RestartSocketListener();
|
|
|
|
ReloadAliveNotifier();
|
|
|
|
ReloadAliveNotifier();
|
|
|
|
|
|
|
|
|
|
|
|
//CreateUnicastClient();
|
|
|
|
CreateUnicastClient();
|
|
|
|
|
|
|
|
|
|
|
|
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
|
|
|
|
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
|
|
|
|
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
|
|
|
|
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
|
|
|
@ -146,6 +206,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
|
|
|
|
|
|
|
|
values["HOST"] = "239.255.255.250:1900";
|
|
|
|
values["HOST"] = "239.255.255.250:1900";
|
|
|
|
values["USER-AGENT"] = "UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2";
|
|
|
|
values["USER-AGENT"] = "UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2";
|
|
|
|
|
|
|
|
values["X-EMBY-SERVERID"] = _appHost.SystemId;
|
|
|
|
|
|
|
|
|
|
|
|
values["MAN"] = "\"ssdp:discover\"";
|
|
|
|
values["MAN"] = "\"ssdp:discover\"";
|
|
|
|
|
|
|
|
|
|
|
@ -162,7 +223,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
// UDP is unreliable, so send 3 requests at a time (per Upnp spec, sec 1.1.2)
|
|
|
|
// UDP is unreliable, so send 3 requests at a time (per Upnp spec, sec 1.1.2)
|
|
|
|
SendDatagram(msg, _ssdpEndp, localIp, true);
|
|
|
|
SendDatagram(msg, _ssdpEndp, localIp, true);
|
|
|
|
|
|
|
|
|
|
|
|
//SendUnicastRequest(msg);
|
|
|
|
SendUnicastRequest(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async void SendDatagram(string msg,
|
|
|
|
public async void SendDatagram(string msg,
|
|
|
@ -242,9 +303,17 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
|
|
|
|
|
|
|
|
var msg = new SsdpMessageBuilder().BuildMessage(header, values);
|
|
|
|
var msg = new SsdpMessageBuilder().BuildMessage(header, values);
|
|
|
|
|
|
|
|
|
|
|
|
SendDatagram(msg, endpoint, null, false, 1);
|
|
|
|
var ipEndPoint = endpoint as IPEndPoint;
|
|
|
|
SendDatagram(msg, endpoint, new IPEndPoint(d.Address, 0), false, 1);
|
|
|
|
if (ipEndPoint != null)
|
|
|
|
//SendDatagram(header, values, endpoint, null, true);
|
|
|
|
{
|
|
|
|
|
|
|
|
SendUnicastRequest(msg, ipEndPoint);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
SendDatagram(msg, endpoint, null, false, 2);
|
|
|
|
|
|
|
|
SendDatagram(msg, endpoint, new IPEndPoint(d.Address, 0), false, 2);
|
|
|
|
|
|
|
|
//SendDatagram(header, values, endpoint, null, true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (enableDebugLogging)
|
|
|
|
if (enableDebugLogging)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -324,20 +393,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
var args = SsdpHelper.ParseSsdpResponse(received);
|
|
|
|
var args = SsdpHelper.ParseSsdpResponse(received);
|
|
|
|
args.EndPoint = endpoint;
|
|
|
|
args.EndPoint = endpoint;
|
|
|
|
|
|
|
|
|
|
|
|
if (IsSelfNotification(args))
|
|
|
|
OnMessageReceived(args, true);
|
|
|
|
{
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (enableDebugLogging)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
|
|
|
|
|
|
|
|
var headerText = string.Join(",", headerTexts.ToArray());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Debug("{0} message received from {1} on {3}. Headers: {2}", args.Method, args.EndPoint, headerText, _multicastSocket.LocalEndPoint);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OnMessageReceived(args);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -357,26 +413,6 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal bool IsSelfNotification(SsdpMessageEventArgs args)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Avoid responding to self search messages
|
|
|
|
|
|
|
|
//string serverId;
|
|
|
|
|
|
|
|
//if (args.Headers.TryGetValue("X-EMBYSERVERID", out serverId) &&
|
|
|
|
|
|
|
|
// string.Equals(serverId, _appHost.SystemId, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
|
|
//{
|
|
|
|
|
|
|
|
// return true;
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string server;
|
|
|
|
|
|
|
|
args.Headers.TryGetValue("SERVER", out server);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (string.Equals(server, _serverSignature, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
|
|
|
|
_config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
|
|
|
@ -440,6 +476,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
values["NTS"] = "ssdp:" + type;
|
|
|
|
values["NTS"] = "ssdp:" + type;
|
|
|
|
values["NT"] = dev.Type;
|
|
|
|
values["NT"] = dev.Type;
|
|
|
|
values["USN"] = dev.USN;
|
|
|
|
values["USN"] = dev.USN;
|
|
|
|
|
|
|
|
values["X-EMBY-SERVERID"] = _appHost.SystemId;
|
|
|
|
|
|
|
|
|
|
|
|
if (logMessage)
|
|
|
|
if (logMessage)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -449,6 +486,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
var msg = new SsdpMessageBuilder().BuildMessage(header, values);
|
|
|
|
var msg = new SsdpMessageBuilder().BuildMessage(header, values);
|
|
|
|
|
|
|
|
|
|
|
|
SendDatagram(msg, _ssdpEndp, new IPEndPoint(dev.Address, 0), true);
|
|
|
|
SendDatagram(msg, _ssdpEndp, new IPEndPoint(dev.Address, 0), true);
|
|
|
|
|
|
|
|
//SendUnicastRequest(msg, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RegisterNotification(string uuid, Uri descriptionUri, IPAddress address, IEnumerable<string> services)
|
|
|
|
public void RegisterNotification(string uuid, Uri descriptionUri, IPAddress address, IEnumerable<string> services)
|
|
|
@ -489,14 +527,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
_logger.ErrorException("Error creating unicast client", ex);
|
|
|
|
_logger.ErrorException("Error creating unicast client", ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
UnicastSetBeginReceive();
|
|
|
|
{
|
|
|
|
|
|
|
|
UnicastSetBeginReceive();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.ErrorException("Error in UnicastSetBeginReceive", ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -522,11 +553,18 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
private void UnicastSetBeginReceive()
|
|
|
|
private void UnicastSetBeginReceive()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var ipRxEnd = new IPEndPoint(IPAddress.Any, _unicastPort);
|
|
|
|
try
|
|
|
|
var udpListener = new UdpState { EndPoint = ipRxEnd };
|
|
|
|
{
|
|
|
|
|
|
|
|
var ipRxEnd = new IPEndPoint(IPAddress.Any, _unicastPort);
|
|
|
|
|
|
|
|
var udpListener = new UdpState { EndPoint = ipRxEnd };
|
|
|
|
|
|
|
|
|
|
|
|
udpListener.UdpClient = _unicastClient;
|
|
|
|
udpListener.UdpClient = _unicastClient;
|
|
|
|
_unicastClient.BeginReceive(UnicastReceiveCallback, udpListener);
|
|
|
|
_unicastClient.BeginReceive(UnicastReceiveCallback, udpListener);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.ErrorException("Error in UnicastSetBeginReceive", ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
@ -540,18 +578,25 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
var endpoint = ((UdpState)(ar.AsyncState)).EndPoint;
|
|
|
|
var endpoint = ((UdpState)(ar.AsyncState)).EndPoint;
|
|
|
|
if (udpClient.Client != null)
|
|
|
|
if (udpClient.Client != null)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var responseBytes = udpClient.EndReceive(ar, ref endpoint);
|
|
|
|
try
|
|
|
|
var args = SsdpHelper.ParseSsdpResponse(responseBytes);
|
|
|
|
{
|
|
|
|
|
|
|
|
var responseBytes = udpClient.EndReceive(ar, ref endpoint);
|
|
|
|
|
|
|
|
var args = SsdpHelper.ParseSsdpResponse(responseBytes);
|
|
|
|
|
|
|
|
|
|
|
|
args.EndPoint = endpoint;
|
|
|
|
args.EndPoint = endpoint;
|
|
|
|
|
|
|
|
|
|
|
|
OnMessageReceived(args);
|
|
|
|
OnMessageReceived(args, false);
|
|
|
|
|
|
|
|
|
|
|
|
UnicastSetBeginReceive();
|
|
|
|
UnicastSetBeginReceive();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (ObjectDisposedException)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async void SendUnicastRequest(string request)
|
|
|
|
private void SendUnicastRequest(string request, int sendCount = 3)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (_unicastClient == null)
|
|
|
|
if (_unicastClient == null)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -560,17 +605,37 @@ namespace MediaBrowser.Dlna.Ssdp
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Debug("Sending unicast search request");
|
|
|
|
_logger.Debug("Sending unicast search request");
|
|
|
|
|
|
|
|
|
|
|
|
byte[] req = Encoding.ASCII.GetBytes(request);
|
|
|
|
|
|
|
|
var ipSsdp = IPAddress.Parse(SSDPAddr);
|
|
|
|
var ipSsdp = IPAddress.Parse(SSDPAddr);
|
|
|
|
var ipTxEnd = new IPEndPoint(ipSsdp, SSDPPort);
|
|
|
|
var ipTxEnd = new IPEndPoint(ipSsdp, SSDPPort);
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < 3; i++)
|
|
|
|
SendUnicastRequest(request, ipTxEnd, sendCount);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async void SendUnicastRequest(string request, IPEndPoint toEndPoint, int sendCount = 3)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (_unicastClient == null)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (i > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Debug("Sending unicast search request");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
byte[] req = Encoding.ASCII.GetBytes(request);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (var i = 0; i < sendCount; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
await Task.Delay(50).ConfigureAwait(false);
|
|
|
|
if (i > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
await Task.Delay(50).ConfigureAwait(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_unicastClient.Send(req, req.Length, toEndPoint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_unicastClient.Send(req, req.Length, ipTxEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_logger.ErrorException("Error in SendUnicastRequest", ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|