From befbd1552381e9dc486a6d81455d846373e296a2 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 3 Oct 2024 23:20:55 +0200 Subject: [PATCH 1/4] Allow to select Qt version via QT_DIR --- CMakeLists.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b348de5..88c1666 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,18 +30,26 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) -find_package(Qt6 QUIET COMPONENTS Core NO_SYSTEM_ENVIRONMENT_PATH) +if (NOT QT_DIR) + find_package(Qt6 QUIET COMPONENTS Core) + set(QT_DIR "${Qt6_DIR}") +endif() + +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core) -if (Qt6_FOUND) +if (QT_VERSION_MAJOR EQUAL 6) find_package(Qt6 REQUIRED COMPONENTS Network Test) find_package(Qt6 QUIET COMPONENTS Zlib) set(Qt_DIR ${QT6_INSTALL_PREFIX}) set(Qt_VERSION ${Qt6_VERSION}) -else() +elseif (QT_VERSION_MAJOR EQUAL 5) find_package(Qt5 5.15 REQUIRED COMPONENTS Network Test) find_package(Qt5 QUIET COMPONENTS Zlib) set(Qt_VERSION ${Qt5_VERSION}) set(Qt_DIR ${Qt5_DIR}) +else() + message(FATAL_ERROR "Could not find Qt") + return() endif() message(STATUS "Using Qt ${Qt_VERSION} from ${Qt_DIR}") From ca47a6f0fc86b9957419e31cb6dd252d25332bf6 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 3 Oct 2024 13:27:21 +0200 Subject: [PATCH 2/4] Sanitize filenames in QncCore library --- http/httpparser.cpp | 8 +- http/httpparser.h | 2 +- mdns/mdnsresolver.cpp | 2 +- mdns/mdnsresolver.h | 2 +- mdns/mdnsresolverdemo.cpp | 2 +- mdns/mdnsurlfinder.cpp | 2 +- qnc/CMakeLists.txt | 15 +-- qnc/abstractresolver.cpp | 101 ++++++++++++++++++ qnc/abstractresolver.h | 57 ++++++++++ qnc/{qncliterals.cpp => literals.cpp} | 8 +- qnc/{qncliterals.h => literals.h} | 14 +-- ...{qncresolver.cpp => multicastresolver.cpp} | 87 +-------------- qnc/multicastresolver.h | 51 +++++++++ qnc/{qncparse.cpp => parse.cpp} | 10 +- qnc/{qncparse.h => parse.h} | 12 +-- qnc/qncresolver.h | 96 ----------------- ssdp/ssdpresolver.cpp | 2 +- ssdp/ssdpresolver.h | 2 +- ssdp/ssdpresolverdemo.cpp | 2 +- tests/auto/CMakeLists.txt | 2 +- .../{tst_qncparse.cpp => tst_coreparse.cpp} | 6 +- tests/auto/tst_httpparser.cpp | 4 +- tests/auto/tst_mdnsmessages.cpp | 4 +- tests/auto/tst_mdnsresolver.cpp | 2 +- tests/auto/tst_ssdpresolver.cpp | 2 +- tests/auto/tst_xmlparser.cpp | 4 +- xml/xmlparser.cpp | 8 +- 27 files changed, 270 insertions(+), 237 deletions(-) create mode 100644 qnc/abstractresolver.cpp create mode 100644 qnc/abstractresolver.h rename qnc/{qncliterals.cpp => literals.cpp} (54%) rename qnc/{qncliterals.h => literals.h} (93%) rename qnc/{qncresolver.cpp => multicastresolver.cpp} (66%) create mode 100644 qnc/multicastresolver.h rename qnc/{qncparse.cpp => parse.cpp} (95%) rename qnc/{qncparse.h => parse.h} (95%) delete mode 100644 qnc/qncresolver.h rename tests/auto/{tst_qncparse.cpp => tst_coreparse.cpp} (99%) diff --git a/http/httpparser.cpp b/http/httpparser.cpp index d5cc68f..31c44e7 100644 --- a/http/httpparser.cpp +++ b/http/httpparser.cpp @@ -4,8 +4,8 @@ #include "httpparser.h" // QtNetworkCrumbs headers -#include "qncliterals.h" -#include "qncparse.h" +#include "literals.h" +#include "parse.h" // Qt headers #include @@ -99,7 +99,7 @@ QByteArray Message::resource() const std::optional Message::statusCode() const { - return qnc::parse(statusField(Type::Response, 1)); + return core::parse(statusField(Type::Response, 1)); } QByteArray Message::statusPhrase() const @@ -196,7 +196,7 @@ QDateTime expiryDateTime(const QByteArray &cacheControl, const QByteArray &expir maxAge != cacheControlList.cend()) { const auto &value = suffixView(*maxAge, s_cacheControlMaxAge.length()); - if (const auto seconds = qnc::parse(value)) + if (const auto seconds = core::parse(value)) return now.addSecs(*seconds); } diff --git a/http/httpparser.h b/http/httpparser.h index 9dac99e..ab38e74 100644 --- a/http/httpparser.h +++ b/http/httpparser.h @@ -5,7 +5,7 @@ #define QNC_HTTPPARSER_H // QtNetworkCrumbs headers -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/mdns/mdnsresolver.cpp b/mdns/mdnsresolver.cpp index 30e655d..52053a2 100755 --- a/mdns/mdnsresolver.cpp +++ b/mdns/mdnsresolver.cpp @@ -6,7 +6,7 @@ // QtNetworkCrumbs headers #include "mdnsmessage.h" #include "mdnsurlfinder.h" -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/mdns/mdnsresolver.h b/mdns/mdnsresolver.h index b94195e..6d97ca4 100755 --- a/mdns/mdnsresolver.h +++ b/mdns/mdnsresolver.h @@ -4,7 +4,7 @@ #ifndef QNCMDNS_MDNSRESOLVER_H #define QNCMDNS_MDNSRESOLVER_H -#include "qncresolver.h" +#include "multicastresolver.h" class QHostAddress; class QNetworkDatagram; diff --git a/mdns/mdnsresolverdemo.cpp b/mdns/mdnsresolverdemo.cpp index c0c6464..283158c 100644 --- a/mdns/mdnsresolverdemo.cpp +++ b/mdns/mdnsresolverdemo.cpp @@ -5,7 +5,7 @@ // QtNetworkCrumbs headers #include "mdnsmessage.h" #include "mdnsresolver.h" -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/mdns/mdnsurlfinder.cpp b/mdns/mdnsurlfinder.cpp index 93a611c..726063d 100644 --- a/mdns/mdnsurlfinder.cpp +++ b/mdns/mdnsurlfinder.cpp @@ -5,7 +5,7 @@ // QtNetworkCrumbs headers #include "mdnsresolver.h" -#include "qncliterals.h" +#include "literals.h" namespace qnc::mdns { namespace { diff --git a/qnc/CMakeLists.txt b/qnc/CMakeLists.txt index 75c365f..4cd30ca 100644 --- a/qnc/CMakeLists.txt +++ b/qnc/CMakeLists.txt @@ -1,11 +1,14 @@ qnc_add_library( QncCore STATIC - qncliterals.cpp - qncliterals.h - qncparse.cpp - qncparse.h - qncresolver.cpp - qncresolver.h + + abstractresolver.cpp + abstractresolver.h + literals.cpp + literals.h + multicastresolver.cpp + multicastresolver.h + parse.cpp + parse.h ) target_link_libraries(QncCore PUBLIC Qt::Network) diff --git a/qnc/abstractresolver.cpp b/qnc/abstractresolver.cpp new file mode 100644 index 0000000..06ad8d4 --- /dev/null +++ b/qnc/abstractresolver.cpp @@ -0,0 +1,101 @@ +/* QtNetworkCrumbs - Some networking toys for Qt + * Copyright (C) 2019-2024 Mathias Hasselmann + */ +#include "abstractresolver.h" + +// Qt headers +#include +#include +#include +#include + +namespace qnc::core { + +namespace { + +using namespace std::chrono_literals; + +Q_LOGGING_CATEGORY(lcResolver, "qnc.core.resolver") + +} // namespace + +AbstractResolver::AbstractResolver(QObject *parent) + : QObject{parent} + , m_timer{new QTimer{this}} +{ + m_timer->callOnTimeout(this, &AbstractResolver::onTimeout); + QTimer::singleShot(0, this, &AbstractResolver::onTimeout); + m_timer->start(15s); +} + +void AbstractResolver::setScanInterval(std::chrono::milliseconds ms) +{ + if (scanIntervalAsDuration() != ms) { + m_timer->setInterval(ms); + emit scanIntervalChanged(scanInterval()); + } +} + +void AbstractResolver::setScanInterval(int ms) +{ + if (scanInterval() != ms) { + m_timer->setInterval(ms); + emit scanIntervalChanged(scanInterval()); + } +} + +std::chrono::milliseconds AbstractResolver::scanIntervalAsDuration() const +{ + return m_timer->intervalAsDuration(); +} + +int AbstractResolver::scanInterval() const +{ + return m_timer->interval(); +} + +AbstractResolver::SocketPointer +AbstractResolver::socketForAddress(const QHostAddress &address) const +{ + return m_sockets[address]; +} + +void AbstractResolver::scanNetworkInterfaces() +{ + auto newSockets = SocketTable{}; + + const auto &allInterfaces = QNetworkInterface::allInterfaces(); + + for (const auto &iface : allInterfaces) { + if (!isSupportedInterface(iface)) + continue; + + const auto addressEntries = iface.addressEntries(); + for (const auto &entry : addressEntries) { + if (!isSupportedAddress(entry.ip())) + continue; + + if (const auto socket = socketForAddress(entry.ip())) { + newSockets.insert(entry.ip(), socket); + continue; + } + + qCInfo(lcResolver, "Creating socket for %ls on %ls", + qUtf16Printable(entry.ip().toString()), + qUtf16Printable(iface.humanReadableName())); + + if (const auto socket = createSocket(iface, entry.ip())) + newSockets.insert(entry.ip(), socket); + } + } + + std::exchange(m_sockets, newSockets); +} + +void AbstractResolver::onTimeout() +{ + scanNetworkInterfaces(); + submitQueries(m_sockets); +} + +} // namespace qnc diff --git a/qnc/abstractresolver.h b/qnc/abstractresolver.h new file mode 100644 index 0000000..fa2e228 --- /dev/null +++ b/qnc/abstractresolver.h @@ -0,0 +1,57 @@ +/* QtNetworkCrumbs - Some networking toys for Qt + * Copyright (C) 2019-2024 Mathias Hasselmann + */ +#ifndef QNCCORE_ABSTRACTRESOLVER_H +#define QNCCORE_ABSTRACTRESOLVER_H + +#include +#include + +class QNetworkInterface; +class QTimer; + +namespace qnc::core { + +class AbstractResolver : public QObject +{ + Q_OBJECT + Q_PROPERTY(int scanInterval READ scanInterval WRITE setScanInterval NOTIFY scanIntervalChanged FINAL) + +public: + AbstractResolver(QObject *parent = nullptr); + + [[nodiscard]] int scanInterval() const; + [[nodiscard]] std::chrono::milliseconds scanIntervalAsDuration() const; + void setScanInterval(std::chrono::milliseconds ms); + +public slots: + void setScanInterval(int ms); + +signals: + void scanIntervalChanged(int interval); + +protected: + using SocketPointer = std::shared_ptr; + using SocketTable = QHash; + + [[nodiscard]] virtual bool isSupportedInterface(const QNetworkInterface &iface) const = 0; + [[nodiscard]] virtual bool isSupportedAddress(const QHostAddress &address) const = 0; + + [[nodiscard]] virtual SocketPointer createSocket(const QNetworkInterface &iface, + const QHostAddress &address) = 0; + + [[nodiscard]] SocketPointer socketForAddress(const QHostAddress &address) const; + + virtual void submitQueries(const SocketTable &sockets) = 0; + +private: + void onTimeout(); + void scanNetworkInterfaces(); + + QTimer *const m_timer; + SocketTable m_sockets; +}; + +} // namespace qnc::core + +#endif // QNCCORE_ABSTRACTRESOLVER_H diff --git a/qnc/qncliterals.cpp b/qnc/literals.cpp similarity index 54% rename from qnc/qncliterals.cpp rename to qnc/literals.cpp index 659bea7..12a578d 100644 --- a/qnc/qncliterals.cpp +++ b/qnc/literals.cpp @@ -1,9 +1,9 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ -#include "qncliterals.h" +#include "literals.h" -namespace qnc { +namespace qnc::core { static_assert('*'_L1.unicode() == 42); static_assert("constexpr"_L1.size() == 9); -} // namespace qnc +} // namespace qnc::core diff --git a/qnc/qncliterals.h b/qnc/literals.h similarity index 93% rename from qnc/qncliterals.h rename to qnc/literals.h index 31287ab..b8512a4 100644 --- a/qnc/qncliterals.h +++ b/qnc/literals.h @@ -1,15 +1,15 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ -#ifndef QNC_QNCLITERALS_H -#define QNC_QNCLITERALS_H +#ifndef QNCCORE_LITERALS_H +#define QNCCORE_LITERALS_H #include #include #include namespace qnc { -namespace literals { +namespace core::literals { namespace compat { #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) @@ -118,10 +118,10 @@ inline auto operator ""_hex(const char *str, std::size_t len) return QByteArray::fromHex({str, static_cast(len)}); } -} // namespace literals +} // namespace core::literals -using namespace literals; +using namespace core::literals; } // namespace qnc -#endif // QNC_QNCLITERALS_H +#endif // QNCCORE_LITERALS_H diff --git a/qnc/qncresolver.cpp b/qnc/multicastresolver.cpp similarity index 66% rename from qnc/qncresolver.cpp rename to qnc/multicastresolver.cpp index f94462f..bbd44b3 100644 --- a/qnc/qncresolver.cpp +++ b/qnc/multicastresolver.cpp @@ -1,13 +1,12 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ -#include "qncresolver.h" +#include "multicastresolver.h" // Qt headers #include #include #include -#include #include #include @@ -15,9 +14,6 @@ namespace qnc::core { namespace { -using namespace std::chrono_literals; - -Q_LOGGING_CATEGORY(lcResolver, "qnc.core.resolver") Q_LOGGING_CATEGORY(lcMulticast, "qnc.core.resolver.multicast") QHostAddress wildcardAddress(const QHostAddress &address) @@ -40,85 +36,6 @@ QHostAddress wildcardAddress(const QHostAddress &address) } // namespace -GenericResolver::GenericResolver(QObject *parent) - : QObject{parent} - , m_timer{new QTimer{this}} -{ - m_timer->callOnTimeout(this, &GenericResolver::onTimeout); - QTimer::singleShot(0, this, &GenericResolver::onTimeout); - m_timer->start(15s); -} - -void GenericResolver::setScanInterval(std::chrono::milliseconds ms) -{ - if (scanIntervalAsDuration() != ms) { - m_timer->setInterval(ms); - emit scanIntervalChanged(scanInterval()); - } -} - -void GenericResolver::setScanInterval(int ms) -{ - if (scanInterval() != ms) { - m_timer->setInterval(ms); - emit scanIntervalChanged(scanInterval()); - } -} - -std::chrono::milliseconds GenericResolver::scanIntervalAsDuration() const -{ - return m_timer->intervalAsDuration(); -} - -int GenericResolver::scanInterval() const -{ - return m_timer->interval(); -} - -GenericResolver::SocketPointer -GenericResolver::socketForAddress(const QHostAddress &address) const -{ - return m_sockets[address]; -} - -void GenericResolver::scanNetworkInterfaces() -{ - auto newSockets = SocketTable{}; - - const auto &allInterfaces = QNetworkInterface::allInterfaces(); - - for (const auto &iface : allInterfaces) { - if (!isSupportedInterface(iface)) - continue; - - const auto addressEntries = iface.addressEntries(); - for (const auto &entry : addressEntries) { - if (!isSupportedAddress(entry.ip())) - continue; - - if (const auto socket = socketForAddress(entry.ip())) { - newSockets.insert(entry.ip(), socket); - continue; - } - - qCInfo(lcResolver, "Creating socket for %ls on %ls", - qUtf16Printable(entry.ip().toString()), - qUtf16Printable(iface.humanReadableName())); - - if (const auto socket = createSocket(iface, entry.ip())) - newSockets.insert(entry.ip(), socket); - } - } - - std::exchange(m_sockets, newSockets); -} - -void GenericResolver::onTimeout() -{ - scanNetworkInterfaces(); - submitQueries(m_sockets); -} - bool MulticastResolver::isSupportedInterface(const QNetworkInterface &iface) const { return isSupportedInterfaceType(iface) diff --git a/qnc/multicastresolver.h b/qnc/multicastresolver.h new file mode 100644 index 0000000..ca0bc11 --- /dev/null +++ b/qnc/multicastresolver.h @@ -0,0 +1,51 @@ +/* QtNetworkCrumbs - Some networking toys for Qt + * Copyright (C) 2019-2024 Mathias Hasselmann + */ +#ifndef QNCCORE_UNICASTRESOLVER_H +#define QNCCORE_UNICASTRESOLVER_H + +#include "abstractresolver.h" + +class QNetworkDatagram; +class QUdpSocket; + +namespace qnc::core { + +class MulticastResolver : public AbstractResolver +{ + Q_OBJECT + +public: + using AbstractResolver::AbstractResolver; + +protected: + [[nodiscard]] bool isSupportedInterface(const QNetworkInterface &iface) const override; + [[nodiscard]] bool isSupportedAddress(const QHostAddress &address) const override; + + [[nodiscard]] SocketPointer createSocket(const QNetworkInterface &iface, + const QHostAddress &address) override; + + void submitQueries(const SocketTable &sockets) override; + + [[nodiscard]] virtual quint16 port() const = 0; + [[nodiscard]] virtual QHostAddress multicastGroup(const QHostAddress &address) const = 0; + [[nodiscard]] virtual QByteArray finalizeQuery(const QHostAddress &address, const QByteArray &query) const; + + virtual void processDatagram(const QNetworkDatagram &message) = 0; + + [[nodiscard]] static bool isSupportedInterfaceType(const QNetworkInterface &iface); + [[nodiscard]] static bool isMulticastInterface(const QNetworkInterface &iface); + [[nodiscard]] static bool isLinkLocalAddress(const QHostAddress &address); + + bool addQuery(QByteArray &&query); + +private: + void onDatagramReceived(QUdpSocket *socket); + bool isOwnMessage(const QNetworkDatagram &message) const; + + QByteArrayList m_queries; +}; + +} // namespace qnc::core + +#endif // QNCCORE_UNICASTRESOLVER_H diff --git a/qnc/qncparse.cpp b/qnc/parse.cpp similarity index 95% rename from qnc/qncparse.cpp rename to qnc/parse.cpp index be3d208..c22fc05 100644 --- a/qnc/qncparse.cpp +++ b/qnc/parse.cpp @@ -1,7 +1,7 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ -#include "qncparse.h" +#include "parse.h" // STL headers #include @@ -10,7 +10,7 @@ using QByteArrayView = QByteArray; #endif // QT_VERSION_MAJOR < 6 -namespace qnc::detail { +namespace qnc::core::detail { template <> void parse(const QByteArrayView &text, bool &value, bool &isValid) @@ -29,7 +29,7 @@ void parse(const QByteArrayView &text, bool &value, bool &isValid) || trimmedText.compare("disabled", Qt::CaseInsensitive) == 0) { value = false; isValid = true; - } else if (const auto &number = qnc::parse(trimmedText)) { + } else if (const auto &number = core::parse(trimmedText)) { value = (number != 0); isValid = true; } else { @@ -95,4 +95,4 @@ template <> void parse(const QUtf8StringView &text, bool &value, bool &is #endif // QT_VERSION_MAJOR >= 6 -} // namespace qnc::detail +} // namespace qnc::core::detail diff --git a/qnc/qncparse.h b/qnc/parse.h similarity index 95% rename from qnc/qncparse.h rename to qnc/parse.h index aafbb43..f76aa9c 100644 --- a/qnc/qncparse.h +++ b/qnc/parse.h @@ -1,8 +1,8 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ -#ifndef QNC_QNCPARSE_H -#define QNC_QNCPARSE_H +#ifndef QNCCORE_PARSE_H +#define QNCCORE_PARSE_H // Qt headers #include @@ -11,7 +11,7 @@ #include #include -namespace qnc { +namespace qnc::core { namespace detail { @@ -78,6 +78,6 @@ std::optional parse(const StringLike &text) { return detail::parse(text); template std::optional parse(const StringLike &text, int base) { return detail::parse(text, base); } -} // namespace qnc +} // namespace qnc::core -#endif // QNC_QNCPARSE_H +#endif // QNCCORE_PARSE_H diff --git a/qnc/qncresolver.h b/qnc/qncresolver.h deleted file mode 100644 index 53fbda5..0000000 --- a/qnc/qncresolver.h +++ /dev/null @@ -1,96 +0,0 @@ -/* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2019-2024 Mathias Hasselmann - */ -#ifndef QNC_QNCRESOLVER_H -#define QNC_QNCRESOLVER_H - -#include -#include -#include -#include - -class QNetworkDatagram; -class QNetworkInterface; -class QTimer; -class QUdpSocket; - -namespace qnc::core { - -class GenericResolver : public QObject -{ - Q_OBJECT - Q_PROPERTY(int scanInterval READ scanInterval WRITE setScanInterval NOTIFY scanIntervalChanged FINAL) - -public: - GenericResolver(QObject *parent = nullptr); - - [[nodiscard]] int scanInterval() const; - [[nodiscard]] std::chrono::milliseconds scanIntervalAsDuration() const; - void setScanInterval(std::chrono::milliseconds ms); - -public slots: - void setScanInterval(int ms); - -signals: - void scanIntervalChanged(int interval); - -protected: - using SocketPointer = std::shared_ptr; - using SocketTable = QHash; - - [[nodiscard]] virtual bool isSupportedInterface(const QNetworkInterface &iface) const = 0; - [[nodiscard]] virtual bool isSupportedAddress(const QHostAddress &address) const = 0; - - [[nodiscard]] virtual SocketPointer createSocket(const QNetworkInterface &iface, - const QHostAddress &address) = 0; - - [[nodiscard]] SocketPointer socketForAddress(const QHostAddress &address) const; - - virtual void submitQueries(const SocketTable &sockets) = 0; - -private: - void onTimeout(); - void scanNetworkInterfaces(); - - QTimer *const m_timer; - SocketTable m_sockets; -}; - -class MulticastResolver : public GenericResolver -{ - Q_OBJECT - -public: - using GenericResolver::GenericResolver; - -protected: - [[nodiscard]] bool isSupportedInterface(const QNetworkInterface &iface) const override; - [[nodiscard]] bool isSupportedAddress(const QHostAddress &address) const override; - - [[nodiscard]] SocketPointer createSocket(const QNetworkInterface &iface, - const QHostAddress &address) override; - - void submitQueries(const SocketTable &sockets) override; - - [[nodiscard]] virtual quint16 port() const = 0; - [[nodiscard]] virtual QHostAddress multicastGroup(const QHostAddress &address) const = 0; - [[nodiscard]] virtual QByteArray finalizeQuery(const QHostAddress &address, const QByteArray &query) const; - - virtual void processDatagram(const QNetworkDatagram &message) = 0; - - [[nodiscard]] static bool isSupportedInterfaceType(const QNetworkInterface &iface); - [[nodiscard]] static bool isMulticastInterface(const QNetworkInterface &iface); - [[nodiscard]] static bool isLinkLocalAddress(const QHostAddress &address); - - bool addQuery(QByteArray &&query); - -private: - void onDatagramReceived(QUdpSocket *socket); - bool isOwnMessage(const QNetworkDatagram &message) const; - - QByteArrayList m_queries; -}; - -} // namespace qnc::core - -#endif // QNC_QNCRESOLVER_H diff --git a/ssdp/ssdpresolver.cpp b/ssdp/ssdpresolver.cpp index 7cc195f..d50cbd7 100644 --- a/ssdp/ssdpresolver.cpp +++ b/ssdp/ssdpresolver.cpp @@ -5,7 +5,7 @@ // QtNetworkCrumbs headers #include "httpparser.h" -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/ssdp/ssdpresolver.h b/ssdp/ssdpresolver.h index 2549cfb..074236b 100644 --- a/ssdp/ssdpresolver.h +++ b/ssdp/ssdpresolver.h @@ -4,7 +4,7 @@ #ifndef QNCSSDP_RESOLVER_H #define QNCSSDP_RESOLVER_H -#include "qncresolver.h" +#include "multicastresolver.h" #include #include diff --git a/ssdp/ssdpresolverdemo.cpp b/ssdp/ssdpresolverdemo.cpp index 3ad3357..527fb26 100644 --- a/ssdp/ssdpresolverdemo.cpp +++ b/ssdp/ssdpresolverdemo.cpp @@ -3,7 +3,7 @@ */ // QtNetworkCrumbs headers -#include "qncliterals.h" +#include "literals.h" #include "ssdpresolver.h" // Qt headers diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt index 3efa388..3085c58 100644 --- a/tests/auto/CMakeLists.txt +++ b/tests/auto/CMakeLists.txt @@ -29,9 +29,9 @@ qnc_add_library( target_link_libraries(QncTestSuport PUBLIC Qt::Test) +add_testcase(tst_coreparse.cpp LIBRARIES QncCore QncTestSuport) add_testcase(tst_httpparser.cpp LIBRARIES QncHttp) add_testcase(tst_mdnsmessages.cpp LIBRARIES QncMdns) add_testcase(tst_mdnsresolver.cpp LIBRARIES QncMdns) -add_testcase(tst_qncparse.cpp LIBRARIES QncCore QncTestSuport) add_testcase(tst_ssdpresolver.cpp LIBRARIES QncSsdp) add_testcase(tst_xmlparser.cpp LIBRARIES QncXml QncTestSuport) diff --git a/tests/auto/tst_qncparse.cpp b/tests/auto/tst_coreparse.cpp similarity index 99% rename from tests/auto/tst_qncparse.cpp rename to tests/auto/tst_coreparse.cpp index ac0e33b..ba91b2b 100644 --- a/tests/auto/tst_qncparse.cpp +++ b/tests/auto/tst_coreparse.cpp @@ -3,8 +3,8 @@ */ // QtNetworkCrumbs headers -#include "qncliterals.h" -#include "qncparse.h" +#include "literals.h" +#include "parse.h" #include "qnctestsupport.h" // Qt headers @@ -240,4 +240,4 @@ private slots: QTEST_GUILESS_MAIN(qnc::core::tests::ParseTest) -#include "tst_qncparse.moc" +#include "tst_coreparse.moc" diff --git a/tests/auto/tst_httpparser.cpp b/tests/auto/tst_httpparser.cpp index 648d501..ee0de55 100644 --- a/tests/auto/tst_httpparser.cpp +++ b/tests/auto/tst_httpparser.cpp @@ -1,9 +1,9 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ #include "httpparser.h" -#include "qncliterals.h" +#include "literals.h" #include diff --git a/tests/auto/tst_mdnsmessages.cpp b/tests/auto/tst_mdnsmessages.cpp index 4c8c9f6..b8ad533 100644 --- a/tests/auto/tst_mdnsmessages.cpp +++ b/tests/auto/tst_mdnsmessages.cpp @@ -1,11 +1,11 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ #include "mdnsmessage.h" // QtNetworkCrumbs headers -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/tests/auto/tst_mdnsresolver.cpp b/tests/auto/tst_mdnsresolver.cpp index 7512029..207fc93 100644 --- a/tests/auto/tst_mdnsresolver.cpp +++ b/tests/auto/tst_mdnsresolver.cpp @@ -6,7 +6,7 @@ #include "mdnsmessage.h" #include "mdnsresolver.h" #include "mdnsurlfinder.h" -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/tests/auto/tst_ssdpresolver.cpp b/tests/auto/tst_ssdpresolver.cpp index d02c740..b9c4321 100644 --- a/tests/auto/tst_ssdpresolver.cpp +++ b/tests/auto/tst_ssdpresolver.cpp @@ -4,7 +4,7 @@ // QtNetworkCrumbs headers #include "ssdpresolver.h" -#include "qncliterals.h" +#include "literals.h" // Qt headers #include diff --git a/tests/auto/tst_xmlparser.cpp b/tests/auto/tst_xmlparser.cpp index e126f29..debd03f 100644 --- a/tests/auto/tst_xmlparser.cpp +++ b/tests/auto/tst_xmlparser.cpp @@ -1,9 +1,9 @@ /* QtNetworkCrumbs - Some networking toys for Qt - * Copyright (C) 2023 Mathias Hasselmann + * Copyright (C) 2019-2024 Mathias Hasselmann */ // QtNetworkCrumbs headers -#include "qncliterals.h" +#include "literals.h" #include "qnctestsupport.h" #include "xmlparser.h" diff --git a/xml/xmlparser.cpp b/xml/xmlparser.cpp index f74307a..6aaae59 100644 --- a/xml/xmlparser.cpp +++ b/xml/xmlparser.cpp @@ -4,8 +4,8 @@ #include "xmlparser.h" // QtNetworkCrumbs headers -#include "qncliterals.h" -#include "qncparse.h" +#include "literals.h" +#include "parse.h" // Qt headers #include @@ -83,7 +83,7 @@ void reportIgnoredAttribute(const QLoggingCategory &category, const QXmlStreamRe template std::optional convert(QStringView text) { - return qnc::parse(text); + return core::parse(text); } template <> @@ -203,7 +203,7 @@ void ParserBase::parseFlag(QStringView text, const std::function &st if (trimmedText.isEmpty()) { store(true); - } else if (const auto parsed = qnc::parse(trimmedText)) { + } else if (const auto parsed = core::parse(trimmedText)) { store(parsed.value()); } else { m_xml->raiseError(tr("Unexpected value for flag: %1").arg(trimmedText)); From f9c0cae5d8a96cdb20b5c40c312a9fd760b15242 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 3 Oct 2024 20:18:23 +0200 Subject: [PATCH 3/4] Use qToUnderlying() in XML parser --- qnc/CMakeLists.txt | 1 + qnc/compat.h | 27 +++++++++++++++++++++++++++ xml/xmlparser.cpp | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 qnc/compat.h diff --git a/qnc/CMakeLists.txt b/qnc/CMakeLists.txt index 4cd30ca..3c0e377 100644 --- a/qnc/CMakeLists.txt +++ b/qnc/CMakeLists.txt @@ -3,6 +3,7 @@ qnc_add_library( abstractresolver.cpp abstractresolver.h + compat.h literals.cpp literals.h multicastresolver.cpp diff --git a/qnc/compat.h b/qnc/compat.h new file mode 100644 index 0000000..2827382 --- /dev/null +++ b/qnc/compat.h @@ -0,0 +1,27 @@ +/* QtNetworkCrumbs - Some networking toys for Qt + * Copyright (C) 2019-2024 Mathias Hasselmann + */ +#ifndef QNCCORE_COMPAT_H +#define QNCCORE_COMPAT_H + +#include + +#if QT_VERSION_MAJOR < 6 + +#define Q_IMPLICIT /* implicit */ + +namespace qnc::core { + +template +constexpr std::underlying_type_t qToUnderlying(T value) noexcept +{ + return static_cast>(value); +} + +} // namespace qnc::core + +using qnc::core::qToUnderlying; + +#endif + +#endif // QNCCORE_COMPAT_H diff --git a/xml/xmlparser.cpp b/xml/xmlparser.cpp index 6aaae59..589719e 100644 --- a/xml/xmlparser.cpp +++ b/xml/xmlparser.cpp @@ -4,6 +4,7 @@ #include "xmlparser.h" // QtNetworkCrumbs headers +#include "compat.h" #include "literals.h" #include "parse.h" @@ -126,7 +127,7 @@ QString parseErrorMessage() void updateVersion(QVersionNumber &version, VersionSegment segment, int number) { - const auto index = static_cast(segment); + const auto index = qToUnderlying(segment); auto segments = version.segments(); if (segments.size() <= index) From 0e982eae2000964b6c51d0dfdeeac1187ce4366f Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Thu, 3 Oct 2024 20:50:01 +0200 Subject: [PATCH 4/4] Move QncCore from qnc into core folder --- CMakeLists.txt | 2 +- {qnc => core}/CMakeLists.txt | 0 {qnc => core}/abstractresolver.cpp | 0 {qnc => core}/abstractresolver.h | 0 {qnc => core}/compat.h | 0 {qnc => core}/literals.cpp | 0 {qnc => core}/literals.h | 0 {qnc => core}/multicastresolver.cpp | 0 {qnc => core}/multicastresolver.h | 0 {qnc => core}/parse.cpp | 0 {qnc => core}/parse.h | 0 11 files changed, 1 insertion(+), 1 deletion(-) rename {qnc => core}/CMakeLists.txt (100%) rename {qnc => core}/abstractresolver.cpp (100%) rename {qnc => core}/abstractresolver.h (100%) rename {qnc => core}/compat.h (100%) rename {qnc => core}/literals.cpp (100%) rename {qnc => core}/literals.h (100%) rename {qnc => core}/multicastresolver.cpp (100%) rename {qnc => core}/multicastresolver.h (100%) rename {qnc => core}/parse.cpp (100%) rename {qnc => core}/parse.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88c1666..70f59b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,9 +103,9 @@ endfunction() add_custom_target(metadata SOURCES LICENSE README.md) add_subdirectory(.github) +add_subdirectory(core) add_subdirectory(http) add_subdirectory(mdns) -add_subdirectory(qnc) add_subdirectory(ssdp) add_subdirectory(xml) diff --git a/qnc/CMakeLists.txt b/core/CMakeLists.txt similarity index 100% rename from qnc/CMakeLists.txt rename to core/CMakeLists.txt diff --git a/qnc/abstractresolver.cpp b/core/abstractresolver.cpp similarity index 100% rename from qnc/abstractresolver.cpp rename to core/abstractresolver.cpp diff --git a/qnc/abstractresolver.h b/core/abstractresolver.h similarity index 100% rename from qnc/abstractresolver.h rename to core/abstractresolver.h diff --git a/qnc/compat.h b/core/compat.h similarity index 100% rename from qnc/compat.h rename to core/compat.h diff --git a/qnc/literals.cpp b/core/literals.cpp similarity index 100% rename from qnc/literals.cpp rename to core/literals.cpp diff --git a/qnc/literals.h b/core/literals.h similarity index 100% rename from qnc/literals.h rename to core/literals.h diff --git a/qnc/multicastresolver.cpp b/core/multicastresolver.cpp similarity index 100% rename from qnc/multicastresolver.cpp rename to core/multicastresolver.cpp diff --git a/qnc/multicastresolver.h b/core/multicastresolver.h similarity index 100% rename from qnc/multicastresolver.h rename to core/multicastresolver.h diff --git a/qnc/parse.cpp b/core/parse.cpp similarity index 100% rename from qnc/parse.cpp rename to core/parse.cpp diff --git a/qnc/parse.h b/core/parse.h similarity index 100% rename from qnc/parse.h rename to core/parse.h