3

I have a problem with a Qt program only receiving UDP [Artnet] datagrams from my STM32 modules when the STM32 is set to some seemingly random, but specific IP addresses.

So, I have the following:

  1. Linux Machine Running Qt program with dynamic IP address
  2. STM32 Running FreeRTOS Module manually set to address A
  3. STM32 Running FreeRTOS Module manually set to address B

I have written the Qt software and used uIP with FreeRTOS on the STM32 boards - modifying uIP to work with UDP properly and added simple Artnet code.

All are on 192.168.0.x subnet.

I've written the Qt program to send out an Artnet poll to the subnet's broadcast address. So, it sends the standard Artnet poll out on UDP port 6454 to address 192.168.0.255. Wireshark, shows my two STM32 modules return Artnet Poll Replies just fine. So far, so good.

However, where it starts to get really weird is that if I, for example, set one STM32 to have an IP address of 192.168.0.177 and the other to 192.168.0.176, the 177 node is seen and processed by the Qt program, however, despite the 176 node sending back a correct Artnet poll reply, the Qt program flatly refuses to read the reply packet. If I change the IP address of the 176 node to be .44, then the Qt program processes the reply. If I change the [working] .177 node to be, say, .43, it does not work.

I should stress that whatever IP address I set the STM32s to, Wireshark indicates all is well with the replies.

Can anyone suggest anything that might shed light on this please? I've played around with netcat, but that doesn't seem to read any of these Artnet replies, no matter what address they come from, so I might misunderstand what netcat can do. I've tried netcat with my Qt program only opening and outbound port, not an inbound and it makes no difference, but again, I might completely misunderstand netcat or something about UDP. Maybe if you open an outbound UDP port, the same inbound is automatically opened?

There are no IP address clashes going on and I have no firewall turned on, on my Linux machine.

Many thanks.

Edit: Added code as requested.

void MainWindow::processPendingDatagrams(void)
{
    struct ArtNetPollReplyStruct *newReply;
    QHostAddress sendingAddress;
    quint16 sendingUdpPort;
    QString versionString;
    QByteArray datagram;

    while (udpReceiveSocket->hasPendingDatagrams())
    {       
        datagram.resize(udpReceiveSocket->pendingDatagramSize());
        udpReceiveSocket->readDatagram(datagram.data(), datagram.size(), &sendingAddress,&sendingUdpPort);
        newReply = (struct ArtNetPollReplyStruct*)(datagram.data());
        if (newReply->OpCode == OP_POLL_REPLY)
            {
            if (sendingAddress != QHostAddress("192.168.0.18"))
                {
                if (checkAndAddAddress(sendingAddress))
                    {
                    versionString = QString::number(newReply->VersionInfoH,10) + "." + QString::number(newReply->VersionInfo,10);
                    addNodeToList(sendingAddress.toString(), versionString);
                    ui->textEdit->append( QString::fromUtf8(newReply->LongName));
                    }
                }
            }
        }
}

The code for initialising the UDP ports is here:

udpSendSocket = new QUdpSocket(this); udpReceiveSocket = new QUdpSocket(this);    
udpSendSocket->bind(6454, QUdpSocket::ShareAddress); 
udpReceiveSocket->bind(QHostAddress::Any,6454);
connect(udpReceiveSocket, SIGNAL(readyRead()),this, SLOT(processPendingDatagrams()));
connect(ui->innoLEDListTable,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(tableItemClicked(QTableWidgetItem*)));
$ ifconfig
enp5s0    Link encap:Ethernet  HWaddr 14:DA:E9:30:36:22  
          inet addr:192.168.0.18  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:265615 errors:0 dropped:0 overruns:0 frame:0
          TX packets:190104 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:306893983 (292.6 MiB)  TX bytes:20997451 (20.0 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:25205 errors:0 dropped:0 overruns:0 frame:0
          TX packets:25205 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6063842 (5.7 MiB)  TX bytes:6063842 (5.7 MiB)

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.2     0.0.0.0         UG    10     0        0 enp5s0
169.254.0.0     0.0.0.0         255.255.0.0     U     10     0        0 enp5s0
192.168.0.0     0.0.0.0         255.255.255.0   U     10     0        0 enp5s0
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
DiBosco
  • 838
  • 8
  • 21
  • This question is unanswerable without you showing the source code that reads the packets. Please show a minimal example: start with an empty `main.cpp` file, and add only the minimum of code needed to set up a socket and put a packet into a `QByteArray`. At that point the problem should demonstrate itself, I hope. – Kuba hasn't forgotten Monica Jul 02 '14 at 11:39
  • Please also show the `ifconfig` and `route -n` output on the linux machine. – Kuba hasn't forgotten Monica Jul 02 '14 at 11:41
  • I've added the info as requested. When the IP address is changed to, say, .176, the processPendingDatagrams() function doesn't get called at all, so I don't think it's an issue with that part of the Qt code. I am happy to be proven wrong though! Many thanks :) – DiBosco Jul 02 '14 at 12:36

1 Answers1

2

You only need one socket. Your problem is with the datagrams arriving at the other socket that you never read from. A socket is bidirectional.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Wow, you're right. No-one on the Qt mailing list picked up on that, great spot. This is my first time with UDP/IP on anything let alone Qt. Thanks a million. – DiBosco Jul 02 '14 at 13:35
  • @DiBosco This is not Qt specific at all. Were you using the POSIX/Unix API directly, it'd be the same. Alas, I only picked up on it because I made you post *relevant* code. I don't know if anyone on the mailing list saw that code. So, as is almost always the case, the question askers keep shooting themselves in the foot by not posting *complete, compile able, minimal* examples that demonstrate their woes. Look at my answers. There's more than a hundred Qt answers I posted with self-contained, single file examples. A few are rather complex :) – Kuba hasn't forgotten Monica Jul 02 '14 at 14:23
  • @DiBosco Part of the problem was deceptive variable naming: the `udpSendSocket` isn't a send socket only. A useful debugging technique is to imagine that all of your variables have meaningless names :) – Kuba hasn't forgotten Monica Jul 02 '14 at 14:25
  • The thing is I *thought* it was a meaningful name. It was ignorance, not knowing that once you open a UDP socket it is bidirectional! :~) – DiBosco Jul 03 '14 at 11:13
  • I did post code to the Qt mailing list, btw. I had LOTS of replies and a few people made suggestions back, most of them mentioning a send and receive socket! I wonder whether many people send and receive on different ports, therefore needing the two sockets? (Total guess.) – DiBosco Jul 03 '14 at 11:17
  • @DiBosco I think that they've got fooled by the variable names too :) I really wonder how many of the ones who replied have ever used UDP sockets in production, and what were their packet loss rates. Maybe everyone and their dog is losing half of their packets but the protocol they use on top of UDP handles it? :) – Kuba hasn't forgotten Monica Jul 03 '14 at 11:49