WIP: Continue to integrate with mdns.h
This commit is contained in:
parent
3f94d8fd63
commit
1685b64026
4 changed files with 285 additions and 325 deletions
core/backends/lan
|
@ -23,6 +23,7 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <QHostInfo>
|
||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
|
|
||||||
|
@ -114,14 +115,14 @@ static int query_callback(int sock, const struct sockaddr* from, size_t addrlen,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdnsWrapper::startDiscovering(const char *serviceType)
|
void MdnsWrapper::startDiscovering(const QString &serviceType)
|
||||||
{
|
{
|
||||||
int num_sockets = listenForQueryResponses();
|
int num_sockets = listenForQueryResponses();
|
||||||
if (num_sockets <= 0) {
|
if (num_sockets <= 0) {
|
||||||
qWarning() << "Failed to open any client sockets";
|
qWarning() << "Failed to open any client sockets";
|
||||||
} else {
|
return;
|
||||||
sendQuery(serviceType);
|
|
||||||
}
|
}
|
||||||
|
sendQuery(serviceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdnsWrapper::stopDiscovering()
|
void MdnsWrapper::stopDiscovering()
|
||||||
|
@ -188,13 +189,14 @@ int MdnsWrapper::listenForQueryResponses()
|
||||||
return sockets.size();
|
return sockets.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdnsWrapper::sendQuery(const char *serviceType)
|
void MdnsWrapper::sendQuery(const QString &serviceType)
|
||||||
{
|
{
|
||||||
qCDebug(KDECONNECT_CORE) << "Sending MDNS query for service" << serviceType;
|
qCDebug(KDECONNECT_CORE) << "Sending MDNS query for service" << serviceType;
|
||||||
|
|
||||||
mdns_query_t query;
|
mdns_query_t query;
|
||||||
query.name = serviceType;
|
QByteArray serviceTypeBytes = serviceType.toLatin1();
|
||||||
query.length = strlen(serviceType);
|
query.name = serviceTypeBytes.data();
|
||||||
|
query.length = serviceTypeBytes.length();
|
||||||
query.type = MDNS_RECORDTYPE_PTR;
|
query.type = MDNS_RECORDTYPE_PTR;
|
||||||
|
|
||||||
size_t capacity = 2048;
|
size_t capacity = 2048;
|
||||||
|
@ -310,105 +312,45 @@ static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, const s
|
||||||
char service_instance_buffer[256] = {0};
|
char service_instance_buffer[256] = {0};
|
||||||
char qualified_hostname_buffer[256] = {0};
|
char qualified_hostname_buffer[256] = {0};
|
||||||
|
|
||||||
// Data for our service including the mDNS records
|
|
||||||
typedef struct {
|
|
||||||
mdns_string_t service;
|
|
||||||
mdns_string_t hostname;
|
|
||||||
mdns_string_t service_instance;
|
|
||||||
mdns_string_t hostname_qualified;
|
|
||||||
struct sockaddr_in address_ipv4;
|
|
||||||
struct sockaddr_in6 address_ipv6;
|
|
||||||
int port;
|
|
||||||
mdns_record_t record_ptr;
|
|
||||||
mdns_record_t record_srv;
|
|
||||||
mdns_record_t record_a;
|
|
||||||
mdns_record_t record_aaaa;
|
|
||||||
mdns_record_t txt_record[2];
|
|
||||||
} service_t;
|
|
||||||
service_t service = {};
|
|
||||||
|
|
||||||
// Open sockets to listen to incoming mDNS queries on port 5353
|
|
||||||
static int open_service_sockets(int* sockets)
|
|
||||||
{
|
|
||||||
// When recieving, each socket can recieve data from all network interfaces
|
|
||||||
// Thus we only need to open one socket for each address family
|
|
||||||
int num_sockets = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
struct sockaddr_in sock_addr;
|
|
||||||
memset(&sock_addr, 0, sizeof(struct sockaddr_in));
|
|
||||||
sock_addr.sin_family = AF_INET;
|
|
||||||
#ifdef _WIN32
|
|
||||||
sock_addr.sin_addr = in4addr_any;
|
|
||||||
#else
|
|
||||||
sock_addr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
#endif
|
|
||||||
sock_addr.sin_port = htons(MDNS_PORT);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
sock_addr.sin_len = sizeof(struct sockaddr_in);
|
|
||||||
#endif
|
|
||||||
int sock = mdns_socket_open_ipv4(&sock_addr);
|
|
||||||
if (sock >= 0)
|
|
||||||
sockets[num_sockets++] = sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
struct sockaddr_in6 sock_addr;
|
|
||||||
memset(&sock_addr, 0, sizeof(struct sockaddr_in6));
|
|
||||||
sock_addr.sin6_family = AF_INET6;
|
|
||||||
sock_addr.sin6_addr = in6addr_any;
|
|
||||||
sock_addr.sin6_port = htons(MDNS_PORT);
|
|
||||||
#ifdef __APPLE__
|
|
||||||
sock_addr.sin6_len = sizeof(struct sockaddr_in6);
|
|
||||||
#endif
|
|
||||||
int sock = mdns_socket_open_ipv6(&sock_addr);
|
|
||||||
if (sock >= 0)
|
|
||||||
sockets[num_sockets++] = sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_sockets;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char sendbuffer[1024];
|
static char sendbuffer[1024];
|
||||||
|
static mdns_record_txt_t txtbuffer[128];
|
||||||
|
static char addrbuffer[64];
|
||||||
|
static char entrybuffer[256];
|
||||||
|
|
||||||
|
const QString dnsSdName = QStringLiteral("_services._dns-sd._udp.local.");
|
||||||
|
|
||||||
// Callback handling questions incoming on service sockets
|
// Callback handling questions incoming on service sockets
|
||||||
static int service_callback(int sock, const struct sockaddr* from, size_t addrlen, mdns_entry_type_t entry,
|
static int service_callback(int sock, const struct sockaddr* from, size_t addrlen, mdns_entry_type_t entry_type,
|
||||||
uint16_t query_id, uint16_t rtype_int, uint16_t rclass, uint32_t ttl, const void* data,
|
uint16_t query_id, uint16_t record_type, uint16_t rclass, uint32_t ttl, const void* data,
|
||||||
size_t size, size_t name_offset, size_t name_length, size_t record_offset,
|
size_t size, size_t name_offset, size_t name_length, size_t record_offset,
|
||||||
size_t record_length, void* user_data) {
|
size_t record_length, void* user_data) {
|
||||||
|
Q_UNUSED(ttl);
|
||||||
|
Q_UNUSED(name_length);
|
||||||
|
Q_UNUSED(record_offset);
|
||||||
|
Q_UNUSED(record_length);
|
||||||
|
|
||||||
static mdns_record_txt_t txtbuffer[128];
|
MdnsServiceAnnouncer::AnnouncedInfo *myself = (MdnsServiceAnnouncer::AnnouncedInfo *)user_data;
|
||||||
static char addrbuffer[64];
|
|
||||||
static char entrybuffer[256];
|
|
||||||
static char namebuffer[256];
|
|
||||||
|
|
||||||
mdns_record_type_t rtype = (mdns_record_type_t)rtype_int;
|
if (entry_type != MDNS_ENTRYTYPE_QUESTION) {
|
||||||
|
|
||||||
(void)sizeof(ttl);
|
|
||||||
if (entry != MDNS_ENTRYTYPE_QUESTION)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const char dns_sd[] = "_services._dns-sd._udp.local.";
|
static char nameBuffer[256];
|
||||||
|
mdns_string_t nameMdnsString = mdns_string_extract(data, size, &name_offset, nameBuffer, sizeof(nameBuffer));
|
||||||
|
QString name = QString::fromLatin1(nameMdnsString.str, nameMdnsString.length);
|
||||||
|
|
||||||
mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from, addrlen);
|
if (name == dnsSdName) {
|
||||||
|
qWarning() << "Someone queried all services for" << recordTypeToStr(record_type);
|
||||||
size_t offset = name_offset;
|
if ((record_type == MDNS_RECORDTYPE_PTR) || (record_type == MDNS_RECORDTYPE_ANY)) {
|
||||||
mdns_string_t name = mdns_string_extract(data, size, &offset, namebuffer, sizeof(namebuffer));
|
|
||||||
|
|
||||||
const char* record_name = recordTypeToStr(rtype);
|
|
||||||
|
|
||||||
printf("Query %s %.*s\n", record_name, MDNS_STRING_FORMAT(name));
|
|
||||||
|
|
||||||
if ((name.length == (sizeof(dns_sd) - 1)) &&
|
|
||||||
(strncmp(name.str, dns_sd, sizeof(dns_sd) - 1) == 0)) {
|
|
||||||
if ((rtype == MDNS_RECORDTYPE_PTR) || (rtype == MDNS_RECORDTYPE_ANY)) {
|
|
||||||
// The PTR query was for the DNS-SD domain, send answer with a PTR record for the
|
// The PTR query was for the DNS-SD domain, send answer with a PTR record for the
|
||||||
// service name we advertise, typically on the "<_service-name>._tcp.local." format
|
// service name we advertise, typically on the "<_service-name>._tcp.local." format
|
||||||
|
|
||||||
// Answer PTR record reverse mapping "<_service-name>._tcp.local." to
|
/*
|
||||||
// "<hostname>.<_service-name>._tcp.local."
|
// Answer PTR record reverse mapping "<_service-name>._tcp.local." to "<hostname>.<_service-name>._tcp.local."
|
||||||
mdns_record_t answer = {
|
mdns_record_t answer;
|
||||||
.name = name, .type = MDNS_RECORDTYPE_PTR, .data.ptr.name = service.service};
|
answer.name = nameMdnsString;
|
||||||
|
answer.type = MDNS_RECORDTYPE_PTR;
|
||||||
|
answer.data.ptr.name = service.service;
|
||||||
|
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
uint16_t unicast = (rclass & MDNS_UNICAST_RESPONSE);
|
uint16_t unicast = (rclass & MDNS_UNICAST_RESPONSE);
|
||||||
|
@ -417,15 +359,15 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
|
|
||||||
if (unicast) {
|
if (unicast) {
|
||||||
mdns_query_answer_unicast(sock, (void*)from, addrlen, (void*)sendbuffer, sizeof(sendbuffer),
|
mdns_query_answer_unicast(sock, (void*)from, addrlen, (void*)sendbuffer, sizeof(sendbuffer),
|
||||||
query_id, rtype, name.str, name.length, answer, NULL, 0, NULL, 0);
|
query_id, (mdns_record_type_t)record_type, nameMdnsString.str, nameMdnsString.length, answer, NULL, 0, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0, 0,
|
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0, 0, 0);
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
} else if ((name.length == service.service.length) &&
|
} else if (name == myself->serviceType) {
|
||||||
(strncmp(name.str, service.service.str, name.length) == 0)) {
|
qWarning() << "Someone queried my service type for" << recordTypeToStr(record_type);
|
||||||
if ((rtype == MDNS_RECORDTYPE_PTR) || (rtype == MDNS_RECORDTYPE_ANY)) {
|
if ((record_type == MDNS_RECORDTYPE_PTR) || (record_type == MDNS_RECORDTYPE_ANY)) {
|
||||||
// The PTR query was for our service (usually "<_service-name._tcp.local"), answer a PTR
|
// The PTR query was for our service (usually "<_service-name._tcp.local"), answer a PTR
|
||||||
// record reverse mapping the queried service name to our service instance name
|
// record reverse mapping the queried service name to our service instance name
|
||||||
// (typically on the "<hostname>.<_service-name>._tcp.local." format), and add
|
// (typically on the "<hostname>.<_service-name>._tcp.local." format), and add
|
||||||
|
@ -433,6 +375,7 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
// qualified hostname (typically "<hostname>.local.") and port, as well as any IPv4/IPv6
|
// qualified hostname (typically "<hostname>.local.") and port, as well as any IPv4/IPv6
|
||||||
// address for the hostname as A/AAAA records, and two test TXT records
|
// address for the hostname as A/AAAA records, and two test TXT records
|
||||||
|
|
||||||
|
/*
|
||||||
// Answer PTR record reverse mapping "<_service-name>._tcp.local." to
|
// Answer PTR record reverse mapping "<_service-name>._tcp.local." to
|
||||||
// "<hostname>.<_service-name>._tcp.local."
|
// "<hostname>.<_service-name>._tcp.local."
|
||||||
mdns_record_t answer = service.record_ptr;
|
mdns_record_t answer = service.record_ptr;
|
||||||
|
@ -463,22 +406,24 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
|
|
||||||
if (unicast) {
|
if (unicast) {
|
||||||
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
||||||
query_id, rtype, name.str, name.length, answer, 0, 0,
|
query_id, (mdns_record_type_t)record_type, name.str, name.length, answer, 0, 0,
|
||||||
additional, additional_count);
|
additional, additional_count);
|
||||||
} else {
|
} else {
|
||||||
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
||||||
additional, additional_count);
|
additional, additional_count);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
} else if ((name.length == service.service_instance.length) &&
|
} else if (name == myself->serviceInstance) {
|
||||||
(strncmp(name.str, service.service_instance.str, name.length) == 0)) {
|
qWarning() << "Someone queried my service instance" << recordTypeToStr(record_type);
|
||||||
if ((rtype == MDNS_RECORDTYPE_SRV) || (rtype == MDNS_RECORDTYPE_ANY)) {
|
if ((record_type == MDNS_RECORDTYPE_SRV) || (record_type == MDNS_RECORDTYPE_ANY)) {
|
||||||
// The SRV query was for our service instance (usually
|
// The SRV query was for our service instance (usually
|
||||||
// "<hostname>.<_service-name._tcp.local"), answer a SRV record mapping the service
|
// "<hostname>.<_service-name._tcp.local"), answer a SRV record mapping the service
|
||||||
// instance name to our qualified hostname (typically "<hostname>.local.") and port, as
|
// instance name to our qualified hostname (typically "<hostname>.local.") and port, as
|
||||||
// well as any IPv4/IPv6 address for the hostname as A/AAAA records, and two test TXT
|
// well as any IPv4/IPv6 address for the hostname as A/AAAA records, and two test TXT
|
||||||
// records
|
// records
|
||||||
|
|
||||||
|
/*
|
||||||
// Answer PTR record reverse mapping "<_service-name>._tcp.local." to
|
// Answer PTR record reverse mapping "<_service-name>._tcp.local." to
|
||||||
// "<hostname>.<_service-name>._tcp.local."
|
// "<hostname>.<_service-name>._tcp.local."
|
||||||
mdns_record_t answer = service.record_srv;
|
mdns_record_t answer = service.record_srv;
|
||||||
|
@ -505,144 +450,179 @@ static int service_callback(int sock, const struct sockaddr* from, size_t addrle
|
||||||
|
|
||||||
if (unicast) {
|
if (unicast) {
|
||||||
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
||||||
query_id, rtype, name.str, name.length, answer, 0, 0,
|
query_id, (mdns_record_type_t)record_type, name.str, name.length, answer, 0, 0,
|
||||||
additional, additional_count);
|
additional, additional_count);
|
||||||
} else {
|
} else {
|
||||||
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
||||||
additional, additional_count);
|
additional, additional_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
} else {
|
} else if (name == myself->hostname) {
|
||||||
|
qWarning() << "Someone queried my host for" << recordTypeToStr(record_type);
|
||||||
|
if (((record_type == MDNS_RECORDTYPE_A) || (record_type == MDNS_RECORDTYPE_ANY)) /* && socketNotifier */) {
|
||||||
|
// The A query was for our qualified hostname (typically "<hostname>.local.") and we
|
||||||
|
// have an IPv4 address, answer with an A record mappiing the hostname to an IPv4
|
||||||
|
// address, as well as any IPv6 address for the hostname, and two test TXT records
|
||||||
|
|
||||||
qWarning() << "Is this for me?" << name.str << "VS" << service.hostname_qualified.str << "i" << service.address_ipv4.sin_family;
|
/*
|
||||||
|
// Answer A records mapping "<hostname>.local." to IPv4 address
|
||||||
|
mdns_record_t answer = service.record_a;
|
||||||
|
|
||||||
if ((name.length == service.hostname_qualified.length) &&
|
mdns_record_t additional[5] = {0};
|
||||||
(strncmp(name.str, service.hostname_qualified.str, name.length) == 0)) {
|
size_t additional_count = 0;
|
||||||
if (((rtype == MDNS_RECORDTYPE_A) || (rtype == MDNS_RECORDTYPE_ANY)) &&
|
|
||||||
(service.address_ipv4.sin_family == AF_INET)) {
|
|
||||||
// The A query was for our qualified hostname (typically "<hostname>.local.") and we
|
|
||||||
// have an IPv4 address, answer with an A record mappiing the hostname to an IPv4
|
|
||||||
// address, as well as any IPv6 address for the hostname, and two test TXT records
|
|
||||||
|
|
||||||
// Answer A records mapping "<hostname>.local." to IPv4 address
|
// AAAA record mapping "<hostname>.local." to IPv6 addresses
|
||||||
mdns_record_t answer = service.record_a;
|
if (service.address_ipv6.sin6_family == AF_INET6)
|
||||||
|
additional[additional_count++] = service.record_aaaa;
|
||||||
|
|
||||||
mdns_record_t additional[5] = {0};
|
// Add two test TXT records for our service instance name, will be coalesced into
|
||||||
size_t additional_count = 0;
|
// one record with both key-value pair strings by the library
|
||||||
|
additional[additional_count++] = service.txt_record[0];
|
||||||
|
additional[additional_count++] = service.txt_record[1];
|
||||||
|
|
||||||
// AAAA record mapping "<hostname>.local." to IPv6 addresses
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
if (service.address_ipv6.sin6_family == AF_INET6)
|
uint16_t unicast = (rclass & MDNS_UNICAST_RESPONSE);
|
||||||
additional[additional_count++] = service.record_aaaa;
|
mdns_string_t addrstr = ip_address_to_string(
|
||||||
|
addrbuffer, sizeof(addrbuffer), (struct sockaddr*)&service.record_a.data.a.addr,
|
||||||
|
sizeof(service.record_a.data.a.addr));
|
||||||
|
printf(" --> answer %.*s IPv4 %.*s (%s)\n", MDNS_STRING_FORMAT(service.record_a.name),
|
||||||
|
MDNS_STRING_FORMAT(addrstr), (unicast ? "unicast" : "multicast"));
|
||||||
|
|
||||||
// Add two test TXT records for our service instance name, will be coalesced into
|
if (unicast) {
|
||||||
// one record with both key-value pair strings by the library
|
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
||||||
additional[additional_count++] = service.txt_record[0];
|
query_id, (mdns_record_type_t)record_type, name.str, name.length, answer, 0, 0,
|
||||||
additional[additional_count++] = service.txt_record[1];
|
additional, additional_count);
|
||||||
|
} else {
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
||||||
uint16_t unicast = (rclass & MDNS_UNICAST_RESPONSE);
|
|
||||||
mdns_string_t addrstr = ip_address_to_string(
|
|
||||||
addrbuffer, sizeof(addrbuffer), (struct sockaddr*)&service.record_a.data.a.addr,
|
|
||||||
sizeof(service.record_a.data.a.addr));
|
|
||||||
printf(" --> answer %.*s IPv4 %.*s (%s)\n", MDNS_STRING_FORMAT(service.record_a.name),
|
|
||||||
MDNS_STRING_FORMAT(addrstr), (unicast ? "unicast" : "multicast"));
|
|
||||||
|
|
||||||
if (unicast) {
|
|
||||||
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
|
||||||
query_id, rtype, name.str, name.length, answer, 0, 0,
|
|
||||||
additional, additional_count);
|
additional, additional_count);
|
||||||
} else {
|
|
||||||
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
|
||||||
additional, additional_count);
|
|
||||||
}
|
|
||||||
} else if (((rtype == MDNS_RECORDTYPE_AAAA) || (rtype == MDNS_RECORDTYPE_ANY)) &&
|
|
||||||
(service.address_ipv6.sin6_family == AF_INET6)) {
|
|
||||||
// The AAAA query was for our qualified hostname (typically "<hostname>.local.") and we
|
|
||||||
// have an IPv6 address, answer with an AAAA record mappiing the hostname to an IPv6
|
|
||||||
// address, as well as any IPv4 address for the hostname, and two test TXT records
|
|
||||||
|
|
||||||
// Answer AAAA records mapping "<hostname>.local." to IPv6 address
|
|
||||||
mdns_record_t answer = service.record_aaaa;
|
|
||||||
|
|
||||||
mdns_record_t additional[5] = {0};
|
|
||||||
size_t additional_count = 0;
|
|
||||||
|
|
||||||
// A record mapping "<hostname>.local." to IPv4 addresses
|
|
||||||
if (service.address_ipv4.sin_family == AF_INET)
|
|
||||||
additional[additional_count++] = service.record_a;
|
|
||||||
|
|
||||||
// Add two test TXT records for our service instance name, will be coalesced into
|
|
||||||
// one record with both key-value pair strings by the library
|
|
||||||
additional[additional_count++] = service.txt_record[0];
|
|
||||||
additional[additional_count++] = service.txt_record[1];
|
|
||||||
|
|
||||||
// Send the answer, unicast or multicast depending on flag in query
|
|
||||||
uint16_t unicast = (rclass & MDNS_UNICAST_RESPONSE);
|
|
||||||
mdns_string_t addrstr =
|
|
||||||
ip_address_to_string(addrbuffer, sizeof(addrbuffer),
|
|
||||||
(struct sockaddr*)&service.record_aaaa.data.aaaa.addr,
|
|
||||||
sizeof(service.record_aaaa.data.aaaa.addr));
|
|
||||||
printf(" --> answer %.*s IPv6 %.*s (%s)\n",
|
|
||||||
MDNS_STRING_FORMAT(service.record_aaaa.name), MDNS_STRING_FORMAT(addrstr),
|
|
||||||
(unicast ? "unicast" : "multicast"));
|
|
||||||
|
|
||||||
if (unicast) {
|
|
||||||
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
|
||||||
query_id, rtype, name.str, name.length, answer, 0, 0,
|
|
||||||
additional, additional_count);
|
|
||||||
} else {
|
|
||||||
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
|
||||||
additional, additional_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
} else if (((record_type == MDNS_RECORDTYPE_AAAA) || (record_type == MDNS_RECORDTYPE_ANY)) /* && socketNotifierV6 */) {
|
||||||
|
// The AAAA query was for our qualified hostname (typically "<hostname>.local.") and we
|
||||||
|
// have an IPv6 address, answer with an AAAA record mappiing the hostname to an IPv6
|
||||||
|
// address, as well as any IPv4 address for the hostname, and two test TXT records
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Answer AAAA records mapping "<hostname>.local." to IPv6 address
|
||||||
|
mdns_record_t answer = service.record_aaaa;
|
||||||
|
|
||||||
|
mdns_record_t additional[5] = {0};
|
||||||
|
size_t additional_count = 0;
|
||||||
|
|
||||||
|
// A record mapping "<hostname>.local." to IPv4 addresses
|
||||||
|
if (service.address_ipv4.sin_family == AF_INET)
|
||||||
|
additional[additional_count++] = service.record_a;
|
||||||
|
|
||||||
|
// Add two test TXT records for our service instance name, will be coalesced into
|
||||||
|
// one record with both key-value pair strings by the library
|
||||||
|
additional[additional_count++] = service.txt_record[0];
|
||||||
|
additional[additional_count++] = service.txt_record[1];
|
||||||
|
|
||||||
|
// Send the answer, unicast or multicast depending on flag in query
|
||||||
|
uint16_t unicast = (rclass & MDNS_UNICAST_RESPONSE);
|
||||||
|
mdns_string_t addrstr =
|
||||||
|
ip_address_to_string(addrbuffer, sizeof(addrbuffer),
|
||||||
|
(struct sockaddr*)&service.record_aaaa.data.aaaa.addr,
|
||||||
|
sizeof(service.record_aaaa.data.aaaa.addr));
|
||||||
|
printf(" --> answer %.*s IPv6 %.*s (%s)\n",
|
||||||
|
MDNS_STRING_FORMAT(service.record_aaaa.name), MDNS_STRING_FORMAT(addrstr),
|
||||||
|
(unicast ? "unicast" : "multicast"));
|
||||||
|
|
||||||
|
if (unicast) {
|
||||||
|
mdns_query_answer_unicast(sock, from, addrlen, sendbuffer, sizeof(sendbuffer),
|
||||||
|
query_id, (mdns_record_type_t)record_type, name.str, name.length, answer, 0, 0,
|
||||||
|
additional, additional_count);
|
||||||
|
} else {
|
||||||
|
mdns_query_answer_multicast(sock, sendbuffer, sizeof(sendbuffer), answer, 0, 0,
|
||||||
|
additional, additional_count);
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
} // else request is not for me
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sockets[32];
|
|
||||||
|
|
||||||
int MdnsWrapper::startAnnouncing(const char* hostname, const char* service_name, int service_port)
|
// Open sockets to listen to incoming mDNS queries on port 5353
|
||||||
|
// When recieving, each socket can recieve data from all network interfaces
|
||||||
|
// Thus we only need to open one socket for each address family
|
||||||
|
int MdnsServiceAnnouncer::listenForQueries()
|
||||||
{
|
{
|
||||||
int num_sockets = open_service_sockets(sockets);
|
auto callback = [this](QSocketDescriptor socket) {
|
||||||
if (num_sockets <= 0) {
|
size_t capacity = 2048;
|
||||||
printf("Failed to open any client sockets\n");
|
void *buffer = malloc(capacity);
|
||||||
return -1;
|
mdns_socket_listen(socket, buffer, capacity, service_callback, &myself);
|
||||||
}
|
free(buffer);
|
||||||
printf("Opened %d socket%s for mDNS service\n", num_sockets, num_sockets ? "s" : "");
|
};
|
||||||
|
|
||||||
size_t service_name_length = strlen(service_name);
|
int numSockets = 0;
|
||||||
if (!service_name_length) {
|
|
||||||
printf("Invalid service name\n");
|
{
|
||||||
return -1;
|
struct sockaddr_in sock_addr;
|
||||||
|
memset(&sock_addr, 0, sizeof(struct sockaddr_in));
|
||||||
|
sock_addr.sin_family = AF_INET;
|
||||||
|
#ifdef _WIN32
|
||||||
|
sock_addr.sin_addr = in4addr_any;
|
||||||
|
#else
|
||||||
|
sock_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
#endif
|
||||||
|
sock_addr.sin_port = htons(MDNS_PORT);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
sock_addr.sin_len = sizeof(struct sockaddr_in);
|
||||||
|
#endif
|
||||||
|
int socket = mdns_socket_open_ipv4(&sock_addr);
|
||||||
|
if (socket >= 0) {
|
||||||
|
socketNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
|
||||||
|
QObject::connect(socketNotifier, &QSocketNotifier::activated, callback);
|
||||||
|
numSockets++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* service_name_buffer = (char*)malloc(service_name_length + 2);
|
{
|
||||||
memcpy(service_name_buffer, service_name, service_name_length);
|
struct sockaddr_in6 sock_addr;
|
||||||
if (service_name_buffer[service_name_length - 1] != '.')
|
memset(&sock_addr, 0, sizeof(struct sockaddr_in6));
|
||||||
service_name_buffer[service_name_length++] = '.';
|
sock_addr.sin6_family = AF_INET6;
|
||||||
service_name_buffer[service_name_length] = 0;
|
sock_addr.sin6_addr = in6addr_any;
|
||||||
service_name = service_name_buffer;
|
sock_addr.sin6_port = htons(MDNS_PORT);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
sock_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||||
|
#endif
|
||||||
|
int socket = mdns_socket_open_ipv6(&sock_addr);
|
||||||
|
if (socket >= 0) {
|
||||||
|
socketNotifierV6 = new QSocketNotifier(socket, QSocketNotifier::Read);
|
||||||
|
QObject::connect(socketNotifierV6, &QSocketNotifier::activated, callback);
|
||||||
|
numSockets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
printf("Service mDNS: %s:%d\n", service_name, service_port);
|
return numSockets;
|
||||||
printf("Hostname: %s\n", hostname);
|
}
|
||||||
|
|
||||||
size_t capacity = 2048;
|
MdnsServiceAnnouncer::MdnsServiceAnnouncer(const QString &name, const QString &serviceType, int port)
|
||||||
void* buffer = malloc(capacity);
|
{
|
||||||
|
myself.serviceType = serviceType;
|
||||||
|
if (!myself.serviceType.endsWith(QChar::fromLatin1('.'))) {
|
||||||
|
// mdns.h needs all the qualified names to end with dot for some reason
|
||||||
|
myself.serviceType.append(QChar::fromLatin1('.'));
|
||||||
|
}
|
||||||
|
myself.port = port;
|
||||||
|
myself.hostname = QHostInfo::localHostName() + QStringLiteral(".local.");
|
||||||
|
myself.serviceInstance = name + QStringLiteral(".") + serviceType;
|
||||||
|
|
||||||
mdns_string_t service_string = (mdns_string_t){service_name, strlen(service_name)};
|
/*
|
||||||
mdns_string_t hostname_string = (mdns_string_t){hostname, strlen(hostname)};
|
// Maybe pre-compute?
|
||||||
|
mdns_string_t service;
|
||||||
// Build the service instance "<hostname>.<_service-name>._tcp.local." string
|
mdns_string_t hostname;
|
||||||
snprintf(service_instance_buffer, sizeof(service_instance_buffer) - 1, "%.*s.%.*s",
|
mdns_string_t service_instance;
|
||||||
MDNS_STRING_FORMAT(hostname_string), MDNS_STRING_FORMAT(service_string));
|
mdns_string_t hostname_qualified;
|
||||||
|
mdns_record_t record_ptr;
|
||||||
qWarning() << service_instance_buffer;
|
mdns_record_t record_srv;
|
||||||
// Build the "<hostname>.local." string
|
mdns_record_t record_a;
|
||||||
|
mdns_record_t record_aaaa;
|
||||||
snprintf(qualified_hostname_buffer, sizeof(qualified_hostname_buffer) - 1, "%.*s.local.",
|
mdns_record_t txt_record[2];
|
||||||
MDNS_STRING_FORMAT(hostname_string));
|
|
||||||
|
|
||||||
memset(&service, 0, sizeof(service));
|
memset(&service, 0, sizeof(service));
|
||||||
service.service.str = service_name;
|
service.service.str = service_name;
|
||||||
|
@ -706,65 +686,45 @@ int MdnsWrapper::startAnnouncing(const char* hostname, const char* service_name,
|
||||||
.rclass = 0,
|
.rclass = 0,
|
||||||
.ttl = 0};
|
.ttl = 0};
|
||||||
|
|
||||||
// Send an announcement on startup of service
|
*/
|
||||||
{
|
}
|
||||||
printf("Sending announce\n");
|
|
||||||
mdns_record_t additional[5] = {0};
|
|
||||||
size_t additional_count = 0;
|
|
||||||
additional[additional_count++] = service.record_srv;
|
|
||||||
if (service.address_ipv4.sin_family == AF_INET)
|
|
||||||
additional[additional_count++] = service.record_a;
|
|
||||||
if (service.address_ipv6.sin6_family == AF_INET6)
|
|
||||||
additional[additional_count++] = service.record_aaaa;
|
|
||||||
additional[additional_count++] = service.txt_record[0];
|
|
||||||
additional[additional_count++] = service.txt_record[1];
|
|
||||||
|
|
||||||
for (int isock = 0; isock < num_sockets; ++isock)
|
void MdnsServiceAnnouncer::startAnnouncing()
|
||||||
mdns_announce_multicast(sockets[isock], buffer, capacity, service.record_ptr, 0, 0,
|
{
|
||||||
additional, additional_count);
|
int num_sockets = listenForQueries();
|
||||||
|
if (num_sockets <= 0) {
|
||||||
|
qWarning() << "Failed to open any client sockets";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
sendMulticastAnnounce(false);
|
||||||
|
}
|
||||||
|
|
||||||
// This is a crude implementation that checks for incoming queries
|
void MdnsServiceAnnouncer::stopAnnouncing()
|
||||||
while (true) {
|
{
|
||||||
int nfds = 0;
|
sendMulticastAnnounce(true);
|
||||||
fd_set readfs;
|
stopListeningForQueries();
|
||||||
FD_ZERO(&readfs);
|
|
||||||
for (int isock = 0; isock < num_sockets; ++isock) {
|
|
||||||
if (sockets[isock] >= nfds)
|
|
||||||
nfds = sockets[isock] + 1;
|
|
||||||
FD_SET(sockets[isock], &readfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = 100000;
|
|
||||||
|
|
||||||
if (select(nfds, &readfs, 0, 0, &timeout) >= 0) {
|
|
||||||
for (int isock = 0; isock < num_sockets; ++isock) {
|
|
||||||
if (FD_ISSET(sockets[isock], &readfs)) {
|
|
||||||
mdns_socket_listen(sockets[isock], buffer, capacity, service_callback,
|
|
||||||
&service);
|
|
||||||
}
|
|
||||||
FD_SET(sockets[isock], &readfs);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
free(service_name_buffer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MdnsServiceAnnouncer::stopListeningForQueries()
|
||||||
|
|
||||||
void MdnsWrapper::stopAnnouncing()
|
|
||||||
{
|
{
|
||||||
printf("Sending goodbye\n");
|
if (socketNotifier != nullptr) {
|
||||||
mdns_record_t additional[5] = {};
|
delete socketNotifier;
|
||||||
|
socketNotifier = nullptr;
|
||||||
|
}
|
||||||
|
if (socketNotifierV6 != nullptr) {
|
||||||
|
delete socketNotifierV6;
|
||||||
|
socketNotifierV6 = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MdnsServiceAnnouncer::sendMulticastAnnounce(bool isGoodbye)
|
||||||
|
{
|
||||||
|
size_t capacity = 2048;
|
||||||
|
void *buffer = malloc(capacity);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mdns_record_t additional[5] = {0};
|
||||||
size_t additional_count = 0;
|
size_t additional_count = 0;
|
||||||
additional[additional_count++] = service.record_srv;
|
additional[additional_count++] = service.record_srv;
|
||||||
if (service.address_ipv4.sin_family == AF_INET)
|
if (service.address_ipv4.sin_family == AF_INET)
|
||||||
|
@ -774,18 +734,16 @@ void MdnsWrapper::stopAnnouncing()
|
||||||
additional[additional_count++] = service.txt_record[0];
|
additional[additional_count++] = service.txt_record[0];
|
||||||
additional[additional_count++] = service.txt_record[1];
|
additional[additional_count++] = service.txt_record[1];
|
||||||
|
|
||||||
size_t capacity = 2048;
|
if (isGoodbye) {
|
||||||
void *buffer = malloc(capacity);
|
qCDebug(KDECONNECT_CORE) << "Sending goodbye";
|
||||||
|
if (socketNotifier) mdns_goodbye_multicast(socketNotifier->socket(), buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
|
||||||
int num_sockets = 2; // FIXME
|
if (socketNotifierV6) mdns_goodbye_multicast(socketNotifierV6->socket(), buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
|
||||||
for (int isock = 0; isock < num_sockets; ++isock) {
|
} else {
|
||||||
mdns_goodbye_multicast(sockets[isock], buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
|
qCDebug(KDECONNECT_CORE) << "Sending announce";
|
||||||
}
|
if (socketNotifier) mdns_announce_multicast(socketNotifier->socket(), buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
|
||||||
|
if (socketNotifierV6) mdns_announce_multicast(socketNotifierV6->socket(), buffer, capacity, service.record_ptr, 0, 0, additional, additional_count);
|
||||||
for (int isock = 0; isock < num_sockets; ++isock) {
|
|
||||||
mdns_socket_close(sockets[isock]);
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
printf("Closed socket%s\n", num_sockets ? "s" : "");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,11 @@ public:
|
||||||
QMap<QString, QString> txtRecords;
|
QMap<QString, QString> txtRecords;
|
||||||
};
|
};
|
||||||
|
|
||||||
int startAnnouncing(const char *hostname, const char *service_name, int service_port);
|
// serviceType should be of the form _kdeconnect._udp.local
|
||||||
void stopAnnouncing();
|
void startDiscovering(const QString &serviceType);
|
||||||
|
|
||||||
void startDiscovering(const char *serviceType);
|
|
||||||
void stopDiscovering();
|
void stopDiscovering();
|
||||||
|
|
||||||
void sendQuery(const char *serviceName);
|
void sendQuery(const QString &serviceName);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void serviceFound(const MdnsService &service);
|
void serviceFound(const MdnsService &service);
|
||||||
|
@ -47,4 +45,40 @@ private:
|
||||||
QVector<QSocketNotifier *> responseSocketNotifiers;
|
QVector<QSocketNotifier *> responseSocketNotifiers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MdnsServiceAnnouncer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct AnnouncedInfo {
|
||||||
|
QString serviceType; // ie: "<_service-type>._tcp.local."
|
||||||
|
QString serviceInstance; // ie: "<service-name>.<_service-type>._tcp.local."
|
||||||
|
QString hostname; // ie: "<hostname>.local."
|
||||||
|
int port;
|
||||||
|
QMap<QString, QString> txtRecords;
|
||||||
|
};
|
||||||
|
|
||||||
|
// serviceType should be of the form _kdeconnect._udp.local
|
||||||
|
MdnsServiceAnnouncer(const QString &name, const QString &serviceType, int port);
|
||||||
|
|
||||||
|
void putTxtRecord(const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
myself.txtRecords[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startAnnouncing();
|
||||||
|
void stopAnnouncing();
|
||||||
|
|
||||||
|
void sendMulticastAnnounce(bool isGoodbye);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int listenForQueries();
|
||||||
|
void stopListeningForQueries();
|
||||||
|
|
||||||
|
AnnouncedInfo myself;
|
||||||
|
|
||||||
|
QSocketNotifier *socketNotifier = nullptr;
|
||||||
|
QSocketNotifier *socketNotifierV6 = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,12 +12,18 @@
|
||||||
|
|
||||||
#include "mdns_wrapper.h"
|
#include "mdns_wrapper.h"
|
||||||
|
|
||||||
#include <QHostInfo>
|
QString kServiceType = QStringLiteral("_kdeconnect._udp.local");
|
||||||
const char *kServiceName = "_kdeconnect._udp.local";
|
|
||||||
|
|
||||||
MdnsDiscovery::MdnsDiscovery(LanLinkProvider *lanLinkProvider)
|
MdnsDiscovery::MdnsDiscovery(LanLinkProvider *lanLinkProvider)
|
||||||
: lanLinkProvider(lanLinkProvider)
|
: lanLinkProvider(lanLinkProvider)
|
||||||
|
, mdnsAnnouncer(KdeConnectConfig::instance().deviceId(), kServiceType, LanLinkProvider::UDP_PORT)
|
||||||
{
|
{
|
||||||
|
KdeConnectConfig &config = KdeConnectConfig::instance();
|
||||||
|
mdnsAnnouncer.putTxtRecord(QStringLiteral("id"), config.deviceId());
|
||||||
|
mdnsAnnouncer.putTxtRecord(QStringLiteral("name"), config.name());
|
||||||
|
mdnsAnnouncer.putTxtRecord(QStringLiteral("type"), config.deviceType().toString());
|
||||||
|
mdnsAnnouncer.putTxtRecord(QStringLiteral("protocol"), QString::number(NetworkPacket::s_protocolVersion));
|
||||||
|
|
||||||
connect(&mdnsWrapper, &MdnsWrapper::serviceFound, [lanLinkProvider](const MdnsWrapper::MdnsService &service) {
|
connect(&mdnsWrapper, &MdnsWrapper::serviceFound, [lanLinkProvider](const MdnsWrapper::MdnsService &service) {
|
||||||
if (KdeConnectConfig::instance().deviceId() == service.name) {
|
if (KdeConnectConfig::instance().deviceId() == service.name) {
|
||||||
qCDebug(KDECONNECT_CORE) << "Discovered myself, ignoring";
|
qCDebug(KDECONNECT_CORE) << "Discovered myself, ignoring";
|
||||||
|
@ -34,58 +40,19 @@ MdnsDiscovery::~MdnsDiscovery()
|
||||||
stopDiscovering();
|
stopDiscovering();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString hostName = QHostInfo::localHostName();
|
|
||||||
|
|
||||||
void MdnsDiscovery::startAnnouncing()
|
void MdnsDiscovery::startAnnouncing()
|
||||||
{
|
{
|
||||||
// mdnsWrapper.startAnnouncing(hostName.toLatin1().data(), kServiceName, LanLinkProvider::UDP_PORT);
|
mdnsAnnouncer.startAnnouncing();
|
||||||
|
|
||||||
/*
|
|
||||||
if (m_publisher != nullptr) {
|
|
||||||
qCDebug(KDECONNECT_CORE) << "MDNS already announcing";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
qCDebug(KDECONNECT_CORE) << "MDNS start announcing";
|
|
||||||
|
|
||||||
KdeConnectConfig &config = KdeConnectConfig::instance();
|
|
||||||
|
|
||||||
m_publisher = new KDNSSD::PublicService(config.deviceId(), kServiceName, LanLinkProvider::UDP_PORT, QStringLiteral("local"));
|
|
||||||
m_publisher->setParent(this);
|
|
||||||
|
|
||||||
// We can't fit the device certificate in this field, so this is not enough info to create a Device and won't be used.
|
|
||||||
QMap<QString, QByteArray> data;
|
|
||||||
data[QStringLiteral("id")] = config.deviceId().toUtf8();
|
|
||||||
data[QStringLiteral("name")] = config.name().toUtf8();
|
|
||||||
data[QStringLiteral("type")] = config.deviceType().toString().toUtf8();
|
|
||||||
data[QStringLiteral("protocol")] = QString::number(NetworkPacket::s_protocolVersion).toUtf8();
|
|
||||||
m_publisher->setTextData(data);
|
|
||||||
|
|
||||||
connect(m_publisher, &KDNSSD::PublicService::published, [](bool successful) {
|
|
||||||
if (successful) {
|
|
||||||
qCDebug(KDECONNECT_CORE) << "MDNS published successfully";
|
|
||||||
} else {
|
|
||||||
qCWarning(KDECONNECT_CORE) << "MDNS failed to publish";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
m_publisher->publishAsync();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdnsDiscovery::stopAnnouncing()
|
void MdnsDiscovery::stopAnnouncing()
|
||||||
{
|
{
|
||||||
// mdnsWrapper.stopAnnouncing();
|
mdnsAnnouncer.stopAnnouncing();
|
||||||
|
|
||||||
// if (m_publisher != nullptr) {
|
|
||||||
// qCDebug(KDECONNECT_CORE) << "MDNS stop announcing";
|
|
||||||
// delete m_publisher;
|
|
||||||
// m_publisher = nullptr;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdnsDiscovery::startDiscovering()
|
void MdnsDiscovery::startDiscovering()
|
||||||
{
|
{
|
||||||
mdnsWrapper.startDiscovering(kServiceName);
|
mdnsWrapper.startDiscovering(kServiceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MdnsDiscovery::stopDiscovering()
|
void MdnsDiscovery::stopDiscovering()
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
private:
|
private:
|
||||||
LanLinkProvider *lanLinkProvider = nullptr;
|
LanLinkProvider *lanLinkProvider = nullptr;
|
||||||
MdnsWrapper mdnsWrapper;
|
MdnsWrapper mdnsWrapper;
|
||||||
|
MdnsServiceAnnouncer mdnsAnnouncer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KDECONNECT_SERVER_H
|
#endif // KDECONNECT_SERVER_H
|
||||||
|
|
Loading…
Reference in a new issue