Skip to content

Commit

Permalink
Merge pull request #34 from hasselmm/bugfix/core-cleanups
Browse files Browse the repository at this point in the history
Various cleanups to QncCore
  • Loading branch information
hasselmm authored Oct 3, 2024
2 parents aa8c142 + 0e982ea commit b8413f5
Show file tree
Hide file tree
Showing 30 changed files with 317 additions and 247 deletions.
16 changes: 12 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down Expand Up @@ -95,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)

Expand Down
15 changes: 15 additions & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
qnc_add_library(
QncCore STATIC

abstractresolver.cpp
abstractresolver.h
compat.h
literals.cpp
literals.h
multicastresolver.cpp
multicastresolver.h
parse.cpp
parse.h
)

target_link_libraries(QncCore PUBLIC Qt::Network)
101 changes: 101 additions & 0 deletions core/abstractresolver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* QtNetworkCrumbs - Some networking toys for Qt
* Copyright (C) 2019-2024 Mathias Hasselmann
*/
#include "abstractresolver.h"

// Qt headers
#include <QLoggingCategory>
#include <QNetworkInterface>
#include <QTimer>
#include <QUdpSocket>

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
57 changes: 57 additions & 0 deletions core/abstractresolver.h
Original file line number Diff line number Diff line change
@@ -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 <QAbstractSocket>
#include <QHostAddress>

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<QAbstractSocket>;
using SocketTable = QHash<QHostAddress, SocketPointer>;

[[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
27 changes: 27 additions & 0 deletions core/compat.h
Original file line number Diff line number Diff line change
@@ -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 <QtGlobal>

#if QT_VERSION_MAJOR < 6

#define Q_IMPLICIT /* implicit */

namespace qnc::core {

template <typename T>
constexpr std::underlying_type_t<T> qToUnderlying(T value) noexcept
{
return static_cast<std::underlying_type_t<T>>(value);
}

} // namespace qnc::core

using qnc::core::qToUnderlying;

#endif

#endif // QNCCORE_COMPAT_H
8 changes: 4 additions & 4 deletions qnc/qncliterals.cpp → core/literals.cpp
Original file line number Diff line number Diff line change
@@ -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
14 changes: 7 additions & 7 deletions qnc/qncliterals.h → core/literals.h
Original file line number Diff line number Diff line change
@@ -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 <QDateTime>
#include <QString>
#include <QUrl>

namespace qnc {
namespace literals {
namespace core::literals {
namespace compat {

#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
Expand Down Expand Up @@ -118,10 +118,10 @@ inline auto operator ""_hex(const char *str, std::size_t len)
return QByteArray::fromHex({str, static_cast<compat::lentype>(len)});
}

} // namespace literals
} // namespace core::literals

using namespace literals;
using namespace core::literals;

} // namespace qnc

#endif // QNC_QNCLITERALS_H
#endif // QNCCORE_LITERALS_H
Loading

0 comments on commit b8413f5

Please sign in to comment.