diff --git a/src/client/QXmppClient.cpp b/src/client/QXmppClient.cpp index 84ca2221d..ef5e45308 100644 --- a/src/client/QXmppClient.cpp +++ b/src/client/QXmppClient.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2009 Manjeet Dahiya +// SPDX-FileCopyrightText: 2023 Melvin Keskin // // SPDX-License-Identifier: LGPL-2.1-or-later @@ -891,6 +892,18 @@ bool QXmppClient::injectMessage(QXmppMessage &&message) return handled; } +/// +/// Sets errors that are ignored if they occur. +/// +/// \param ignoredErrors errors to be ignored +/// +/// \since QXmpp 1.6 +/// +void QXmppClient::setIgnoredErrors(const QMap> &ignoredErrors) +{ + d->ignoredErrors = ignoredErrors; +} + /// /// Give extensions a chance to handle incoming stanzas. /// @@ -943,6 +956,13 @@ void QXmppClient::_q_streamDisconnected() void QXmppClient::_q_streamError(QXmppClient::Error err) { + // SKip errors that are valid during special procedures such as account creation/deletion. + if (d->ignoredErrors.contains(err) && + (err != QXmppClient::XmppStreamError || + d->ignoredErrors.value(err).contains(d->stream->xmppStreamError()))) { + return; + } + if (d->stream->configuration().autoReconnectionEnabled()) { if (err == QXmppClient::XmppStreamError) { // if we receive a resource conflict, inhibit reconnection diff --git a/src/client/QXmppClient.h b/src/client/QXmppClient.h index 419ef190a..2771fc954 100644 --- a/src/client/QXmppClient.h +++ b/src/client/QXmppClient.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2009 Manjeet Dahiya +// SPDX-FileCopyrightText: 2023 Melvin Keskin // // SPDX-License-Identifier: LGPL-2.1-or-later @@ -325,6 +326,8 @@ public Q_SLOTS: void injectIq(const QDomElement &element, const std::optional &e2eeMetadata); bool injectMessage(QXmppMessage &&message); + void setIgnoredErrors(const QMap> &ignoredErrors); + private Q_SLOTS: void _q_elementReceived(const QDomElement &element, bool &handled); void _q_reconnect(); @@ -339,6 +342,7 @@ private Q_SLOTS: friend class QXmppClientExtension; friend class QXmppInternalClientExtension; friend class TestClient; + friend class QXmppRegistrationManager; }; #endif // QXMPPCLIENT_H diff --git a/src/client/QXmppClient_p.h b/src/client/QXmppClient_p.h index 855040e8d..2d0413b36 100644 --- a/src/client/QXmppClient_p.h +++ b/src/client/QXmppClient_p.h @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: 2020 Manjeet Dahiya // SPDX-FileCopyrightText: 2020 Linus Jahn +// SPDX-FileCopyrightText: 2023 Melvin Keskin // // SPDX-License-Identifier: LGPL-2.1-or-later @@ -18,9 +19,9 @@ #ifndef QXMPPCLIENT_P_H #define QXMPPCLIENT_P_H +#include "QXmppClient.h" #include "QXmppPresence.h" -class QXmppClient; class QXmppClientExtension; class QXmppE2eeExtension; class QXmppLogger; @@ -38,6 +39,7 @@ class QXmppClientPrivate QXmppLogger *logger; /// Pointer to the XMPP stream QXmppOutgoingClient *stream; + QMap> ignoredErrors; QXmppE2eeExtension *encryptionExtension; diff --git a/src/client/QXmppRegistrationManager.cpp b/src/client/QXmppRegistrationManager.cpp index 72ff910a2..b96792107 100644 --- a/src/client/QXmppRegistrationManager.cpp +++ b/src/client/QXmppRegistrationManager.cpp @@ -87,6 +87,8 @@ void QXmppRegistrationManager::deleteAccount() auto iq = QXmppRegisterIq::createUnregistrationRequest(); d->deleteAccountIqId = iq.id(); + client()->setIgnoredErrors({ { QXmppClient::KeepAliveError, {} }, + { QXmppClient::XmppStreamError, { QXmppStanza::Error::Conflict, QXmppStanza::Error::NotAuthorized } } }); client()->sendPacket(iq); } @@ -170,6 +172,12 @@ bool QXmppRegistrationManager::registerOnConnectEnabled() const void QXmppRegistrationManager::setRegisterOnConnectEnabled(bool enabled) { d->registerOnConnectEnabled = enabled; + + if (enabled) { + client()->setIgnoredErrors({ { QXmppClient::XmppStreamError, { QXmppStanza::Error::ConnectionTimeout } } }); + } else { + client()->setIgnoredErrors({}); + } } /// \cond @@ -282,8 +290,15 @@ void QXmppRegistrationManager::setClient(QXmppClient *client) connect(disco, &QXmppDiscoveryManager::infoReceived, this, &QXmppRegistrationManager::handleDiscoInfo); } - connect(client, &QXmppClient::disconnected, this, [this]() { + connect(client, &QXmppClient::disconnected, this, [this, client]() { setSupportedByServer(false); + client->setIgnoredErrors({}); + + if (!d->deleteAccountIqId.isEmpty()) { + info(QStringLiteral("Account deleted successfully.")); + Q_EMIT accountDeleted(); + d->deleteAccountIqId.clear(); + } }); } diff --git a/src/client/QXmppRegistrationManager.h b/src/client/QXmppRegistrationManager.h index 3de3813fb..55761ebfe 100644 --- a/src/client/QXmppRegistrationManager.h +++ b/src/client/QXmppRegistrationManager.h @@ -154,9 +154,8 @@ class QXmppRegistrationManagerPrivate; ///

Filling out the registration form

/// /// Now you need to fill out the registration form. If that takes some time, which is often the case -/// when user interaction is required, the server can close the connection triggering -/// QXmppClient::error() to emit QXmppStanza::Error::ConnectionTimeout before the completed form is -/// submitted to the server. That is due to some servers kicking unauthorized clients after a few +/// when user interaction is required, the server can close the connection before the completed form +/// is submitted to the server. That is due to some servers kicking unauthorized clients after a few /// seconds when they are inactive. In order to support account creation for both servers closing /// the connection and servers keeping it open, you need to handle those cases appropriately. ///