Skip to content

Commit

Permalink
Fix search responses to match UPnP tests.
Browse files Browse the repository at this point in the history
Fix and add tests for correct behaviour
Nuget updates pre-publishign.
  • Loading branch information
Troy Willmot committed Sep 16, 2017
1 parent 994e690 commit b8c14d7
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 82 deletions.
2 changes: 1 addition & 1 deletion src/Main/PublishNugetPackage.cmd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@echo off
echo Press any key to publish
pause
".nuget\NuGet.exe" push Rssdp.3.5.4.nupkg -Source https://www.nuget.org/api/v2/package
".nuget\NuGet.exe" push Rssdp.3.5.6.nupkg -Source https://www.nuget.org/api/v2/package
pause
4 changes: 2 additions & 2 deletions src/Main/Rssdp.Shared/AssemblyInfoCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
[assembly: AssemblyCopyright("Released under the MIT license; http://choosealicense.com/licenses/mit/; https://github.com/Yortw/RSSDP")]
[assembly: AssemblyTrademark("")]

[assembly: AssemblyVersion("3.5.5.0")]
[assembly: AssemblyFileVersion("3.5.5.0")]
[assembly: AssemblyVersion("3.5.6.0")]
[assembly: AssemblyFileVersion("3.5.6.0")]
98 changes: 65 additions & 33 deletions src/Main/Rssdp.Shared/SsdpDevicePublisherBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -402,24 +402,7 @@ private void ProcessSearchRequest(string mx, string searchTarget, UdpEndPoint en
devices = GetDevicesMatchingSearchTarget(searchTarget, devices);

if (devices != null)
{
_Log.LogInfo(String.Format("Sending search responses for {0} devices", devices.Count()));

if (searchTarget.Contains(":service:"))
{
foreach (var device in devices)
{
SendServiceSearchResponses(device, searchTarget, endPoint);
}
}
else
{
foreach (var device in devices)
{
SendDeviceSearchResponses(device, endPoint);
}
}
}
SendSearchResponses(searchTarget, endPoint, devices);
else
_Log.LogWarning("Sending search responses for 0 devices (no matching targets).");
});
Expand All @@ -446,17 +429,18 @@ select device
{
if (searchTarget.Contains(":service:"))
{
devices = (from
device in GetAllDevicesAsFlatEnumerable()
where
(
from s in
device.Services
where String.Compare(s.FullServiceType, searchTarget, StringComparison.OrdinalIgnoreCase) == 0
select s
).Any()
select device
).ToArray();
devices =
(
from device in GetAllDevicesAsFlatEnumerable()
where
(
from s in
device.Services
where String.Compare(s.FullServiceType, searchTarget, StringComparison.OrdinalIgnoreCase) == 0
select s
).Any()
select device
).ToArray();
}
else
{
Expand Down Expand Up @@ -497,19 +481,67 @@ private IEnumerable<SsdpDevice> GetAllDevicesAsFlatEnumerable()
return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices));
}

private void SendDeviceSearchResponses(SsdpDevice device, UdpEndPoint endPoint)
private void SendSearchResponses(string searchTarget, UdpEndPoint endPoint, IEnumerable<SsdpDevice> devices)
{
_Log.LogInfo(String.Format("Sending search (target = {1}) responses for {0} devices", devices.Count(), searchTarget));

if (searchTarget.Contains(":service:"))
{
foreach (var device in devices)
{
SendServiceSearchResponses(device, searchTarget, endPoint);
}
}
else
{
foreach (var device in devices)
{
SendDeviceSearchResponses(device, searchTarget, endPoint);
}
}
}

private void SendDeviceSearchResponses(SsdpDevice device, string searchTarget, UdpEndPoint endPoint)
{
//http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0-20080424.pdf - page 21
//For ssdp:all - Respond 3+2d+k times for a root device with d embedded devices and s embedded services but only k distinct service types
//Root devices - Respond once (special handling when in related/Win Explorer support mode)
//Udn (uuid) - Response once
//Device type - response once
//Service type - respond once per service type

bool isRootDevice = (device as SsdpRootDevice) != null;
if (isRootDevice)
bool sendAll = searchTarget == SsdpConstants.SsdpDiscoverAllSTHeader;
bool sendRootDevices = searchTarget == SsdpConstants.UpnpDeviceTypeRootDevice || searchTarget == SsdpConstants.PnpDeviceTypeRootDevice;

if (isRootDevice && (sendAll || sendRootDevices))
{
SendSearchResponse(SsdpConstants.UpnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), endPoint);
if (IsWindowsExplorerSupportEnabled)
SendSearchResponse(SsdpConstants.PnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), endPoint);
}

SendSearchResponse(device.Udn, device, device.Udn, endPoint);
if (sendAll || searchTarget.StartsWith("uuid:"))
SendSearchResponse(device.Udn, device, device.Udn, endPoint);

if (sendAll || searchTarget.Contains(":device:"))
SendSearchResponse(device.FullDeviceType, device, GetUsn(device.Udn, device.FullDeviceType), endPoint);

SendSearchResponse(device.FullDeviceType, device, GetUsn(device.Udn, device.FullDeviceType), endPoint);
if (searchTarget == SsdpConstants.SsdpDiscoverAllSTHeader)
{
//Send 1 search response for each unique service type for all devices found
var serviceTypes =
(
from s
in device.Services
select s.FullServiceType
).Distinct().ToArray();

foreach (var st in serviceTypes)
{
SendServiceSearchResponses(device, st, endPoint);
}
}
}

private void SendServiceSearchResponses(SsdpDevice device, string searchTarget, UdpEndPoint endPoint)
Expand Down
4 changes: 2 additions & 2 deletions src/Main/Rssdp.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Rssdp</id>
<version>3.5.5</version>
<version>3.5.6-beta</version>
<title>Rssdp</title>
<authors>Troy Willmot</authors>
<owners>Yortw</owners>
Expand All @@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Really Simple Service Discovery Protocol - a 100% .Net implementation of the SSDP protocol for publishing custom/basic devices, and discovering all device types on a network.</description>
<summary>A 100% .Net implementation of the SSDP protocol for basic and custom device types.</summary>
<releaseNotes>Use Multicast socket options for binding to local IP provided to socket factory (regressed in v3.0.0.0).</releaseNotes>
<releaseNotes>Fixes for search responses to match UPnP 1.1 specification.</releaseNotes>
<copyright>Copyright 2017</copyright>
<language>en-AU</language>
<tags>portable xamarin ios android windowsphone winrt uwp mobile ssdp discovery device service protocol upnp netfx40 .net4</tags>
Expand Down
Loading

0 comments on commit b8c14d7

Please sign in to comment.