1
0
forked from blue/squawk

Message receipt manager not takes care of the message reception, switched on embedded reconnect

This commit is contained in:
Blue 2020-03-27 23:59:30 +03:00
parent 57d6e3adab
commit fe1ae8567a
7 changed files with 113 additions and 56 deletions

View File

@ -40,6 +40,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
vm(client.findExtension<QXmppVCardManager>()),
um(new QXmppUploadRequestManager()),
dm(client.findExtension<QXmppDiscoveryManager>()),
rcpm(new QXmppMessageReceiptManager()),
contacts(),
conferences(),
maxReconnectTimes(0),
@ -58,6 +59,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
config.setDomain(p_server);
config.setPassword(p_password);
config.setAutoAcceptSubscriptions(true);
config.setAutoReconnectionEnabled(false);
QObject::connect(&client, &QXmppClient::connected, this, &Account::onClientConnected);
QObject::connect(&client, &QXmppClient::disconnected, this, &Account::onClientDisconnected);
@ -101,6 +103,10 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
QObject::connect(network, &NetworkAccess::uploadFileComplete, this, &Account::onFileUploaded);
QObject::connect(network, &NetworkAccess::uploadFileError, this, &Account::onFileUploadError);
client.addExtension(rcpm);
QObject::connect(rcpm, &QXmppMessageReceiptManager::messageDelivered, this, &Account::onReceiptReceived);
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
path += "/" + name;
QDir dir(path);
@ -160,6 +166,8 @@ Account::~Account()
delete itr->second;
}
delete rcpm;
delete dm;
delete um;
delete bm;
delete mm;
@ -200,8 +208,8 @@ void Core::Account::onClientConnected()
if (state == Shared::connecting) {
reconnectTimes = maxReconnectTimes;
state = Shared::connected;
cm->setCarbonsEnabled(true);
dm->requestItems(getServer());
dm->requestInfo(getServer());
emit connectionStateChanged(state);
} else {
qDebug() << "Something weird had happened - xmpp client reported about successful connection but account wasn't in" << state << "state";
@ -560,14 +568,15 @@ void Core::Account::onMessageReceived(const QXmppMessage& msg)
if (itr != pendingStateMessages.end()) {
QString jid = itr->second;
RosterItem* cnt = getRosterItem(jid);
if (cnt != 0) {
cnt->changeMessageState(id, Shared::Message::State::error);
}
;
emit changeMessage(jid, id, {
QMap<QString, QVariant> cData = {
{"state", static_cast<uint>(Shared::Message::State::error)},
{"errorText", msg.error().text()}
});
};
if (cnt != 0) {
cnt->changeMessage(id, cData);
}
;
emit changeMessage(jid, id, cData);
pendingStateMessages.erase(itr);
handled = true;
} else {
@ -610,35 +619,43 @@ QString Core::Account::getFullJid() const
return getLogin() + "@" + getServer() + "/" + getResource();
}
void Core::Account::sendMessage(const Shared::Message& data)
void Core::Account::sendMessage(Shared::Message data)
{
QString jid = data.getPenPalJid();
QString id = data.getId();
RosterItem* ri = getRosterItem(jid);
if (state == Shared::connected) {
QXmppMessage msg(getFullJid(), data.getTo(), data.getBody(), data.getThread());
msg.setId(data.getId());
msg.setId(id);
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
msg.setOutOfBandUrl(data.getOutOfBandUrl());
msg.setReceiptRequested(true);
RosterItem* ri = 0;
std::map<QString, Contact*>::const_iterator itr = contacts.find(data.getPenPalJid());
if (itr != contacts.end()) {
ri = itr->second;
bool sent = client.sendPacket(msg);
if (sent) {
data.setState(Shared::Message::State::sent);
} else {
std::map<QString, Conference*>::const_iterator ritr = conferences.find(data.getPenPalJid());
if (ritr != conferences.end()) {
ri = ritr->second;
}
data.setState(Shared::Message::State::error);
data.setErrorText("Couldn't send message via QXMPP library check out logs");
}
if (ri != 0) {
ri->appendMessageToArchive(data);
pendingStateMessages.insert(std::make_pair(data.getId(), data.getPenPalJid()));
if (sent) {
pendingStateMessages.insert(std::make_pair(id, jid));
}
}
client.sendPacket(msg);
} else {
qDebug() << "An attempt to send message with not connected account " << name << ", skipping";
data.setState(Shared::Message::State::error);
data.setErrorText("You are is offline or reconnecting");
}
emit changeMessage(jid, id, {
{"state", static_cast<uint>(data.getState())},
{"errorText", data.getErrorText()}
});
}
void Core::Account::sendMessage(const Shared::Message& data, const QString& path)
@ -659,7 +676,7 @@ void Core::Account::sendMessage(const Shared::Message& data, const QString& path
um->requestUploadSlot(file);
}
} else {
emit onFileUploadError(data.getId(), "Uploading file dissapeared or your system user has no permission to read it");
emit onFileUploadError(data.getId(), "Uploading file no longer exists or your system user has no permission to read it");
qDebug() << "Requested upload slot in account" << name << "for file" << path << "but the file doesn't exist or is not readable";
}
} else {
@ -717,18 +734,17 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
}));
handleNewContact(cnt);
}
if (outgoing) {
if (forwarded) {
sMsg.setState(Shared::Message::State::sent);
}
} else {
sMsg.setState(Shared::Message::State::delivered);
}
cnt->appendMessageToArchive(sMsg);
emit message(sMsg);
if (!forwarded && !outgoing) {
if (msg.isReceiptRequested() && id.size() > 0) {
QXmppMessage receipt(getFullJid(), msg.from(), "");
receipt.setReceiptId(id);
client.sendPacket(receipt);
}
}
return true;
}
return false;
@ -752,9 +768,10 @@ bool Core::Account::handleGroupMessage(const QXmppMessage& msg, bool outgoing, b
std::map<QString, QString>::const_iterator pItr = pendingStateMessages.find(id);
if (pItr != pendingStateMessages.end()) {
cnt->changeMessageState(id, Shared::Message::State::delivered);
QMap<QString, QVariant> cData = {{"state", static_cast<uint>(Shared::Message::State::delivered)}};
cnt->changeMessage(id, cData);
pendingStateMessages.erase(pItr);
emit changeMessage(jid, id, {{"state", static_cast<uint>(Shared::Message::State::delivered)}});
emit changeMessage(jid, id, cData);
} else {
cnt->appendMessageToArchive(sMsg);
QDateTime minAgo = QDateTime::currentDateTime().addSecs(-60);
@ -765,14 +782,6 @@ bool Core::Account::handleGroupMessage(const QXmppMessage& msg, bool outgoing, b
}
}
if (!forwarded && !outgoing) {
if (msg.isReceiptRequested() && id.size() > 0) {
QXmppMessage receipt(getFullJid(), msg.from(), "");
receipt.setReceiptId(id);
client.sendPacket(receipt);
}
}
return true;
}
return false;
@ -1658,11 +1667,32 @@ void Core::Account::onFileUploadError(const QString& messageId, const QString& e
void Core::Account::onDiscoveryItemsReceived(const QXmppDiscoveryIq& items)
{
for (QXmppDiscoveryIq::Item item : items.items()) {
dm->requestInfo(item.jid());
if (item.jid() != getServer()) {
dm->requestInfo(item.jid());
}
}
}
void Core::Account::onDiscoveryInfoReceived(const QXmppDiscoveryIq& info)
{
if (info.from() == getServer()) {
if (info.features().contains("urn:xmpp:carbons:2")) {
cm->setCarbonsEnabled(true);
}
}
}
void Core::Account::onReceiptReceived(const QString& jid, const QString& id)
{
std::map<QString, QString>::const_iterator itr = pendingStateMessages.find(id);
if (itr != pendingStateMessages.end()) {
QMap<QString, QVariant> cData = {{"state", static_cast<uint>(Shared::Message::State::delivered)}};
RosterItem* ri = getRosterItem(itr->second);
if (ri != 0) {
ri->changeMessage(id, cData);
}
pendingStateMessages.erase(itr);
emit changeMessage(itr->second, id, cData);
}
}

View File

@ -41,6 +41,8 @@
#include <QXmppHttpUploadIq.h>
#include <QXmppVCardIq.h>
#include <QXmppVCardManager.h>
#include <QXmppMessageReceiptManager.h>
#include "global.h"
#include "contact.h"
#include "conference.h"
@ -76,7 +78,7 @@ public:
void setResource(const QString& p_resource);
void setAvailability(Shared::Availability avail);
QString getFullJid() const;
void sendMessage(const Shared::Message& data);
void sendMessage(Shared::Message data);
void sendMessage(const Shared::Message& data, const QString& path);
void requestArchive(const QString& jid, int count, const QString& before);
void setReconnectTimes(unsigned int times);
@ -139,6 +141,7 @@ private:
QXmppVCardManager* vm;
QXmppUploadRequestManager* um;
QXmppDiscoveryManager* dm;
QXmppMessageReceiptManager* rcpm;
std::map<QString, Contact*> contacts;
std::map<QString, Conference*> conferences;
unsigned int maxReconnectTimes;
@ -206,6 +209,8 @@ private slots:
void onFileUploadError(const QString& messageId, const QString& errMsg);
void onDiscoveryItemsReceived (const QXmppDiscoveryIq& items);
void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info);
void onReceiptReceived(const QString& jid, const QString &id);
private:
void addedAccount(const QString &bareJid);

View File

@ -208,7 +208,7 @@ Shared::Message Core::Archive::getMessage(const std::string& id, MDB_txn* txn)
}
}
void Core::Archive::setMessageState(const QString& id, Shared::Message::State state)
void Core::Archive::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
if (!opened) {
throw Closed("setMessageState", jid.toStdString());
@ -220,21 +220,42 @@ void Core::Archive::setMessageState(const QString& id, Shared::Message::State st
std::string strId(id.toStdString());
try {
Shared::Message msg = getMessage(strId, txn);
msg.setState(state);
QDateTime oTime = msg.getTime();
bool idChange = msg.change(data);
MDB_val lmdbKey, lmdbData;
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
msg.serialize(ds);
lmdbKey.mv_size = strId.size();
lmdbKey.mv_data = (char*)strId.c_str();
int rc;
if (idChange) {
rc = mdb_del(txn, main, &lmdbKey, &lmdbData);
if (rc == 0) {
strId = msg.getId().toStdString();
lmdbKey.mv_size = strId.size();
lmdbKey.mv_data = (char*)strId.c_str();
quint64 stamp = oTime.toMSecsSinceEpoch();
lmdbData.mv_data = (quint8*)&stamp;
lmdbData.mv_size = 8;
rc = mdb_put(txn, order, &lmdbData, &lmdbKey, 0);
if (rc != 0) {
throw Unknown(jid.toStdString(), mdb_strerror(rc));
}
} else {
throw Unknown(jid.toStdString(), mdb_strerror(rc));
}
}
lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data();
int rc = mdb_put(txn, main, &lmdbKey, &lmdbData, 0);
rc = mdb_put(txn, main, &lmdbKey, &lmdbData, 0);
if (rc == 0) {
rc = mdb_txn_commit(txn);
} else {
mdb_txn_abort(txn);
throw Unknown(jid.toStdString(), mdb_strerror(rc));
}

View File

@ -24,9 +24,9 @@
#include <QMimeDatabase>
#include <QMimeType>
#include "../global.h"
#include "global.h"
#include "exception.h"
#include <lmdb.h>
#include "../exception.h"
#include <list>
namespace Core {
@ -46,7 +46,7 @@ public:
bool addElement(const Shared::Message& message);
unsigned int addElements(const std::list<Shared::Message>& messages);
Shared::Message getElement(const QString& id);
void setMessageState(const QString& id, Shared::Message::State state);
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
Shared::Message oldest();
QString oldestId();
Shared::Message newest();

View File

@ -221,12 +221,12 @@ void Core::RosterItem::appendMessageToArchive(const Shared::Message& msg)
}
}
void Core::RosterItem::changeMessageState(const QString& id, Shared::Message::State newState)
void Core::RosterItem::changeMessage(const QString& id, const QMap<QString, QVariant>& data)
{
bool found = false;
for (Shared::Message& msg : appendCache) {
if (msg.getId() == id) {
msg.setState(newState);
msg.change(data);
found = true;
break;
}
@ -235,7 +235,7 @@ void Core::RosterItem::changeMessageState(const QString& id, Shared::Message::St
if (!found) {
for (Shared::Message& msg : hisoryCache) {
if (msg.getId() == id) {
msg.setState(newState);
msg.change(data);
found = true;
break;
}
@ -244,7 +244,7 @@ void Core::RosterItem::changeMessageState(const QString& id, Shared::Message::St
if (!found) {
try {
archive->setMessageState(id, newState);
archive->changeMessage(id, data);
found = true;
} catch (const Archive::NotFound& e) {
qDebug() << "An attempt to change state to the message" << id << "but it couldn't be found";
@ -254,7 +254,7 @@ void Core::RosterItem::changeMessageState(const QString& id, Shared::Message::St
if (found) {
for (Shared::Message& msg : responseCache) {
if (msg.getId() == id) {
msg.setState(newState);
msg.change(data);
break;
}
}

View File

@ -72,7 +72,7 @@ public:
virtual Shared::VCard handleResponseVCard(const QXmppVCardIq& card, const QString& resource);
virtual void handlePresence(const QXmppPresence& pres) = 0;
void changeMessageState(const QString& id, Shared::Message::State newState);
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
signals:
void nameChanged(const QString& name);

View File

@ -71,6 +71,7 @@ void Chat::handleSendMessage(const QString& text)
msg.setOutgoing(true);
msg.generateRandomId();
msg.setCurrentTime();
msg.setState(Shared::Message::State::pending);
addMessage(msg);
emit sendMessage(msg);
}