UPnP Multicast: missing answers from M-SEARCH (Discovery)
Asked Answered
S

3

16

I created a small program to test UPnP Multicast (Visual C# 2010 Express, running on Windows 7 Professional 64 Bit). I can receive the UPnP NOTIFY Messages from UPnP Devices in my Network. But when i send the M-SEARCH Message, i get no Answers.

I have tested the same code on a iOS environment (Monotouch for iOS, running on a iPhone simulator on a Mac). There it runs fine and i get all the search responses from my UPnP devices. I can also see the M-SEARCH message from my windows program.

It looks like Windows (or a Firewall?) is hiding the search responses. Any idea?

Here is the code:

IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 1900);
IPEndPoint MulticastEndPoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);

Socket UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.Bind(LocalEndPoint);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);

Console.WriteLine("UDP-Socket setup done...\r\n");

string SearchString = "M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:3\r\n\r\n";

UdpSocket.SendTo(Encoding.UTF8.GetBytes(SearchString), SocketFlags.None, MulticastEndPoint);

Console.WriteLine("M-Search sent...\r\n");

byte[] ReceiveBuffer = new byte[64000];

int ReceivedBytes = 0;

while (true)
{
    if (UdpSocket.Available > 0)
    {
        ReceivedBytes = UdpSocket.Receive(ReceiveBuffer, SocketFlags.None);

        if (ReceivedBytes > 0)
        {
            Console.WriteLine(Encoding.UTF8.GetString(ReceiveBuffer, 0, ReceivedBytes));
        }
    }
}
Shameful answered 9/10, 2012 at 7:19 Comment(3)
What is MulticastEndPoint set to?Lancastrian
Are you sure that the M-SEARCH you see on iOS is the one from your Windows program? Have you tried another UPnP discovery tool on your Windows box?Wingo
@PavelZdenek: Yes I'm sure. I have attached some extra characters on the M-SEARCH message so I could recognize the message on iOS.Buckish
S
19

Yeah, I solved the problem! Small mistake, big impact:

My program is sending the M-SEARCH on port 1900 which is bound to the UPnP multicast group. Because i bound the LocalEndPoint to the same port, the UPnP devices answers with unicast to port 1900. On iOS it worked, because my program was the only service bound to this port. But on the PC, i found several services bound to port 1900 (found with "netstat -p UDP -a"). So the unicast messages from the UPnP devices was absorbed by one of the other services.

The solution: I bound the LocalEndPoint to a free port (e.g. 60000), and now it works fine!

IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 60000);
Shameful answered 10/10, 2012 at 8:46 Comment(3)
You were faster than me :-) Yeah, Windows by default runs SSDP service. Have a look with netstat option -bWingo
I have the same Problem but I can't change my Port. Is there any other way to fix this Problem?Systematic
Don't bind to a specific port (60000), just ask for an ephemeral (0)! Or one day this may fail because someone else is using 60000Dustan
T
5

On create of local endpoint use port 0 (zero) to bind a free port not using a fixed port. Another point discovered. Binding IPAddress.Any or IPAddress.Loopback get responses from Microsoft (local?) system where as binding to one of the LAN address(es) get responses from the local net. Getting first IPV4 address can be done like this:

IPAddress localNetwork = Dns.GetHostAddresses(Environment.GetEnvironmentVariable("COMPUTERNAME")).Where(ia => (ia.AddressFamily == AddressFamily.InterNetwork)).First();
Theodora answered 2/4, 2014 at 20:26 Comment(3)
There is no really boundary to IPV4, I've found the IP V6 multicast addresses FF02::C (link-local), FF05::C (site-local), FF08::C (organization-local) and FF0E::C (global). Note that scope of IP V4 is site-local. Found at Wikipedia - SSDPTheodora
Environment.GetEnvironmentVariable("COMPUTERNAME") can be replaced by Environment.MachineName.Theodora
Thanks for this one. IPAddress.Any was returning 0.0.0.0 for my machine and nothing was being sent/received (I have about 30 VPNs and other network adapters configured so that might be cause).Edward
D
1

For posterity: setting all these options above is unnecessary for M-SEARCH and might even be counter-productive:

UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);

So don't do it.

Dustan answered 2/3, 2016 at 22:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.