diff --git a/core/account.cpp b/core/account.cpp index 4b25737..e1bbfb9 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -51,6 +51,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& um(new QXmppUploadRequestManager()), dm(client.findExtension()), rcpm(new QXmppMessageReceiptManager()), + psm(new QXmppPubSubManager()), reconnectScheduled(false), reconnectTimer(new QTimer), network(p_net), @@ -58,7 +59,8 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& lastError(Error::none), pepSupport(Shared::Support::unknown), active(p_active), - notReadyPassword(false) + notReadyPassword(false), + loadingOmemo(false) { config.setUser(p_login); config.setDomain(p_server); @@ -99,10 +101,31 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& client.addExtension(rcpm); QObject::connect(rcpm, &QXmppMessageReceiptManager::messageDelivered, mh, &MessageHandler::onReceiptReceived); + client.addExtension(psm); + #ifdef WITH_OMEMO client.addExtension(tm); client.addExtension(om); - qDebug("Added OMEMO manager"); + + if (oh->hasOwnDevice()) { + QFuture future = om->load(); + loadingOmemo = true; + + QFutureWatcher *watcher = new QFutureWatcher(this); + QObject::connect(watcher, &QFutureWatcherBase::finished, [watcher, this] () { + loadingOmemo = false; + if (state == Shared::ConnectionState::scheduled) { + client.connectToServer(config, presence); + } + if (watcher->result()) { + qDebug() << "successfully loaded OMEMO data for account" << getName(); + } else { + qDebug() << "couldn't load OMEMO data for account" << getName(); + } + watcher->deleteLater(); + }); + watcher->setFuture(future); + } #endif reconnectTimer->setSingleShot(true); @@ -162,7 +185,12 @@ void Core::Account::connect() if (notReadyPassword) { emit needPassword(); } else { - client.connectToServer(config, presence); + if (loadingOmemo) { + state = Shared::ConnectionState::scheduled; + emit connectionStateChanged(state); + } else { + client.connectToServer(config, presence); + } } } else { @@ -186,7 +214,12 @@ void Core::Account::disconnect() } if (state != Shared::ConnectionState::disconnected) { //rh->clearConferences(); - client.disconnectFromServer(); + if (state != Shared::ConnectionState::scheduled) { + client.disconnectFromServer(); + } else { + state = Shared::ConnectionState::disconnected; + emit connectionStateChanged(state); + } } } @@ -199,9 +232,29 @@ void Core::Account::onClientStateChange(QXmppClient::State st) Shared::ConnectionState os = state; state = Shared::ConnectionState::connected; if (os == Shared::ConnectionState::connecting) { - qDebug() << "running service discovery for account" << name; - dm->requestItems(getServer()); - dm->requestInfo(getServer()); +#ifdef WITH_OMEMO + if (!oh->hasOwnDevice()) { + qDebug() << "setting up OMEMO data for account" << getName(); + QFuture future = om->setUp(); + QFutureWatcher *watcher = new QFutureWatcher(this); + QObject::connect(watcher, &QFutureWatcherBase::finished, [watcher, this] () { + if (watcher->result()) { + qDebug() << "successfully set up OMEMO data for account" << getName(); + } else { + qDebug() << "couldn't set up OMEMO data for account" << getName(); + } + watcher->deleteLater(); + if (state == Shared::ConnectionState::connected) { + runDiscoveryService(); + } + }); + watcher->setFuture(future); + } else { + runDiscoveryService(); + } +#else + runDiscoveryService(); +#endif } lastError = Error::none; emit connectionStateChanged(state); @@ -270,6 +323,13 @@ void Core::Account::setAvailability(Shared::Availability avail) } } +void Core::Account::runDiscoveryService() { + qDebug() << "running service discovery for account" << name; + dm->requestItems(getServer()); + dm->requestInfo(getServer()); +} + + void Core::Account::onPresenceReceived(const QXmppPresence& p_presence) { QString id = p_presence.from(); diff --git a/core/account.h b/core/account.h index 7e5e3b0..393b6e6 100644 --- a/core/account.h +++ b/core/account.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -195,6 +196,7 @@ private: QXmppUploadRequestManager* um; QXmppDiscoveryManager* dm; QXmppMessageReceiptManager* rcpm; + QXmppPubSubManager* psm; bool reconnectScheduled; QTimer* reconnectTimer; @@ -204,6 +206,7 @@ private: Shared::Support pepSupport; bool active; bool notReadyPassword; + bool loadingOmemo; private slots: void onClientStateChange(QXmppClient::State state); @@ -223,6 +226,7 @@ private: void handleDisconnection(); void onReconnectTimer(); void setPepSupport(Shared::Support support); + void runDiscoveryService(); }; } diff --git a/core/handlers/discoveryhandler.cpp b/core/handlers/discoveryhandler.cpp index 2464f07..20e982c 100644 --- a/core/handlers/discoveryhandler.cpp +++ b/core/handlers/discoveryhandler.cpp @@ -21,7 +21,8 @@ Core::DiscoveryHandler::DiscoveryHandler(Core::Account* account): QObject(), - acc(account) {} + acc(account), + omemoToCarbonsConnected (false) {} Core::DiscoveryHandler::~DiscoveryHandler() {} @@ -79,6 +80,19 @@ void Core::DiscoveryHandler::onInfoReceived(const QXmppDiscoveryIq& info) if (enableCC) { qDebug() << "Enabling carbon copies for account" << accName; acc->cm->setCarbonsEnabled(true); +#ifdef WITH_OMEMO + if (!omemoToCarbonsConnected && acc->oh->hasOwnDevice()) { + // connect(this, &QXmppCarbonManager::messageSent, acc->om, &QXmppOmemoManager::handleMessage); + // connect(this, &QXmppCarbonManager::messageReceived, acc->om, &QXmppOmemoManager::handleMessage); + omemoToCarbonsConnected = true; + } + } else { + if (omemoToCarbonsConnected) { + // disconnect(this, &QXmppCarbonManager::messageSent, acc->om, &QXmppOmemoManager::handleMessage); + // disconnect(this, &QXmppCarbonManager::messageReceived, acc->om, &QXmppOmemoManager::handleMessage); + omemoToCarbonsConnected = false; + } +#endif } qDebug() << "Requesting account" << accName << "capabilities"; diff --git a/core/handlers/discoveryhandler.h b/core/handlers/discoveryhandler.h index e4ef265..4bf5baf 100644 --- a/core/handlers/discoveryhandler.h +++ b/core/handlers/discoveryhandler.h @@ -40,6 +40,7 @@ private slots: private: Account* acc; + bool omemoToCarbonsConnected; }; } diff --git a/core/handlers/omemohandler.cpp b/core/handlers/omemohandler.cpp index 25ac752..8ce5932 100644 --- a/core/handlers/omemohandler.cpp +++ b/core/handlers/omemohandler.cpp @@ -31,7 +31,7 @@ Core::OmemoHandler::OmemoHandler(Account* account) : db.open(); try { QVariant own = meta->getRecord("ownDevice"); - ownDevice.value() = own.value(); + ownDevice = own.value(); qDebug() << "Successfully found own device omemo data for account" << acc->getName(); } catch (const DataBase::NotFound& e) { qDebug() << "No device omemo data was found for account" << acc->getName(); @@ -42,6 +42,10 @@ Core::OmemoHandler::~OmemoHandler() { db.close(); } +bool Core::OmemoHandler::hasOwnDevice() { + return ownDevice.has_value(); +} + QFuture Core::OmemoHandler::emptyVoidFuture() { QFutureInterface result(QFutureInterfaceBase::Started); result.reportFinished(); @@ -101,7 +105,7 @@ QFuture Core::OmemoHandler::addPreKeyPairs(const QHash Core::OmemoHandler::addSignedPreKeyPair(uint32_t keyId, const QXmppOmemoStorage::SignedPreKeyPair& keyPair) { - signedPreKeyPairs->addRecord(keyId, keyPair); + signedPreKeyPairs->forceRecord(keyId, keyPair); return emptyVoidFuture(); } diff --git a/core/handlers/omemohandler.h b/core/handlers/omemohandler.h index 537dfec..bae14cb 100644 --- a/core/handlers/omemohandler.h +++ b/core/handlers/omemohandler.h @@ -49,6 +49,8 @@ public: QFuture resetAll() override; + bool hasOwnDevice(); + private: static QFuture emptyVoidFuture(); diff --git a/core/squawk.cpp b/core/squawk.cpp index 3b976b0..6600fcb 100644 --- a/core/squawk.cpp +++ b/core/squawk.cpp @@ -265,10 +265,13 @@ void Core::Squawk::disconnectAccount(const QString& account) void Core::Squawk::onAccountConnectionStateChanged(Shared::ConnectionState p_state) { Account* acc = static_cast(sender()); - emit changeAccount(acc->getName(), { - {"state", QVariant::fromValue(p_state)}, - {"error", ""} - }); + QMap changes = { + {"state", QVariant::fromValue(p_state)} + }; + if (acc->getLastError() == Account::Error::none) { + changes.insert("error", ""); + } + emit changeAccount(acc->getName(), changes); #ifdef WITH_KWALLET if (p_state == Shared::ConnectionState::connected) { diff --git a/core/squawk.h b/core/squawk.h index cdaaf6e..da4aa7e 100644 --- a/core/squawk.h +++ b/core/squawk.h @@ -187,15 +187,6 @@ private slots: private: void readSettings(); - void parseAccount( - const QString& login, - const QString& server, - const QString& password, - const QString& name, - const QString& resource, - bool active, - Shared::AccountPassword passwordType - ); static const quint64 passwordHash = 0x08d054225ac4871d; }; diff --git a/main/main.cpp b/main/main.cpp index 58063e0..020d755 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -52,6 +52,9 @@ int main(int argc, char *argv[]) qRegisterMetaType("Shared::Availability"); #ifdef WITH_OMEMO qRegisterMetaType("QXmppOmemoStorage::OwnDevice"); + qRegisterMetaTypeStreamOperators("QXmppOmemoStorage::OwnDevice"); + qRegisterMetaType("QXmppOmemoStorage::Device"); + qRegisterMetaType("QXmppOmemoStorage::SignedPreKeyPair"); #endif QApplication app(argc, argv); diff --git a/shared/enums.h b/shared/enums.h index a32b57e..7a1f092 100644 --- a/shared/enums.h +++ b/shared/enums.h @@ -29,12 +29,13 @@ Q_NAMESPACE enum class ConnectionState { disconnected, + scheduled, connecting, connected, error }; Q_ENUM_NS(ConnectionState) -static const std::deque connectionStateThemeIcons = {"state-offline", "state-sync", "state-ok", "state-error"}; +static const std::deque connectionStateThemeIcons = {"state-offline", "state-sync", "state-sync", "state-ok", "state-error"}; static const ConnectionState ConnectionStateHighest = ConnectionState::error; static const ConnectionState ConnectionStateLowest = ConnectionState::disconnected; diff --git a/shared/global.cpp b/shared/global.cpp index 6519952..a6f17dc 100644 --- a/shared/global.cpp +++ b/shared/global.cpp @@ -49,7 +49,8 @@ Shared::Global::Global(): }), connectionState({ tr("Disconnected", "ConnectionState"), - tr("Connecting", "ConnectionState"), + tr("Scheduled", "ConnectionState"), + tr("Connecting", "ConnectionState"), tr("Connected", "ConnectionState"), tr("Error", "ConnectionState") }), diff --git a/shared/icons.h b/shared/icons.h index 540d3e9..cf31b3b 100644 --- a/shared/icons.h +++ b/shared/icons.h @@ -48,6 +48,7 @@ static const std::deque fallbackSubscriptionStateThemeIconsLightBig = { static const std::deque fallbackConnectionStateThemeIconsLightBig = { ":images/fallback/light/big/state-offline.svg", ":images/fallback/light/big/state-sync.svg", + ":images/fallback/light/big/state-sync.svg", ":images/fallback/light/big/state-ok.svg", ":images/fallback/light/big/state-error.svg" }; @@ -73,6 +74,7 @@ static const std::deque fallbackSubscriptionStateThemeIconsLightSmall = static const std::deque fallbackConnectionStateThemeIconsLightSmall = { ":images/fallback/light/small/state-offline.svg", ":images/fallback/light/small/state-sync.svg", + ":images/fallback/light/small/state-sync.svg", ":images/fallback/light/small/state-ok.svg", ":images/fallback/light/small/state-error.svg" }; @@ -98,6 +100,7 @@ static const std::deque fallbackSubscriptionStateThemeIconsDarkBig = { static const std::deque fallbackConnectionStateThemeIconsDarkBig = { ":images/fallback/dark/big/state-offline.svg", ":images/fallback/dark/big/state-sync.svg", + ":images/fallback/dark/big/state-sync.svg", ":images/fallback/dark/big/state-ok.svg", ":images/fallback/dark/big/state-error.svg" }; @@ -123,6 +126,7 @@ static const std::deque fallbackSubscriptionStateThemeIconsDarkSmall = static const std::deque fallbackConnectionStateThemeIconsDarkSmall = { ":images/fallback/dark/small/state-offline.svg", ":images/fallback/dark/small/state-sync.svg", + ":images/fallback/dark/small/state-sync.svg", ":images/fallback/dark/small/state-ok.svg", ":images/fallback/dark/small/state-error.svg" };