WIP: Return some ip in ip records
This commit is contained in:
parent
d76e7e0eeb
commit
6765f16976
4 changed files with 105 additions and 40 deletions
|
@ -72,6 +72,7 @@ void LanLinkProvider::onNetworkConfigurationChanged(const QNetworkConfiguration
|
||||||
if (m_lastConfig != config && config.state() == QNetworkConfiguration::Active) {
|
if (m_lastConfig != config && config.state() == QNetworkConfiguration::Active) {
|
||||||
m_lastConfig = config;
|
m_lastConfig = config;
|
||||||
onNetworkChange();
|
onNetworkChange();
|
||||||
|
m_mdnsDiscovery.onNetworkChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ int Discoverer::listenForQueryResponses()
|
||||||
|
|
||||||
static char buffer[2048];
|
static char buffer[2048];
|
||||||
size_t num_records = mdns_query_recv(socket, buffer, sizeof(buffer), query_callback, (void *)&discoveredService, 0);
|
size_t num_records = mdns_query_recv(socket, buffer, sizeof(buffer), query_callback, (void *)&discoveredService, 0);
|
||||||
|
Q_UNUSED(num_records);
|
||||||
|
|
||||||
// qCDebug(KDECONNECT_CORE) << "Discovered service" << discoveredService.name << "at" << discoveredService.address << "in" << num_records <<
|
// qCDebug(KDECONNECT_CORE) << "Discovered service" << discoveredService.name << "at" << discoveredService.address << "in" << num_records <<
|
||||||
// "records via socket" << socket;
|
// "records via socket" << socket;
|
||||||
|
@ -207,8 +208,41 @@ static mdns_string_t createMdnsString(const QByteArray &str)
|
||||||
return mdns_string_t{str.constData(), (size_t)str.length()};
|
return mdns_string_t{str.constData(), (size_t)str.length()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QHostAddress findBestAddressMatch(QVector<QHostAddress> hostAddresses, const struct sockaddr *fromAddress)
|
||||||
|
{
|
||||||
|
if (hostAddresses.size() == 1 || fromAddress == nullptr) {
|
||||||
|
return hostAddresses[0];
|
||||||
|
}
|
||||||
|
// FIXME
|
||||||
|
return hostAddresses[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static sockaddr_in qHostAddresstoSockaddr(QHostAddress hostAddress)
|
||||||
|
{
|
||||||
|
Q_ASSERT(hostAddress.protocol() == QAbstractSocket::IPv4Protocol);
|
||||||
|
sockaddr_in socketAddress;
|
||||||
|
memset(&socketAddress, 0, sizeof(socketAddress));
|
||||||
|
socketAddress.sin_family = AF_INET;
|
||||||
|
socketAddress.sin_addr.s_addr = htonl(hostAddress.toIPv4Address());
|
||||||
|
return socketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sockaddr_in6 qHostAddresstoSockaddr6(QHostAddress hostAddress)
|
||||||
|
{
|
||||||
|
Q_ASSERT(hostAddress.protocol() == QAbstractSocket::IPv6Protocol);
|
||||||
|
sockaddr_in6 socketAddress;
|
||||||
|
memset(&socketAddress, 0, sizeof(socketAddress));
|
||||||
|
socketAddress.sin6_family = AF_INET6;
|
||||||
|
Q_IPV6ADDR ipv6Address = hostAddress.toIPv6Address();
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
socketAddress.sin6_addr.s6_addr[i] = ipv6Address[i];
|
||||||
|
}
|
||||||
|
return socketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
static mdns_record_t createMdnsRecord(const Announcer::AnnouncedInfo &self,
|
static mdns_record_t createMdnsRecord(const Announcer::AnnouncedInfo &self,
|
||||||
mdns_record_type_t record_type,
|
mdns_record_type_t record_type,
|
||||||
|
const struct sockaddr *fromAddress = nullptr, // used to determine IP to set in A and AAAA records
|
||||||
QHash<QByteArray, QByteArray>::const_iterator txtIterator = {})
|
QHash<QByteArray, QByteArray>::const_iterator txtIterator = {})
|
||||||
{
|
{
|
||||||
mdns_record_t answer;
|
mdns_record_t answer;
|
||||||
|
@ -228,11 +262,11 @@ static mdns_record_t createMdnsRecord(const Announcer::AnnouncedInfo &self,
|
||||||
break;
|
break;
|
||||||
case MDNS_RECORDTYPE_A: // maps "<hostname>.local." to IPv4
|
case MDNS_RECORDTYPE_A: // maps "<hostname>.local." to IPv4
|
||||||
answer.name = createMdnsString(self.hostname);
|
answer.name = createMdnsString(self.hostname);
|
||||||
answer.data.a.addr = self.address_ipv4;
|
answer.data.a.addr = qHostAddresstoSockaddr(findBestAddressMatch(self.addressesV4, fromAddress));
|
||||||
break;
|
break;
|
||||||
case MDNS_RECORDTYPE_AAAA: // maps "<hostname>.local." to IPv6
|
case MDNS_RECORDTYPE_AAAA: // maps "<hostname>.local." to IPv6
|
||||||
answer.name = createMdnsString(self.hostname);
|
answer.name = createMdnsString(self.hostname);
|
||||||
answer.data.aaaa.addr = self.address_ipv6;
|
answer.data.aaaa.addr = qHostAddresstoSockaddr6(findBestAddressMatch(self.addressesV6, fromAddress));
|
||||||
break;
|
break;
|
||||||
case MDNS_RECORDTYPE_TXT:
|
case MDNS_RECORDTYPE_TXT:
|
||||||
answer.name = createMdnsString(self.serviceInstance);
|
answer.name = createMdnsString(self.serviceInstance);
|
||||||
|
@ -241,7 +275,7 @@ static mdns_record_t createMdnsRecord(const Announcer::AnnouncedInfo &self,
|
||||||
answer.data.txt.value = createMdnsString(txtIterator.value());
|
answer.data.txt.value = createMdnsString(txtIterator.value());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
@ -298,15 +332,15 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
|
|
||||||
QVector<mdns_record_t> additional;
|
QVector<mdns_record_t> additional;
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_SRV));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_SRV));
|
||||||
if (self.address_ipv4.sin_family == AF_INET) {
|
if (!self.addressesV4.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A, from));
|
||||||
}
|
}
|
||||||
if (self.address_ipv4.sin_family == AF_INET6) {
|
if (!self.addressesV6.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA, from));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, txtIterator));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, nullptr, txtIterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
|
@ -332,15 +366,15 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
mdns_record_t answer = createMdnsRecord(self, MDNS_RECORDTYPE_SRV);
|
mdns_record_t answer = createMdnsRecord(self, MDNS_RECORDTYPE_SRV);
|
||||||
|
|
||||||
QVector<mdns_record_t> additional;
|
QVector<mdns_record_t> additional;
|
||||||
if (self.address_ipv4.sin_family == AF_INET) {
|
if (!self.addressesV4.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A, from));
|
||||||
}
|
}
|
||||||
if (self.address_ipv4.sin_family == AF_INET6) {
|
if (!self.addressesV6.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA, from));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, txtIterator));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, nullptr, txtIterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
|
@ -358,19 +392,19 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
}
|
}
|
||||||
} else if (name == self.hostname) {
|
} else if (name == self.hostname) {
|
||||||
qWarning() << "Someone queried my host for" << recordTypeToStr(record_type);
|
qWarning() << "Someone queried my host for" << recordTypeToStr(record_type);
|
||||||
if (((record_type == MDNS_RECORDTYPE_A) || (record_type == MDNS_RECORDTYPE_ANY)) && self.address_ipv4.sin_family == AF_INET) {
|
if (((record_type == MDNS_RECORDTYPE_A) || (record_type == MDNS_RECORDTYPE_ANY)) && !self.addressesV4.empty()) {
|
||||||
// The A query was for our qualified hostname and we have an IPv4 address, answer with an A
|
// The A query was for our qualified hostname and we have an IPv4 address, answer with an A
|
||||||
// record mapping the hostname to an IPv4 address, as well as an AAAA record and TXT records
|
// record mapping the hostname to an IPv4 address, as well as an AAAA record and TXT records
|
||||||
|
|
||||||
mdns_record_t answer = createMdnsRecord(self, MDNS_RECORDTYPE_A);
|
mdns_record_t answer = createMdnsRecord(self, MDNS_RECORDTYPE_A, from);
|
||||||
|
|
||||||
QVector<mdns_record_t> additional;
|
QVector<mdns_record_t> additional;
|
||||||
if (self.address_ipv4.sin_family == AF_INET6) {
|
if (!self.addressesV6.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA, from));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, txtIterator));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, nullptr, txtIterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
|
@ -385,19 +419,19 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
||||||
additional.constData(), additional.length());
|
additional.constData(), additional.length());
|
||||||
}
|
}
|
||||||
} else if (((record_type == MDNS_RECORDTYPE_AAAA) || (record_type == MDNS_RECORDTYPE_ANY)) && self.address_ipv6.sin6_family == AF_INET6) {
|
} else if (((record_type == MDNS_RECORDTYPE_AAAA) || (record_type == MDNS_RECORDTYPE_ANY)) && !self.addressesV6.empty()) {
|
||||||
// The AAAA query was for our qualified hostname and we have an IPv6 address, answer with an AAAA
|
// The AAAA query was for our qualified hostname and we have an IPv6 address, answer with an AAAA
|
||||||
// record mapping the hostname to an IPv4 address, as well as an A record and TXT records
|
// record mapping the hostname to an IPv4 address, as well as an A record and TXT records
|
||||||
|
|
||||||
mdns_record_t answer = createMdnsRecord(self, MDNS_RECORDTYPE_AAAA);
|
mdns_record_t answer = createMdnsRecord(self, MDNS_RECORDTYPE_AAAA, from);
|
||||||
|
|
||||||
QVector<mdns_record_t> additional;
|
QVector<mdns_record_t> additional;
|
||||||
if (self.address_ipv4.sin_family == AF_INET) {
|
if (!self.addressesV4.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A, from));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, txtIterator));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, nullptr, txtIterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
|
@ -479,11 +513,33 @@ Announcer::Announcer(const QString &serviceName, const QString &serviceType, uin
|
||||||
// mdns.h needs all the qualified names to end with dot for some reason
|
// mdns.h needs all the qualified names to end with dot for some reason
|
||||||
self.serviceType.append('.');
|
self.serviceType.append('.');
|
||||||
}
|
}
|
||||||
self.port = port;
|
|
||||||
self.hostname = QHostInfo::localHostName().toLatin1() + QByteArray(".local.");
|
|
||||||
self.serviceInstance = serviceName.toLatin1() + '.' + self.serviceType;
|
self.serviceInstance = serviceName.toLatin1() + '.' + self.serviceType;
|
||||||
memset(&self.address_ipv4, 0, sizeof(struct sockaddr_in));
|
self.hostname = QHostInfo::localHostName().toLatin1() + ".local.";
|
||||||
memset(&self.address_ipv6, 0, sizeof(struct sockaddr_in6));
|
self.port = port;
|
||||||
|
detectHostAddresses();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Announcer::detectHostAddresses()
|
||||||
|
{
|
||||||
|
qWarning() << "detectHostAddresses";
|
||||||
|
self.addressesV4.clear();
|
||||||
|
self.addressesV6.clear();
|
||||||
|
for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
|
||||||
|
int flags = iface.flags();
|
||||||
|
if (!(flags & QNetworkInterface::IsUp) || !(flags & QNetworkInterface::CanMulticast) || (flags & QNetworkInterface::IsLoopBack)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const QNetworkAddressEntry &ifaceAddress : iface.addressEntries()) {
|
||||||
|
QHostAddress sourceAddress = ifaceAddress.ip();
|
||||||
|
if (sourceAddress.protocol() == QAbstractSocket::IPv4Protocol && sourceAddress != QHostAddress::LocalHost) {
|
||||||
|
qWarning() << "Found ipv4" << sourceAddress;
|
||||||
|
self.addressesV4.append(sourceAddress);
|
||||||
|
} else if (sourceAddress.protocol() == QAbstractSocket::IPv6Protocol && sourceAddress != QHostAddress::LocalHostIPv6) {
|
||||||
|
qWarning() << "Found ipv6" << sourceAddress;
|
||||||
|
self.addressesV6.append(sourceAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Announcer::startAnnouncing()
|
void Announcer::startAnnouncing()
|
||||||
|
@ -520,15 +576,15 @@ void Announcer::sendMulticastAnnounce(bool isGoodbye)
|
||||||
|
|
||||||
QVector<mdns_record_t> additional;
|
QVector<mdns_record_t> additional;
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_SRV));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_SRV));
|
||||||
if (self.address_ipv4.sin_family == AF_INET) {
|
if (!self.addressesV4.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_A));
|
||||||
}
|
}
|
||||||
if (self.address_ipv4.sin_family == AF_INET6) {
|
if (!self.addressesV6.empty()) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_AAAA));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
for (auto txtIterator = self.txtRecords.cbegin(); txtIterator != self.txtRecords.cend(); txtIterator++) {
|
||||||
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, txtIterator));
|
additional.append(createMdnsRecord(self, MDNS_RECORDTYPE_TXT, nullptr, txtIterator));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char buffer[2048];
|
static char buffer[2048];
|
||||||
|
|
|
@ -13,13 +13,6 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <winsock2.h>
|
|
||||||
#include <ws2ipdef.h>
|
|
||||||
#else
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A Qt wrapper for the mdns.h header-only library
|
* A Qt wrapper for the mdns.h header-only library
|
||||||
* from https://github.com/mjansson/mdns
|
* from https://github.com/mjansson/mdns
|
||||||
|
@ -39,7 +32,7 @@ public:
|
||||||
QMap<QString, QString> txtRecords;
|
QMap<QString, QString> txtRecords;
|
||||||
};
|
};
|
||||||
|
|
||||||
// serviceType should be of the form _kdeconnect._udp.local
|
// serviceType must be of the form "_<name>._<tcp/udp>.local"
|
||||||
void startDiscovering(const QString &serviceType);
|
void startDiscovering(const QString &serviceType);
|
||||||
void stopDiscovering();
|
void stopDiscovering();
|
||||||
|
|
||||||
|
@ -64,8 +57,8 @@ public:
|
||||||
QByteArray serviceType; // ie: "<_service-type>._tcp.local."
|
QByteArray serviceType; // ie: "<_service-type>._tcp.local."
|
||||||
QByteArray serviceInstance; // ie: "<service-name>.<_service-type>._tcp.local."
|
QByteArray serviceInstance; // ie: "<service-name>.<_service-type>._tcp.local."
|
||||||
QByteArray hostname; // ie: "<hostname>.local."
|
QByteArray hostname; // ie: "<hostname>.local."
|
||||||
struct sockaddr_in address_ipv4;
|
QVector<QHostAddress> addressesV4;
|
||||||
struct sockaddr_in6 address_ipv6;
|
QVector<QHostAddress> addressesV6;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
QHash<QByteArray, QByteArray> txtRecords;
|
QHash<QByteArray, QByteArray> txtRecords;
|
||||||
};
|
};
|
||||||
|
@ -83,10 +76,19 @@ public:
|
||||||
|
|
||||||
void sendMulticastAnnounce(bool isGoodbye);
|
void sendMulticastAnnounce(bool isGoodbye);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
// notify that network interfaces changed since the creation of this Announcer
|
||||||
|
void onNetworkChange()
|
||||||
|
{
|
||||||
|
detectHostAddresses();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int listenForQueries();
|
int listenForQueries();
|
||||||
void stopListeningForQueries();
|
void stopListeningForQueries();
|
||||||
|
|
||||||
|
void detectHostAddresses();
|
||||||
|
|
||||||
AnnouncedInfo self;
|
AnnouncedInfo self;
|
||||||
|
|
||||||
QSocketNotifier *socketNotifier = nullptr;
|
QSocketNotifier *socketNotifier = nullptr;
|
||||||
|
|
|
@ -29,6 +29,12 @@ public:
|
||||||
void stopAnnouncing();
|
void stopAnnouncing();
|
||||||
void startAnnouncing();
|
void startAnnouncing();
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void onNetworkChange()
|
||||||
|
{
|
||||||
|
mdnsAnnouncer.onNetworkChange();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LanLinkProvider *lanLinkProvider = nullptr;
|
LanLinkProvider *lanLinkProvider = nullptr;
|
||||||
MdnsWrapper::Discoverer mdnsDiscoverer;
|
MdnsWrapper::Discoverer mdnsDiscoverer;
|
||||||
|
|
Loading…
Reference in a new issue