forked from blue/squawk
Message receipt manager not takes care of the message reception, switched on embedded reconnect
This commit is contained in:
parent
57d6e3adab
commit
fe1ae8567a
112
core/account.cpp
112
core/account.cpp
@ -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()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -207,6 +210,8 @@ private slots:
|
||||
void onDiscoveryItemsReceived (const QXmppDiscoveryIq& items);
|
||||
void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info);
|
||||
|
||||
void onReceiptReceived(const QString& jid, const QString &id);
|
||||
|
||||
private:
|
||||
void addedAccount(const QString &bareJid);
|
||||
void handleNewContact(Contact* contact);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user