From bbfbd53123ca765d343374a8ed4a95c574e94f9b Mon Sep 17 00:00:00 2001 From: Albert Vaca Cintora Date: Mon, 31 Jul 2023 11:04:16 +0200 Subject: [PATCH] Implement IP match function --- core/backends/lan/mdns_wrapper.cpp | 55 +++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/core/backends/lan/mdns_wrapper.cpp b/core/backends/lan/mdns_wrapper.cpp index ac41722d0..c4104f4af 100644 --- a/core/backends/lan/mdns_wrapper.cpp +++ b/core/backends/lan/mdns_wrapper.cpp @@ -243,13 +243,60 @@ static mdns_string_t createMdnsString(const QByteArray &str) return mdns_string_t{str.constData(), (size_t)str.length()}; } -static QHostAddress findBestAddressMatch(QVector hostAddresses, const struct sockaddr *fromAddress) +int countCommonLeadingBits(quint32 int1, quint32 int2) { + int count = 0; + while (int1 != 0 && int2 != 0) { + if ((int1 & 0x80000000) == (int2 & 0x80000000)) { + count++; + int1 <<= 1; + int2 <<= 1; + } else { + break; + } + } + return count; +} + +static QHostAddress findBestAddressMatchV4(QVector hostAddresses, const struct sockaddr *fromAddress) { + Q_ASSERT(!hostAddresses.empty()); if (hostAddresses.size() == 1 || fromAddress == nullptr) { return hostAddresses[0]; } - // FIXME + + QHostAddress otherIp = QHostAddress(fromAddress); + + if (otherIp.protocol() != QAbstractSocket::IPv4Protocol) { + return hostAddresses[0]; + } + + // qDebug() << "I have more than one IP address:" << hostAddresses << "- Finding best match for source IP:" << otherIp; + + QHostAddress matchingIp = hostAddresses[0]; + int matchingBits = -1; + quint32 rawOtherIp = otherIp.toIPv4Address(); + for (const QHostAddress& ip : hostAddresses) { + Q_ASSERT(ip.protocol() == QAbstractSocket::IPv4Protocol); + quint32 rawMyIp = ip.toIPv4Address(); + // Since we don't have the network mask, we just compare the prefixes of the IPs to find the longest match + int matchingBitsCount = countCommonLeadingBits(rawMyIp, rawOtherIp); + if (matchingBitsCount > matchingBits) { + matchingIp = ip; + matchingBits = matchingBitsCount; + } + } + + // qDebug() << "Found match:" << matchingIp; + + return matchingIp; +} + +static QHostAddress findBestAddressMatchV6(QVector hostAddresses, const struct sockaddr *fromAddress) +{ + Q_ASSERT(!hostAddresses.empty()); + // We could do the same logic for v6 that we do for V4, but we don't care that much about IPv6 return hostAddresses[0]; + Q_UNUSED(fromAddress); } static mdns_record_t createMdnsRecord(const Announcer::AnnouncedInfo &self, @@ -275,11 +322,11 @@ static mdns_record_t createMdnsRecord(const Announcer::AnnouncedInfo &self, break; case MDNS_RECORDTYPE_A: // maps ".local." to IPv4 answer.name = createMdnsString(self.hostname); - answer.data.a.addr = qHostAddresstoSockaddr(findBestAddressMatch(self.addressesV4, fromAddress)); + answer.data.a.addr = qHostAddressToSockaddr(findBestAddressMatchV4(self.addressesV4, fromAddress)); break; case MDNS_RECORDTYPE_AAAA: // maps ".local." to IPv6 answer.name = createMdnsString(self.hostname); - answer.data.aaaa.addr = qHostAddresstoSockaddr6(findBestAddressMatch(self.addressesV6, fromAddress)); + answer.data.aaaa.addr = qHostAddressToSockaddr6(findBestAddressMatchV6(self.addressesV6, fromAddress)); break; case MDNS_RECORDTYPE_TXT: answer.name = createMdnsString(self.serviceInstance);