truvorskameikin / udp-discovery-cpp

A small library to add local network discovery feature to your C++ programs with no dependencies
MIT License
60 stars 28 forks source link

multiple network interfaces #25

Open michalfapso opened 3 years ago

michalfapso commented 3 years ago

When I ran ./udp-discovery-example both both test1 and the same with test2 on the same windows computer, they both discovered each other.

It worked also when I ran it with test3 and test4 on another linux computer on the same network.

But the services test1 and test2 didn't discover test3 and test4 and vice versa.

I suspect this issue might be related to having multiple network interfaces on both computers (mostly created by docker). I had similar problem with my simple UDP broadcast implementation using Qt. First two examples below worked only in some cases, but the third one worked well in all my tests. Maybe it could help you to solve the issue also in this project.

This didn't work:

QUdpSocket s;
s.writeDatagram(QByteArray(), QHostAddress::Broadcast, PORT);

This didn't work either:

QUdpSocket s;
QNetworkDatagram datagram(QByteArray(), QHostAddress::Broadcast, PORT);
// Send the packet to all network interfaces
for (int i=0; i<QNetworkInterface::allInterfaces().size(); i++) {
    datagram.setInterfaceIndex(i);
    s.writeDatagram(datagram);
}

This finally worked (got it from here: https://forum.qt.io/post/187963):

// Get network interfaces list
QUdpSocket s;
QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < ifaces.size(); i++) {
    auto iface = ifaces[i];
    // Get all IP addresses for the current interface
    QList<QNetworkAddressEntry> addrs = iface.addressEntries();
    // And for any IP address, if it is IPv4 and the interface is active, send the packet
    for (int j = 0; j < addrs.size(); j++) {
        auto addr = addrs[j];
        if ((addr.ip().protocol() == QAbstractSocket::IPv4Protocol) && (addr.broadcast().toString() != "")) {
            s.writeDatagram(QByteArray(), addr.broadcast(), PORT);
        }
    }
}

You can search for documentation of Qt classes here: https://doc.qt.io/qt-5/index.html

truvorskameikin commented 3 years ago

Hi Michal, thank you for the very detailed bug description!

We already tried to solve the very similar issue in #19. I created the enum-interfaces branch for proving that sending packets to broadcast addresses of all available interfaces will help. But this mechanism is only implemented for Windows. Can you please check that enum-interfaces branch will make peers running on Windows visible to Linux peers?

https://github.com/truvorskameikin/udp-discovery-cpp/issues/19#issuecomment-792364907 for the reference.

michalfapso commented 3 years ago

Hi Dmitrii, the enum-interfaces branch works perfectly! Good job!

truvorskameikin commented 3 years ago

Great! Am I right that Windows peers are visible to Linux peers but Linux peers are still not visible to Windows peers? If this is the case that I will extend the enumeration mechanism to linux-like systems.

michalfapso commented 3 years ago

Linux peers see windows peers and also windows peers see linux peers. It works both ways.

So in my setup with 4 peers, one linux peer outputs (the other one on linux has similar output):

Discovered peers: 3
 - 192.168.1.147:56327, both
 - 192.168.1.102:56691, both
 - 192.168.1.147:53572, both

and one windows peer outputs (not sure why it shows so many discovered peers, the other one on windows has similar output):

Discovered peers: 7
 - 192.168.1.147:56327, both
 - 172.28.48.1:56327, both
 - 192.168.112.1:56327, both
 - 192.168.200.1:56327, both
 - 192.168.99.1:56327, both
 - 192.168.1.102:56691, both
 - 192.168.1.102:43860, both

Here is my ipconfig on the windows computer:

$ ipconfig

Windows IP Configuration

Ethernet adapter vEthernet (WSL):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::283e:cc05:5859:55f6%58
   IPv4 Address. . . . . . . . . . . : 172.28.48.1
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   Default Gateway . . . . . . . . . :

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::a059:18cc:d060:2473%23
   IPv4 Address. . . . . . . . . . . : 192.168.1.147
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

Ethernet adapter VirtualBox Host-Only Network #4:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::5415:c23:cac6:1fee%25
   IPv4 Address. . . . . . . . . . . : 192.168.99.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :

Wireless LAN adapter Local Area Connection* 3:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Ethernet adapter VMware Network Adapter VMnet1:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::b5f9:f5dc:87f6:8fee%15
   IPv4 Address. . . . . . . . . . . : 192.168.112.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :

Ethernet adapter VMware Network Adapter VMnet8:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::354b:707a:388b:8582%11
   IPv4 Address. . . . . . . . . . . : 192.168.200.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :

Ethernet adapter Bluetooth Network Connection:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Wireless LAN adapter Wi-Fi:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

and ifconfig on my linux computer:

$ ifconfig
br-a9ecddf398c3: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:5eff:fec2:38dc  prefixlen 64  scopeid 0x20<link>
        ether 02:42:5e:c2:38:dc  txqueuelen 0  (Ethernet)
        RX packets 509  bytes 1737884 (1.7 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 595  bytes 141098 (141.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:f7ff:fedc:9f5a  prefixlen 64  scopeid 0x20<link>
        ether 02:42:f7:dc:9f:5a  txqueuelen 0  (Ethernet)
        RX packets 204695  bytes 10910032 (10.9 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 472050  bytes 692129553 (692.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker_gwbridge: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.23.0.1  netmask 255.255.0.0  broadcast 172.23.255.255
        ether 02:42:ef:5e:4e:96  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s25: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.102  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::51f9:7b7c:69b7:ab06  prefixlen 64  scopeid 0x20<link>
        ether 38:ea:a7:87:e8:e1  txqueuelen 1000  (Ethernet)
        RX packets 26913050  bytes 23799121802 (23.7 GB)
        RX errors 0  dropped 3208  overruns 0  frame 0
        TX packets 21927607  bytes 5818933203 (5.8 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 20  memory 0xd4800000-d4820000  

enx028037ec0200: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether 02:80:37:ec:02:00  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 16715107  bytes 1363454134 (1.3 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16715107  bytes 1363454134 (1.3 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0