1

This one has been driving me crazy for a while. Since I have never done any network related code, I am unable to conclude the results of this experiment.

I am provided with information about a server that broadcasts relevant information using SSDP. I was given the IP and port as per the standard. I was also given the query and search target I need to use on the receiver side. I am using my latest iteration for this example in which I decided to use a singleton class that manages the discovery. The true ST string I am using is one I was provided as well, disregard the one below...

DiscoveryManager.h

class DiscoveryManager : public QObject
{

private:
    DiscoveryManager( QObject *parent=0 );
public:
    ~DiscoveryManager();

    // Public Accessor for the singleton instance of the class
    static DiscoveryManager* Instance();

    void Discover();

public:
    void readPending();

private:
    // Singleton instance of the class
    static DiscoveryManager* _instance;
    QUdpSocket* socket;
};

DiscoveryManager.cpp

// Definition of singleton instance
DiscoveryManager* DiscoveryManager::_instance;

// Network Parameters
quint16 port = 1900;
QHostAddress groupAddress = QHostAddress("239.255.255.250");

DiscoveryManager::DiscoveryManager(QObject *parent)
    : QObject(parent)   
    , socket( nullptr )
{
    socket = new QUdpSocket(this);
    auto ok = m_sock->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress);
    if (!ok) 
    {
        printf("Bind Error\n");
        return;
    }

    ok = socket->joinMulticastGroup(groupAddress);
    if (!ok) {
        printf("Join Multicast Group Failed\n");
        return;
    }

    connect(socket, SIGNAL(readyRead()), this, SLOT(readPending()));
}

DiscoveryManager* DiscoveryManager::Instance()
{
  if(_instance == nullptr)
  {
    _instance = new DiscoveryManager();
  }
  return _instance;
}

void
DiscoveryManager::startDiscovery()
{
    QByteArray message("M-SEARCH * HTTP/1.1\r\n"        \
                       "HOST: 239.255.255.250:1900\r\n" \
                       "MAN: \"ssdp:discover\"\r\n" \
                       "MX: 5\r\n" \
                       "ST: ***:******-****-***:*******:***********:*\r\n" \
                       "\r\n");

    auto writeOk = socket->writeDatagram(message.data(), groupAddress, port);
    if (writeOk == -1) {
        printf("Writing Datagram failed\n");
        return;
    }
}


void
DiscoveryManager::readPending()
{
    while (socket->hasPendingDatagrams()) {
        QByteArray reply;
        reply.resize(socket->pendingDatagramSize());
        socket->readDatagram(reply.data(), reply.size());

        // ... Parse Text Here ...
    }
}

Results: 90% of the time, this fails. When I attempt to print the messages, the response I get is always an echo of what I queried. Regardless of how long I leave it, the correct response never arrives. On the other hand, when the conditions are "just right", the discovery is flawless and always returns a result immediately.

Expected Results: I expect to see a server response with more information such as the location.

Considerations:

  1. Since I have difficulty understanding why network related code fail, I cannot conclude from the results whether my receiver code is not correct, or whether the server was not set up correctly. What could be an indicator for me to use? Can things such as VPNs set up in the space affect this? Does it matter if the server is running on my local machine?
  2. I have gone through plenty of iterations where I tried using different connection flags, destroying and resetting the object or socket before attempting again, and even executed a loop that would query over 5000 times to understand the behavior.
  3. If this code does not look like one, I have tried reproducing the exact same code and order provided by Qt documentation.
AAS.N
  • 183
  • 1
  • 18
  • The echo is probably because you are binding to listen on port 1900, so when you send a broadcast to everyone on port 1900 the router sends it straight back to you and you receive it. Whether this is also interfering with actual responses from other devices on the network, possibly? – Wilco Mar 27 '20 at 09:14

1 Answers1

1

I ran into similar problems on Mac but not the same code on iOS. Did you managed to fix it? How?

Well, the only way I had to get the responses is binding to a different port than 1900 but I don't know if is the correct way. I found this by using wireshark, for example Google Chrome uses "random" port as a source port when sending a M-SEARCH and 1900 as destination.

By setting the bind port to 1900 I was only able to get the datagrams sent to "239.255.255.250" for example other software M-SEARCH or devices NOTIFY messages.

This is supossed to make your code work:

auto ok = m_sock->bind(QHostAddress::AnyIPv4, 56123, QUdpSocket::ShareAddress);
jsseu
  • 23
  • 4