From 5f557b7c7316908d302789649db5e0aba7dd4ce9 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 27 Jan 2015 19:46:16 -0500 Subject: [PATCH] According to the spec: http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0-20080424.pdf device responses to search should be delayed a random duration between 0 and the delay, not equal to the delay. --- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 41 +++++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index bd3098ecd..105ecc650 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -62,20 +62,14 @@ namespace MediaBrowser.Dlna.Ssdp { if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase)) { - string mx = null; - args.Headers.TryGetValue("mx", out mx); - int delaySeconds; - if (!string.IsNullOrWhiteSpace(mx) && - int.TryParse(mx, NumberStyles.Any, CultureInfo.InvariantCulture, out delaySeconds) - && delaySeconds > 0) + TimeSpan delay = GetSearchDelay(args.Headers); + + if (_config.GetDlnaConfiguration().EnableDebugLogging) { - if (_config.GetDlnaConfiguration().EnableDebugLogging) - { - _logger.Debug("Delaying search response by {0} seconds", delaySeconds); - } - - await Task.Delay(delaySeconds * 1000).ConfigureAwait(false); + _logger.Debug("Delaying search response by {0} seconds", delay.TotalSeconds); } + + await Task.Delay(delay).ConfigureAwait(false); RespondToSearch(args.EndPoint, args.Headers["st"]); } @@ -148,6 +142,29 @@ namespace MediaBrowser.Dlna.Ssdp StartQueueTimer(); } + /// + /// According to the spec: http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0-20080424.pdf + /// Device responses should be delayed a random duration between 0 and this many seconds to balance + /// load for the control point when it processes responses. In my testing kodi times out after mx + /// so we will generate from mx - 1 + /// + /// The mx headers + /// A timepsan for the amount to delay before returning search result. + private TimeSpan GetSearchDelay(Dictionary headers) + { + string mx; + headers.TryGetValue("mx", out mx); + int delaySeconds = 0; + if (!string.IsNullOrWhiteSpace(mx) + && int.TryParse(mx, NumberStyles.Any, CultureInfo.InvariantCulture, out delaySeconds) + && delaySeconds > 1) + { + delaySeconds = new Random().Next(delaySeconds - 1); + } + + return TimeSpan.FromSeconds(delaySeconds); + } + private void RespondToSearch(EndPoint endpoint, string deviceType) { if (_config.GetDlnaConfiguration().EnableDebugLogging)