添加广播MDNS服务
This commit is contained in:
32
FactoryTestTool/ThirdParty/qmdnsengine/src/abstractserver.cpp
vendored
Normal file
32
FactoryTestTool/ThirdParty/qmdnsengine/src/abstractserver.cpp
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/abstractserver.h>
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
AbstractServer::AbstractServer(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
108
FactoryTestTool/ThirdParty/qmdnsengine/src/bitmap.cpp
vendored
Normal file
108
FactoryTestTool/ThirdParty/qmdnsengine/src/bitmap.cpp
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/bitmap.h>
|
||||
|
||||
#include "bitmap_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
BitmapPrivate::BitmapPrivate()
|
||||
: length(0),
|
||||
data(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
BitmapPrivate::~BitmapPrivate()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
void BitmapPrivate::free()
|
||||
{
|
||||
if (data) {
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapPrivate::fromData(quint8 newLength, const quint8 *newData)
|
||||
{
|
||||
data = new quint8[newLength];
|
||||
for (int i = 0; i < newLength; ++i) {
|
||||
data[i] = newData[i];
|
||||
}
|
||||
length = newLength;
|
||||
}
|
||||
|
||||
Bitmap::Bitmap()
|
||||
: d(new BitmapPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Bitmap::Bitmap(const Bitmap &other)
|
||||
: d(new BitmapPrivate)
|
||||
{
|
||||
d->fromData(other.d->length, other.d->data);
|
||||
}
|
||||
|
||||
Bitmap &Bitmap::operator=(const Bitmap &other)
|
||||
{
|
||||
d->free();
|
||||
d->fromData(other.d->length, other.d->data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Bitmap::operator==(const Bitmap &other)
|
||||
{
|
||||
if (d->length != other.d->length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < d->length; ++i) {
|
||||
if (d->data[i] != other.d->data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bitmap::~Bitmap()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
quint8 Bitmap::length() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
const quint8 *Bitmap::data() const
|
||||
{
|
||||
return d->data;
|
||||
}
|
||||
|
||||
void Bitmap::setData(quint8 length, const quint8 *data)
|
||||
{
|
||||
d->free();
|
||||
d->fromData(length, data);
|
||||
}
|
||||
49
FactoryTestTool/ThirdParty/qmdnsengine/src/bitmap_p.h
vendored
Normal file
49
FactoryTestTool/ThirdParty/qmdnsengine/src/bitmap_p.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_BITMAP_P_H
|
||||
#define QMDNSENGINE_BITMAP_P_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class BitmapPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
BitmapPrivate();
|
||||
virtual ~BitmapPrivate();
|
||||
|
||||
void free();
|
||||
void fromData(quint8 newLength, const quint8 *newData);
|
||||
|
||||
quint8 length;
|
||||
quint8 *data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_BITMAP_P_H
|
||||
291
FactoryTestTool/ThirdParty/qmdnsengine/src/browser.cpp
vendored
Normal file
291
FactoryTestTool/ThirdParty/qmdnsengine/src/browser.cpp
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/abstractserver.h>
|
||||
#include <qmdnsengine/browser.h>
|
||||
#include <qmdnsengine/cache.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/mdns.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
#include "browser_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
BrowserPrivate::BrowserPrivate(Browser *browser, AbstractServer *server, const QByteArray &type, Cache *existingCache)
|
||||
: QObject(browser),
|
||||
server(server),
|
||||
type(type),
|
||||
cache(existingCache ? existingCache : new Cache(this)),
|
||||
q(browser)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &BrowserPrivate::onMessageReceived);
|
||||
connect(cache, &Cache::shouldQuery, this, &BrowserPrivate::onShouldQuery);
|
||||
connect(cache, &Cache::recordExpired, this, &BrowserPrivate::onRecordExpired);
|
||||
connect(&queryTimer, &QTimer::timeout, this, &BrowserPrivate::onQueryTimeout);
|
||||
connect(&serviceTimer, &QTimer::timeout, this, &BrowserPrivate::onServiceTimeout);
|
||||
|
||||
queryTimer.setInterval(60 * 1000);
|
||||
queryTimer.setSingleShot(true);
|
||||
|
||||
serviceTimer.setInterval(100);
|
||||
serviceTimer.setSingleShot(true);
|
||||
|
||||
// Immediately begin browsing for services
|
||||
onQueryTimeout();
|
||||
}
|
||||
|
||||
// TODO: multiple SRV records not supported
|
||||
|
||||
bool BrowserPrivate::updateService(const QByteArray &fqName)
|
||||
{
|
||||
// Split the FQDN into service name and type
|
||||
int index = fqName.indexOf('.');
|
||||
QByteArray serviceName = fqName.left(index);
|
||||
QByteArray serviceType = fqName.mid(index + 1);
|
||||
|
||||
// Immediately return if a PTR record does not exist
|
||||
Record ptrRecord;
|
||||
if (!cache->lookupRecord(serviceType, PTR, ptrRecord)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a SRV record is missing, query for it (by returning true)
|
||||
Record srvRecord;
|
||||
if (!cache->lookupRecord(fqName, SRV, srvRecord)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Service service;
|
||||
service.setName(serviceName);
|
||||
service.setType(serviceType);
|
||||
service.setHostname(srvRecord.target());
|
||||
service.setPort(srvRecord.port());
|
||||
|
||||
// If TXT records are available for the service, add their values
|
||||
QList<Record> txtRecords;
|
||||
if (cache->lookupRecords(fqName, TXT, txtRecords)) {
|
||||
QMap<QByteArray, QByteArray> attributes;
|
||||
for (const Record &record : qAsConst(txtRecords)) {
|
||||
for (auto i = record.attributes().constBegin();
|
||||
i != record.attributes().constEnd(); ++i) {
|
||||
attributes.insert(i.key(), i.value());
|
||||
}
|
||||
}
|
||||
service.setAttributes(attributes);
|
||||
}
|
||||
|
||||
// If the service existed, this is an update; otherwise it is a new
|
||||
// addition; emit the appropriate signal
|
||||
if (!services.contains(fqName)) {
|
||||
emit q->serviceAdded(service);
|
||||
} else if(services.value(fqName) != service) {
|
||||
emit q->serviceUpdated(service);
|
||||
}
|
||||
|
||||
services.insert(fqName, service);
|
||||
hostnames.insert(service.hostname());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BrowserPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (!message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool any = type == MdnsBrowseType;
|
||||
|
||||
// Use a set to track all services that are updated in the message to
|
||||
// prevent unnecessary queries for SRV and TXT records
|
||||
QSet<QByteArray> updateNames;
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
bool cacheRecord = false;
|
||||
|
||||
switch (record.type()) {
|
||||
case PTR:
|
||||
if (any && record.name() == MdnsBrowseType) {
|
||||
ptrTargets.insert(record.target());
|
||||
serviceTimer.start();
|
||||
cacheRecord = true;
|
||||
} else if (any || record.name() == type) {
|
||||
updateNames.insert(record.target());
|
||||
cacheRecord = true;
|
||||
}
|
||||
break;
|
||||
case SRV:
|
||||
case TXT:
|
||||
if (any || record.name().endsWith("." + type)) {
|
||||
updateNames.insert(record.name());
|
||||
cacheRecord = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cacheRecord) {
|
||||
cache->addRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
// For each of the services marked to be updated, perform the update and
|
||||
// make a list of all missing SRV records
|
||||
QSet<QByteArray> queryNames;
|
||||
for (const QByteArray &name : qAsConst(updateNames)) {
|
||||
if (updateService(name)) {
|
||||
queryNames.insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Cache A / AAAA records after services are processed to ensure hostnames are known
|
||||
for (const Record &record : records) {
|
||||
bool cacheRecord = false;
|
||||
|
||||
switch (record.type()) {
|
||||
case A:
|
||||
case AAAA:
|
||||
cacheRecord = hostnames.contains(record.name());
|
||||
break;
|
||||
}
|
||||
if (cacheRecord) {
|
||||
cache->addRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
// Build and send a query for all of the SRV and TXT records
|
||||
if (queryNames.count()) {
|
||||
Message queryMessage;
|
||||
for (const QByteArray &name : qAsConst(queryNames)) {
|
||||
Query query;
|
||||
query.setName(name);
|
||||
query.setType(SRV);
|
||||
queryMessage.addQuery(query);
|
||||
query.setType(TXT);
|
||||
queryMessage.addQuery(query);
|
||||
}
|
||||
server->sendMessageToAll(queryMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserPrivate::onShouldQuery(const Record &record)
|
||||
{
|
||||
// Assume that all messages in the cache are still in use (by the browser)
|
||||
// and attempt to renew them immediately
|
||||
|
||||
Query query;
|
||||
query.setName(record.name());
|
||||
query.setType(record.type());
|
||||
Message message;
|
||||
message.addQuery(query);
|
||||
server->sendMessageToAll(message);
|
||||
}
|
||||
|
||||
void BrowserPrivate::onRecordExpired(const Record &record)
|
||||
{
|
||||
// If the SRV record has expired for a service, then it must be
|
||||
// removed - TXT records on the other hand, cause an update
|
||||
|
||||
QByteArray serviceName;
|
||||
switch (record.type()) {
|
||||
case SRV:
|
||||
serviceName = record.name();
|
||||
break;
|
||||
case TXT:
|
||||
updateService(record.name());
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
Service service = services.value(serviceName);
|
||||
if (!service.name().isNull()) {
|
||||
emit q->serviceRemoved(service);
|
||||
services.remove(serviceName);
|
||||
updateHostnames();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserPrivate::onQueryTimeout()
|
||||
{
|
||||
Query query;
|
||||
query.setName(type);
|
||||
query.setType(PTR);
|
||||
Message message;
|
||||
message.addQuery(query);
|
||||
|
||||
// TODO: including too many records could cause problems
|
||||
|
||||
// Include PTR records for the target that are already known
|
||||
QList<Record> records;
|
||||
if (cache->lookupRecords(query.name(), PTR, records)) {
|
||||
for (const Record &record : qAsConst(records)) {
|
||||
message.addRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
server->sendMessageToAll(message);
|
||||
queryTimer.start();
|
||||
}
|
||||
|
||||
void BrowserPrivate::onServiceTimeout()
|
||||
{
|
||||
if (ptrTargets.count()) {
|
||||
Message message;
|
||||
for (const QByteArray &target : qAsConst(ptrTargets)) {
|
||||
|
||||
// Add a query for PTR records
|
||||
Query query;
|
||||
query.setName(target);
|
||||
query.setType(PTR);
|
||||
message.addQuery(query);
|
||||
|
||||
// Include PTR records for the target that are already known
|
||||
QList<Record> records;
|
||||
if (cache->lookupRecords(target, PTR, records)) {
|
||||
for (const Record &record : qAsConst(records)) {
|
||||
message.addRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server->sendMessageToAll(message);
|
||||
ptrTargets.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserPrivate::updateHostnames()
|
||||
{
|
||||
hostnames.clear();
|
||||
|
||||
for (const auto& service : services) {
|
||||
hostnames.insert(service.hostname());
|
||||
}
|
||||
}
|
||||
|
||||
Browser::Browser(AbstractServer *server, const QByteArray &type, Cache *cache, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new BrowserPrivate(this, server, type, cache))
|
||||
{
|
||||
}
|
||||
83
FactoryTestTool/ThirdParty/qmdnsengine/src/browser_p.h
vendored
Normal file
83
FactoryTestTool/ThirdParty/qmdnsengine/src/browser_p.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_BROWSER_P_H
|
||||
#define QMDNSENGINE_BROWSER_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
|
||||
#include <qmdnsengine/service.h>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Browser;
|
||||
class Cache;
|
||||
class Message;
|
||||
class Record;
|
||||
|
||||
class BrowserPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BrowserPrivate(Browser *browser, AbstractServer *server, const QByteArray &type, Cache *existingCache);
|
||||
|
||||
bool updateService(const QByteArray &fqName);
|
||||
|
||||
AbstractServer *server;
|
||||
QByteArray type;
|
||||
|
||||
Cache *cache;
|
||||
QSet<QByteArray> ptrTargets;
|
||||
QMap<QByteArray, Service> services;
|
||||
QSet<QByteArray> hostnames;
|
||||
|
||||
QTimer queryTimer;
|
||||
QTimer serviceTimer;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onShouldQuery(const Record &record);
|
||||
void onRecordExpired(const Record &record);
|
||||
|
||||
void onQueryTimeout();
|
||||
void onServiceTimeout();
|
||||
|
||||
private:
|
||||
void updateHostnames();
|
||||
|
||||
Browser *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_BROWSER_P_H
|
||||
173
FactoryTestTool/ThirdParty/qmdnsengine/src/cache.cpp
vendored
Normal file
173
FactoryTestTool/ThirdParty/qmdnsengine/src/cache.cpp
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QtGlobal>
|
||||
#if(QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
#include <QRandomGenerator>
|
||||
#define USE_QRANDOMGENERATOR
|
||||
#endif
|
||||
|
||||
#include <qmdnsengine/cache.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
|
||||
#include "cache_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
CachePrivate::CachePrivate(Cache *cache)
|
||||
: QObject(cache),
|
||||
q(cache)
|
||||
{
|
||||
connect(&timer, &QTimer::timeout, this, &CachePrivate::onTimeout);
|
||||
|
||||
timer.setSingleShot(true);
|
||||
}
|
||||
|
||||
void CachePrivate::onTimeout()
|
||||
{
|
||||
// Loop through all of the records in the cache, emitting the appropriate
|
||||
// signal when a trigger has passed, determining when the next trigger
|
||||
// will occur, and removing records that have expired
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QDateTime newNextTrigger;
|
||||
|
||||
for (auto i = entries.begin(); i != entries.end();) {
|
||||
|
||||
// Loop through the triggers and remove ones that have already
|
||||
// passed
|
||||
bool shouldQuery = false;
|
||||
for (auto j = i->triggers.begin(); j != i->triggers.end();) {
|
||||
if ((*j) <= now) {
|
||||
shouldQuery = true;
|
||||
j = i->triggers.erase(j);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If triggers remain, determine the next earliest one; if none
|
||||
// remain, the record has expired and should be removed
|
||||
if (i->triggers.length()) {
|
||||
if (newNextTrigger.isNull() || i->triggers.at(0) < newNextTrigger) {
|
||||
newNextTrigger = i->triggers.at(0);
|
||||
}
|
||||
if (shouldQuery) {
|
||||
emit q->shouldQuery(i->record);
|
||||
}
|
||||
++i;
|
||||
} else {
|
||||
emit q->recordExpired(i->record);
|
||||
i = entries.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
// If newNextTrigger contains a value, it will be the time for the next
|
||||
// trigger and the timer should be started again
|
||||
nextTrigger = newNextTrigger;
|
||||
if (!nextTrigger.isNull()) {
|
||||
timer.start(now.msecsTo(nextTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
Cache::Cache(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new CachePrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
void Cache::addRecord(const Record &record)
|
||||
{
|
||||
// If a record exists that matches, remove it from the cache; if the TTL
|
||||
// is nonzero, it will be added back to the cache with updated times
|
||||
for (auto i = d->entries.begin(); i != d->entries.end();) {
|
||||
if ((record.flushCache() &&
|
||||
(*i).record.name() == record.name() &&
|
||||
(*i).record.type() == record.type()) ||
|
||||
(*i).record == record) {
|
||||
|
||||
// If the TTL is set to 0, indicate that the record was removed
|
||||
if (record.ttl() == 0) {
|
||||
emit recordExpired((*i).record);
|
||||
}
|
||||
|
||||
i = d->entries.erase(i);
|
||||
|
||||
// No need to continue further if the TTL was set to 0
|
||||
if (record.ttl() == 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the current time to calculate the triggers and add a random offset
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
#ifdef USE_QRANDOMGENERATOR
|
||||
qint64 random = QRandomGenerator::global()->bounded(20);
|
||||
#else
|
||||
qint64 random = qrand() % 20;
|
||||
#endif
|
||||
|
||||
QList<QDateTime> triggers{
|
||||
now.addMSecs(record.ttl() * 500 + random), // 50%
|
||||
now.addMSecs(record.ttl() * 850 + random), // 85%
|
||||
now.addMSecs(record.ttl() * 900 + random), // 90%
|
||||
now.addMSecs(record.ttl() * 950 + random), // 95%
|
||||
now.addSecs(record.ttl())
|
||||
};
|
||||
|
||||
// Append the record and its triggers
|
||||
d->entries.append({record, triggers});
|
||||
|
||||
// Check if the new record's first trigger is earlier than the next
|
||||
// scheduled trigger; if so, restart the timer
|
||||
if (d->nextTrigger.isNull() || triggers.at(0) < d->nextTrigger) {
|
||||
d->nextTrigger = triggers.at(0);
|
||||
d->timer.start(now.msecsTo(d->nextTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
bool Cache::lookupRecord(const QByteArray &name, quint16 type, Record &record) const
|
||||
{
|
||||
QList<Record> records;
|
||||
if (lookupRecords(name, type, records)) {
|
||||
record = records.at(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Cache::lookupRecords(const QByteArray &name, quint16 type, QList<Record> &records) const
|
||||
{
|
||||
bool recordsAdded = false;
|
||||
for (const CachePrivate::Entry &entry : d->entries) {
|
||||
if ((name.isNull() || entry.record.name() == name) &&
|
||||
(type == ANY || entry.record.type() == type)) {
|
||||
records.append(entry.record);
|
||||
recordsAdded = true;
|
||||
}
|
||||
}
|
||||
return recordsAdded;
|
||||
}
|
||||
69
FactoryTestTool/ThirdParty/qmdnsengine/src/cache_p.h
vendored
Normal file
69
FactoryTestTool/ThirdParty/qmdnsengine/src/cache_p.h
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_CACHE_P_H
|
||||
#define QMDNSENGINE_CACHE_P_H
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Cache;
|
||||
|
||||
class CachePrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Record record;
|
||||
QList<QDateTime> triggers;
|
||||
};
|
||||
|
||||
CachePrivate(Cache *cache);
|
||||
|
||||
QTimer timer;
|
||||
QList<Entry> entries;
|
||||
QDateTime nextTrigger;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Cache *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_CACHE_P_H
|
||||
376
FactoryTestTool/ThirdParty/qmdnsengine/src/dns.cpp
vendored
Normal file
376
FactoryTestTool/ThirdParty/qmdnsengine/src/dns.cpp
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QtEndian>
|
||||
|
||||
#include <qmdnsengine/bitmap.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
template<class T>
|
||||
bool parseInteger(const QByteArray &packet, quint16 &offset, T &value)
|
||||
{
|
||||
if (offset + sizeof(T) > static_cast<unsigned int>(packet.length())) {
|
||||
return false; // out-of-bounds
|
||||
}
|
||||
value = qFromBigEndian<T>(reinterpret_cast<const uchar*>(packet.constData() + offset));
|
||||
offset += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void writeInteger(QByteArray &packet, quint16 &offset, T value)
|
||||
{
|
||||
value = qToBigEndian<T>(value);
|
||||
packet.append(reinterpret_cast<const char*>(&value), sizeof(T));
|
||||
offset += sizeof(T);
|
||||
}
|
||||
|
||||
bool parseName(const QByteArray &packet, quint16 &offset, QByteArray &name)
|
||||
{
|
||||
quint16 offsetEnd = 0;
|
||||
quint16 offsetPtr = offset;
|
||||
forever {
|
||||
quint8 nBytes;
|
||||
if (!parseInteger<quint8>(packet, offset, nBytes)) {
|
||||
return false;
|
||||
}
|
||||
if (!nBytes) {
|
||||
break;
|
||||
}
|
||||
switch (nBytes & 0xc0) {
|
||||
case 0x00:
|
||||
if (offset + nBytes > packet.length()) {
|
||||
return false; // length exceeds message
|
||||
}
|
||||
name.append(packet.mid(offset, nBytes));
|
||||
name.append('.');
|
||||
offset += nBytes;
|
||||
break;
|
||||
case 0xc0:
|
||||
{
|
||||
quint8 nBytes2;
|
||||
quint16 newOffset;
|
||||
if (!parseInteger<quint8>(packet, offset, nBytes2)) {
|
||||
return false;
|
||||
}
|
||||
newOffset = ((nBytes & ~0xc0) << 8) | nBytes2;
|
||||
if (newOffset >= offsetPtr) {
|
||||
return false; // prevent infinite loop
|
||||
}
|
||||
offsetPtr = newOffset;
|
||||
if (!offsetEnd) {
|
||||
offsetEnd = offset;
|
||||
}
|
||||
offset = newOffset;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false; // no other types supported
|
||||
}
|
||||
}
|
||||
if (offsetEnd) {
|
||||
offset = offsetEnd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void writeName(QByteArray &packet, quint16 &offset, const QByteArray &name, QMap<QByteArray, quint16> &nameMap)
|
||||
{
|
||||
QByteArray fragment = name;
|
||||
if (fragment.endsWith('.')) {
|
||||
fragment.chop(1);
|
||||
}
|
||||
while (fragment.length()) {
|
||||
if (nameMap.contains(fragment)) {
|
||||
writeInteger<quint16>(packet, offset, nameMap.value(fragment) | 0xc000);
|
||||
return;
|
||||
}
|
||||
nameMap.insert(fragment, offset);
|
||||
int index = fragment.indexOf('.');
|
||||
if (index == -1) {
|
||||
index = fragment.length();
|
||||
}
|
||||
writeInteger<quint8>(packet, offset, index);
|
||||
packet.append(fragment.left(index));
|
||||
offset += index;
|
||||
fragment.remove(0, index + 1);
|
||||
}
|
||||
writeInteger<quint8>(packet, offset, 0);
|
||||
}
|
||||
|
||||
bool parseRecord(const QByteArray &packet, quint16 &offset, Record &record)
|
||||
{
|
||||
QByteArray name;
|
||||
quint16 type, class_, dataLen;
|
||||
quint32 ttl;
|
||||
if (!parseName(packet, offset, name) ||
|
||||
!parseInteger<quint16>(packet, offset, type) ||
|
||||
!parseInteger<quint16>(packet, offset, class_) ||
|
||||
!parseInteger<quint32>(packet, offset, ttl) ||
|
||||
!parseInteger<quint16>(packet, offset, dataLen)) {
|
||||
return false;
|
||||
}
|
||||
record.setName(name);
|
||||
record.setType(type);
|
||||
record.setFlushCache(class_ & 0x8000);
|
||||
record.setTtl(ttl);
|
||||
switch (type) {
|
||||
case A:
|
||||
{
|
||||
quint32 ipv4Addr;
|
||||
if (!parseInteger<quint32>(packet, offset, ipv4Addr)) {
|
||||
return false;
|
||||
}
|
||||
record.setAddress(QHostAddress(ipv4Addr));
|
||||
break;
|
||||
}
|
||||
case AAAA:
|
||||
{
|
||||
if (offset + 16 > packet.length()) {
|
||||
return false;
|
||||
}
|
||||
record.setAddress(QHostAddress(
|
||||
reinterpret_cast<const quint8*>(packet.constData() + offset)
|
||||
));
|
||||
offset += 16;
|
||||
break;
|
||||
}
|
||||
case NSEC:
|
||||
{
|
||||
QByteArray nextDomainName;
|
||||
quint8 number;
|
||||
quint8 length;
|
||||
if (!parseName(packet, offset, nextDomainName) ||
|
||||
!parseInteger<quint8>(packet, offset, number) ||
|
||||
!parseInteger<quint8>(packet, offset, length) ||
|
||||
number != 0 ||
|
||||
offset + length > packet.length()) {
|
||||
return false;
|
||||
}
|
||||
Bitmap bitmap;
|
||||
bitmap.setData(length, reinterpret_cast<const quint8*>(packet.constData() + offset));
|
||||
record.setNextDomainName(nextDomainName);
|
||||
record.setBitmap(bitmap);
|
||||
offset += length;
|
||||
break;
|
||||
}
|
||||
case PTR:
|
||||
{
|
||||
QByteArray target;
|
||||
if (!parseName(packet, offset, target)) {
|
||||
return false;
|
||||
}
|
||||
record.setTarget(target);
|
||||
break;
|
||||
}
|
||||
case SRV:
|
||||
{
|
||||
quint16 priority, weight, port;
|
||||
QByteArray target;
|
||||
if (!parseInteger<quint16>(packet, offset, priority) ||
|
||||
!parseInteger<quint16>(packet, offset, weight) ||
|
||||
!parseInteger<quint16>(packet, offset, port) ||
|
||||
!parseName(packet, offset, target)) {
|
||||
return false;
|
||||
}
|
||||
record.setPriority(priority);
|
||||
record.setWeight(weight);
|
||||
record.setPort(port);
|
||||
record.setTarget(target);
|
||||
break;
|
||||
}
|
||||
case TXT:
|
||||
{
|
||||
quint16 start = offset;
|
||||
while (offset < start + dataLen) {
|
||||
quint8 nBytes;
|
||||
if (!parseInteger<quint8>(packet, offset, nBytes) ||
|
||||
offset + nBytes > packet.length()) {
|
||||
return false;
|
||||
}
|
||||
if (nBytes == 0) {
|
||||
break;
|
||||
}
|
||||
QByteArray attr(packet.constData() + offset, nBytes);
|
||||
offset += nBytes;
|
||||
int splitIndex = attr.indexOf('=');
|
||||
if (splitIndex == -1) {
|
||||
record.addAttribute(attr, QByteArray());
|
||||
} else {
|
||||
record.addAttribute(attr.left(splitIndex), attr.mid(splitIndex + 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
offset += dataLen;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void writeRecord(QByteArray &packet, quint16 &offset, Record &record, QMap<QByteArray, quint16> &nameMap)
|
||||
{
|
||||
writeName(packet, offset, record.name(), nameMap);
|
||||
writeInteger<quint16>(packet, offset, record.type());
|
||||
writeInteger<quint16>(packet, offset, record.flushCache() ? 0x8001 : 1);
|
||||
writeInteger<quint32>(packet, offset, record.ttl());
|
||||
offset += 2;
|
||||
QByteArray data;
|
||||
switch (record.type()) {
|
||||
case A:
|
||||
writeInteger<quint32>(data, offset, record.address().toIPv4Address());
|
||||
break;
|
||||
case AAAA:
|
||||
{
|
||||
Q_IPV6ADDR ipv6Addr = record.address().toIPv6Address();
|
||||
data.append(reinterpret_cast<const char*>(&ipv6Addr), sizeof(Q_IPV6ADDR));
|
||||
offset += data.length();
|
||||
break;
|
||||
}
|
||||
case NSEC:
|
||||
{
|
||||
quint8 length = record.bitmap().length();
|
||||
writeName(data, offset, record.nextDomainName(), nameMap);
|
||||
writeInteger<quint8>(data, offset, 0);
|
||||
writeInteger<quint8>(data, offset, length);
|
||||
data.append(reinterpret_cast<const char*>(record.bitmap().data()), length);
|
||||
offset += length;
|
||||
break;
|
||||
}
|
||||
case PTR:
|
||||
writeName(data, offset, record.target(), nameMap);
|
||||
break;
|
||||
case SRV:
|
||||
writeInteger<quint16>(data, offset, record.priority());
|
||||
writeInteger<quint16>(data, offset, record.weight());
|
||||
writeInteger<quint16>(data, offset, record.port());
|
||||
writeName(data, offset, record.target(), nameMap);
|
||||
break;
|
||||
case TXT:
|
||||
if (!record.attributes().count()) {
|
||||
writeInteger<quint8>(data, offset, 0);
|
||||
break;
|
||||
}
|
||||
for (auto i = record.attributes().constBegin(); i != record.attributes().constEnd(); ++i) {
|
||||
QByteArray entry = i.value().isNull() ? i.key() : i.key() + "=" + i.value();
|
||||
writeInteger<quint8>(data, offset, entry.length());
|
||||
data.append(entry);
|
||||
offset += entry.length();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
offset -= 2;
|
||||
writeInteger<quint16>(packet, offset, data.length());
|
||||
packet.append(data);
|
||||
}
|
||||
|
||||
bool fromPacket(const QByteArray &packet, Message &message)
|
||||
{
|
||||
quint16 offset = 0;
|
||||
quint16 transactionId, flags, nQuestion, nAnswer, nAuthority, nAdditional;
|
||||
if (!parseInteger<quint16>(packet, offset, transactionId) ||
|
||||
!parseInteger<quint16>(packet, offset, flags) ||
|
||||
!parseInteger<quint16>(packet, offset, nQuestion) ||
|
||||
!parseInteger<quint16>(packet, offset, nAnswer) ||
|
||||
!parseInteger<quint16>(packet, offset, nAuthority) ||
|
||||
!parseInteger<quint16>(packet, offset, nAdditional)) {
|
||||
return false;
|
||||
}
|
||||
message.setTransactionId(transactionId);
|
||||
message.setResponse(flags & 0x8400);
|
||||
message.setTruncated(flags & 0x0200);
|
||||
for (int i = 0; i < nQuestion; ++i) {
|
||||
QByteArray name;
|
||||
quint16 type, class_;
|
||||
if (!parseName(packet, offset, name) ||
|
||||
!parseInteger<quint16>(packet, offset, type) ||
|
||||
!parseInteger<quint16>(packet, offset, class_)) {
|
||||
return false;
|
||||
}
|
||||
Query query;
|
||||
query.setName(name);
|
||||
query.setType(type);
|
||||
query.setUnicastResponse(class_ & 0x8000);
|
||||
message.addQuery(query);
|
||||
}
|
||||
quint16 nRecord = nAnswer + nAuthority + nAdditional;
|
||||
for (int i = 0; i < nRecord; ++i) {
|
||||
Record record;
|
||||
if (!parseRecord(packet, offset, record)) {
|
||||
return false;
|
||||
}
|
||||
message.addRecord(record);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void toPacket(const Message &message, QByteArray &packet)
|
||||
{
|
||||
quint16 offset = 0;
|
||||
quint16 flags = (message.isResponse() ? 0x8400 : 0) |
|
||||
(message.isTruncated() ? 0x200 : 0);
|
||||
writeInteger<quint16>(packet, offset, message.transactionId());
|
||||
writeInteger<quint16>(packet, offset, flags);
|
||||
writeInteger<quint16>(packet, offset, message.queries().length());
|
||||
writeInteger<quint16>(packet, offset, message.records().length());
|
||||
writeInteger<quint16>(packet, offset, 0);
|
||||
writeInteger<quint16>(packet, offset, 0);
|
||||
QMap<QByteArray, quint16> nameMap;
|
||||
const auto queries = message.queries();
|
||||
for (const Query &query : queries) {
|
||||
writeName(packet, offset, query.name(), nameMap);
|
||||
writeInteger<quint16>(packet, offset, query.type());
|
||||
writeInteger<quint16>(packet, offset, query.unicastResponse() ? 0x8001 : 1);
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (Record record : records) {
|
||||
writeRecord(packet, offset, record, nameMap);
|
||||
}
|
||||
}
|
||||
|
||||
QString typeName(quint16 type)
|
||||
{
|
||||
switch (type) {
|
||||
case A: return "A";
|
||||
case AAAA: return "AAAA";
|
||||
case ANY: return "ANY";
|
||||
case NSEC: return "NSEC";
|
||||
case PTR: return "PTR";
|
||||
case SRV: return "SRV";
|
||||
case TXT: return "TXT";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
183
FactoryTestTool/ThirdParty/qmdnsengine/src/hostname.cpp
vendored
Normal file
183
FactoryTestTool/ThirdParty/qmdnsengine/src/hostname.cpp
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QHostInfo>
|
||||
#include <QNetworkAddressEntry>
|
||||
#include <QNetworkInterface>
|
||||
|
||||
#include <qmdnsengine/abstractserver.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/hostname.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
#include "hostname_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
HostnamePrivate::HostnamePrivate(Hostname *hostname, AbstractServer *server)
|
||||
: QObject(hostname),
|
||||
server(server),
|
||||
q(hostname)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &HostnamePrivate::onMessageReceived);
|
||||
connect(®istrationTimer, &QTimer::timeout, this, &HostnamePrivate::onRegistrationTimeout);
|
||||
connect(&rebroadcastTimer, &QTimer::timeout, this, &HostnamePrivate::onRebroadcastTimeout);
|
||||
|
||||
registrationTimer.setInterval(2 * 1000);
|
||||
registrationTimer.setSingleShot(true);
|
||||
|
||||
rebroadcastTimer.setInterval(30 * 60 * 1000);
|
||||
rebroadcastTimer.setSingleShot(true);
|
||||
|
||||
// Immediately assert the hostname
|
||||
onRebroadcastTimeout();
|
||||
}
|
||||
|
||||
void HostnamePrivate::assertHostname()
|
||||
{
|
||||
// Begin with the local hostname and replace any "." with "-" (I'm looking
|
||||
// at you, macOS)
|
||||
QByteArray localHostname = QHostInfo::localHostName().toUtf8();
|
||||
localHostname = localHostname.replace('.', '-');
|
||||
|
||||
// If the suffix > 1, then append a "-2", "-3", etc. to the hostname to
|
||||
// aid in finding one that is unique and not in use
|
||||
hostname = (hostnameSuffix == 1 ? localHostname:
|
||||
localHostname + "-" + QByteArray::number(hostnameSuffix)) + ".local.";
|
||||
|
||||
// Compose a query for A and AAAA records matching the hostname
|
||||
Query ipv4Query;
|
||||
ipv4Query.setName(hostname);
|
||||
ipv4Query.setType(A);
|
||||
Query ipv6Query;
|
||||
ipv6Query.setName(hostname);
|
||||
ipv6Query.setType(AAAA);
|
||||
Message message;
|
||||
message.addQuery(ipv4Query);
|
||||
message.addQuery(ipv6Query);
|
||||
|
||||
server->sendMessageToAll(message);
|
||||
|
||||
// If no reply is received after two seconds, the hostname is available
|
||||
registrationTimer.start();
|
||||
}
|
||||
|
||||
bool HostnamePrivate::generateRecord(const QHostAddress &srcAddress, quint16 type, Record &record)
|
||||
{
|
||||
// Attempt to find the interface that corresponds with the provided
|
||||
// address and determine this device's address from the interface
|
||||
|
||||
const auto interfaces = QNetworkInterface::allInterfaces();
|
||||
for (const QNetworkInterface &networkInterface : interfaces) {
|
||||
const auto entries = networkInterface.addressEntries();
|
||||
for (const QNetworkAddressEntry &entry : entries) {
|
||||
if (srcAddress.isInSubnet(entry.ip(), entry.prefixLength())) {
|
||||
for (const QNetworkAddressEntry &newEntry : entries) {
|
||||
QHostAddress address = newEntry.ip();
|
||||
if ((address.protocol() == QAbstractSocket::IPv4Protocol && type == A) ||
|
||||
(address.protocol() == QAbstractSocket::IPv6Protocol && type == AAAA)) {
|
||||
record.setName(hostname);
|
||||
record.setType(type);
|
||||
record.setAddress(address);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HostnamePrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (message.isResponse()) {
|
||||
if (hostnameRegistered) {
|
||||
return;
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if ((record.type() == A || record.type() == AAAA) && record.name() == hostname) {
|
||||
++hostnameSuffix;
|
||||
assertHostname();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!hostnameRegistered) {
|
||||
return;
|
||||
}
|
||||
Message reply;
|
||||
reply.reply(message);
|
||||
const auto queries = message.queries();
|
||||
for (const Query &query : queries) {
|
||||
if ((query.type() == A || query.type() == AAAA) && query.name() == hostname) {
|
||||
Record record;
|
||||
if (generateRecord(message.address(), query.type(), record)) {
|
||||
reply.addRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reply.records().count()) {
|
||||
server->sendMessage(reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HostnamePrivate::onRegistrationTimeout()
|
||||
{
|
||||
hostnameRegistered = true;
|
||||
if (hostname != hostnamePrev) {
|
||||
emit q->hostnameChanged(hostname);
|
||||
}
|
||||
|
||||
// Re-assert the hostname in half an hour
|
||||
rebroadcastTimer.start();
|
||||
}
|
||||
|
||||
void HostnamePrivate::onRebroadcastTimeout()
|
||||
{
|
||||
hostnamePrev = hostname;
|
||||
hostnameRegistered = false;
|
||||
hostnameSuffix = 1;
|
||||
|
||||
assertHostname();
|
||||
}
|
||||
|
||||
Hostname::Hostname(AbstractServer *server, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new HostnamePrivate(this, server))
|
||||
{
|
||||
}
|
||||
|
||||
bool Hostname::isRegistered() const
|
||||
{
|
||||
return d->hostnameRegistered;
|
||||
}
|
||||
|
||||
QByteArray Hostname::hostname() const
|
||||
{
|
||||
return d->hostname;
|
||||
}
|
||||
75
FactoryTestTool/ThirdParty/qmdnsengine/src/hostname_p.h
vendored
Normal file
75
FactoryTestTool/ThirdParty/qmdnsengine/src/hostname_p.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_HOSTNAME_P_H
|
||||
#define QMDNSENGINE_HOSTNAME_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class QHostAddress;
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Hostname;
|
||||
class Message;
|
||||
class Record;
|
||||
|
||||
class HostnamePrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
HostnamePrivate(Hostname *hostname, AbstractServer *server);
|
||||
|
||||
void assertHostname();
|
||||
bool generateRecord(const QHostAddress &srcAddress, quint16 type, Record &record);
|
||||
|
||||
AbstractServer *server;
|
||||
|
||||
QByteArray hostnamePrev;
|
||||
QByteArray hostname;
|
||||
bool hostnameRegistered;
|
||||
int hostnameSuffix;
|
||||
|
||||
QTimer registrationTimer;
|
||||
QTimer rebroadcastTimer;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onRegistrationTimeout();
|
||||
void onRebroadcastTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Hostname *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_HOSTNAME_P_H
|
||||
35
FactoryTestTool/ThirdParty/qmdnsengine/src/mdns.cpp
vendored
Normal file
35
FactoryTestTool/ThirdParty/qmdnsengine/src/mdns.cpp
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/mdns.h>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
const quint16 MdnsPort = 5353;
|
||||
const QHostAddress MdnsIpv4Address("224.0.0.251");
|
||||
const QHostAddress MdnsIpv6Address("ff02::fb");
|
||||
const QByteArray MdnsBrowseType("_services._dns-sd._udp.local.");
|
||||
|
||||
}
|
||||
148
FactoryTestTool/ThirdParty/qmdnsengine/src/message.cpp
vendored
Normal file
148
FactoryTestTool/ThirdParty/qmdnsengine/src/message.cpp
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/mdns.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
#include "message_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
MessagePrivate::MessagePrivate()
|
||||
: port(0),
|
||||
transactionId(0),
|
||||
isResponse(false),
|
||||
isTruncated(false)
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message()
|
||||
: d(new MessagePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message(const Message &other)
|
||||
: d(new MessagePrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Message &Message::operator=(const Message &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QHostAddress Message::address() const
|
||||
{
|
||||
return d->address;
|
||||
}
|
||||
|
||||
void Message::setAddress(const QHostAddress &address)
|
||||
{
|
||||
d->address = address;
|
||||
}
|
||||
|
||||
quint16 Message::port() const
|
||||
{
|
||||
return d->port;
|
||||
}
|
||||
|
||||
void Message::setPort(quint16 port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
quint16 Message::transactionId() const
|
||||
{
|
||||
return d->transactionId;
|
||||
}
|
||||
|
||||
void Message::setTransactionId(quint16 transactionId)
|
||||
{
|
||||
d->transactionId = transactionId;
|
||||
}
|
||||
|
||||
bool Message::isResponse() const
|
||||
{
|
||||
return d->isResponse;
|
||||
}
|
||||
|
||||
void Message::setResponse(bool isResponse)
|
||||
{
|
||||
d->isResponse = isResponse;
|
||||
}
|
||||
|
||||
bool Message::isTruncated() const
|
||||
{
|
||||
return d->isTruncated;
|
||||
}
|
||||
|
||||
void Message::setTruncated(bool isTruncated)
|
||||
{
|
||||
d->isTruncated = isTruncated;
|
||||
}
|
||||
|
||||
QList<Query> Message::queries() const
|
||||
{
|
||||
return d->queries;
|
||||
}
|
||||
|
||||
void Message::addQuery(const Query &query)
|
||||
{
|
||||
d->queries.append(query);
|
||||
}
|
||||
|
||||
QList<Record> Message::records() const
|
||||
{
|
||||
return d->records;
|
||||
}
|
||||
|
||||
void Message::addRecord(const Record &record)
|
||||
{
|
||||
d->records.append(record);
|
||||
}
|
||||
|
||||
void Message::reply(const Message &other)
|
||||
{
|
||||
if (other.port() == MdnsPort) {
|
||||
if (other.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
setAddress(MdnsIpv4Address);
|
||||
} else {
|
||||
setAddress(MdnsIpv6Address);
|
||||
}
|
||||
} else {
|
||||
setAddress(other.address());
|
||||
}
|
||||
setPort(other.port());
|
||||
setTransactionId(other.transactionId());
|
||||
setResponse(true);
|
||||
}
|
||||
54
FactoryTestTool/ThirdParty/qmdnsengine/src/message_p.h
vendored
Normal file
54
FactoryTestTool/ThirdParty/qmdnsengine/src/message_p.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_MESSAGE_P_H
|
||||
#define QMDNSENGINE_MESSAGE_P_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QList>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Query;
|
||||
class Record;
|
||||
|
||||
class MessagePrivate
|
||||
{
|
||||
public:
|
||||
|
||||
MessagePrivate();
|
||||
|
||||
QHostAddress address;
|
||||
quint16 port;
|
||||
quint16 transactionId;
|
||||
bool isResponse;
|
||||
bool isTruncated;
|
||||
QList<Query> queries;
|
||||
QList<Record> records;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_MESSAGE_P_H
|
||||
107
FactoryTestTool/ThirdParty/qmdnsengine/src/prober.cpp
vendored
Normal file
107
FactoryTestTool/ThirdParty/qmdnsengine/src/prober.cpp
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/abstractserver.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/prober.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
|
||||
#include "prober_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ProberPrivate::ProberPrivate(Prober *prober, AbstractServer *server, const Record &record)
|
||||
: QObject(prober),
|
||||
server(server),
|
||||
confirmed(false),
|
||||
proposedRecord(record),
|
||||
suffix(1),
|
||||
q(prober)
|
||||
{
|
||||
// All records should contain at least one "."
|
||||
int index = record.name().indexOf('.');
|
||||
name = record.name().left(index);
|
||||
type = record.name().mid(index);
|
||||
|
||||
connect(server, &AbstractServer::messageReceived, this, &ProberPrivate::onMessageReceived);
|
||||
connect(&timer, &QTimer::timeout, this, &ProberPrivate::onTimeout);
|
||||
|
||||
timer.setSingleShot(true);
|
||||
|
||||
assertRecord();
|
||||
}
|
||||
|
||||
void ProberPrivate::assertRecord()
|
||||
{
|
||||
// Use the current suffix to set the name of the proposed record
|
||||
QString tmpName = suffix == 1
|
||||
? QString("%1%2").arg(name, type.constData())
|
||||
: QString("%1-%2%3").arg(name.constData(), QByteArray::number(suffix), type);
|
||||
|
||||
proposedRecord.setName(tmpName.toUtf8());
|
||||
|
||||
// Broadcast a query for the proposed name (using an ANY query) and
|
||||
// include the proposed record in the query
|
||||
Query query;
|
||||
query.setName(proposedRecord.name());
|
||||
query.setType(ANY);
|
||||
Message message;
|
||||
message.addQuery(query);
|
||||
message.addRecord(proposedRecord);
|
||||
server->sendMessageToAll(message);
|
||||
|
||||
// Wait two seconds to confirm it is unique
|
||||
timer.stop();
|
||||
timer.start(2 * 1000);
|
||||
}
|
||||
|
||||
void ProberPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
// If the response matches the proposed record, increment the suffix and
|
||||
// try with the new name
|
||||
|
||||
if (confirmed || !message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if (record.name() == proposedRecord.name() && record.type() == proposedRecord.type()) {
|
||||
++suffix;
|
||||
assertRecord();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProberPrivate::onTimeout()
|
||||
{
|
||||
confirmed = true;
|
||||
emit q->nameConfirmed(proposedRecord.name());
|
||||
}
|
||||
|
||||
Prober::Prober(AbstractServer *server, const Record &record, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ProberPrivate(this, server, record))
|
||||
{
|
||||
}
|
||||
72
FactoryTestTool/ThirdParty/qmdnsengine/src/prober_p.h
vendored
Normal file
72
FactoryTestTool/ThirdParty/qmdnsengine/src/prober_p.h
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_PROBER_P_H
|
||||
#define QMDNSENGINE_PROBER_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Message;
|
||||
class Prober;
|
||||
|
||||
class ProberPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ProberPrivate(Prober *prober, AbstractServer *server, const Record &record);
|
||||
|
||||
void assertRecord();
|
||||
|
||||
AbstractServer *server;
|
||||
QTimer timer;
|
||||
|
||||
bool confirmed;
|
||||
|
||||
Record proposedRecord;
|
||||
QByteArray name;
|
||||
QByteArray type;
|
||||
int suffix;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Prober *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_PROBER_P_H
|
||||
235
FactoryTestTool/ThirdParty/qmdnsengine/src/provider.cpp
vendored
Normal file
235
FactoryTestTool/ThirdParty/qmdnsengine/src/provider.cpp
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/abstractserver.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/hostname.h>
|
||||
#include <qmdnsengine/mdns.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/prober.h>
|
||||
#include <qmdnsengine/provider.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
|
||||
#include "provider_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ProviderPrivate::ProviderPrivate(QObject *parent, AbstractServer *server, Hostname *hostname)
|
||||
: QObject(parent),
|
||||
server(server),
|
||||
hostname(hostname),
|
||||
prober(nullptr),
|
||||
initialized(false),
|
||||
confirmed(false)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &ProviderPrivate::onMessageReceived);
|
||||
connect(hostname, &Hostname::hostnameChanged, this, &ProviderPrivate::onHostnameChanged);
|
||||
|
||||
browsePtrProposed.setName(MdnsBrowseType);
|
||||
browsePtrProposed.setType(PTR);
|
||||
ptrProposed.setType(PTR);
|
||||
srvProposed.setType(SRV);
|
||||
txtProposed.setType(TXT);
|
||||
}
|
||||
|
||||
ProviderPrivate::~ProviderPrivate()
|
||||
{
|
||||
if (confirmed) {
|
||||
farewell();
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderPrivate::announce()
|
||||
{
|
||||
// Broadcast a message with each of the records
|
||||
|
||||
Message message;
|
||||
message.setResponse(true);
|
||||
message.addRecord(ptrRecord);
|
||||
message.addRecord(srvRecord);
|
||||
message.addRecord(txtRecord);
|
||||
server->sendMessageToAll(message);
|
||||
}
|
||||
|
||||
void ProviderPrivate::confirm()
|
||||
{
|
||||
// Confirm that the desired name is unique through probing
|
||||
|
||||
if (prober) {
|
||||
delete prober;
|
||||
}
|
||||
prober = new Prober(server, srvProposed, this);
|
||||
connect(prober, &Prober::nameConfirmed, [this](const QByteArray &name) {
|
||||
|
||||
// If existing records were confirmed, indicate that they are no
|
||||
// longer valid
|
||||
if (confirmed) {
|
||||
farewell();
|
||||
} else {
|
||||
confirmed = true;
|
||||
}
|
||||
|
||||
// Update the proposed records
|
||||
ptrProposed.setTarget(name);
|
||||
srvProposed.setName(name);
|
||||
txtProposed.setName(name);
|
||||
|
||||
// Publish the proposed records and announce them
|
||||
publish();
|
||||
|
||||
delete prober;
|
||||
prober = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void ProviderPrivate::farewell()
|
||||
{
|
||||
// Send a message indicating that the existing records are no longer valid
|
||||
// by setting their TTL to 0
|
||||
|
||||
ptrRecord.setTtl(0);
|
||||
srvRecord.setTtl(0);
|
||||
txtRecord.setTtl(0);
|
||||
announce();
|
||||
}
|
||||
|
||||
void ProviderPrivate::publish()
|
||||
{
|
||||
// Copy the proposed records over and announce them
|
||||
|
||||
browsePtrRecord = browsePtrProposed;
|
||||
ptrRecord = ptrProposed;
|
||||
srvRecord = srvProposed;
|
||||
txtRecord = txtProposed;
|
||||
announce();
|
||||
}
|
||||
|
||||
void ProviderPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (!confirmed || message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool sendBrowsePtr = false;
|
||||
bool sendPtr = false;
|
||||
bool sendSrv = false;
|
||||
bool sendTxt = false;
|
||||
|
||||
// Determine which records to send based on the queries
|
||||
const auto queries = message.queries();
|
||||
for (const Query &query : queries) {
|
||||
if (query.type() == PTR && query.name() == MdnsBrowseType) {
|
||||
sendBrowsePtr = true;
|
||||
} else if (query.type() == PTR && query.name() == ptrRecord.name()) {
|
||||
sendPtr = true;
|
||||
} else if (query.type() == SRV && query.name() == srvRecord.name()) {
|
||||
sendSrv = true;
|
||||
} else if (query.type() == TXT && query.name() == txtRecord.name()) {
|
||||
sendTxt = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove records to send if they are already known
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if (record == ptrRecord) {
|
||||
sendPtr = false;
|
||||
} else if (record == srvRecord) {
|
||||
sendSrv = false;
|
||||
} else if (record == txtRecord) {
|
||||
sendTxt = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Include the SRV and TXT if the PTR is being sent
|
||||
if (sendPtr) {
|
||||
sendSrv = sendTxt = true;
|
||||
}
|
||||
|
||||
// If any records should be sent, compose a message reply
|
||||
if (sendBrowsePtr || sendPtr || sendSrv || sendTxt) {
|
||||
Message reply;
|
||||
reply.reply(message);
|
||||
if (sendBrowsePtr) {
|
||||
reply.addRecord(browsePtrRecord);
|
||||
}
|
||||
if (sendPtr) {
|
||||
reply.addRecord(ptrRecord);
|
||||
}
|
||||
if (sendSrv) {
|
||||
reply.addRecord(srvRecord);
|
||||
}
|
||||
if (sendTxt) {
|
||||
reply.addRecord(txtRecord);
|
||||
}
|
||||
server->sendMessage(reply);
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderPrivate::onHostnameChanged(const QByteArray &newHostname)
|
||||
{
|
||||
// Update the proposed SRV record
|
||||
srvProposed.setTarget(newHostname);
|
||||
|
||||
// If initialized, confirm the record
|
||||
if (initialized) {
|
||||
confirm();
|
||||
}
|
||||
}
|
||||
|
||||
Provider::Provider(AbstractServer *server, Hostname *hostname, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ProviderPrivate(this, server, hostname))
|
||||
{
|
||||
}
|
||||
|
||||
void Provider::update(const Service &service)
|
||||
{
|
||||
d->initialized = true;
|
||||
|
||||
// Clean the service name
|
||||
QByteArray serviceName = service.name();
|
||||
serviceName = serviceName.replace('.', '-');
|
||||
|
||||
// Update the proposed records
|
||||
QByteArray fqName = serviceName + "." + service.type();
|
||||
d->browsePtrProposed.setTarget(service.type());
|
||||
d->ptrProposed.setName(service.type());
|
||||
d->ptrProposed.setTarget(fqName);
|
||||
d->srvProposed.setName(fqName);
|
||||
d->srvProposed.setPort(service.port());
|
||||
d->srvProposed.setTarget(d->hostname->hostname());
|
||||
d->txtProposed.setName(fqName);
|
||||
d->txtProposed.setAttributes(service.attributes());
|
||||
|
||||
// Assuming a valid hostname exists, check to see if the new service uses
|
||||
// a different name - if so, it must first be confirmed
|
||||
if (d->hostname->isRegistered()) {
|
||||
if (!d->confirmed || fqName != d->srvRecord.name()) {
|
||||
d->confirm();
|
||||
} else {
|
||||
d->publish();
|
||||
}
|
||||
}
|
||||
}
|
||||
81
FactoryTestTool/ThirdParty/qmdnsengine/src/provider_p.h
vendored
Normal file
81
FactoryTestTool/ThirdParty/qmdnsengine/src/provider_p.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_PROVIDER_P_H
|
||||
#define QMDNSENGINE_PROVIDER_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <qmdnsengine/record.h>
|
||||
#include <qmdnsengine/service.h>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Hostname;
|
||||
class Message;
|
||||
class Prober;
|
||||
|
||||
class ProviderPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ProviderPrivate(QObject *parent, AbstractServer *server, Hostname *hostname);
|
||||
virtual ~ProviderPrivate();
|
||||
|
||||
void announce();
|
||||
void confirm();
|
||||
void farewell();
|
||||
void publish();
|
||||
|
||||
AbstractServer *server;
|
||||
Hostname *hostname;
|
||||
Prober *prober;
|
||||
|
||||
Service service;
|
||||
bool initialized;
|
||||
bool confirmed;
|
||||
|
||||
Record browsePtrRecord;
|
||||
Record ptrRecord;
|
||||
Record srvRecord;
|
||||
Record txtRecord;
|
||||
|
||||
Record browsePtrProposed;
|
||||
Record ptrProposed;
|
||||
Record srvProposed;
|
||||
Record txtProposed;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onHostnameChanged(const QByteArray &hostname);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_PROVIDER_P_H
|
||||
100
FactoryTestTool/ThirdParty/qmdnsengine/src/query.cpp
vendored
Normal file
100
FactoryTestTool/ThirdParty/qmdnsengine/src/query.cpp
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
|
||||
#include "query_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
QueryPrivate::QueryPrivate()
|
||||
: type(0),
|
||||
unicastResponse(false)
|
||||
{
|
||||
}
|
||||
|
||||
Query::Query()
|
||||
: d(new QueryPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Query::Query(const Query &other)
|
||||
: d(new QueryPrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Query &Query::operator=(const Query &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Query::~Query()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QByteArray Query::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Query::setName(const QByteArray &name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
quint16 Query::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Query::setType(quint16 type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
bool Query::unicastResponse() const
|
||||
{
|
||||
return d->unicastResponse;
|
||||
}
|
||||
|
||||
void Query::setUnicastResponse(bool unicastResponse)
|
||||
{
|
||||
d->unicastResponse = unicastResponse;
|
||||
}
|
||||
|
||||
QDebug QMdnsEngine::operator<<(QDebug dbg, const Query &query)
|
||||
{
|
||||
QDebugStateSaver saver(dbg);
|
||||
Q_UNUSED(saver);
|
||||
|
||||
dbg.noquote().nospace() << "Query(" << typeName(query.type()) << " " << query.name() << ")";
|
||||
|
||||
return dbg;
|
||||
}
|
||||
46
FactoryTestTool/ThirdParty/qmdnsengine/src/query_p.h
vendored
Normal file
46
FactoryTestTool/ThirdParty/qmdnsengine/src/query_p.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_QUERY_P_H
|
||||
#define QMDNSENGINE_QUERY_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class QueryPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
QueryPrivate();
|
||||
|
||||
QByteArray name;
|
||||
quint16 type;
|
||||
bool unicastResponse;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_QUERY_P_H
|
||||
218
FactoryTestTool/ThirdParty/qmdnsengine/src/record.cpp
vendored
Normal file
218
FactoryTestTool/ThirdParty/qmdnsengine/src/record.cpp
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
#include "record_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
RecordPrivate::RecordPrivate()
|
||||
: type(0),
|
||||
flushCache(false),
|
||||
ttl(3600),
|
||||
priority(0),
|
||||
weight(0),
|
||||
port(0)
|
||||
{
|
||||
}
|
||||
|
||||
Record::Record()
|
||||
: d(new RecordPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Record::Record(const Record &other)
|
||||
: d(new RecordPrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Record &Record::operator=(const Record &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Record::operator==(const Record &other) const
|
||||
{
|
||||
return d->name == other.d->name &&
|
||||
d->type == other.d->type &&
|
||||
d->address == other.d->address &&
|
||||
d->target == other.d->target &&
|
||||
d->nextDomainName == other.d->nextDomainName &&
|
||||
d->priority == other.d->priority &&
|
||||
d->weight == other.d->weight &&
|
||||
d->port == other.d->port &&
|
||||
d->attributes == other.d->attributes &&
|
||||
d->bitmap == other.d->bitmap;
|
||||
}
|
||||
|
||||
bool Record::operator!=(const Record &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
Record::~Record()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QByteArray Record::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Record::setName(const QByteArray &name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
quint16 Record::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Record::setType(quint16 type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
bool Record::flushCache() const
|
||||
{
|
||||
return d->flushCache;
|
||||
}
|
||||
|
||||
void Record::setFlushCache(bool flushCache)
|
||||
{
|
||||
d->flushCache = flushCache;
|
||||
}
|
||||
|
||||
quint32 Record::ttl() const
|
||||
{
|
||||
return d->ttl;
|
||||
}
|
||||
|
||||
void Record::setTtl(quint32 ttl)
|
||||
{
|
||||
d->ttl = ttl;
|
||||
}
|
||||
|
||||
QHostAddress Record::address() const
|
||||
{
|
||||
return d->address;
|
||||
}
|
||||
|
||||
void Record::setAddress(const QHostAddress &address)
|
||||
{
|
||||
d->address = address;
|
||||
}
|
||||
|
||||
QByteArray Record::target() const
|
||||
{
|
||||
return d->target;
|
||||
}
|
||||
|
||||
void Record::setTarget(const QByteArray &target)
|
||||
{
|
||||
d->target = target;
|
||||
}
|
||||
|
||||
QByteArray Record::nextDomainName() const
|
||||
{
|
||||
return d->nextDomainName;
|
||||
}
|
||||
|
||||
void Record::setNextDomainName(const QByteArray &nextDomainName)
|
||||
{
|
||||
d->nextDomainName = nextDomainName;
|
||||
}
|
||||
|
||||
quint16 Record::priority() const
|
||||
{
|
||||
return d->priority;
|
||||
}
|
||||
|
||||
void Record::setPriority(quint16 priority)
|
||||
{
|
||||
d->priority = priority;
|
||||
}
|
||||
|
||||
quint16 Record::weight() const
|
||||
{
|
||||
return d->weight;
|
||||
}
|
||||
|
||||
void Record::setWeight(quint16 weight)
|
||||
{
|
||||
d->weight = weight;
|
||||
}
|
||||
|
||||
quint16 Record::port() const
|
||||
{
|
||||
return d->port;
|
||||
}
|
||||
|
||||
void Record::setPort(quint16 port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
QMap<QByteArray, QByteArray> Record::attributes() const
|
||||
{
|
||||
return d->attributes;
|
||||
}
|
||||
|
||||
void Record::setAttributes(const QMap<QByteArray, QByteArray> &attributes)
|
||||
{
|
||||
d->attributes = attributes;
|
||||
}
|
||||
|
||||
void Record::addAttribute(const QByteArray &key, const QByteArray &value)
|
||||
{
|
||||
d->attributes.insert(key, value);
|
||||
}
|
||||
|
||||
Bitmap Record::bitmap() const
|
||||
{
|
||||
return d->bitmap;
|
||||
}
|
||||
|
||||
void Record::setBitmap(const Bitmap &bitmap)
|
||||
{
|
||||
d->bitmap = bitmap;
|
||||
}
|
||||
|
||||
QDebug QMdnsEngine::operator<<(QDebug dbg, const Record &record)
|
||||
{
|
||||
QDebugStateSaver saver(dbg);
|
||||
Q_UNUSED(saver);
|
||||
|
||||
dbg.noquote().nospace() << "Record(" << typeName(record.type()) << " " << record.name() << ")";
|
||||
|
||||
return dbg;
|
||||
}
|
||||
59
FactoryTestTool/ThirdParty/qmdnsengine/src/record_p.h
vendored
Normal file
59
FactoryTestTool/ThirdParty/qmdnsengine/src/record_p.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_RECORD_P_H
|
||||
#define QMDNSENGINE_RECORD_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHostAddress>
|
||||
#include <QMap>
|
||||
|
||||
#include <qmdnsengine/bitmap.h>
|
||||
|
||||
namespace QMdnsEngine {
|
||||
|
||||
class RecordPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
RecordPrivate();
|
||||
|
||||
QByteArray name;
|
||||
quint16 type;
|
||||
bool flushCache;
|
||||
quint32 ttl;
|
||||
|
||||
QHostAddress address;
|
||||
QByteArray target;
|
||||
QByteArray nextDomainName;
|
||||
quint16 priority;
|
||||
quint16 weight;
|
||||
quint16 port;
|
||||
QMap<QByteArray, QByteArray> attributes;
|
||||
Bitmap bitmap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_RECORD_P_H
|
||||
116
FactoryTestTool/ThirdParty/qmdnsengine/src/resolver.cpp
vendored
Normal file
116
FactoryTestTool/ThirdParty/qmdnsengine/src/resolver.cpp
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <qmdnsengine/abstractserver.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/cache.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/query.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
#include <qmdnsengine/resolver.h>
|
||||
|
||||
#include "resolver_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ResolverPrivate::ResolverPrivate(Resolver *resolver, AbstractServer *server, const QByteArray &name, Cache *cache)
|
||||
: QObject(resolver),
|
||||
server(server),
|
||||
name(name),
|
||||
cache(cache ? cache : new Cache(this)),
|
||||
q(resolver)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &ResolverPrivate::onMessageReceived);
|
||||
connect(&timer, &QTimer::timeout, this, &ResolverPrivate::onTimeout);
|
||||
|
||||
// Query for new records
|
||||
query();
|
||||
|
||||
// Pull the existing records from the cache
|
||||
timer.setSingleShot(true);
|
||||
timer.start(0);
|
||||
}
|
||||
|
||||
QList<Record> ResolverPrivate::existing() const
|
||||
{
|
||||
QList<Record> records;
|
||||
cache->lookupRecords(name, A, records);
|
||||
cache->lookupRecords(name, AAAA, records);
|
||||
return records;
|
||||
}
|
||||
|
||||
void ResolverPrivate::query() const
|
||||
{
|
||||
Message message;
|
||||
|
||||
// Add a query for A and AAAA records
|
||||
Query query;
|
||||
query.setName(name);
|
||||
query.setType(A);
|
||||
message.addQuery(query);
|
||||
query.setType(AAAA);
|
||||
message.addQuery(query);
|
||||
|
||||
// Add existing (known) records to the query
|
||||
const auto records = existing();
|
||||
for (const Record &record : records) {
|
||||
message.addRecord(record);
|
||||
}
|
||||
|
||||
// Send the query
|
||||
server->sendMessageToAll(message);
|
||||
}
|
||||
|
||||
void ResolverPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (!message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if (record.name() == name && (record.type() == A || record.type() == AAAA)) {
|
||||
cache->addRecord(record);
|
||||
if (!addresses.contains(record.address())) {
|
||||
emit q->resolved(record.address());
|
||||
addresses.insert(record.address());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResolverPrivate::onTimeout()
|
||||
{
|
||||
const auto records = existing();
|
||||
for (const Record &record : records) {
|
||||
emit q->resolved(record.address());
|
||||
}
|
||||
}
|
||||
|
||||
Resolver::Resolver(AbstractServer *server, const QByteArray &name, Cache *cache, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ResolverPrivate(this, server, name, cache))
|
||||
{
|
||||
}
|
||||
71
FactoryTestTool/ThirdParty/qmdnsengine/src/resolver_p.h
vendored
Normal file
71
FactoryTestTool/ThirdParty/qmdnsengine/src/resolver_p.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_RESOLVER_P_H
|
||||
#define QMDNSENGINE_RESOLVER_P_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Cache;
|
||||
class Message;
|
||||
class Record;
|
||||
class Resolver;
|
||||
|
||||
class ResolverPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ResolverPrivate(Resolver *resolver, AbstractServer *server, const QByteArray &name, Cache *cache);
|
||||
|
||||
QList<Record> existing() const;
|
||||
void query() const;
|
||||
|
||||
AbstractServer *server;
|
||||
QByteArray name;
|
||||
Cache *cache;
|
||||
QSet<QHostAddress> addresses;
|
||||
QTimer timer;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Resolver *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_RESOLVER_P_H
|
||||
159
FactoryTestTool/ThirdParty/qmdnsengine/src/server.cpp
vendored
Normal file
159
FactoryTestTool/ThirdParty/qmdnsengine/src/server.cpp
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
# include <cerrno>
|
||||
# include <cstring>
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QNetworkInterface>
|
||||
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/mdns.h>
|
||||
#include <qmdnsengine/message.h>
|
||||
#include <qmdnsengine/server.h>
|
||||
|
||||
#include "server_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ServerPrivate::ServerPrivate(Server *server)
|
||||
: QObject(server),
|
||||
q(server)
|
||||
{
|
||||
connect(&timer, &QTimer::timeout, this, &ServerPrivate::onTimeout);
|
||||
connect(&ipv4Socket, &QUdpSocket::readyRead, this, &ServerPrivate::onReadyRead);
|
||||
connect(&ipv6Socket, &QUdpSocket::readyRead, this, &ServerPrivate::onReadyRead);
|
||||
|
||||
timer.setInterval(60 * 1000);
|
||||
timer.setSingleShot(true);
|
||||
onTimeout();
|
||||
}
|
||||
|
||||
bool ServerPrivate::bindSocket(QUdpSocket &socket, const QHostAddress &address)
|
||||
{
|
||||
// Exit early if the socket is already bound
|
||||
if (socket.state() == QAbstractSocket::BoundState) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// I cannot find the correct combination of flags that allows the socket
|
||||
// to bind properly on Linux, so on that platform, we must manually create
|
||||
// the socket and initialize the QUdpSocket with it
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
if (!socket.bind(address, MdnsPort, QAbstractSocket::ShareAddress)) {
|
||||
int arg = 1;
|
||||
if (setsockopt(socket.socketDescriptor(), SOL_SOCKET, SO_REUSEADDR,
|
||||
reinterpret_cast<char*>(&arg), sizeof(int))) {
|
||||
emit q->error(strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (!socket.bind(address, MdnsPort, QAbstractSocket::ReuseAddressHint)) {
|
||||
emit q->error(socket.errorString());
|
||||
return false;
|
||||
}
|
||||
#ifdef Q_OS_UNIX
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServerPrivate::onTimeout()
|
||||
{
|
||||
// A timer is used to run a set of operations once per minute; first, the
|
||||
// two sockets are bound - if this fails, another attempt is made once per
|
||||
// timeout; secondly, all network interfaces are enumerated; if the
|
||||
// interface supports multicast, the socket will join the mDNS multicast
|
||||
// groups
|
||||
|
||||
bool ipv4Bound = bindSocket(ipv4Socket, QHostAddress::AnyIPv4);
|
||||
bool ipv6Bound = bindSocket(ipv6Socket, QHostAddress::AnyIPv6);
|
||||
|
||||
if (ipv4Bound || ipv6Bound) {
|
||||
const auto interfaces = QNetworkInterface::allInterfaces();
|
||||
for (const QNetworkInterface &networkInterface : interfaces) {
|
||||
if (networkInterface.flags() & QNetworkInterface::CanMulticast) {
|
||||
if (ipv4Bound) {
|
||||
ipv4Socket.joinMulticastGroup(MdnsIpv4Address, networkInterface);
|
||||
}
|
||||
if (ipv6Bound) {
|
||||
ipv6Socket.joinMulticastGroup(MdnsIpv6Address, networkInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timer.start();
|
||||
}
|
||||
|
||||
void ServerPrivate::onReadyRead()
|
||||
{
|
||||
// Read the packet from the socket
|
||||
QUdpSocket *socket = qobject_cast<QUdpSocket*>(sender());
|
||||
QByteArray packet;
|
||||
packet.resize(socket->pendingDatagramSize());
|
||||
QHostAddress address;
|
||||
quint16 port;
|
||||
socket->readDatagram(packet.data(), packet.size(), &address, &port);
|
||||
|
||||
// Attempt to decode the packet
|
||||
Message message;
|
||||
if (fromPacket(packet, message)) {
|
||||
message.setAddress(address);
|
||||
message.setPort(port);
|
||||
emit q->messageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
Server::Server(QObject *parent)
|
||||
: AbstractServer(parent),
|
||||
d(new ServerPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
void Server::sendMessage(const Message &message)
|
||||
{
|
||||
QByteArray packet;
|
||||
toPacket(message, packet);
|
||||
if (message.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
d->ipv4Socket.writeDatagram(packet, message.address(), message.port());
|
||||
} else {
|
||||
d->ipv6Socket.writeDatagram(packet, message.address(), message.port());
|
||||
}
|
||||
}
|
||||
|
||||
void Server::sendMessageToAll(const Message &message)
|
||||
{
|
||||
QByteArray packet;
|
||||
toPacket(message, packet);
|
||||
d->ipv4Socket.writeDatagram(packet, MdnsIpv4Address, MdnsPort);
|
||||
d->ipv6Socket.writeDatagram(packet, MdnsIpv6Address, MdnsPort);
|
||||
}
|
||||
65
FactoryTestTool/ThirdParty/qmdnsengine/src/server_p.h
vendored
Normal file
65
FactoryTestTool/ThirdParty/qmdnsengine/src/server_p.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_SERVER_P_H
|
||||
#define QMDNSENGINE_SERVER_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QUdpSocket>
|
||||
|
||||
class QHostAddress;
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Server;
|
||||
|
||||
class ServerPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ServerPrivate(Server *server);
|
||||
|
||||
bool bindSocket(QUdpSocket &socket, const QHostAddress &address);
|
||||
|
||||
QTimer timer;
|
||||
QUdpSocket ipv4Socket;
|
||||
QUdpSocket ipv6Socket;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onTimeout();
|
||||
void onReadyRead();
|
||||
|
||||
private:
|
||||
|
||||
Server *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_SERVER_P_H
|
||||
139
FactoryTestTool/ThirdParty/qmdnsengine/src/service.cpp
vendored
Normal file
139
FactoryTestTool/ThirdParty/qmdnsengine/src/service.cpp
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <qmdnsengine/service.h>
|
||||
|
||||
#include "service_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ServicePrivate::ServicePrivate()
|
||||
{
|
||||
}
|
||||
|
||||
Service::Service()
|
||||
: d(new ServicePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Service::Service(const Service &other)
|
||||
: d(new ServicePrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Service &Service::operator=(const Service &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Service::operator==(const Service &other) const
|
||||
{
|
||||
return d->type == other.d->type &&
|
||||
d->name == other.d->name &&
|
||||
d->port == other.d->port &&
|
||||
d->attributes == other.d->attributes;
|
||||
}
|
||||
|
||||
bool Service::operator!=(const Service &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
Service::~Service()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QByteArray Service::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Service::setType(const QByteArray &type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
QByteArray Service::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Service::setName(const QByteArray &name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
QByteArray Service::hostname() const
|
||||
{
|
||||
return d->hostname;
|
||||
}
|
||||
|
||||
void Service::setHostname(const QByteArray &hostname)
|
||||
{
|
||||
d->hostname = hostname;
|
||||
}
|
||||
|
||||
quint16 Service::port() const
|
||||
{
|
||||
return d->port;
|
||||
}
|
||||
|
||||
void Service::setPort(quint16 port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
QMap<QByteArray, QByteArray> Service::attributes() const
|
||||
{
|
||||
return d->attributes;
|
||||
}
|
||||
|
||||
void Service::setAttributes(const QMap<QByteArray, QByteArray> &attributes)
|
||||
{
|
||||
d->attributes = attributes;
|
||||
}
|
||||
|
||||
void Service::addAttribute(const QByteArray &key, const QByteArray &value)
|
||||
{
|
||||
d->attributes.insert(key, value);
|
||||
}
|
||||
|
||||
QDebug QMdnsEngine::operator<<(QDebug debug, const Service &service)
|
||||
{
|
||||
QDebugStateSaver saver(debug);
|
||||
Q_UNUSED(saver);
|
||||
|
||||
debug.noquote().nospace()
|
||||
<< "Service(name: " << service.name()
|
||||
<< ", type: " << service.type()
|
||||
<< ", hostname: " << service.hostname()
|
||||
<< ", port: " << service.port()
|
||||
<< ", attributes: " << service.attributes()
|
||||
<< ")";
|
||||
|
||||
return debug;
|
||||
}
|
||||
49
FactoryTestTool/ThirdParty/qmdnsengine/src/service_p.h
vendored
Normal file
49
FactoryTestTool/ThirdParty/qmdnsengine/src/service_p.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_SERVICE_P_H
|
||||
#define QMDNSENGINE_SERVICE_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class ServicePrivate
|
||||
{
|
||||
public:
|
||||
|
||||
ServicePrivate();
|
||||
|
||||
QByteArray type;
|
||||
QByteArray name;
|
||||
QByteArray hostname;
|
||||
quint16 port;
|
||||
QMap<QByteArray, QByteArray> attributes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_SERVICE_P_H
|
||||
Reference in New Issue
Block a user