Yortw / RSSDP

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.

Home Page:http://yortw.github.io/RSSDP/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SSDP search on specific local ip not working

Gohico opened this issue · comments

Hi,

first of all great project - works brilliantly although I have one problem with different networks and SSDP broadcasts.
So the scenario:
I'm connected to two different Wifi networks the same time - both are connections to Cameras (which run in hot spot mode). Sadly those cameras have both the same IP as you can't configure it while they run in hotspot mode...
I have identified the local IP endpoints which bind to the cameras - say 192.168.1.158 and 192.168.1.240.

If I perform a search as in your FAQ:

        private async Task<SsdpDevice> SearchForDeviceSsdp(string localIpEnpoint)
        {
            int localPort = _rnd.Next(50000, 55000); //seen here: https://github.com/Yortw/RSSDP/issues/38           
            Rssdp.Infrastructure.SsdpCommunicationsServer localPortServer = new 
            Rssdp.Infrastructure.SsdpCommunicationsServer(new Rssdp.SocketFactory(localIpEnpoint));
            using (var deviceLocator = new SsdpDeviceLocator(localPortServer), localPort)
            {
                deviceLocator.NotificationFilter = SONY_API_IDENTIFIER; //filters for the camera API
                try
                {
                    IEnumerable<DiscoveredSsdpDevice> foundCameraApi = await deviceLocator.SearchAsync();

                    var discoveredSsdpDevices = foundCameraApi as DiscoveredSsdpDevice[] ?? foundCameraApi.ToArray();
                    foreach (var foundDevice in discoveredSsdpDevices)
                    {
                        SsdpDevice fullDeviceInfo = await foundDevice.GetDeviceInfo();
                        return fullDeviceInfo;
                    }
                }
                catch (Exception e)
                {
                }
            }
            return null;
        }

I always get the same camera. So the DeviceInfo contains the name of the camera - I can see I always get the same ID. So I can't differentiate between those cams. On the other side I do later call the API of each camera individually - to take a photo - which works fine.

So I'm wondering if there could be an issue with search based on a locally bound IP.

So calling the API is a bit messy right now but the ServicePoint reset (or set to local IP) is basically this:

                ServicePoint servicePointG = ServicePointManager.FindServicePoint(new Uri(camera.CameraApiEndpoint));
                servicePointG.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) => new IPEndPoint(IPAddress.Parse(camera.LocalIpBindingEndpoint), 0);

                servicePointG.ConnectionLeaseTimeout = 0;

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(camera.CameraApiEndpoint);
                req.ContentType = "application/json";
                req.KeepAlive = false;
                req.Method = "POST";
                req.Timeout = 10000;

So I'm kinda sure the communication is basically fine - just the SSDP on a specific locally bound IP does not work (but would be needed so I know which cam is which).
Currently the GetDeviceInfo call always returns exactly the same result - independent of the local IP (which shouldn't be the case).

Any help would be awesome.
Thanks
Nico

Hi,

Thanks for the kind words and the issue report.

Can I just clarify what the issue(s) are?

You've mentioned that

GetDeviceInfo always returns the same result"

which sort of makes sense. Internally it uses HttpClient to do the GET to the device endpoint, and I don't actually know how to bind HttpClient to a specific adapter - normally it decides itself. So I can understand why that might not work, and if that's the problem then I can investigate a solution.

However you've also said the "search doesn't work bound to a local adapter" and I'm not sure why that would be the case or how to test this. I can be connected to two different networks on my dev machine (though my opportunities for this are limited as I normally only have one network at home & work) , and performing a search bound to different IP's definitely returns me different results. A common problem other people have had is the default network adapter chosen being one that isn't connected or isn't the one they expect, and then they do not get any results (or at least not the results they expect). That was why I updated RSSDP to support taking a local IP to bind to, and I haven't seen/reproduced/heard about any failures of it since.

So are both the search and getdeviceinfo working incorrectly, or are you getting the right search result but getdeviceinfo always returns the response from one device?

You said

I always get the same camera. So the DeviceInfo contains the name of the camera - I can see I always get the same ID

but if GetDeviceInfo is broken that would be true even if the search was working properly, so again, I just need to narrow down the problem so I can investigate.

If it is only GetDeviceInfo that is broken, you can probably work around it on your own until I can provide a fix. You need to use the same logic you've used for calling the API to take a photo, but use the GET http method, content type of "application/xml" and send the request to the DeviceLocation address specified on the search result object. That will give you back the XML, and then you should be able to either read that manually or pass it to the SsdpDevice to parse it into one of the RSSDP objects.

Thanks.

Hi,

thanks for the super fast response.

From what I have learned so far (while working with the cameras) is that some 'HttpClients' can be bound to local endpoints - some not... Due to this I used the HttpWebRequest in a different place - as its possible to provide a ServicePoint delegate.

My hope was the via doing this:
using (var deviceLocator = new SsdpDeviceLocator(localPortServer), localPort)
I'm binding the deviceLocator to a local IP/ network interface. So when starting a search there I'm only getting SSDP endpoint on this interface.

I'm doing this call (using (var deviceLocator = new SsdpDeviceLocator(localPortServer), localPort)) for each local network interface (I have two) - but when checking the DeviceFriendlyName in the same loop iteration its always the same (on both IPs/ local interfaces).
Which makes sense if GetDeviceInfo() is based on HttpClient (could have looked up that myself - sorry).
As my cameras are identical models I can't differentiate on search level - the only way to separate the cameras is via the DeviceFriendlyName. All other paramters are the same - at least the search returns the same content.
Therefore I rely a bit on GetDeviceInfo()

As mentioned I have two cameras - both running in AccessPoint mode - and both Access points having the same bloody hardcoded IP (its silly... to get the REST API working on the cameras you must switch them into RemoteControlMode - which opens an Access point. There the IP of the camera is hardcoded - there is no way to change this. Or I haven't found one)...
So the only way to differentiate the cameras is via the 'DeviceFriendlyName' that comes out of the DeviceInfo.

Again thanks alot... I believe I know where my problem is located...
It might be a useful improvement for you in the long run - as I would guess having the option to bind the SsdpDeviceLocator only makes sense if GetDeviceInfo() is bound to the same local IP endpoint.

On the other side this is a rare use case I guess :)