diff options
25 files changed, 1169 insertions, 592 deletions
diff --git a/.qmake.conf b/.qmake.conf index b5e35ea..c6f1702 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -3,4 +3,4 @@ load(qt_build_config) CONFIG += warning_clean DEFINES += QT_NO_FOREACH -MODULE_VERSION = 5.13.1 +MODULE_VERSION = 5.14.0 diff --git a/examples/knx/device/mainwindow.cpp b/examples/knx/device/mainwindow.cpp index 54d3b6a..f1516a2 100644 --- a/examples/knx/device/mainwindow.cpp +++ b/examples/knx/device/mainwindow.cpp @@ -170,13 +170,16 @@ void MainWindow::on_actionImport_triggered() on_devices_currentIndexChanged(ui->devices->currentIndex()); } -void MainWindow::on_devices_currentIndexChanged(int /* index */) +void MainWindow::on_devices_currentIndexChanged(int index) { delete m_device; + m_device = nullptr; ui->secureConfigs->clear(); - const auto model = qobject_cast<QStandardItemModel*>(ui->devices->model()); - m_device = static_cast<DeviceItem *> (model->item(ui->devices->currentIndex()))->clone(); + if (index >= 0) { + const auto model = qobject_cast<QStandardItemModel*>(ui->devices->model()); + m_device = static_cast<DeviceItem *> (model->item(ui->devices->currentIndex()))->clone(); + } if (m_device) { const auto deviceInfo = m_device->info(); @@ -190,6 +193,8 @@ void MainWindow::on_devices_currentIndexChanged(int /* index */) .arg(config.userId()) .arg(ia.isValid() ? ia.toString() : tr("No specific address")), i); } + } else { + m_device = new DeviceItem({}); } ui->secureConfigs->setEnabled(bool(ui->secureConfigs->count()) @@ -311,6 +316,7 @@ void MainWindow::setupInterfaces() if (i < 0) return; m_discoveryAgent.stop(); + ui->devices->clear(); m_discoveryAgent.setLocalAddress(QHostAddress(ui->interfaces->currentData() .toStringList().first())); m_discoveryAgent.start(); diff --git a/examples/knx/discoverer/main.cpp b/examples/knx/discoverer/main.cpp index 3cf564b..d9944cb 100644 --- a/examples/knx/discoverer/main.cpp +++ b/examples/knx/discoverer/main.cpp @@ -56,8 +56,6 @@ #include <QtKnx/QKnxNetIpServerDiscoveryAgent> #include <QtKnx/QKnxNetIpSrpBuilder> -#include <QtNetwork/QNetworkInterface> - static QString familyToString(QKnxNetIp::ServiceFamily id) { switch (id) { @@ -83,17 +81,6 @@ static QString familyToString(QKnxNetIp::ServiceFamily id) return "Unknown"; } -QString interfaceFromAddress(const QHostAddress &address) -{ - auto interfaces = QNetworkInterface::allInterfaces(); - for (const auto &interface : qAsConst(interfaces)) { - if (interface.allAddresses().contains(address)) - return interface.humanReadableName(); - } - return QString(address == QHostAddress(QKnxNetIp::Constants::MulticastAddress) - ? "Multicast" : "Unknown"); -} - int main(int argc, char *argv[]) { QCoreApplication discoverer(argc, argv); @@ -130,10 +117,8 @@ int main(int argc, char *argv[]) agent.setLocalPort(parser.value("localPort").toUInt()); agent.setTimeout(parser.value("timeout").toInt() * 1000); - if (parser.isSet("localAddress")) { + if (parser.isSet("localAddress")) agent.setLocalAddress(QHostAddress(parser.value("localAddress"))); - agent.setResponseType(QKnxNetIpServerDiscoveryAgent::ResponseType::Unicast); - } if (parser.isSet("unicast")) agent.setResponseType(QKnxNetIpServerDiscoveryAgent::ResponseType::Unicast); @@ -189,21 +174,25 @@ int main(int argc, char *argv[]) QObject::connect(&agent, &QKnxNetIpServerDiscoveryAgent::finished, &discoverer, &QCoreApplication::quit); - agent.start(); - - if (agent.error() == QKnxNetIpServerDiscoveryAgent::Error::None) - discoverer.exec(); + if (!parser.isSet("localAddress")) { + agent.start(QKnxNetIpServerDiscoveryAgent::InterfaceType::Ethernet + | QKnxNetIpServerDiscoveryAgent::InterfaceType::Wifi); + } else { + agent.start(QVector<QHostAddress> { agent.localAddress() }); + } - qInfo().noquote() << endl << "Device used to send the search request:"; - qInfo().noquote() << QString::fromLatin1(" Network interface: %1, address: %2, port: %3") - .arg(interfaceFromAddress(agent.localAddress()), agent.localAddress().toString()) - .arg(agent.localPort()); + if (agent.error() == QKnxNetIpServerDiscoveryAgent::Error::None + && agent.state() == QKnxNetIpServerDiscoveryAgent::State::Running) { + discoverer.exec(); + } const auto servers = agent.discoveredServers(); if (servers.size() > 0) { qInfo().noquote() << endl << QString::fromLatin1("%1 server(s) found on the network.") .arg(servers.size()); for (auto server : servers) { + qInfo().noquote() << QString::fromLatin1(" Network interface: %1, address: %2") + .arg(server.networkInterface().humanReadableName(), server.hostAddress().toString()); qInfo().noquote() << QString::fromLatin1(" Server: %1").arg(server.deviceName()); qInfo().noquote() << QString::fromLatin1(" Individual address: %1").arg(server .individualAddress().toString()); diff --git a/examples/knx/feature/mainwindow.cpp b/examples/knx/feature/mainwindow.cpp index 7e44327..8f32b06 100644 --- a/examples/knx/feature/mainwindow.cpp +++ b/examples/knx/feature/mainwindow.cpp @@ -170,13 +170,16 @@ void MainWindow::on_actionImport_triggered() on_devices_currentIndexChanged(ui->devices->currentIndex()); } -void MainWindow::on_devices_currentIndexChanged(int /* index */) +void MainWindow::on_devices_currentIndexChanged(int index) { delete m_device; + m_device = nullptr; ui->secureConfigs->clear(); - const auto model = qobject_cast<QStandardItemModel*>(ui->devices->model()); - m_device = static_cast<DeviceItem *> (model->item(ui->devices->currentIndex()))->clone(); + if (index >= 0) { + const auto model = qobject_cast<QStandardItemModel*>(ui->devices->model()); + m_device = static_cast<DeviceItem *> (model->item(ui->devices->currentIndex()))->clone(); + } if (m_device) { const auto deviceInfo = m_device->info(); @@ -190,6 +193,8 @@ void MainWindow::on_devices_currentIndexChanged(int /* index */) .arg(config.userId()) .arg(ia.isValid() ? ia.toString() : tr("No specific address")), i); } + } else { + m_device = new DeviceItem({}); } ui->secureConfigs->setEnabled(bool(ui->secureConfigs->count()) @@ -280,6 +285,7 @@ void MainWindow::setupInterfaces() if (i < 0) return; m_discoveryAgent.stop(); + ui->devices->clear(); m_discoveryAgent.setLocalAddress(QHostAddress(ui->interfaces->currentData() .toStringList().first())); m_discoveryAgent.start(); diff --git a/examples/knx/group/mainwindow.cpp b/examples/knx/group/mainwindow.cpp index 4100e03..2e297af 100644 --- a/examples/knx/group/mainwindow.cpp +++ b/examples/knx/group/mainwindow.cpp @@ -169,13 +169,16 @@ void MainWindow::on_actionImport_triggered() on_devices_currentIndexChanged(ui->devices->currentIndex()); } -void MainWindow::on_devices_currentIndexChanged(int /* index */) +void MainWindow::on_devices_currentIndexChanged(int index) { delete m_device; + m_device = nullptr; ui->secureConfigs->clear(); - const auto model = qobject_cast<QStandardItemModel*>(ui->devices->model()); - m_device = static_cast<DeviceItem *> (model->item(ui->devices->currentIndex()))->clone(); + if (index >= 0) { + const auto model = qobject_cast<QStandardItemModel*>(ui->devices->model()); + m_device = static_cast<DeviceItem *> (model->item(ui->devices->currentIndex()))->clone(); + } if (m_device) { const auto deviceInfo = m_device->info(); @@ -189,6 +192,8 @@ void MainWindow::on_devices_currentIndexChanged(int /* index */) .arg(config.userId()) .arg(ia.isValid() ? ia.toString() : tr("No specific address")), i); } + } else { + m_device = new DeviceItem({}); } ui->secureConfigs->setEnabled(bool(ui->secureConfigs->count()) @@ -288,6 +293,7 @@ void MainWindow::setupInterfaces() if (i < 0) return; m_discoveryAgent.stop(); + ui->devices->clear(); m_discoveryAgent.setLocalAddress(QHostAddress(ui->interfaces->currentData() .toStringList().first())); m_discoveryAgent.start(); diff --git a/examples/knx/router/main.cpp b/examples/knx/router/main.cpp index f9ccc9a..5218661 100644 --- a/examples/knx/router/main.cpp +++ b/examples/knx/router/main.cpp @@ -238,14 +238,13 @@ int main(int argc, char *argv[]) QNetworkInterface iface { QNetworkInterface::interfaceFromName(cliParser.value("interface")) }; if (!iface.isValid()) { auto interfaces = iface.allInterfaces(); - QList<QNetworkInterface>::iterator found = ( std::find_if(interfaces.begin(), - interfaces.end(), - [](const QNetworkInterface &i){ - return i.type() == QNetworkInterface::Ethernet; - })); + QList<QNetworkInterface>::iterator found = std::find_if( + interfaces.begin(), interfaces.end(), [](const QNetworkInterface &i) { + return i.type() == QNetworkInterface::Ethernet; + } + ); if (found == iface.allInterfaces().end()) { - qInfo().noquote() << "No valid network interface given and no " - "Ethernet adapter found. "; + qInfo().noquote() << "No valid network interface given and no Ethernet adapter found."; cliParser.showHelp(); } iface = static_cast<QNetworkInterface>(*found); diff --git a/src/knx/core/qknxbytearray.cpp b/src/knx/core/qknxbytearray.cpp index a93e3fa..bfec17d 100644 --- a/src/knx/core/qknxbytearray.cpp +++ b/src/knx/core/qknxbytearray.cpp @@ -243,6 +243,9 @@ void QKnxByteArray::clear() */ void QKnxByteArray::resize(int size) { + if (size == m_bytes.size()) + return; + if (size > m_bytes.size()) m_bytes.append(size - m_bytes.size(), 0x00); else diff --git a/src/knx/core/qknxbytearray.h b/src/knx/core/qknxbytearray.h index f6feba5..b48b9c5 100644 --- a/src/knx/core/qknxbytearray.h +++ b/src/knx/core/qknxbytearray.h @@ -92,7 +92,11 @@ public: void resize(int size); inline quint8 at(int i) const { return m_bytes.at(i); } - inline void set(int i, quint8 val) { m_bytes[i] = val; } + + inline void set(int i, quint8 val) { + Q_ASSERT(i >= 0 && i < size()); + m_bytes[i] = val; + } inline void setValue(int i, quint8 val) { diff --git a/src/knx/netip/netip.pri b/src/knx/netip/netip.pri index 88e2d58..4a154ab 100644 --- a/src/knx/netip/netip.pri +++ b/src/knx/netip/netip.pri @@ -96,6 +96,7 @@ SOURCES += $$PWD/qknxnetip.cpp \ $$PWD/qknxnetipsearchresponse.cpp \ $$PWD/qknxnetipserverdescriptionagent.cpp \ $$PWD/qknxnetipserverdiscoveryagent.cpp \ + $$PWD/qknxnetipserverdiscoveryagent_p.cpp \ $$PWD/qknxnetipserverinfo.cpp \ $$PWD/qknxnetipservicefamiliesdib.cpp \ $$PWD/qknxnetipstruct.cpp \ diff --git a/src/knx/netip/qknxnetipconnectionheader.cpp b/src/knx/netip/qknxnetipconnectionheader.cpp index 4bf2859..e571e43 100644 --- a/src/knx/netip/qknxnetipconnectionheader.cpp +++ b/src/knx/netip/qknxnetipconnectionheader.cpp @@ -237,7 +237,7 @@ QKnxNetIpConnectionHeader QKnxNetIpConnectionHeader::fromBytes(const QKnxByteArr if (availableSize < 4 && availableSize < totalSize) return {}; // header might be corrupted - QKnxNetIpConnectionHeader hdr{ bytes.at(index + 1), bytes.at(index + 2), bytes.at(index + 3) }; + QKnxNetIpConnectionHeader hdr { bytes.at(index + 1), bytes.at(index + 2), bytes.at(index + 3) }; if (totalSize > 4) hdr.setConnectionTypeSpecificHeaderItems(bytes.mid(index + 4, totalSize - 4)); return hdr; diff --git a/src/knx/netip/qknxnetiproutingindication.cpp b/src/knx/netip/qknxnetiproutingindication.cpp index d84e732..43a1758 100644 --- a/src/knx/netip/qknxnetiproutingindication.cpp +++ b/src/knx/netip/qknxnetiproutingindication.cpp @@ -156,7 +156,7 @@ QKnxNetIpRoutingIndicationProxy::Builder QKnxNetIpRoutingIndicationProxy::builde \code QKnxLinkLayerFrame linkFrame = // create a link frame ....; auto netIpframe = QKnxNetIpRoutingIndicationProxy::builder() - .setLinkLayerFrame(linkFrame) + .setCemi(linkFrame) .create(); \endcode diff --git a/src/knx/netip/qknxnetipserverdiscoveryagent.cpp b/src/knx/netip/qknxnetipserverdiscoveryagent.cpp index 30c3d1d..d00fd74 100644 --- a/src/knx/netip/qknxnetipserverdiscoveryagent.cpp +++ b/src/knx/netip/qknxnetipserverdiscoveryagent.cpp @@ -119,6 +119,8 @@ QT_BEGIN_NAMESPACE A network error occurred. \value NotIPv4 The network protocol used is not IPv4. + \value Timeout + A timeout occurred while waiting for the description response. \value Unknown An unknown error occurred. */ @@ -181,288 +183,12 @@ QT_BEGIN_NAMESPACE \a state. */ -QKnxNetIpServerDiscoveryAgentPrivate::QKnxNetIpServerDiscoveryAgentPrivate(const QHostAddress &addr, - quint16 prt) - : port(prt) - , address(addr) -{} - -namespace QKnxPrivate -{ - static void clearSocket(QUdpSocket **socket) - { - if (*socket) { - (*socket)->disconnect(); - (*socket)->deleteLater(); - (*socket) = nullptr; - } - } -} - -void QKnxNetIpServerDiscoveryAgentPrivate::setupSocket() -{ - usedPort = port; - usedAddress = address; - QKnxPrivate::clearSocket(&socket); - - Q_Q(QKnxNetIpServerDiscoveryAgent); - socket = new QUdpSocket(q); - socket->setSocketOption(QUdpSocket::SocketOption::MulticastTtlOption, ttl); - - QObject::connect(socket, &QUdpSocket::stateChanged, [&](QUdpSocket::SocketState s) { - Q_Q(QKnxNetIpServerDiscoveryAgent); - switch (s) { - case QUdpSocket::BoundState: - setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Running); - - if (type == QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast) { - QNetworkInterface mni; - const auto interfaces = QNetworkInterface::allInterfaces(); - for (const auto &iface : interfaces) { - if (!iface.flags().testFlag(QNetworkInterface::CanMulticast)) - continue; - - const auto entries = iface.addressEntries(); - for (const auto &entry : entries) { - auto ip = entry.ip(); - if (ip.protocol() != QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) - continue; - if (ip != address) - continue; - mni = iface; - break; - } - } - - if (socket->joinMulticastGroup(multicastAddress, mni)) { - usedPort = multicastPort; - usedAddress = multicastAddress; - } else { - setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error::Network, - QKnxNetIpServerDiscoveryAgent::tr("Could not join multicast group.")); - q->stop(); - } - } else { - usedPort = socket->localPort(); - usedAddress = socket->localAddress(); - } - - if (q->state() == QKnxNetIpServerDiscoveryAgent::State::Running) { - servers.clear(); - - const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> flags(discoveryMode); - if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1)) { - auto frame = QKnxNetIpSearchRequestProxy::builder() - .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() - .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) - .setPort(nat ? quint16(0u) : usedPort).create() - ).create(); - socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, - multicastPort); - } - - if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2)) { - auto frame = QKnxNetIpSearchRequestProxy::extendedBuilder() - .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() - .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) - .setPort(nat ? quint16(0u) : usedPort).create() - ) - .setExtendedParameters(srps).create(); - socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, - multicastPort); - } - - setupAndStartReceiveTimer(); - setupAndStartFrequencyTimer(); - } - break; - default: - break; - } - }); - - using overload = void (QUdpSocket::*)(QUdpSocket::SocketError); - QObject::connect(socket, - static_cast<overload>(&QUdpSocket::error), [&](QUdpSocket::SocketError) { - setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error::Network, - socket->errorString()); - - Q_Q(QKnxNetIpServerDiscoveryAgent); - q->stop(); - }); - - QObject::connect(socket, &QUdpSocket::readyRead, [&]() { - Q_Q(QKnxNetIpServerDiscoveryAgent); - while (socket->hasPendingDatagrams()) { - if (q->state() != QKnxNetIpServerDiscoveryAgent::State::Running) - break; - - auto datagram = socket->receiveDatagram(); - auto data = QKnxByteArray::fromByteArray(datagram.data()); - const auto header = QKnxNetIpFrameHeader::fromBytes(data, 0); - if (!header.isValid()) - continue; - - if (header.serviceType() != QKnxNetIp::ServiceType::SearchResponse && - header.serviceType() != QKnxNetIp::ServiceType::ExtendedSearchResponse) { - continue; - } - - auto frame = QKnxNetIpFrame::fromBytes(data); - auto response = QKnxNetIpSearchResponseProxy(frame); - if (!response.isValid()) - continue; - - const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> flags(discoveryMode); - if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1) - && !response.isExtended()) { - setAndEmitDeviceDiscovered({ - (nat ? QKnxNetIpHpaiProxy::builder() - .setHostAddress(datagram.senderAddress()) - .setPort(datagram.senderPort()).create() - : response.controlEndpoint() - ), response.deviceHardware(), response.supportedFamilies() - }); - } - - if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2) - && response.isExtended()) { - const auto optionalDibs = response.optionalDibs(); - setAndEmitDeviceDiscovered({ - (nat ? QKnxNetIpHpaiProxy::builder() - .setHostAddress(datagram.senderAddress()) - .setPort(datagram.senderPort()).create() - : response.controlEndpoint() - ), response.deviceHardware(), response.supportedFamilies(), - [&optionalDibs]() -> QKnxNetIpDib { - for (const auto &dib : qAsConst(optionalDibs)) { - if (dib.code() == QKnxNetIp::DescriptionType::TunnelingInfo) - return dib; - } - return {}; - }(), - [&optionalDibs]() -> QKnxNetIpDib { - for (const auto &dib : qAsConst(optionalDibs)) { - if (dib.code() == QKnxNetIp::DescriptionType::ExtendedDeviceInfo) - return dib; - } - return {}; - }() - }); - } - } - }); -} - -namespace QKnxPrivate -{ - static void clearTimer(QTimer **timer) - { - if (*timer) { - (*timer)->stop(); - (*timer)->disconnect(); - (*timer)->deleteLater(); - (*timer) = nullptr; - } - } -} - -void QKnxNetIpServerDiscoveryAgentPrivate::setupAndStartReceiveTimer() -{ - Q_Q(QKnxNetIpServerDiscoveryAgent); - - QKnxPrivate::clearTimer(&receiveTimer); - if (timeout >= 0) { - receiveTimer = new QTimer(q); - receiveTimer->setSingleShot(true); - receiveTimer->start(timeout); - QObject::connect(receiveTimer, &QTimer::timeout, q, &QKnxNetIpServerDiscoveryAgent::stop); - } -} - -void QKnxNetIpServerDiscoveryAgentPrivate::setupAndStartFrequencyTimer() -{ - Q_Q(QKnxNetIpServerDiscoveryAgent); - - QKnxPrivate::clearTimer(&frequencyTimer); - if (frequency > 0) { - frequencyTimer = new QTimer(q); - frequencyTimer->setSingleShot(false); - frequencyTimer->start(60000 / frequency); - - QObject::connect(frequencyTimer, &QTimer::timeout, [&]() { - Q_Q(QKnxNetIpServerDiscoveryAgent); - if (q->state() == QKnxNetIpServerDiscoveryAgent::State::Running) { - servers.clear(); - - const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> flags(discoveryMode); - if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1)) { - auto frame = QKnxNetIpSearchRequestProxy::builder() - .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() - .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) - .setPort(nat ? quint16(0u) : usedPort).create() - ).create(); - socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, - multicastPort); - } - - if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2)) { - auto frame = QKnxNetIpSearchRequestProxy::extendedBuilder() - .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() - .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) - .setPort(nat ? quint16(0u) : usedPort).create() - ) - .setExtendedParameters(srps).create(); - socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, - multicastPort); - } - } - }); - } -} - -void QKnxNetIpServerDiscoveryAgentPrivate::setAndEmitStateChanged( - QKnxNetIpServerDiscoveryAgent::State newState) -{ - state = newState; - - Q_Q(QKnxNetIpServerDiscoveryAgent); - emit q->stateChanged(newState); - - if (state == QKnxNetIpServerDiscoveryAgent::State::Running) - emit q->started(); - else if (state == QKnxNetIpServerDiscoveryAgent::State::NotRunning) - emit q->finished(); -} - -void QKnxNetIpServerDiscoveryAgentPrivate::setAndEmitDeviceDiscovered( - const QKnxNetIpServerInfo &discoveryInfo) -{ - servers.append(discoveryInfo); - - Q_Q(QKnxNetIpServerDiscoveryAgent); - emit q->deviceDiscovered(discoveryInfo); -} - -void QKnxNetIpServerDiscoveryAgentPrivate::setAndEmitErrorOccurred( - QKnxNetIpServerDiscoveryAgent::Error newError, const QString &message) -{ - error = newError; - errorString = message; - - Q_Q(QKnxNetIpServerDiscoveryAgent); - emit q->errorOccurred(error, errorString); -} - - -// -- QKnxNetIpServerDiscoveryAgent - /*! Creates a KNXnet/IP server discovery agent with the parent \a parent. */ QKnxNetIpServerDiscoveryAgent::QKnxNetIpServerDiscoveryAgent(QObject *parent) - : QKnxNetIpServerDiscoveryAgent(QHostAddress(QHostAddress::AnyIPv4), 0u, parent) + : QKnxNetIpServerDiscoveryAgent(QHostAddress(QHostAddress::Null), 0U, parent) {} /*! @@ -470,7 +196,7 @@ QKnxNetIpServerDiscoveryAgent::QKnxNetIpServerDiscoveryAgent(QObject *parent) */ QKnxNetIpServerDiscoveryAgent::~QKnxNetIpServerDiscoveryAgent() { - stop(); + d_func()->stop(); } /*! @@ -479,7 +205,7 @@ QKnxNetIpServerDiscoveryAgent::~QKnxNetIpServerDiscoveryAgent() */ QKnxNetIpServerDiscoveryAgent::QKnxNetIpServerDiscoveryAgent(const QHostAddress &localAddress, QObject *parent) - : QKnxNetIpServerDiscoveryAgent(localAddress, 0u, parent) + : QKnxNetIpServerDiscoveryAgent(localAddress, 0U, parent) {} /*! @@ -500,8 +226,7 @@ QKnxNetIpServerDiscoveryAgent::QKnxNetIpServerDiscoveryAgent(const QHostAddress */ QKnxNetIpServerDiscoveryAgent::State QKnxNetIpServerDiscoveryAgent::state() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->state; + return d_func()->state; } /*! @@ -509,8 +234,7 @@ QKnxNetIpServerDiscoveryAgent::State QKnxNetIpServerDiscoveryAgent::state() cons */ QKnxNetIpServerDiscoveryAgent::Error QKnxNetIpServerDiscoveryAgent::error() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->error; + return d_func()->error; } /*! @@ -518,8 +242,7 @@ QKnxNetIpServerDiscoveryAgent::Error QKnxNetIpServerDiscoveryAgent::error() cons */ QString QKnxNetIpServerDiscoveryAgent::errorString() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->errorString; + return d_func()->errorString; } /*! @@ -527,8 +250,7 @@ QString QKnxNetIpServerDiscoveryAgent::errorString() const */ QVector<QKnxNetIpServerInfo> QKnxNetIpServerDiscoveryAgent::discoveredServers() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->servers; + return d_func()->servers; } /*! @@ -567,7 +289,8 @@ QHostAddress QKnxNetIpServerDiscoveryAgent::localAddress() const } /*! - Sets the host address of a discovery agent to \a address. + Sets the host address of a discovery agent to \a address. To unset the local + address use \l QHostAddress::Null. \note If the address changes during discovery, the new address will not be used until the next run. @@ -587,8 +310,7 @@ void QKnxNetIpServerDiscoveryAgent::setLocalAddress(const QHostAddress &address) */ int QKnxNetIpServerDiscoveryAgent::timeout() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->timeout; + return d_func()->timeout; } /*! @@ -604,7 +326,6 @@ void QKnxNetIpServerDiscoveryAgent::setTimeout(int msec) { Q_D(QKnxNetIpServerDiscoveryAgent); d->timeout = msec; - d->setupAndStartReceiveTimer(); } /*! @@ -615,8 +336,7 @@ void QKnxNetIpServerDiscoveryAgent::setTimeout(int msec) */ int QKnxNetIpServerDiscoveryAgent::searchFrequency() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->frequency; + return d_func()->frequency; } /*! @@ -641,8 +361,7 @@ void QKnxNetIpServerDiscoveryAgent::setSearchFrequency(int timesPerMinute) */ bool QKnxNetIpServerDiscoveryAgent::natAware() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->nat; + return d_func()->nat; } /*! @@ -666,8 +385,7 @@ void QKnxNetIpServerDiscoveryAgent::setNatAware(bool useNat) */ quint8 QKnxNetIpServerDiscoveryAgent::multicastTtl() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->ttl; + return d_func()->ttl; } /*! @@ -687,8 +405,7 @@ void QKnxNetIpServerDiscoveryAgent::setMulticastTtl(quint8 ttl) */ QKnxNetIpServerDiscoveryAgent::ResponseType QKnxNetIpServerDiscoveryAgent::responseType() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->type; + return d_func()->type; } /*! @@ -709,8 +426,7 @@ void QKnxNetIpServerDiscoveryAgent::setResponseType(QKnxNetIpServerDiscoveryAgen */ QKnxNetIpServerDiscoveryAgent::DiscoveryModes QKnxNetIpServerDiscoveryAgent::discoveryMode() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->discoveryMode; + return d_func()->mode; } /*! @@ -724,18 +440,18 @@ void QKnxNetIpServerDiscoveryAgent::setDiscoveryMode(QKnxNetIpServerDiscoveryAge { Q_D(QKnxNetIpServerDiscoveryAgent); if (d->state == QKnxNetIpServerDiscoveryAgent::State::NotRunning) - d->discoveryMode = mode; + d->mode = mode; } /*! \since 5.12 + Returns the search request parameter (SRP) objects used in an \l {QKnxNetIpServerDiscoveryAgent::CoreV2} {extended search request}. */ QVector<QKnxNetIpSrp> QKnxNetIpServerDiscoveryAgent::extendedSearchParameters() const { - Q_D(const QKnxNetIpServerDiscoveryAgent); - return d->srps; + return d_func()->srps; } /*! @@ -752,8 +468,7 @@ QVector<QKnxNetIpSrp> QKnxNetIpServerDiscoveryAgent::extendedSearchParameters() */ void QKnxNetIpServerDiscoveryAgent::setExtendedSearchParameters(const QVector<QKnxNetIpSrp> &srps) { - Q_D(QKnxNetIpServerDiscoveryAgent); - d->srps = srps; + d_func()->srps = srps; } /*! @@ -761,26 +476,7 @@ void QKnxNetIpServerDiscoveryAgent::setExtendedSearchParameters(const QVector<QK */ void QKnxNetIpServerDiscoveryAgent::start() { - Q_D(QKnxNetIpServerDiscoveryAgent); - - if (d->state != QKnxNetIpServerDiscoveryAgent::State::NotRunning) - return; - - auto isIPv4 = true; - d->address.toIPv4Address(&isIPv4); - if (isIPv4) { - d->setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Starting); - - d->setupSocket(); - if (d->type == QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast) { - d->socket->bind(QHostAddress::AnyIPv4, d->multicastPort, QUdpSocket::ShareAddress - | QAbstractSocket::ReuseAddressHint); - } else { - d->socket->bind(d->address, d->port); - } - } else { - d->setAndEmitErrorOccurred(Error::NotIPv4, tr("Only IPv4 local address supported.")); - } + d_func()->start(); } /*! @@ -791,32 +487,37 @@ void QKnxNetIpServerDiscoveryAgent::start() void QKnxNetIpServerDiscoveryAgent::start(int timeout) { d_func()->timeout = timeout; - start(); + d_func()->start(); } /*! - Stops a server discovery agent. + Starts a server discovery agent with the network interfaces specified by + the list of local host \a addresses. + + \note Does not emit the errorOccurred signal. */ -void QKnxNetIpServerDiscoveryAgent::stop() +void QKnxNetIpServerDiscoveryAgent::start(const QVector<QHostAddress> &addresses) { - Q_D(QKnxNetIpServerDiscoveryAgent); - - if (d->state == State::Stopping || d->state == State::NotRunning) - return; - - d->setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Stopping); + d_func()->start(addresses); +} - if (d->type == QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast - && d->socket->state() == QUdpSocket::BoundState) { - d->socket->leaveMulticastGroup(d->multicastAddress); - } - d->socket->close(); +/*! + Starts a server discovery agent with the network interfaces specified by + the list of interface types \a types. - QKnxPrivate::clearSocket(&(d->socket)); - QKnxPrivate::clearTimer(&(d->receiveTimer)); - QKnxPrivate::clearTimer(&(d->frequencyTimer)); + \note Does not emit the errorOccurred signal. +*/ +void QKnxNetIpServerDiscoveryAgent::start(QKnxNetIpServerDiscoveryAgent::InterfaceTypes types) +{ + d_func()->start(types); +} - d->setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::NotRunning); +/*! + Stops a server discovery agent. +*/ +void QKnxNetIpServerDiscoveryAgent::stop() +{ + d_func()->stop(); } /*! diff --git a/src/knx/netip/qknxnetipserverdiscoveryagent.h b/src/knx/netip/qknxnetipserverdiscoveryagent.h index 0fd0455..b7bdf83 100644 --- a/src/knx/netip/qknxnetipserverdiscoveryagent.h +++ b/src/knx/netip/qknxnetipserverdiscoveryagent.h @@ -60,6 +60,7 @@ public: None, Network, NotIPv4, + Timeout, Unknown = 0x80 }; Q_ENUM(Error) @@ -79,8 +80,17 @@ public: Q_ENUM(DiscoveryMode) Q_DECLARE_FLAGS(DiscoveryModes, DiscoveryMode) + enum class InterfaceType : quint8 + { + Loopback = 0x01, + Ethernet = 0x02, + Wifi = 0x04 + }; + Q_ENUM(InterfaceType) + Q_DECLARE_FLAGS(InterfaceTypes, InterfaceType) + QKnxNetIpServerDiscoveryAgent(QObject *parent = nullptr); - ~QKnxNetIpServerDiscoveryAgent(); + ~QKnxNetIpServerDiscoveryAgent() override; explicit QKnxNetIpServerDiscoveryAgent(const QHostAddress &localAddress, QObject *parent = nullptr); @@ -122,9 +132,12 @@ public: public Q_SLOTS: void start(); - void start(int timeout); void stop(); + void start(int timeout); + void start(const QVector<QHostAddress> &localAddresses); + void start(QKnxNetIpServerDiscoveryAgent::InterfaceTypes types); + Q_SIGNALS: void started(); void finished(); @@ -137,6 +150,7 @@ private: QKnxNetIpServerDiscoveryAgent(QKnxNetIpServerDiscoveryAgentPrivate &dd, QObject *parent); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QKnxNetIpServerDiscoveryAgent::DiscoveryModes) +Q_DECLARE_OPERATORS_FOR_FLAGS(QKnxNetIpServerDiscoveryAgent::InterfaceTypes) QT_END_NAMESPACE diff --git a/src/knx/netip/qknxnetipserverdiscoveryagent_p.cpp b/src/knx/netip/qknxnetipserverdiscoveryagent_p.cpp new file mode 100644 index 0000000..44e7bb5 --- /dev/null +++ b/src/knx/netip/qknxnetipserverdiscoveryagent_p.cpp @@ -0,0 +1,684 @@ +/****************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtKnx module. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ + +#include "qknxnetipserverdiscoveryagent.h" +#include "qknxnetipserverdiscoveryagent_p.h" + +#include <QtCore/qthread.h> + +QT_BEGIN_NAMESPACE + +namespace QKnxPrivate +{ + static void clearSocket(QUdpSocket **socket) + { + if (*socket) { + (*socket)->disconnect(); + (*socket)->deleteLater(); + (*socket) = nullptr; + } + } + + static void clearTimer(QTimer **timer) + { + if (*timer) { + (*timer)->stop(); + (*timer)->disconnect(); + (*timer)->deleteLater(); + (*timer) = nullptr; + } + } + + static QVector<Adapter> adaptersForAddresses(const QVector<QHostAddress> addresses) + { + QVector<Adapter> adapters; + auto all = QNetworkInterface::allInterfaces(); + for (const auto &iface : all) { + const auto flags = iface.flags(); + if (!flags.testFlag(QNetworkInterface::IsUp) + && !flags.testFlag(QNetworkInterface::IsRunning) + && !flags.testFlag(QNetworkInterface::CanMulticast)) continue; + + const auto type = iface.type(); + if (type != QNetworkInterface::Wifi + && type != QNetworkInterface::Loopback + && type != QNetworkInterface::Ethernet) continue; + + const auto entries = iface.addressEntries(); + for (const auto &entry : entries) { + const auto address = entry.ip(); + if (address.protocol() != QAbstractSocket::IPv4Protocol) + continue; + if (!addresses.contains(address)) + continue; + adapters.append({ address, iface }); + break; + } + } + return adapters; + } +} + +Discoverer::Discoverer(const QHostAddress &address, const QNetworkInterface iface, const DiscovererConfig &c) + : QObject(nullptr) + , m_address(address) + , m_iface(iface) + , m_config(c) +{} + +Discoverer::~Discoverer() +{ + finish(); +} + +void Discoverer::start() +{ + if (m_state != QKnxNetIpServerDiscoveryAgent::State::NotRunning) + return; + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Starting); + + auto isIPv4 = true; + m_address.toIPv4Address(&isIPv4); + if (!isIPv4) { + emit errorOccurred(QKnxNetIpServerDiscoveryAgent::Error::NotIPv4, + QKnxNetIpServerDiscoveryAgent::tr("Only IPv4 local address supported.")); + return finish(); + } + + m_socket = new QUdpSocket; + connect(m_socket, &QUdpSocket::readyRead, this, &Discoverer::onReadyRead); + using overload = void (QUdpSocket::*)(QUdpSocket::SocketError); + connect(m_socket, static_cast<overload>(&QUdpSocket::error), this, &Discoverer::onError); + + bool bound = m_socket->bind(m_config.Multicast ? QHostAddress::AnyIPv4 + : m_address, + m_config.Multicast ? 3671 : 0, + QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); + if (!bound) + return finish(); + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Running); + + if (m_config.Multicast) { + m_socket->setMulticastInterface(m_iface); + if (!m_socket->joinMulticastGroup(m_multicast, m_iface)) { + emit errorOccurred(QKnxNetIpServerDiscoveryAgent::Error::Network, + QKnxNetIpServerDiscoveryAgent::tr("Could not join multicast group.")); + return finish(); + } + m_socket->setSocketOption(QUdpSocket::SocketOption::MulticastTtlOption, m_config.Ttl); + } + + m_timer = new QTimer; + m_timer->setSingleShot(true); + connect(m_timer, &QTimer::timeout, this, &Discoverer::onTimeout); + + if (m_config.DiscoveryCoreV1) { + const auto frame = QKnxNetIpSearchRequestProxy::builder() + .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::Builder() + .setPort(m_config.Nat ? 0 : (m_config.Multicast ? 3671 : m_socket->localPort())) + .setHostAddress(m_config.Nat ? QHostAddress::AnyIPv4 + : (m_config.Multicast ? m_multicast : m_address)) + .create()) + .create(); + + if (frame.isValid()) + m_socket->writeDatagram(frame.bytes().toByteArray(), m_multicast, 3671); + } + + if (m_config.DiscoveryCoreV2) { + const auto frame = QKnxNetIpSearchRequestProxy::extendedBuilder() + .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::Builder() + .setPort(m_config.Nat ? 0 : (m_config.Multicast ? 3671 : m_socket->localPort())) + .setHostAddress(m_config.Nat ? QHostAddress::AnyIPv4 + : (m_config.Multicast ? m_multicast : m_address)) + .create()) + .setExtendedParameters(m_config.ExtendedSearchParameters) + .create(); + if (frame.isValid()) + m_socket->writeDatagram(frame.bytes().toByteArray(), m_multicast, 3671); + } + + m_timer->start(m_config.Timeout); +} + +void Discoverer::finish() +{ + if (m_state == QKnxNetIpServerDiscoveryAgent::State::Stopping + || m_state == QKnxNetIpServerDiscoveryAgent::State::NotRunning) { + return; + } + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Stopping); + + QKnxPrivate::clearTimer(&m_timer); + + if (m_socket) { + if (m_config.Multicast && m_socket->state() == QUdpSocket::BoundState) { + m_socket->setMulticastInterface({}); + m_socket->leaveMulticastGroup(m_multicast, m_iface); + } + QKnxPrivate::clearSocket(&m_socket); + } + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::NotRunning); +} + +void Discoverer::onTimeout() +{ + if (m_devices.isEmpty()) + emit timeout(); + finish(); +} + +void Discoverer::onReadyRead() +{ + while (m_socket->hasPendingDatagrams()) { + if (m_state != QKnxNetIpServerDiscoveryAgent::State::Running) + break; + + const auto datagram = m_socket->receiveDatagram(); + const auto data = QKnxByteArray::fromByteArray(datagram.data()); + const auto header = QKnxNetIpFrameHeader::fromBytes(data, 0); + if (!header.isValid()) + continue; + + if (header.serviceType() != QKnxNetIp::ServiceType::SearchResponse + && header.serviceType() != QKnxNetIp::ServiceType::ExtendedSearchResponse) { + continue; + } + + const auto frame = QKnxNetIpFrame::fromBytes(data); + const auto proxy = QKnxNetIpSearchResponseProxy(frame); + if (!proxy.isValid()) + continue; + + if (m_config.DiscoveryCoreV1 && !proxy.isExtended()) { + emit deviceDiscovered( + { + (m_config.Nat ? QKnxNetIpHpaiProxy::builder() + .setHostAddress(datagram.senderAddress()) + .setPort(datagram.senderPort()).create() + : proxy.controlEndpoint()), + proxy.deviceHardware(), + proxy.supportedFamilies(), + m_address, m_iface + } + ); + } + + if (m_config.DiscoveryCoreV2 && proxy.isExtended()) { + const auto optionalDibs = proxy.optionalDibs(); + emit deviceDiscovered( + { + (m_config.Nat ? QKnxNetIpHpaiProxy::builder() + .setHostAddress(datagram.senderAddress()) + .setPort(datagram.senderPort()).create() + : proxy.controlEndpoint()), + proxy.deviceHardware(), + proxy.supportedFamilies(), + m_address, m_iface, + [&optionalDibs]() -> QKnxNetIpDib { + for (const auto &dib : qAsConst(optionalDibs)) { + if (dib.code() == QKnxNetIp::DescriptionType::TunnelingInfo) + return dib; + } + return {}; + }(), + [&optionalDibs]() -> QKnxNetIpDib { + for (const auto &dib : qAsConst(optionalDibs)) { + if (dib.code() == QKnxNetIp::DescriptionType::ExtendedDeviceInfo) + return dib; + } + return {}; + }() + } + ); + } + } +} + +void Discoverer::onError(QUdpSocket::SocketError /* error */) +{ + emit errorOccurred(QKnxNetIpServerDiscoveryAgent::Error::Network, + m_socket ? m_socket->errorString() + : QKnxNetIpServerDiscoveryAgent::tr("Unknown socket error happened.") + ); + finish(); +} + +void Discoverer::setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State state) +{ + m_state = state; + emit stateChanged(m_state); + + if (m_state == QKnxNetIpServerDiscoveryAgent::State::Starting) + emit started(); + if (m_state == QKnxNetIpServerDiscoveryAgent::State::Stopping) + emit finished(this); +} + +QKnxNetIpServerDiscoveryAgentPrivate::QKnxNetIpServerDiscoveryAgentPrivate(const QHostAddress &addr, + quint16 prt) + : port(prt) + , address(addr) +{} + +void QKnxNetIpServerDiscoveryAgentPrivate::setupSocket() +{ + usedPort = port; + usedAddress = address; + QKnxPrivate::clearSocket(&socket); + + Q_Q(QKnxNetIpServerDiscoveryAgent); + socket = new QUdpSocket(q); + + adapter = QKnxPrivate::adaptersForAddresses(QVector<QHostAddress> { address }).value(0); + QObject::connect(socket, &QUdpSocket::stateChanged, q, [&](QUdpSocket::SocketState s) { + Q_Q(QKnxNetIpServerDiscoveryAgent); + switch (s) { + case QUdpSocket::BoundState: + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Running); + socket->setSocketOption(QUdpSocket::SocketOption::MulticastTtlOption, ttl); + + if (type == QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast) { + QNetworkInterface mni; + const auto interfaces = QNetworkInterface::allInterfaces(); + for (const auto &iface : interfaces) { + if (!iface.flags().testFlag(QNetworkInterface::CanMulticast)) + continue; + + const auto entries = iface.addressEntries(); + for (const auto &entry : entries) { + auto ip = entry.ip(); + if (ip.protocol() != QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) + continue; + if (ip != address) + continue; + mni = iface; + break; + } + } + + if (mni.isValid()) + socket->setMulticastInterface(mni); + + if (socket->joinMulticastGroup(multicastAddress, mni)) { + usedPort = multicastPort; + usedAddress = multicastAddress; + } else { + setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error::Network, + QKnxNetIpServerDiscoveryAgent::tr("Could not join multicast group.")); + q->stop(); + } + } else { + usedPort = socket->localPort(); + usedAddress = socket->localAddress(); + } + + if (q->state() == QKnxNetIpServerDiscoveryAgent::State::Running) { + servers.clear(); + + const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> flags(mode); + if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1)) { + auto frame = QKnxNetIpSearchRequestProxy::builder() + .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() + .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) + .setPort(nat ? quint16(0u) : usedPort).create() + ).create(); + socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, + multicastPort); + } + + if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2)) { + auto frame = QKnxNetIpSearchRequestProxy::extendedBuilder() + .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() + .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) + .setPort(nat ? quint16(0u) : usedPort).create() + ) + .setExtendedParameters(srps).create(); + socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, + multicastPort); + } + + setupAndStartReceiveTimer(); + setupAndStartFrequencyTimer(); + } + break; + default: + break; + } + }); + + using overload = void (QUdpSocket::*)(QUdpSocket::SocketError); + QObject::connect(socket, + static_cast<overload>(&QUdpSocket::error), q, [&](QUdpSocket::SocketError) { + setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error::Network, + socket->errorString()); + + Q_Q(QKnxNetIpServerDiscoveryAgent); + q->stop(); + }); + + QObject::connect(socket, &QUdpSocket::readyRead, q, [&]() { + Q_Q(QKnxNetIpServerDiscoveryAgent); + while (socket->hasPendingDatagrams()) { + if (q->state() != QKnxNetIpServerDiscoveryAgent::State::Running) + break; + + auto datagram = socket->receiveDatagram(); + auto data = QKnxByteArray::fromByteArray(datagram.data()); + const auto header = QKnxNetIpFrameHeader::fromBytes(data, 0); + if (!header.isValid()) + continue; + + if (header.serviceType() != QKnxNetIp::ServiceType::SearchResponse && + header.serviceType() != QKnxNetIp::ServiceType::ExtendedSearchResponse) { + continue; + } + + auto frame = QKnxNetIpFrame::fromBytes(data); + auto response = QKnxNetIpSearchResponseProxy(frame); + if (!response.isValid()) + continue; + + const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> flags(mode); + if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1) + && !response.isExtended()) { + setAndEmitDeviceDiscovered({ + (nat ? QKnxNetIpHpaiProxy::builder() + .setHostAddress(datagram.senderAddress()) + .setPort(datagram.senderPort()).create() + : response.controlEndpoint() + ), response.deviceHardware(), response.supportedFamilies(), + adapter.address, adapter.iface + }); + } + + if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2) + && response.isExtended()) { + const auto optionalDibs = response.optionalDibs(); + setAndEmitDeviceDiscovered({ + (nat ? QKnxNetIpHpaiProxy::builder() + .setHostAddress(datagram.senderAddress()) + .setPort(datagram.senderPort()).create() + : response.controlEndpoint() + ), response.deviceHardware(), response.supportedFamilies(), + adapter.address, adapter.iface, + [&optionalDibs]() -> QKnxNetIpDib { + for (const auto &dib : qAsConst(optionalDibs)) { + if (dib.code() == QKnxNetIp::DescriptionType::TunnelingInfo) + return dib; + } + return {}; + }(), + [&optionalDibs]() -> QKnxNetIpDib { + for (const auto &dib : qAsConst(optionalDibs)) { + if (dib.code() == QKnxNetIp::DescriptionType::ExtendedDeviceInfo) + return dib; + } + return {}; + }() + }); + } + } + }); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::setupAndStartReceiveTimer() +{ + Q_Q(QKnxNetIpServerDiscoveryAgent); + + QKnxPrivate::clearTimer(&receiveTimer); + if (timeout >= 0) { + receiveTimer = new QTimer(q); + receiveTimer->setSingleShot(true); + receiveTimer->start(timeout); + QObject::connect(receiveTimer, &QTimer::timeout, q, &QKnxNetIpServerDiscoveryAgent::stop); + } +} + +void QKnxNetIpServerDiscoveryAgentPrivate::setupAndStartFrequencyTimer() +{ + Q_Q(QKnxNetIpServerDiscoveryAgent); + + QKnxPrivate::clearTimer(&frequencyTimer); + if (frequency > 0) { + frequencyTimer = new QTimer(q); + frequencyTimer->setSingleShot(false); + frequencyTimer->start(60000 / frequency); + + QObject::connect(frequencyTimer, &QTimer::timeout, q, [&]() { + Q_Q(QKnxNetIpServerDiscoveryAgent); + if (q->state() == QKnxNetIpServerDiscoveryAgent::State::Running) { + servers.clear(); + + const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> flags(mode); + if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1)) { + auto frame = QKnxNetIpSearchRequestProxy::builder() + .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() + .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) + .setPort(nat ? quint16(0u) : usedPort).create() + ).create(); + socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, + multicastPort); + } + + if (flags.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2)) { + auto frame = QKnxNetIpSearchRequestProxy::extendedBuilder() + .setDiscoveryEndpoint(QKnxNetIpHpaiProxy::builder() + .setHostAddress(nat ? QHostAddress::AnyIPv4 : usedAddress) + .setPort(nat ? quint16(0u) : usedPort).create() + ) + .setExtendedParameters(srps).create(); + socket->writeDatagram(frame.bytes().toByteArray(), multicastAddress, + multicastPort); + } + } + }); + } +} + +void QKnxNetIpServerDiscoveryAgentPrivate::setAndEmitStateChanged( + QKnxNetIpServerDiscoveryAgent::State newState) +{ + state = newState; + + Q_Q(QKnxNetIpServerDiscoveryAgent); + emit q->stateChanged(newState); + + if (state == QKnxNetIpServerDiscoveryAgent::State::Running) + emit q->started(); + else if (state == QKnxNetIpServerDiscoveryAgent::State::NotRunning) + emit q->finished(); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::setAndEmitDeviceDiscovered( + const QKnxNetIpServerInfo &discoveryInfo) +{ + servers.append(discoveryInfo); + + Q_Q(QKnxNetIpServerDiscoveryAgent); + emit q->deviceDiscovered(discoveryInfo); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::setAndEmitErrorOccurred( + QKnxNetIpServerDiscoveryAgent::Error newError, const QString &message) +{ + error = newError; + errorString = message; + + Q_Q(QKnxNetIpServerDiscoveryAgent); + emit q->errorOccurred(error, errorString); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::start() +{ + if (state != QKnxNetIpServerDiscoveryAgent::State::NotRunning) + return; + + if (address.isNull()) + address = QHostAddress(QHostAddress::AnyIPv4); + + auto isIPv4 = true; + address.toIPv4Address(&isIPv4); + if (isIPv4) { + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Starting); + setupSocket(); + if (type == QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast) { + socket->bind(QHostAddress::AnyIPv4, multicastPort, QUdpSocket::ShareAddress + | QAbstractSocket::ReuseAddressHint); + } else { + socket->bind(address, port); + } + } else { + setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error::NotIPv4, + QKnxNetIpServerDiscoveryAgent::tr("Only IPv4 local address supported.")); + } +} + +void QKnxNetIpServerDiscoveryAgentPrivate::start(const QVector<Adapter> &adapters) +{ + if (state != QKnxNetIpServerDiscoveryAgent::State::NotRunning) + return; + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Starting); + + if (adapters.isEmpty()) + return stop(); + + Q_Q(QKnxNetIpServerDiscoveryAgent); + const QFlags<QKnxNetIpServerDiscoveryAgent::ResponseType> rtype(type); + const QFlags<QKnxNetIpServerDiscoveryAgent::DiscoveryMode> dmode(mode); + const DiscovererConfig config { + ttl, + timeout, + nat, + rtype.testFlag(QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast), + dmode.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1), + dmode.testFlag(QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV2), + srps + }; + + bool connectError = (adapters.count() == 1); + for (const auto &adapter : adapters) { + auto discoverer = new Discoverer(adapter.address, adapter.iface, config); + discoveries.append(discoverer); + + auto thread = new QThread; + discoverer->moveToThread(thread); + QObject::connect(thread, &QThread::started, discoverer, &Discoverer::start); + QObject::connect(thread, &QThread::finished, discoverer, &Discoverer::deleteLater); + + QObject::connect(thread, &QThread::started, discoverer, &Discoverer::start); + QObject::connect(thread, &QThread::finished, discoverer, &Discoverer::finish); + + QObject::connect(discoverer, &Discoverer::finished, q, [&](Discoverer *ds) { + discoveries.removeAll(ds); + if (discoveries.isEmpty()) + stop(); + }); + QObject::connect(discoverer, &Discoverer::finished, thread, &QThread::quit); + QObject::connect(discoverer, &Discoverer::deviceDiscovered, q, [&](const QKnxNetIpServerInfo &server) { + setAndEmitDeviceDiscovered(server); + }); + if (connectError) { + QObject::connect(discoverer, &Discoverer::errorOccurred, q, + [&](QKnxNetIpServerDiscoveryAgent::Error error, const QString &errorString) { + setAndEmitErrorOccurred(error, errorString); + }); + } + thread->start(); + } + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Running); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::start(const QVector<QHostAddress> addresses) +{ + start(QKnxPrivate::adaptersForAddresses(addresses)); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::start(QKnxNetIpServerDiscoveryAgent::InterfaceTypes types) +{ + QVector<Adapter> adapters; + auto all = QNetworkInterface::allInterfaces(); + for (const auto &iface : all) { + const auto flags = iface.flags(); + if (!flags.testFlag(QNetworkInterface::IsUp) + && !flags.testFlag(QNetworkInterface::IsRunning) + && !flags.testFlag(QNetworkInterface::CanMulticast)) continue; + + const bool wifi = types.testFlag(QKnxNetIpServerDiscoveryAgent::InterfaceType::Wifi); + const bool loopback = types.testFlag(QKnxNetIpServerDiscoveryAgent::InterfaceType::Loopback); + const bool ethernet = types.testFlag(QKnxNetIpServerDiscoveryAgent::InterfaceType::Ethernet); + + const auto type = iface.type(); + if (!(wifi && type == QNetworkInterface::Wifi) + && !(loopback && type == QNetworkInterface::Loopback) + && !(ethernet && type == QNetworkInterface::Ethernet)) continue; + + const auto entries = iface.addressEntries(); + for (const auto &entry : entries) { + const auto address = entry.ip(); + if (address.protocol() != QAbstractSocket::IPv4Protocol) + continue; + adapters.append({ address, iface }); + break; + } + } + start(adapters); +} + +void QKnxNetIpServerDiscoveryAgentPrivate::stop() +{ + if (state == QKnxNetIpServerDiscoveryAgent::State::Stopping + || state == QKnxNetIpServerDiscoveryAgent::State::NotRunning) { + return; + } + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::Stopping); + + if (socket) { + if (type == QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast + && socket->state() == QUdpSocket::BoundState) { + socket->leaveMulticastGroup(multicastAddress); + } + socket->close(); + } + + QKnxPrivate::clearSocket(&(socket)); + QKnxPrivate::clearTimer(&(receiveTimer)); + QKnxPrivate::clearTimer(&(frequencyTimer)); + + setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State::NotRunning); +} + +QT_END_NAMESPACE diff --git a/src/knx/netip/qknxnetipserverdiscoveryagent_p.h b/src/knx/netip/qknxnetipserverdiscoveryagent_p.h index 21bdcdf..46be5fe 100644 --- a/src/knx/netip/qknxnetipserverdiscoveryagent_p.h +++ b/src/knx/netip/qknxnetipserverdiscoveryagent_p.h @@ -47,14 +47,94 @@ #include <QtKnx/qknxnetipsearchrequest.h> #include <QtKnx/qknxnetipsearchresponse.h> #include <QtKnx/qknxnetipserverdiscoveryagent.h> + #include <QtNetwork/qhostaddress.h> #include <QtNetwork/qnetworkdatagram.h> +#include <QtNetwork/qnetworkinterface.h> #include <QtNetwork/qudpsocket.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE +struct Adapter +{ + QHostAddress address; + QNetworkInterface iface; +}; + +struct DiscovererConfig +{ + DiscovererConfig() = default; + ~DiscovererConfig() = default; + + DiscovererConfig(int ttl, int timeout, bool nat, bool multicast, bool coreV1, bool coreV2, + const QVector<QKnxNetIpSrp> &srps) + : Ttl(ttl) + , Timeout(timeout) + , Nat(nat) + , Multicast(multicast) + , DiscoveryCoreV1(coreV1) + , DiscoveryCoreV2(coreV2) + , ExtendedSearchParameters(srps) + {} + + int Ttl { 64 }; + int Timeout { 3000 }; + + bool Nat { false }; + bool Multicast { true }; + + bool DiscoveryCoreV1 { true }; + bool DiscoveryCoreV2 { true }; + + QVector<QKnxNetIpSrp> ExtendedSearchParameters; +}; + +class Discoverer : public QObject +{ + Q_OBJECT + +public: + Discoverer(const QHostAddress &address, const QNetworkInterface iface, const DiscovererConfig &config); + ~Discoverer() override; + +public slots: + void start(); + void finish(); + +signals: + void started(); + void timeout(); + void finished(Discoverer *iam); + + void stateChanged(QKnxNetIpServerDiscoveryAgent::State state); + void errorOccurred(QKnxNetIpServerDiscoveryAgent::Error error, const QString &errorString); + + void deviceDiscovered(const QKnxNetIpServerInfo &discoveryInfo); + +private slots: + void onTimeout(); + void onReadyRead(); + void onError(QUdpSocket::SocketError error); + +private: + void setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State state); + +private: + QHostAddress m_address; + QNetworkInterface m_iface; + + QTimer *m_timer { nullptr }; + QUdpSocket *m_socket { nullptr }; + + DiscovererConfig m_config; + QVector<QByteArray> m_devices; + + QHostAddress m_multicast { QStringLiteral("224.0.23.12") }; + QKnxNetIpServerDiscoveryAgent::State m_state { QKnxNetIpServerDiscoveryAgent::State::NotRunning }; +}; + class Q_KNX_EXPORT QKnxNetIpServerDiscoveryAgentPrivate final : public QObjectPrivate { Q_DECLARE_PUBLIC(QKnxNetIpServerDiscoveryAgent) @@ -70,7 +150,13 @@ public: void setAndEmitStateChanged(QKnxNetIpServerDiscoveryAgent::State newState); void setAndEmitDeviceDiscovered(const QKnxNetIpServerInfo &discoveryInfo); - void setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error e, const QString &message); + void setAndEmitErrorOccurred(QKnxNetIpServerDiscoveryAgent::Error newError, const QString &message); + + void start(); + void start(const QVector<Adapter> &adapters); + void start(const QVector<QHostAddress> addresses); + void start(QKnxNetIpServerDiscoveryAgent::InterfaceTypes types); + void stop(); private: QUdpSocket *socket { nullptr }; @@ -78,12 +164,12 @@ private: QTimer *frequencyTimer { nullptr }; quint16 port { 0 }, usedPort { 0 }; - QHostAddress address { QHostAddress::AnyIPv4 }, usedAddress; + QHostAddress address { QHostAddress::Null }, usedAddress; const quint16 multicastPort { QKnxNetIp::Constants::DefaultPort }; const QHostAddress multicastAddress { QLatin1String(QKnxNetIp::Constants::MulticastAddress) }; - quint8 ttl { 60 }; + quint8 ttl { 64 }; bool nat { false }; int frequency { 0 }; int timeout { QKnxNetIp::Timeout::SearchTimeout }; @@ -96,9 +182,12 @@ private: QKnxNetIpServerDiscoveryAgent::ResponseType type { QKnxNetIpServerDiscoveryAgent::ResponseType::Multicast }; - QKnxNetIpServerDiscoveryAgent::DiscoveryModes discoveryMode + QKnxNetIpServerDiscoveryAgent::DiscoveryModes mode { QKnxNetIpServerDiscoveryAgent::DiscoveryMode::CoreV1 }; QVector<QKnxNetIpSrp> srps; + + Adapter adapter; + QVector<Discoverer*> discoveries; }; QT_END_NAMESPACE diff --git a/src/knx/netip/qknxnetipserverinfo.cpp b/src/knx/netip/qknxnetipserverinfo.cpp index 31ac706..d8c6b62 100644 --- a/src/knx/netip/qknxnetipserverinfo.cpp +++ b/src/knx/netip/qknxnetipserverinfo.cpp @@ -98,7 +98,9 @@ QT_BEGIN_NAMESPACE */ QKnxNetIpServerInfo::QKnxNetIpServerInfo() : d_ptr(new QKnxNetIpServerInfoPrivate) -{} +{ + qRegisterMetaType<QKnxNetIpServerInfo>(); +} /*! Deletes a KNXnet/IP server information object. @@ -254,6 +256,32 @@ QKnxNetIpDib QKnxNetIpServerInfo::extendedHardware() const } /*! + \since 5.14 + + Returns the host address which has been used to discover the KNXnet/IP + server hardware. + + \sa QHostAddress +*/ +QHostAddress QKnxNetIpServerInfo::hostAddress() const +{ + return d_ptr->address; +} + +/*! + \since 5.14 + + Returns the network interface which has been used to discover the KNXnet/IP + server hardware. + + \sa QNetworkInterface +*/ +QNetworkInterface QKnxNetIpServerInfo::networkInterface() const +{ + return d_ptr->iinterface; +} + +/*! Constructs a copy of \a other. */ QKnxNetIpServerInfo::QKnxNetIpServerInfo(const QKnxNetIpServerInfo &other) @@ -321,16 +349,13 @@ void QKnxNetIpServerInfo::swap(QKnxNetIpServerInfo &other) Q_DECL_NOTHROW d_ptr.swap(other.d_ptr); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! \internal */ QKnxNetIpServerInfo::QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNetIpDib &hardware, -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QKnxNetIpDib services) -#else - const QKnxNetIpDib &services) // ### Qt6: pass services as const reference -#endif : QKnxNetIpServerInfo() { d_ptr->hpai = hpai; @@ -338,17 +363,29 @@ QKnxNetIpServerInfo::QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNe d_ptr->services = services; } - /*! \internal */ QKnxNetIpServerInfo::QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNetIpDib &hardware, const QKnxNetIpDib &services, const QKnxNetIpDib &tunneling, const QKnxNetIpDib &extHardware) + : QKnxNetIpServerInfo(hpai, hardware, services, {}, {}, tunneling, extHardware) +{} + +#endif + +/*! + \internal +*/ +QKnxNetIpServerInfo::QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNetIpDib &hardware, + const QKnxNetIpDib &services, const QHostAddress &address, const QNetworkInterface &iinterface, + const QKnxNetIpDib &tunneling, const QKnxNetIpDib &extHardware) : QKnxNetIpServerInfo() { d_ptr->hpai = hpai; d_ptr->hardware = hardware; d_ptr->services = services; + d_ptr->address = address; + d_ptr->iinterface = iinterface; d_ptr->tunnelingInfo = tunneling; d_ptr->extendedHardware = extHardware; } diff --git a/src/knx/netip/qknxnetipserverinfo.h b/src/knx/netip/qknxnetipserverinfo.h index 772586f..4db9656 100644 --- a/src/knx/netip/qknxnetipserverinfo.h +++ b/src/knx/netip/qknxnetipserverinfo.h @@ -39,6 +39,7 @@ #include <QtKnx/qknxnetiptunnelinginfodib.h> #include <QtNetwork/qhostaddress.h> +#include <QtNetwork/qnetworkinterface.h> QT_BEGIN_NAMESPACE @@ -46,6 +47,7 @@ struct QKnxNetIpServerInfoPrivate; class Q_KNX_EXPORT QKnxNetIpServerInfo final { + friend class Discoverer; friend class QKnxNetIpServerDiscoveryAgentPrivate; friend class QKnxNetIpServerDescriptionAgentPrivate; @@ -72,6 +74,9 @@ public: QKnxNetIpDib tunnelingInfo() const; QKnxNetIpDib extendedHardware() const; + QHostAddress hostAddress() const; + QNetworkInterface networkInterface() const; + QKnxNetIpServerInfo(const QKnxNetIpServerInfo &other); QKnxNetIpServerInfo &operator=(const QKnxNetIpServerInfo &other); @@ -84,16 +89,23 @@ public: void swap(QKnxNetIpServerInfo &other) Q_DECL_NOTHROW; private: - QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNetIpDib &hardware, #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNetIpDib &hardware, QKnxNetIpDib services); -#else - const QKnxNetIpDib &services); -#endif QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, const QKnxNetIpDib &hardware, const QKnxNetIpDib &services, const QKnxNetIpDib &tunnelingInfo, const QKnxNetIpDib &extendedHardware); +#endif + + QKnxNetIpServerInfo(const QKnxNetIpHpai &hpai, + const QKnxNetIpDib &hardware, + const QKnxNetIpDib &services, + const QHostAddress &hostAddress, + const QNetworkInterface &iinterface, + const QKnxNetIpDib &tunnelingInfo = {}, + const QKnxNetIpDib &extendedHardware = {}); + explicit QKnxNetIpServerInfo(QKnxNetIpServerInfoPrivate &dd); private: diff --git a/src/knx/netip/qknxnetipserverinfo_p.h b/src/knx/netip/qknxnetipserverinfo_p.h index 869d909..ca0fd50 100644 --- a/src/knx/netip/qknxnetipserverinfo_p.h +++ b/src/knx/netip/qknxnetipserverinfo_p.h @@ -42,11 +42,15 @@ // #include <QtCore/qshareddata.h> + #include <QtKnx/qtknxglobal.h> #include <QtKnx/qknxnetipdevicedib.h> #include <QtKnx/qknxnetiphpai.h> #include <QtKnx/qknxnetipservicefamiliesdib.h> +#include <QtNetwork/qhostaddress.h> +#include <QtNetwork/qnetworkinterface.h> + QT_BEGIN_NAMESPACE struct Q_KNX_EXPORT QKnxNetIpServerInfoPrivate final : public QSharedData @@ -59,6 +63,8 @@ struct Q_KNX_EXPORT QKnxNetIpServerInfoPrivate final : public QSharedData QKnxNetIpDib services; QKnxNetIpDib tunnelingInfo; QKnxNetIpDib extendedHardware; + QHostAddress address; + QNetworkInterface iinterface; }; QT_END_NAMESPACE diff --git a/src/knx/qknxdevicemanagementframe.cpp b/src/knx/qknxdevicemanagementframe.cpp index 562dd00..c36c5ca 100644 --- a/src/knx/qknxdevicemanagementframe.cpp +++ b/src/knx/qknxdevicemanagementframe.cpp @@ -339,6 +339,7 @@ void QKnxDeviceManagementFrame::setObjectInstance(quint8 instance) { if (instance < 1) return; + d_ptr->m_serviceInformation.resize(3); d_ptr->m_serviceInformation.set(2, instance); } @@ -359,8 +360,10 @@ QKnxInterfaceObjectProperty QKnxDeviceManagementFrame::property() const */ void QKnxDeviceManagementFrame::setProperty(QKnxInterfaceObjectProperty pid) { - if (QKnxInterfaceObjectProperty::isProperty(pid)) + if (QKnxInterfaceObjectProperty::isProperty(pid)) { + d_ptr->m_serviceInformation.resize(4); d_ptr->m_serviceInformation.set(3, quint8(pid)); + } } /*! @@ -384,6 +387,8 @@ void QKnxDeviceManagementFrame::setNumberOfElements(quint8 numOfElements) { if (numOfElements > 0x0f) return; + + d_ptr->m_serviceInformation.resize(5); d_ptr->m_serviceInformation.set(4, (d_ptr->m_serviceInformation.value(4) & 0x0f) | (numOfElements << 4)); } @@ -475,8 +480,7 @@ void QKnxDeviceManagementFrame::setError(QKnxNetIpCemiServer::Error error) switch (messageCode()) { case MessageCode::PropertyReadConfirmation: case MessageCode::PropertyWriteConfirmation: { - if (d_ptr->m_serviceInformation.size() < 7) - d_ptr->m_serviceInformation.resize(7); + d_ptr->m_serviceInformation.resize(7); d_ptr->m_serviceInformation.set(6, quint8(error)); } default: @@ -523,8 +527,7 @@ void QKnxDeviceManagementFrame::setReturnCode(QKnxNetIpCemiServer::ReturnCode co return; } - if (d_ptr->m_serviceInformation.size() < 6) - d_ptr->m_serviceInformation.resize(6); + d_ptr->m_serviceInformation.resize(6); d_ptr->m_serviceInformation.set(5, quint8(code)); } diff --git a/src/knx/ssl/qknxsecurekey.cpp b/src/knx/ssl/qknxsecurekey.cpp index 5aadbf9..8ca21ae 100644 --- a/src/knx/ssl/qknxsecurekey.cpp +++ b/src/knx/ssl/qknxsecurekey.cpp @@ -57,9 +57,9 @@ public: } #if QT_CONFIG(opensslv11) - EVP_PKEY *m_evpPKey{ nullptr }; + EVP_PKEY *m_evpPKey { nullptr }; #endif - QKnxSecureKey::Type m_type{ QKnxSecureKey::Type::Invalid }; + QKnxSecureKey::Type m_type { QKnxSecureKey::Type::Invalid }; }; /*! diff --git a/src/knx/ssl/qsslsocket_openssl11_symbols_p.h b/src/knx/ssl/qsslsocket_openssl11_symbols_p.h index 0fe4ad3..bb88cf1 100644 --- a/src/knx/ssl/qsslsocket_openssl11_symbols_p.h +++ b/src/knx/ssl/qsslsocket_openssl11_symbols_p.h @@ -82,6 +82,7 @@ Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem(); int q_DSA_bits(DSA *a); int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); +Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a); int q_EVP_PKEY_base_id(EVP_PKEY *a); int q_RSA_bits(RSA *a); int q_OPENSSL_sk_num(OPENSSL_STACK *a); @@ -136,7 +137,6 @@ unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session) q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr) int q_EVP_PKEY_set_type(EVP_PKEY *pkey, int type); -int q_EVP_PKEY_up_ref(EVP_PKEY *pkey); int q_EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, const unsigned char *pt, size_t ptlen); diff --git a/src/knx/ssl/qsslsocket_openssl_symbols.cpp b/src/knx/ssl/qsslsocket_openssl_symbols.cpp index c89cafb..d46f869 100644 --- a/src/knx/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/knx/ssl/qsslsocket_openssl_symbols.cpp @@ -62,11 +62,11 @@ # include <QtCore/qlibrary.h> #endif #include <QtCore/qmutex.h> -#include <private/qmutexpool_p.h> #include <QtCore/qdatetime.h> #if defined(Q_OS_UNIX) #include <QtCore/qdir.h> #endif +#include <QtCore/private/qmemory_p.h> #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) #include <link.h> #endif @@ -142,47 +142,47 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName) // Below are the functions first introduced in version 1.1: -DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return 0, return) +DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return nullptr, return) DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return) DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return) -DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return 0, return) -DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return) +DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return nullptr, return) +DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return) DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return) DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return) +DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return) DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG) -DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG) DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) -DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return 0, return) +DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return) DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return) DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return) DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return) -DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return 0, return) -DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return 0, return) +DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return nullptr, return) +DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return nullptr, return) DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return) -DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return 0, return) +DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return nullptr, return) DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG) -DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return 0, return) +DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return nullptr, return) DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG) DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return) -DEFINEFUNC(const char *, OpenSSL_version, int a, a, return 0, return) +DEFINEFUNC(const char *, OpenSSL_version, int a, a, return nullptr, return) DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return) DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG) DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return) DEFINEFUNC2(int, EVP_PKEY_set_type, EVP_PKEY *pkey, pkey, int type, type, return 0, return) DEFINEFUNC3(int, EVP_PKEY_set1_tls_encodedpoint, EVP_PKEY *pkey, pkey, const unsigned char *pt, pt, size_t ptlen, ptlen, return 0, return) -DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *pkey, pkey, return 0, return) DEFINEFUNC2(EVP_PKEY *, d2i_PrivateKey_bio, BIO *bp, bp, EVP_PKEY **a, a, return nullptr, return) DEFINEFUNC2(int, i2d_PUBKEY_bio, BIO *bp, bp, EVP_PKEY *pkey, pkey, return 0, return) @@ -198,15 +198,15 @@ DEFINEFUNC4(EVP_PKEY *, EVP_PKEY_new_raw_private_key, int type, type, ENGINE *e, // Functions below are either deprecated or removed in OpenSSL >= 1.1: -DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return) +DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return nullptr, return) #ifdef SSLEAY_MACROS -DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return) +DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return nullptr, return) #endif -DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return) +DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return nullptr, return) DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG) -DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return) -DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return) +DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return nullptr, return) +DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return) DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG) DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG) @@ -217,23 +217,23 @@ DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG) DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG) #ifdef SSLEAY_MACROS -DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) -DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) +DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return nullptr, return) +DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return nullptr, return) #endif // SSLEAY_MACROS DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return) DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG) #if OPENSSL_VERSION_NUMBER >= 0x10000000L -DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG) DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG) -DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return) +DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return nullptr, return) #else -DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG) DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG) -DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return) +DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return nullptr, return) #endif // OPENSSL_VERSION_NUMBER >= 0x10000000L DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return) @@ -245,49 +245,49 @@ DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO #if OPENSSL_VERSION_NUMBER >= 0x10000000L #ifndef OPENSSL_NO_SSL2 -DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif #ifndef OPENSSL_NO_SSL3_METHOD -DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif -DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x10001000L -DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif #ifndef OPENSSL_NO_SSL2 -DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif #ifndef OPENSSL_NO_SSL3_METHOD -DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif -DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x10001000L -DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif #else #ifndef OPENSSL_NO_SSL2 -DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif #ifndef OPENSSL_NO_SSL3_METHOD -DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif -DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return) #ifndef OPENSSL_NO_SSL2 -DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif #ifndef OPENSSL_NO_SSL3_METHOD -DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif -DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return) #endif -DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return) +DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return nullptr, return) #ifdef SSLEAY_MACROS DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return) @@ -295,17 +295,17 @@ DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, retur #ifndef OPENSSL_NO_EC DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return) #endif -DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return) -DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return) +DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return nullptr, return) +DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return nullptr, return) #ifndef OPENSSL_NO_EC -DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return) +DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return nullptr, return) #endif #endif -DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return) -DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return) +DEFINEFUNC(const char *, SSLeay_version, int a, a, return nullptr, return) #endif // QT_CONFIG(opensslv11) @@ -314,22 +314,22 @@ DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return) DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return) DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return) DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return) -DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return) +DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return nullptr, return) DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return) DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return) DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return) DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast<BN_ULONG>(-1), return) #ifndef OPENSSL_NO_EC -DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return) +DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return nullptr, return) DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return) #endif -DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) -DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return) +DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return nullptr, return) DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return) DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return 0, return) +DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return nullptr, return) DEFINEFUNC(void, EVP_CIPHER_CTX_free, EVP_CIPHER_CTX *a, a, return, DUMMYARG) DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return) DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return) @@ -338,13 +338,13 @@ DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER * DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return) DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return) #ifndef OPENSSL_NO_DES -DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return nullptr, return) #endif #ifndef OPENSSL_NO_RC2 -DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return nullptr, return) #endif -DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) @@ -352,16 +352,16 @@ DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return) #endif DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) -DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return) -DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return) +DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return) +DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return) #ifndef OPENSSL_NO_EC -DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return 0, return) +DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return) #endif -DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) -DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return) -DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return) +DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return nullptr, return) +DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return nullptr, return) DEFINEFUNC(int, OBJ_sn2nid, const char *s, s, return 0, return) DEFINEFUNC(int, OBJ_ln2nid, const char *s, s, return 0, return) DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return) @@ -370,24 +370,24 @@ DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) #ifndef SSLEAY_MACROS -DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) -DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) -DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) #ifndef OPENSSL_NO_EC -DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) #endif -DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) #ifndef OPENSSL_NO_EC DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) #endif #endif // !SSLEAY_MACROS -DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) -DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) -DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) #ifndef OPENSSL_NO_EC -DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) #endif DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) @@ -396,20 +396,20 @@ DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, ret #endif DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG) DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return) -DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return) DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return) -DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return) +DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return nullptr, return) DEFINEFUNC2(int, SSL_CIPHER_get_bits, const SSL_CIPHER *a, a, int *b, b, return 0, return) DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return) DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return) DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return) DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG) #if OPENSSL_VERSION_NUMBER >= 0x10000000L -DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return) +DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return nullptr, return) #else -DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return) +DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return nullptr, return) #endif DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return) DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return) @@ -420,9 +420,9 @@ DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return) DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) -DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return 0, return) +DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x10002000L -DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return 0, return); +DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return); DEFINEFUNC(void, SSL_CONF_CTX_free, SSL_CONF_CTX *a, a, return ,return); DEFINEFUNC2(void, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX *a, a, SSL_CTX *b, b, return, return); DEFINEFUNC2(unsigned int, SSL_CONF_CTX_set_flags, SSL_CONF_CTX *a, a, unsigned int b, b, return 0, return); @@ -430,23 +430,23 @@ DEFINEFUNC(int, SSL_CONF_CTX_finish, SSL_CONF_CTX *a, a, return 0, return); DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char *c, c, return 0, return); #endif DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG) -DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return) +DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x10000000L -DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return) +DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return) #else -DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return) +DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return) #endif DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) -DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return) -DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return) +DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return) +DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x00908000L // 0.9.8 broke SC and BC by changing this function's signature. DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) #else DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return) #endif -DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return) +DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return) DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return) DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return) DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG) @@ -455,8 +455,8 @@ DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG) DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return) DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, return -1, return) DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG) -DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return) -DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return) +DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return nullptr, return) +DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x10001000L DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return) DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return NULL, return) @@ -470,18 +470,18 @@ DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, re DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return) DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return) #ifndef SSLEAY_MACROS -DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return) +DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return nullptr, return) #endif DEFINEFUNC2(void, X509_print, BIO *a, a, X509 *b, b, return, DUMMYARG); -DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return 0, return) +DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return nullptr, return) DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG) -DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return 0, return) +DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return nullptr, return) DEFINEFUNC(int, X509_get_ext_count, X509 *a, a, return 0, return) -DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return 0, return) -DEFINEFUNC(const X509V3_EXT_METHOD *, X509V3_EXT_get, X509_EXTENSION *a, a, return 0, return) -DEFINEFUNC(void *, X509V3_EXT_d2i, X509_EXTENSION *a, a, return 0, return) +DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return nullptr, return) +DEFINEFUNC(const X509V3_EXT_METHOD *, X509V3_EXT_get, X509_EXTENSION *a, a, return nullptr, return) +DEFINEFUNC(void *, X509V3_EXT_d2i, X509_EXTENSION *a, a, return nullptr, return) DEFINEFUNC(int, X509_EXTENSION_get_critical, X509_EXTENSION *a, a, return 0, return) -DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, return 0, return) +DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, return nullptr, return) DEFINEFUNC(void, BASIC_CONSTRAINTS_free, BASIC_CONSTRAINTS *a, a, return, DUMMYARG) DEFINEFUNC(void, AUTHORITY_KEYID_free, AUTHORITY_KEYID *a, a, return, DUMMYARG) DEFINEFUNC(void, GENERAL_NAME_free, GENERAL_NAME *a, a, return, DUMMYARG) @@ -491,28 +491,28 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, const ASN1_STRING *b, b, return 0 DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, return) #endif DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return) -DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return) -DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return) -DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return 0, return) +DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return nullptr, return) +DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return nullptr, return) +DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return nullptr, return) DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return) DEFINEFUNC(int, X509_NAME_entry_count, X509_NAME *a, a, return 0, return) -DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return 0, return) -DEFINEFUNC(ASN1_STRING *, X509_NAME_ENTRY_get_data, X509_NAME_ENTRY *a, a, return 0, return) -DEFINEFUNC(ASN1_OBJECT *, X509_NAME_ENTRY_get_object, X509_NAME_ENTRY *a, a, return 0, return) -DEFINEFUNC(EVP_PKEY *, X509_PUBKEY_get, X509_PUBKEY *a, a, return 0, return) +DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return nullptr, return) +DEFINEFUNC(ASN1_STRING *, X509_NAME_ENTRY_get_data, X509_NAME_ENTRY *a, a, return nullptr, return) +DEFINEFUNC(ASN1_OBJECT *, X509_NAME_ENTRY_get_object, X509_NAME_ENTRY *a, a, return nullptr, return) +DEFINEFUNC(EVP_PKEY *, X509_PUBKEY_get, X509_PUBKEY *a, a, return nullptr, return) DEFINEFUNC(void, X509_STORE_free, X509_STORE *a, a, return, DUMMYARG) -DEFINEFUNC(X509_STORE *, X509_STORE_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(X509_STORE *, X509_STORE_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC2(int, X509_STORE_add_cert, X509_STORE *a, a, X509 *b, b, return 0, return) DEFINEFUNC(void, X509_STORE_CTX_free, X509_STORE_CTX *a, a, return, DUMMYARG) DEFINEFUNC4(int, X509_STORE_CTX_init, X509_STORE_CTX *a, a, X509_STORE *b, b, X509 *c, c, STACK_OF(X509) *d, d, return -1, return) DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, return -1, return) DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return) DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return) -DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return 0, return) -DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return nullptr, return) +DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return) DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return) -DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return) +DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) #if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) DEFINEFUNC6(int, SSL_select_next_proto, unsigned char **out, out, unsigned char *outlen, outlen, const unsigned char *in, in, unsigned int inlen, inlen, @@ -539,15 +539,15 @@ DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char * unsigned *len, len, return, DUMMYARG) #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... -DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) -DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return 0, return) +DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) -DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return 0, return) +DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) #ifndef OPENSSL_NO_EC -DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return 0, return) -DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return 0, return) +DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return) +DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return) DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG) DEFINEFUNC2(size_t, EC_get_builtin_curves, EC_builtin_curve * r, r, size_t nitems, nitems, return 0, return) #if OPENSSL_VERSION_NUMBER >= 0x10002000L @@ -557,7 +557,7 @@ DEFINEFUNC(int, EC_curve_nist2nid, const char *name, name, return 0, return) DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKEY **pkey, pkey, \ X509 **cert, cert, STACK_OF(X509) **ca, ca, return 1, return); -DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return 0, return); +DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return nullptr, return); DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG) #if OPENSSL_VERSION_NUMBER >= 0x10000000L @@ -584,8 +584,8 @@ DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG) #endif #define RESOLVEFUNC(func) \ - if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \ - && !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \ + if (!(_q_##func = _q_PTR_##func(libs.ssl->resolve(#func))) \ + && !(_q_##func = _q_PTR_##func(libs.crypto->resolve(#func)))) \ qsslSocketCannotResolveSymbolWarning(#func); #if !defined QT_LINKED_OPENSSL @@ -664,7 +664,7 @@ static QStringList libraryPathList() // search in .app/Contents/Frameworks UInt32 packageType; - CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, NULL); + CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, nullptr); if (packageType == FOUR_CHAR_CODE('APPL')) { QUrl bundleUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyBundleURL(CFBundleGetMainBundle()))); QUrl frameworksUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle()))); @@ -684,7 +684,7 @@ static QStringList libraryPathList() // discover paths of already loaded libraries QSet<QString> loadedPaths; dl_iterate_phdr(dlIterateCallback, &loadedPaths); - paths.append(loadedPaths.toList()); + paths.append(loadedPaths.values()); #endif return paths; @@ -721,34 +721,31 @@ static QStringList findAllLibCrypto() # endif #ifdef Q_OS_WIN -static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, QPair<QSystemLibrary*, QSystemLibrary*> &pair) -{ - pair.first = 0; - pair.second = 0; - QSystemLibrary *ssleay32 = new QSystemLibrary(ssleay32LibName); +struct LoadedOpenSsl { + std::unique_ptr<QSystemLibrary> ssl, crypto; +}; + +static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, LoadedOpenSsl &result) +{ + auto ssleay32 = qt_make_unique<QSystemLibrary>(ssleay32LibName); if (!ssleay32->load(false)) { - delete ssleay32; return FALSE; } - QSystemLibrary *libeay32 = new QSystemLibrary(libeay32LibName); + auto libeay32 = qt_make_unique<QSystemLibrary>(libeay32LibName); if (!libeay32->load(false)) { - delete ssleay32; - delete libeay32; return FALSE; } - pair.first = ssleay32; - pair.second = libeay32; + result.ssl = std::move(ssleay32); + result.crypto = std::move(libeay32); return TRUE; } -static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32() +static LoadedOpenSsl loadOpenSsl() { - QPair<QSystemLibrary*,QSystemLibrary*> pair; - pair.first = 0; - pair.second = 0; + LoadedOpenSsl result; #if QT_CONFIG(opensslv11) // With OpenSSL 1.1 the names have changed to libssl-1_1(-x64) and libcrypto-1_1(-x64), for builds using @@ -761,7 +758,7 @@ static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32() #endif // !Q_PROCESSOR_x86_64 tryToLoadOpenSslWin32Library(QLatin1String("libssl-1_1" QT_SSL_SUFFIX), - QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), pair); + QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result); #undef QT_SSL_SUFFIX @@ -770,28 +767,30 @@ static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32() // When OpenSSL is built using MSVC then the libraries are named 'ssleay32.dll' and 'libeay32'dll'. // When OpenSSL is built using GCC then different library names are used (depending on the OpenSSL version) // The oldest version of a GCC-based OpenSSL which can be detected by the code below is 0.9.8g (released in 2007) - if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), pair)) { - if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), pair)) { - if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), pair)) { - tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), pair); + if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), result)) { + if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), result)) { + if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), result)) { + tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), result); } } } #endif // !QT_CONFIG(opensslv11) - return pair; + return result; } #else -static QPair<QLibrary*, QLibrary*> loadOpenSsl() +struct LoadedOpenSsl { + std::unique_ptr<QLibrary> ssl, crypto; +}; + +static LoadedOpenSsl loadOpenSsl() { - QPair<QLibrary*,QLibrary*> pair; + LoadedOpenSsl result = {qt_make_unique<QLibrary>(), qt_make_unique<QLibrary>()}; # if defined(Q_OS_UNIX) - QLibrary *&libssl = pair.first; - QLibrary *&libcrypto = pair.second; - libssl = new QLibrary; - libcrypto = new QLibrary; + QLibrary * const libssl = result.ssl.get(); + QLibrary * const libcrypto = result.crypto.get(); // Try to find the libssl library on the system. // @@ -809,6 +808,17 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl() // reason, we will search a few common paths (see findAllLibSsl() above) in hopes // we find one that works. // + // If that fails, for OpenSSL 1.0 we also try some fallbacks -- look up + // libssl.so with a hardcoded soname. The reason is QTBUG-68156: the binary + // builds of Qt happen (at the time of this writing) on RHEL machines, + // which change SHLIB_VERSION_NUMBER to a non-portable string. When running + // those binaries on the target systems, this code won't pick up + // libssl.so.MODIFIED_SHLIB_VERSION_NUMBER because it doesn't exist there. + // Given that the only 1.0 supported release (at the time of this writing) + // is 1.0.2, with soname "1.0.0", give that a try too. Note that we mandate + // OpenSSL >= 1.0.0 with a configure-time check, and OpenSSL has kept binary + // compatibility between 1.0.0 and 1.0.2. + // // It is important, however, to try the canonical name and the unversioned name // without going through the loop. By not specifying a path, we let the system // dlopen(3) function determine it for us. This will include any DT_RUNPATH or @@ -824,11 +834,32 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl() libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER)); if (libcrypto->load() && libssl->load()) { // libssl.so.<SHLIB_VERSION_NUMBER> and libcrypto.so.<SHLIB_VERSION_NUMBER> found - return pair; + return result; } else { libssl->unload(); libcrypto->unload(); } + +#if !QT_CONFIG(opensslv11) + // first-and-half attempts: for OpenSSL 1.0 try to load some hardcoded sonames: + // - "1.0.0" is the official upstream one + // - "1.0.2" is found on some distributions (e.g. Debian) that patch OpenSSL + static const QLatin1String fallbackSonames[] = { + QLatin1String("1.0.0"), + QLatin1String("1.0.2") + }; + + for (auto fallbackSoname : fallbackSonames) { + libssl->setFileNameAndVersion(QLatin1String("ssl"), fallbackSoname); + libcrypto->setFileNameAndVersion(QLatin1String("crypto"), fallbackSoname); + if (libcrypto->load() && libssl->load()) { + return result; + } else { + libssl->unload(); + libcrypto->unload(); + } + } +#endif #endif #ifndef Q_OS_DARWIN @@ -842,7 +873,7 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl() libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); if (libcrypto->load() && libssl->load()) { // libssl.so.0 and libcrypto.so.0 found - return pair; + return result; } else { libssl->unload(); libcrypto->unload(); @@ -867,7 +898,7 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl() if (libssl->load()) { // libssl.so.x and libcrypto.so.x found - return pair; + return result; } else { libssl->unload(); } @@ -877,41 +908,33 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl() } // failed to load anything - delete libssl; - delete libcrypto; - libssl = libcrypto = 0; - return pair; + result = {}; + return result; # else // not implemented for this platform yet - return pair; + return result; # endif } #endif +static QBasicMutex symbolResolveMutex; +static QBasicAtomicInt symbolsResolved = Q_BASIC_ATOMIC_INITIALIZER(false); +static bool triedToResolveSymbols = false; + bool q_resolveOpenSslSymbols() { - static bool symbolsResolved = false; - static bool triedToResolveSymbols = false; -#ifndef QT_NO_THREAD -#if QT_CONFIG(opensslv11) - QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl)); -#else - QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init)); -#endif -#endif - if (symbolsResolved) + if (symbolsResolved.loadAcquire()) + return true; + QMutexLocker locker(&symbolResolveMutex); + if (symbolsResolved.loadRelaxed()) return true; if (triedToResolveSymbols) return false; triedToResolveSymbols = true; -#ifdef Q_OS_WIN - QPair<QSystemLibrary *, QSystemLibrary *> libs = loadOpenSslWin32(); -#else - QPair<QLibrary *, QLibrary *> libs = loadOpenSsl(); -#endif - if (!libs.first || !libs.second) + LoadedOpenSsl libs = loadOpenSsl(); + if (!libs.ssl || !libs.crypto) // failed to load them return false; @@ -921,6 +944,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(OPENSSL_init_crypto) RESOLVEFUNC(ASN1_STRING_get0_data) RESOLVEFUNC(EVP_CIPHER_CTX_reset) + RESOLVEFUNC(EVP_PKEY_up_ref) RESOLVEFUNC(EVP_PKEY_base_id) RESOLVEFUNC(RSA_bits) RESOLVEFUNC(OPENSSL_sk_new_null) @@ -951,8 +975,6 @@ bool q_resolveOpenSslSymbols() if (!_q_OpenSSL_version) { // Apparently, we were built with OpenSSL 1.1 enabled but are now using // a wrong library. - delete libs.first; - delete libs.second; qCWarning(lcSsl, "Incompatible version of OpenSSL"); return false; } @@ -962,7 +984,6 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(DSA_bits) RESOLVEFUNC(EVP_PKEY_set_type) - RESOLVEFUNC(EVP_PKEY_up_ref) RESOLVEFUNC(EVP_PKEY_set1_tls_encodedpoint) RESOLVEFUNC(d2i_PrivateKey_bio) @@ -1047,8 +1068,6 @@ bool q_resolveOpenSslSymbols() // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to // resolve this symbol as a failure to resolve symbols. // The right operand of '||' above is ... a bit of paranoia. - delete libs.first; - delete libs.second; qCWarning(lcSsl, "Incompatible version of OpenSSL"); return false; } @@ -1306,9 +1325,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EVP_sha256) #endif - symbolsResolved = true; - delete libs.first; - delete libs.second; + symbolsResolved.storeRelease(true); return true; } #endif // QT_CONFIG(library) diff --git a/tests/auto/qknxnetipcri/tst_qknxnetipcri.cpp b/tests/auto/qknxnetipcri/tst_qknxnetipcri.cpp index c86c3af..2deae37 100644 --- a/tests/auto/qknxnetipcri/tst_qknxnetipcri.cpp +++ b/tests/auto/qknxnetipcri/tst_qknxnetipcri.cpp @@ -200,7 +200,7 @@ void tst_QKnxNetIpCri::testAdditionalData() .create(); frame2 = QKnxNetIpCriProxy::builder() .setConnectionType(QKnxNetIp::ConnectionType::Tunnel) - .setAdditionalData(QKnxByteArray{ quint8(QKnxNetIp::TunnelLayer::Link), 0x00 } + .setAdditionalData(QKnxByteArray { quint8(QKnxNetIp::TunnelLayer::Link), 0x00 } + address.bytes()) .create(); QCOMPARE(frame, frame2); diff --git a/tests/auto/qknxnetiprouter/tst_qknxnetiprouter.cpp b/tests/auto/qknxnetiprouter/tst_qknxnetiprouter.cpp index 3474b61..47a002b 100644 --- a/tests/auto/qknxnetiprouter/tst_qknxnetiprouter.cpp +++ b/tests/auto/qknxnetiprouter/tst_qknxnetiprouter.cpp @@ -327,7 +327,7 @@ QKnxNetIpFrame dummyRoutingIndication(QKnxAddress dst, quint8 hopCount = 6) .setMedium(QKnx::MediumType::NetIP) .createFrame(); return QKnxNetIpRoutingIndicationProxy::builder() - .setLinkLayerFrame(frame) + .setCemi(frame) .create(); } diff --git a/tests/auto/qknxtunnelframefactory/tst_qknxtunnelframefactory.cpp b/tests/auto/qknxtunnelframefactory/tst_qknxtunnelframefactory.cpp index 6a42544..af06c8f 100644 --- a/tests/auto/qknxtunnelframefactory/tst_qknxtunnelframefactory.cpp +++ b/tests/auto/qknxtunnelframefactory/tst_qknxtunnelframefactory.cpp @@ -300,7 +300,7 @@ void tst_QKnxLinkLayerFrameBuilder::testMemoryRead() .create(); QCOMPARE(extctr.destinationAddressType(), QKnxAddress::Type::Individual); auto byts = extctr.bytes(); - QCOMPARE(extctr.bytes(), QKnxByteArray{0x60}); + QCOMPARE(extctr.bytes(), QKnxByteArray { 0x60 }); auto frame = QKnxLinkLayerFrame::builder().setControlField(ctrl).setExtendedControlField(extctr) .setTpdu(tpdu).setDestinationAddress(destination).setSourceAddress(source) |