diff options
Diffstat (limited to 'src/knx/netip/qknxnetipendpointconnection.cpp')
-rw-r--r-- | src/knx/netip/qknxnetipendpointconnection.cpp | 196 |
1 files changed, 72 insertions, 124 deletions
diff --git a/src/knx/netip/qknxnetipendpointconnection.cpp b/src/knx/netip/qknxnetipendpointconnection.cpp index 0afba7b..7d0a5a8 100644 --- a/src/knx/netip/qknxnetipendpointconnection.cpp +++ b/src/knx/netip/qknxnetipendpointconnection.cpp @@ -153,95 +153,64 @@ void QKnxNetIpEndpointConnectionPrivate::setup() m_errorString = QString(); m_error = QKnxNetIpEndpointConnection::Error::None; - QObject::connect(m_dataEndpoint, &QUdpSocket::readyRead, [&]() { - while (m_dataEndpoint && m_dataEndpoint->state() == QUdpSocket::BoundState - && m_dataEndpoint->hasPendingDatagrams()) { - auto datagram = m_dataEndpoint->receiveDatagram(); - QKnxByteArray data(datagram.data().constData(), datagram.data().size()); - const auto header = QKnxNetIpFrameHeader::fromBytes(data, 0); - if (header.isValid() && header.totalSize() == data.size()) { - // TODO: fix the version and validity checks - // if (!m_supportedVersions.contains(header.protocolVersion())) { - // send E_VERSION_NOT_SUPPORTED confirmation frame - // send disconnect request - // } else if (header.protocolVersion() != m_dataEndpointVersion { - // send disconnect request - // } else { - // TODO: set the m_dataEndpointVersion once we receive or send the first frame - switch (header.serviceType()) { - case QKnxNetIp::ServiceType::TunnelingRequest: - processTunnelingRequest(QKnxNetIpFrame::fromBytes(data, 0)); - break; - case QKnxNetIp::ServiceType::TunnelingAcknowledge: - processTunnelingAcknowledge(QKnxNetIpFrame::fromBytes(data, 0)); - break; - case QKnxNetIp::ServiceType::DeviceConfigurationRequest: - processDeviceConfigurationRequest(QKnxNetIpFrame::fromBytes(data, 0)); - break; - case QKnxNetIp::ServiceType::DeviceConfigurationAcknowledge: - processDeviceConfigurationAcknowledge(QKnxNetIpFrame::fromBytes(data, 0)); - break; - default: - processDatagram(QKnxNetIpEndpointConnection::EndpointType::Data, datagram); - break; - } - // } - } - } - }); + QObject::connect(m_socket, &QUdpSocket::readyRead, [&]() { + while (m_socket && m_socket->state() == QUdpSocket::BoundState + && m_socket->hasPendingDatagrams()) { + auto datagram = m_socket->receiveDatagram(); + auto data = QKnxByteArray::fromByteArray(datagram.data()); - using overload = void (QUdpSocket::*)(QUdpSocket::SocketError); - QObject::connect(m_dataEndpoint, - static_cast<overload>(&QUdpSocket::error), [&](QUdpSocket::SocketError) { - setAndEmitErrorOccurred(QKnxNetIpEndpointConnection::Error::Network, - m_dataEndpoint->errorString()); - - Q_Q(QKnxNetIpEndpointConnection); - q->disconnectFromHost(); - }); - - QObject::connect(m_controlEndpoint, &QUdpSocket::readyRead, [&]() { - while (m_controlEndpoint && m_controlEndpoint->state() == QUdpSocket::BoundState - && m_controlEndpoint->hasPendingDatagrams()) { - auto datagram = m_controlEndpoint->receiveDatagram(); - QKnxByteArray data(datagram.data().constData(), datagram.data().size()); const auto header = QKnxNetIpFrameHeader::fromBytes(data, 0); - if (header.isValid() && header.totalSize() == data.size()) { - // TODO: fix the version and validity checks - // if (!m_supportedVersions.contains(header.protocolVersion())) { - // send E_VERSION_NOT_SUPPORTED confirmation frame - // send disconnect request - // } else if (header.protocolVersion() != m_controlEndpointVersion) { - // send disconnect request - // } else { - switch (header.serviceType()) { - case QKnxNetIp::ServiceType::ConnectResponse: - processConnectResponse(QKnxNetIpFrame::fromBytes(data, 0), datagram); - break; - case QKnxNetIp::ServiceType::ConnectionStateResponse: - processConnectionStateResponse(QKnxNetIpFrame::fromBytes(data, 0)); - break; - case QKnxNetIp::ServiceType::DisconnectRequest: - processDisconnectRequest(QKnxNetIpFrame::fromBytes(data, 0)); - break; - case QKnxNetIp::ServiceType::DisconnectResponse: - processDisconnectResponse(QKnxNetIpFrame::fromBytes(data, 0)); - break; - default: - processDatagram(QKnxNetIpEndpointConnection::EndpointType::Control, - datagram); - break; - } - // } + if (!header.isValid() || header.totalSize() != data.size()) + continue; + + // TODO: fix the version and validity checks + // if (!m_supportedVersions.contains(header.protocolVersion())) { + // send E_VERSION_NOT_SUPPORTED confirmation frame + // send disconnect request + // } else if (header.protocolVersion() != m_controlEndpointVersion) { + // send disconnect request + // } else { + // TODO: set the m_dataEndpointVersion once we receive or send the first frame + switch (header.serviceType()) { + case QKnxNetIp::ServiceType::ConnectResponse: + processConnectResponse(QKnxNetIpFrame::fromBytes(data, 0), datagram); + break; + case QKnxNetIp::ServiceType::ConnectionStateResponse: + processConnectionStateResponse(QKnxNetIpFrame::fromBytes(data, 0)); + break; + case QKnxNetIp::ServiceType::DisconnectRequest: + processDisconnectRequest(QKnxNetIpFrame::fromBytes(data, 0)); + break; + case QKnxNetIp::ServiceType::DisconnectResponse: + processDisconnectResponse(QKnxNetIpFrame::fromBytes(data, 0)); + break; + + case QKnxNetIp::ServiceType::TunnelingRequest: + processTunnelingRequest(QKnxNetIpFrame::fromBytes(data, 0)); + break; + case QKnxNetIp::ServiceType::TunnelingAcknowledge: + processTunnelingAcknowledge(QKnxNetIpFrame::fromBytes(data, 0)); + break; + case QKnxNetIp::ServiceType::DeviceConfigurationRequest: + processDeviceConfigurationRequest(QKnxNetIpFrame::fromBytes(data, 0)); + break; + case QKnxNetIp::ServiceType::DeviceConfigurationAcknowledge: + processDeviceConfigurationAcknowledge(QKnxNetIpFrame::fromBytes(data, 0)); + break; + + default: + processDatagram(datagram); + break; } + // } } }); using overload = void (QUdpSocket::*)(QUdpSocket::SocketError); - QObject::connect(m_controlEndpoint, + QObject::connect(m_socket, static_cast<overload>(&QUdpSocket::error), [&](QUdpSocket::SocketError) { setAndEmitErrorOccurred(QKnxNetIpEndpointConnection::Error::Network, - m_controlEndpoint->errorString()); + m_socket->errorString()); Q_Q(QKnxNetIpEndpointConnection); q->disconnectFromHost(); @@ -256,11 +225,8 @@ void QKnxNetIpEndpointConnectionPrivate::cleanup() QKnxPrivate::clearTimer(&m_disconnectRequestTimer); QKnxPrivate::clearTimer(&m_acknowledgeTimer); - if (m_dataEndpoint) m_dataEndpoint->close(); - if (m_controlEndpoint) m_controlEndpoint->close(); - - QKnxPrivate::clearSocket(&m_dataEndpoint); - QKnxPrivate::clearSocket(&m_controlEndpoint); + if (m_socket) m_socket->close(); + QKnxPrivate::clearSocket(&m_socket); setAndEmitStateChanged(QKnxNetIpEndpointConnection::State::Disconnected); } @@ -269,7 +235,7 @@ bool QKnxNetIpEndpointConnectionPrivate::sendCemiRequest() { if (!m_waitForAcknowledgement) { m_waitForAcknowledgement = true; - m_dataEndpoint->writeDatagram(m_lastSendCemiRequest.bytes().toByteArray(), + m_socket->writeDatagram(m_lastSendCemiRequest.bytes().toByteArray(), m_remoteDataEndpoint.address, m_remoteDataEndpoint.port); m_cemiRequests++; m_acknowledgeTimer->start(m_acknowledgeTimeout); @@ -282,7 +248,7 @@ void QKnxNetIpEndpointConnectionPrivate::sendStateRequest() qDebug().noquote().nospace() << "Sending connection state request: 0x" << m_lastStateRequest .bytes().toHex(); - m_controlEndpoint->writeDatagram(m_lastStateRequest.bytes().toByteArray(), + m_socket->writeDatagram(m_lastStateRequest.bytes().toByteArray(), m_remoteControlEndpoint.address, m_remoteControlEndpoint.port); m_stateRequests++; @@ -311,7 +277,7 @@ void QKnxNetIpEndpointConnectionPrivate::processTunnelingRequest(const QKnxNetIp .create(); qDebug() << "Sending tunneling acknowledge:" << ack; - m_dataEndpoint->writeDatagram(ack.bytes().toByteArray(), + m_socket->writeDatagram(ack.bytes().toByteArray(), m_remoteDataEndpoint.address, m_remoteDataEndpoint.port); if (!counterEquals) @@ -383,7 +349,7 @@ void QKnxNetIpEndpointConnectionPrivate::processDeviceConfigurationRequest(const .create(); qDebug() << "Sending device configuration acknowledge:" << ack; - m_dataEndpoint->writeDatagram(ack.bytes().toByteArray(), + m_socket->writeDatagram(ack.bytes().toByteArray(), m_remoteDataEndpoint.address, m_remoteDataEndpoint.port); m_receiveCount++; @@ -459,7 +425,7 @@ void QKnxNetIpEndpointConnectionPrivate::processConnectResponse(const QKnxNetIpF m_lastStateRequest = QKnxNetIpConnectionStateRequestProxy::builder() .setChannelId(m_channelId) - .setControlEndpoint(m_nat ? m_natEndpoint : m_localControlEndpoint) + .setControlEndpoint(m_nat ? m_natEndpoint : m_localEndpoint) .create(); QTimer::singleShot(0, [&]() { sendStateRequest(); }); @@ -509,7 +475,7 @@ void QKnxNetIpEndpointConnectionPrivate::processDisconnectRequest(const QKnxNetI .create(); qDebug() << "Sending disconnect response:" << frame; - m_controlEndpoint->writeDatagram(frame.bytes().toByteArray(), + m_socket->writeDatagram(frame.bytes().toByteArray(), m_remoteControlEndpoint.address, m_remoteControlEndpoint.port); Q_Q(QKnxNetIpEndpointConnection); @@ -533,8 +499,7 @@ void QKnxNetIpEndpointConnectionPrivate::processDisconnectResponse(const QKnxNet } } -void QKnxNetIpEndpointConnectionPrivate::processDatagram(QKnxNetIpEndpointConnection::EndpointType, - const QNetworkDatagram &) +void QKnxNetIpEndpointConnectionPrivate::processDatagram(const QNetworkDatagram &) {} void QKnxNetIpEndpointConnectionPrivate::setAndEmitStateChanged( @@ -602,7 +567,7 @@ quint8 QKnxNetIpEndpointConnection::netIpHeaderVersion(EndpointType endpoint) co quint16 QKnxNetIpEndpointConnection::localPort() const { Q_D(const QKnxNetIpEndpointConnection); - return d->m_localControlEndpoint.port; + return d->m_localEndpoint.port; } void QKnxNetIpEndpointConnection::setLocalPort(quint16 port) @@ -616,7 +581,7 @@ QHostAddress QKnxNetIpEndpointConnection::localAddress() const Q_D(const QKnxNetIpEndpointConnection); if (d->m_state == QKnxNetIpEndpointConnection::Disconnected) return d->m_user.address; - return d->m_localControlEndpoint.address; + return d->m_localEndpoint.address; } void QKnxNetIpEndpointConnection::setLocalAddress(const QHostAddress &address) @@ -702,32 +667,18 @@ void QKnxNetIpEndpointConnection::connectToHost(const QHostAddress &address, qui d->setAndEmitStateChanged(QKnxNetIpEndpointConnection::State::Starting); - auto socket = new QUdpSocket(this); - QKnxPrivate::clearSocket(&(d->m_controlEndpoint)); - if (!socket->bind(d->m_user.address, d->m_user.port)) { - d->setAndEmitErrorOccurred(QKnxNetIpEndpointConnection::Error::Network, - QKnxNetIpEndpointConnection::tr("Could not bind local control endpoint: %1") - .arg(socket->errorString())); - QKnxPrivate::clearSocket(&socket); - d->setAndEmitStateChanged(QKnxNetIpEndpointConnection::State::Disconnected); - return; - } - d->m_controlEndpoint = socket; - d->m_localControlEndpoint = Endpoint(socket->localAddress(), socket->localPort()); + QKnxPrivate::clearSocket(&(d->m_socket)); - socket = new QUdpSocket(this); - QKnxPrivate::clearSocket(&(d->m_dataEndpoint)); - if (!socket->bind(d->m_localControlEndpoint.address, 0)) { + d->m_socket = new QUdpSocket(this); + if (!d->m_socket->bind(d->m_user.address, d->m_user.port)) { d->setAndEmitErrorOccurred(QKnxNetIpEndpointConnection::Error::Network, - QKnxNetIpEndpointConnection::tr("Could not bind local data endpoint: %1") - .arg(socket->errorString())); - QKnxPrivate::clearSocket(&socket); - QKnxPrivate::clearSocket(&(d->m_controlEndpoint)); + QKnxNetIpEndpointConnection::tr("Could not bind endpoint: %1") + .arg(d->m_socket->errorString())); + QKnxPrivate::clearSocket(&d->m_socket); d->setAndEmitStateChanged(QKnxNetIpEndpointConnection::State::Disconnected); return; } - d->m_dataEndpoint = socket; - d->m_localDataEndpoint = Endpoint(socket->localAddress(), socket->localPort()); + d->m_localEndpoint = Endpoint(d->m_socket->localAddress(), d->m_socket->localPort()); d->setAndEmitStateChanged(QKnxNetIpEndpointConnection::State::Bound); @@ -736,11 +687,8 @@ void QKnxNetIpEndpointConnection::connectToHost(const QHostAddress &address, qui d->setAndEmitStateChanged(QKnxNetIpEndpointConnection::State::Connecting); auto request = QKnxNetIpConnectRequestProxy::builder() - .setControlEndpoint(d->m_nat ? d->m_natEndpoint : d->m_localControlEndpoint) - // TODO: Fix this. It cannot work in NAT mode, because the sever does not know the data - // endpoint address if we pass a NAT endpoint. The most likely solution will be to use a - // single socket for control and data endpoint... - .setDataEndpoint(d->m_nat ? d->m_natEndpoint : d->m_localDataEndpoint) + .setControlEndpoint(d->m_nat ? d->m_natEndpoint : d->m_localEndpoint) + .setDataEndpoint(d->m_nat ? d->m_natEndpoint : d->m_localEndpoint) .setRequestInformation(d->m_cri) .create(); d->m_controlEndpointVersion = request.header().protocolVersion(); @@ -749,7 +697,7 @@ void QKnxNetIpEndpointConnection::connectToHost(const QHostAddress &address, qui d->m_connectRequestTimer->start(QKnxNetIp::ConnectRequestTimeout); - d->m_controlEndpoint->writeDatagram(request.bytes().toByteArray(), + d->m_socket->writeDatagram(request.bytes().toByteArray(), d->m_remoteControlEndpoint.address, d->m_remoteControlEndpoint.port); } @@ -768,11 +716,11 @@ void QKnxNetIpEndpointConnection::disconnectFromHost() } else { auto frame = QKnxNetIpDisconnectRequestProxy::builder() .setChannelId(d->m_channelId) - .setControlEndpoint(d->m_nat ? d->m_natEndpoint : d->m_localControlEndpoint) + .setControlEndpoint(d->m_nat ? d->m_natEndpoint : d->m_localEndpoint) .create(); qDebug() << "Sending disconnect request:" << frame; - d->m_controlEndpoint->writeDatagram(frame.bytes().toByteArray(), + d->m_socket->writeDatagram(frame.bytes().toByteArray(), d->m_remoteControlEndpoint.address, d->m_remoteControlEndpoint.port); d->m_disconnectRequestTimer->start(QKnxNetIp::DisconnectRequestTimeout); |