256 lines
7.6 KiB
C++
256 lines
7.6 KiB
C++
|
// Squawk messenger.
|
||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU General Public License as published by
|
||
|
// the Free Software Foundation, either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include "delaymanager.h"
|
||
|
|
||
|
#include "cardinternal.h"
|
||
|
#include "infoforuser.h"
|
||
|
#include "owncardinternal.h"
|
||
|
#include "owninfoforuser.h"
|
||
|
|
||
|
Core::DelayManager::DelayManager(Job::Id mpj, QObject* parent) :
|
||
|
QObject(parent),
|
||
|
maxParallelJobs(mpj),
|
||
|
nextJobId(1),
|
||
|
scheduledJobs(),
|
||
|
scheduledJobsById(scheduledJobs.get<id>()),
|
||
|
jobSequence(scheduledJobs.get<sequence>()),
|
||
|
runningJobs(),
|
||
|
ownVCardJobId(0),
|
||
|
ownInfoJobId(0),
|
||
|
scheduledVCards(),
|
||
|
requestedVCards(),
|
||
|
requestedBundles()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
Core::DelayManager::~DelayManager() {}
|
||
|
|
||
|
Core::Job::Id Core::DelayManager::getNextJobId() {
|
||
|
Job::Id id = nextJobId++;
|
||
|
if (id == 0)
|
||
|
id = nextJobId++;
|
||
|
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::getInfo(const QString& jid) {
|
||
|
Job* job = nullptr;
|
||
|
#ifdef WITH_OMEMO
|
||
|
std::map<QString, Job::Id>::const_iterator bitr = requestedBundles.find(jid);
|
||
|
if (bitr != requestedBundles.end())
|
||
|
job = runningJobs.at(bitr->second);
|
||
|
else
|
||
|
#endif
|
||
|
job = getVCardJob(jid);
|
||
|
|
||
|
if (job != nullptr) {
|
||
|
if (job->getType() == Job::Type::cardInternal)
|
||
|
replaceJob(new InfoForUser(job->id, jid));
|
||
|
} else
|
||
|
scheduleJob(new InfoForUser(getNextJobId(), jid));
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::getOwnInfo() {
|
||
|
if (ownInfoJobId == 0) {
|
||
|
if (ownVCardJobId != 0)
|
||
|
replaceJob(new OwnInfoForUser(ownVCardJobId));
|
||
|
else
|
||
|
scheduleJob(new OwnInfoForUser(getNextJobId()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::getVCard(const QString& jid) {
|
||
|
Job* job = getVCardJob(jid);
|
||
|
if (job == nullptr)
|
||
|
scheduleJob(new CardInternal(getNextJobId(), jid));
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::getOwnVCard() {
|
||
|
if (ownInfoJobId == 0)
|
||
|
scheduleJob(new OwnCardInternal(getNextJobId()));
|
||
|
}
|
||
|
|
||
|
Core::Job* Core::DelayManager::getVCardJob(const QString& jid) {
|
||
|
Job* job = nullptr;
|
||
|
std::map<QString, Job::Id>::const_iterator sitr = scheduledVCards.find(jid);
|
||
|
if (sitr == scheduledVCards.end()) {
|
||
|
std::map<QString, Job::Id>::const_iterator ritr = requestedVCards.find(jid);
|
||
|
if (ritr != requestedVCards.end())
|
||
|
job = runningJobs.at(ritr->second);
|
||
|
} else {
|
||
|
job = *(scheduledJobsById.find(sitr->second));
|
||
|
}
|
||
|
|
||
|
return job;
|
||
|
}
|
||
|
void Core::DelayManager::preScheduleJob(Core::Job* job) {
|
||
|
switch (job->getType()) {
|
||
|
case Job::Type::cardInternal:
|
||
|
scheduledVCards.emplace(static_cast<CardInternal*>(job)->jid, job->id);
|
||
|
break;
|
||
|
case Job::Type::ownCardInternal:
|
||
|
ownVCardJobId = job->id;
|
||
|
break;
|
||
|
case Job::Type::infoForUser:
|
||
|
scheduledVCards.emplace(static_cast<InfoForUser*>(job)->jid, job->id);
|
||
|
break;
|
||
|
case Job::Type::ownInfoForUser:
|
||
|
ownVCardJobId = job->id;
|
||
|
ownInfoJobId = job->id;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::scheduleJob(Core::Job* job) {
|
||
|
preScheduleJob(job);
|
||
|
if (runningJobs.size() < maxParallelJobs) {
|
||
|
executeJob(job);
|
||
|
} else {
|
||
|
scheduledJobs.push_back(job);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::preExecuteJob(Core::Job* job) {
|
||
|
switch (job->getType()) {
|
||
|
case Job::Type::cardInternal:
|
||
|
case Job::Type::infoForUser: {
|
||
|
CardInternal* cij = static_cast<CardInternal*>(job);
|
||
|
requestedVCards.emplace(cij->jid, job->id);
|
||
|
scheduledVCards.erase(cij->jid);
|
||
|
}
|
||
|
break;
|
||
|
case Job::Type::ownInfoForUser:
|
||
|
case Job::Type::ownCardInternal:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::executeJob(Core::Job* job) {
|
||
|
preExecuteJob(job);
|
||
|
runningJobs.emplace(job->id, job);
|
||
|
switch (job->getType()) {
|
||
|
case Job::Type::cardInternal:
|
||
|
case Job::Type::infoForUser:
|
||
|
emit requestVCard(static_cast<CardInternal*>(job)->jid);
|
||
|
break;
|
||
|
case Job::Type::ownInfoForUser:
|
||
|
case Job::Type::ownCardInternal:
|
||
|
emit requestOwnVCard();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::jobIsDone(Job::Id jobId) {
|
||
|
std::map<Job::Id, Job*>::const_iterator itr = runningJobs.find(jobId);
|
||
|
if (itr == runningJobs.end()) {
|
||
|
throw 8573; //not supposed to happen, ever
|
||
|
}
|
||
|
Job* job = itr->second;
|
||
|
delete job;
|
||
|
runningJobs.erase(itr);
|
||
|
if (scheduledJobs.size() > 0) {
|
||
|
Job* job = scheduledJobs.front();
|
||
|
scheduledJobs.pop_front();
|
||
|
executeJob(job);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::replaceJob(Core::Job* job) {
|
||
|
preScheduleJob(job);
|
||
|
std::map<Job::Id, Job*>::iterator itr = runningJobs.find(job->id);
|
||
|
if (itr != runningJobs.end()) {
|
||
|
preExecuteJob(job);
|
||
|
delete itr->second;
|
||
|
itr->second = job;
|
||
|
} else {
|
||
|
StorageById::iterator sitr = scheduledJobsById.find(job->id);
|
||
|
if (sitr != scheduledJobsById.end()) {
|
||
|
delete *(sitr);
|
||
|
scheduledJobsById.replace(sitr, job);
|
||
|
} else {
|
||
|
throw 8574; //not supposed to happen, ever
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::receivedVCard(const QString& jid, const Shared::VCard& card) {
|
||
|
std::map<QString, Job::Id>::const_iterator cardItr = requestedVCards.find(jid);
|
||
|
if (cardItr == requestedVCards.end()) {
|
||
|
throw 8575; //never supposed to happen, the state is not correct;
|
||
|
} else {
|
||
|
Job::Id jobId = cardItr->second;
|
||
|
requestedVCards.erase(cardItr);
|
||
|
Job* job = runningJobs.at(jobId);
|
||
|
switch (job->getType()) {
|
||
|
case Job::Type::cardInternal:
|
||
|
jobIsDone(jobId);
|
||
|
emit receivedCard(jid, card);
|
||
|
break;
|
||
|
case Job::Type::infoForUser:
|
||
|
#ifdef WITH_OMEMO
|
||
|
requestedBundles.emplace(jid, jobId);
|
||
|
//TODO save card!
|
||
|
emit requestBundles(jid);
|
||
|
#else
|
||
|
{
|
||
|
Shared::Info info(jid);
|
||
|
info.turnIntoContact(card);
|
||
|
emit receivedInfo(info);
|
||
|
}
|
||
|
jobIsDone(jobId);
|
||
|
#endif
|
||
|
emit receivedCard(jid, card);
|
||
|
break;
|
||
|
default:
|
||
|
throw 8576;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::ownVCardReceived(const Shared::VCard& card) {
|
||
|
Job::Id jobId = ownVCardJobId;
|
||
|
ownVCardJobId = 0;
|
||
|
Job* job = runningJobs.at(jobId);
|
||
|
switch (job->getType()) {
|
||
|
case Job::Type::ownCardInternal:
|
||
|
jobIsDone(jobId);
|
||
|
emit receivedOwnCard(card);
|
||
|
break;
|
||
|
case Job::Type::ownInfoForUser:
|
||
|
#ifdef WITH_OMEMO
|
||
|
//requestedBundles.emplace(jid, jobId);
|
||
|
//TODO save card!
|
||
|
emit requestOwnBundle();
|
||
|
#else
|
||
|
{
|
||
|
Shared::Info info("");
|
||
|
info.turnIntoOwnAccount(card);
|
||
|
emit receivedOwnInfo(info);
|
||
|
}
|
||
|
jobIsDone(jobId);
|
||
|
#endif
|
||
|
emit receivedOwnCard(card);
|
||
|
break;
|
||
|
default:
|
||
|
throw 8576;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Core::DelayManager::receivedBundles(const QString& jid) {
|
||
|
|
||
|
}
|