0

I'm trying to get a little SSDP client / server up and running. So far the server is working just fine, responding to my M-SEARCH (according to wireshark). The client code is written in Visual Studio using Winsock2 (see code below). The problem is that the response never reaches my recv call when i send the search to the multicast address.

I already tried sending and receiving directly to the server ip address, which will generate a response that reaches my recv call correctly. However, when i change the ip to the multicast addess, it doesn't work (even though i can see the response on Wireshark!). So for some reason the socket (on OS level?) refuses to pass it on to the application.

I should note that the response is always unicast.

Here's my code:

#include <Winsock2.h> // before Windows.h, else Winsock 1 conflict
#include <Ws2tcpip.h> // needed for ip_mreq definition for multicast
#include <Windows.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define SERVERPORT 1900
char buff[] = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: ssdp:discover\r\nST: ssdp:all\r\n\r\n";

int main()
{
    char rcvdbuff[1000];
    int len, Ret = 2;

    WSADATA wsaData;
    if (WSAStartup(0x0101, &wsaData)) {
        perror("WSAStartup");
        return 1;
    }

    struct sockaddr_in their_addr;
    SOCKET sock;

    sock = socket(AF_INET, SOCK_DGRAM, 0);

    their_addr.sin_family = AF_INET;
    ////THIS APPROACH DOES NOT WORK
    their_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
    //THIS APPROACH WORKS - SOMEHOW THE SOCKET IS BOUND TO THIS IP AND CAN THUS RECEIVE
    //their_addr.sin_addr.s_addr = inet_addr("192.168.3.90");
    their_addr.sin_port = htons(SERVERPORT);
    len = sizeof(struct sockaddr_in);

    while (1)
    {
        printf("buff:\n%s\n", buff);
        Ret = sendto(sock, buff, strlen(buff), 0, (struct sockaddr*)&their_addr, len);
        if (Ret < 0)
        {
            printf("error in SENDTO() function");
            closesocket(sock);
            return 0;
        }

        //Receiving Text from server
        printf("\n\nwaiting to recv:\n");
        memset(rcvdbuff, 0, sizeof(rcvdbuff));
        Ret = recvfrom(sock, rcvdbuff, sizeof(rcvdbuff), 0, (struct sockaddr *)&their_addr, &len);
        if (Ret < 0)
        {
            printf("Error in Receiving");
            return 0;
        }
        rcvdbuff[Ret - 1] = '\0';
        printf("RECEIVED MESSAGE FROM SERVER\t: %s\n", rcvdbuff);

        //Delay for testing purpose
        Sleep(3 * 1000);
    }
    closesocket(sock);
    WSACleanup();
}

I tried one interesting thing (without restarting the application!):

1) First send to the direct ip address (192.168.3.90)

2) Get response

3) Now send to the multicast address

4) Now the response gets back just fine!

It's as if the socket somehow 'knows' the unicast address from the first send/recv call.

Does anyone know what to do or how to debug?

SupAl
  • 517
  • 3
  • 12
  • My guess is that is has something to do with you using `their_addr` and `len` for both the `sendto` and `recvfrom` calls. Have you tried to use different variables (both for the socket address structure and the structure length) for the different calls? Have you tried stepping through the code in a debugger to see exactly when the code starts to fail? Also, when either `sendto` or `recvfrom` fails, you should print the value of `errno` to learn *why* it failed. – Some programmer dude May 28 '19 at 13:52
  • Well, it does work just fine when i send directly to 192.168.3.90 with this setup. The recvfrom never fails when i send to the multicast address, it just doesn't receive any data (even though I can see the response in Wireshark!), so there really is no error codes to check. I think the OS somehow doesn't pass the datagram on to the application. – SupAl May 28 '19 at 14:05
  • I suspect I've missed something here, but... if you want to receive IP multicast packets then you need to join the multicast group in question. Something like [`setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, ...)`](http://man7.org/linux/man-pages/man7/ip.7.html). – G.M. May 28 '19 at 14:06
  • It's not a multicast packet, since the response is unicast (from 192.168.3.90 -> "my ip address") – SupAl May 28 '19 at 14:07

1 Answers1

1

I think I've found the solution to the question: Windows Firewall. Here's a quote over from Quora:

Only connections that are explicitly allowed, using firewall rules, are permitted. Windows Firewall, by default, allows all outboundconnections, and permits only established inbound connections (that is, an inbound connection that is in direct response to an outbound connection initiated from your computer or network).

This is exactly the situation: We've not established an outbound connection, and thus it's blocked by Windows Firewall!

In the other case, when I first send directly, Windows Firewall opens up for that exact inbound connection and therefore the subsequent multicast send gets a response.

SupAl
  • 517
  • 3
  • 12