1
0
mirror of https://github.com/qt/qtmqtt.git synced 2026-10-25 16:16:26 +00:00

Fix reconnecting after transport error

In case a connection fails due to a transport error, the client must be
able to try to reconnect. Hence, reset the error state when
connectToHost is called. Furthermore the socket needs to be re-created
if it has been instantiated by QMqttClient previously.

Task-number: QTBUG-65726
Change-Id: Id54e5f91a8ca4d0c7be6f51f1ad79e090c681584
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This commit is contained in:
Maurice Kalinowski 2018-01-30 11:40:15 +01:00
parent 50a203b7eb
commit 68fe97befd
3 changed files with 66 additions and 2 deletions

View File

@ -419,6 +419,7 @@ void QMqttClient::connectToHost(bool encrypted, const QString &sslPeerName)
d->setStateAndError(Disconnected, TransportInvalid);
return;
}
d->m_error = QMqttClient::NoError; // Fresh reconnect, unset error
d->setStateAndError(Connecting);
if (d->m_cleanSession)

View File

@ -87,8 +87,12 @@ bool QMqttConnection::ensureTransport(bool createSecureIfNeeded)
{
qCDebug(lcMqttConnection) << Q_FUNC_INFO << m_transport;
if (m_transport)
return true;
if (m_transport) {
if (m_ownTransport)
delete m_transport;
else
return true;
}
// We are asked to create a transport layer
if (m_clientPrivate->m_hostname.isEmpty() || m_clientPrivate->m_port == 0) {

View File

@ -29,6 +29,7 @@
#include "broker_connection.h"
#include <QtCore/QString>
#include <QtNetwork/QTcpServer>
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtMqtt/QMqttClient>
@ -55,6 +56,7 @@ private Q_SLOTS:
void subscribeLongTopic();
void dataIncludingZero();
void publishLongTopic();
void reconnect_QTBUG65726();
private:
QProcess m_brokerProcess;
QString m_testBroker;
@ -388,6 +390,63 @@ void Tst_QMqttClient::publishLongTopic()
QCOMPARE(pub, -1);
}
class FakeServer : public QObject
{
Q_OBJECT
public:
FakeServer() {
server = new QTcpServer();
connect(server, &QTcpServer::newConnection, this, &FakeServer::createSocket);
server->listen(QHostAddress::Any, 5726);
}
public slots:
void createSocket() {
socket = server->nextPendingConnection();
connect(socket, &QTcpSocket::readyRead, this, &FakeServer::connectionRequested);
}
void connectionRequested() {
// We assume it is always a connect statement, so no verification is done
socket->readAll();
QByteArray response;
response += 0x20;
response += quint8(2); // Payload size
if (!connectionSuccess) {
response += quint8(255); // Causes ProtocolViolation
response += quint8(13);
} else {
response += char(0); // ackFlags
response += char(0); // result
}
qDebug() << "Fake server response:" << connectionSuccess;
socket->write(response);
}
public:
QTcpServer *server;
QTcpSocket *socket;
bool connectionSuccess{false};
};
void Tst_QMqttClient::reconnect_QTBUG65726()
{
FakeServer server;
QMqttClient client;
client.setClientId(QLatin1String("bugclient"));
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
QTRY_COMPARE(client.error(), QMqttClient::ProtocolViolation);
server.connectionSuccess = true;
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
QTRY_COMPARE(client.error(), QMqttClient::NoError);
}
QTEST_MAIN(Tst_QMqttClient)
#include "tst_qmqttclient.moc"