ClientThread.cpp 6.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/*
 *  Kaidan - A user-friendly XMPP client for every device!
 *
 *  Copyright (C) 2016-2018 Kaidan developers and contributors
 *  (see the LICENSE file for a full list of copyright authors)
 *
 *  Kaidan 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.
 *
 *  In addition, as a special exception, the author of Kaidan gives
 *  permission to link the code of its release with the OpenSSL
 *  project's "OpenSSL" library (or with modified versions of it that
 *  use the same license as the "OpenSSL" library), and distribute the
 *  linked executables. You must obey the GNU General Public License in
 *  all respects for all of the code used other than "OpenSSL". If you
 *  modify this file, you may extend this exception to your version of
 *  the file, but you are not obligated to do so.  If you do not wish to
 *  do so, delete this exception statement from your version.
 *
 *  Kaidan 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 Kaidan.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "ClientThread.h"
// Kaidan
#include "ClientWorker.h"
#include "AvatarFileStorage.h"
#include "RosterManager.h"
#include "PresenceHandler.h"
#include "ServiceDiscoveryManager.h"
#include "Database.h"
#include "MessageSessionHandler.h"
#include "MessageHandler.h"
#include "VCardManager.h"
#include "XmlLogHandler.h"
// Qt
#include <QDebug>
#include <QMutexLocker>
#include <QTimer>
// gloox
#include <gloox/rostermanager.h>
#include <gloox/receipt.h>
#include <gloox/forward.h>
#include <gloox/carbons.h>
#include <gloox/vcardmanager.h>
#include <gloox/vcardupdate.h>

// package fetch interval in ms
static const unsigned int KAIDAN_CLIENT_LOOP_INTERVAL = 30;

ClientThread::ClientThread(RosterModel *rosterModel, MessageModel *messageModel,
                           AvatarFileStorage *avatarStorage, Credentials creds,
60
                           QSettings *settings, QGuiApplication *app, QObject *parent):
61 62 63 64 65 66 67 68
                           QThread(parent), rosterModel(rosterModel),
                           messageModel(messageModel), avatarStorage(avatarStorage),
                           creds(creds), settings(settings),
                           connState(ConnectionState::StateNone)
{
	// Set custom thread name
	setObjectName("XmppClient");

69 70
	client = new GlooxClient(gloox::JID(creds.jid.toStdString()),
	                         creds.password.toStdString());
71 72 73
	client->bindResource(creds.jidResource.toStdString()); // set resource / device name
	client->setTls(gloox::TLSRequired); // require encryption

74
	worker = new ClientWorker(client, this, app);
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	connect(this, &ClientThread::connectRequested, worker, &ClientWorker::xmppConnect);
	connect(this, &ClientThread::disconnectRequested, worker, &ClientWorker::xmppDisconnect);
	connect(this, &ClientThread::stopWorkTimerRequested, worker, &ClientWorker::stopWorkTimer);

	// The constructor is executed in the main thread, so we still need to move
	// all QObject-based objects to the client thread.
	worker->moveToThread(this);
	workTimer.moveToThread(this);
}

ClientThread::~ClientThread()
{
	// This is being executed in the main thread, not the client thread itself

	// stop client loop timer from client thread
	emit stopWorkTimerRequested();

	exit(); // exit event loop
	wait(); // wait for run() to finish

	delete worker;
	delete messageSessionHandler;
	delete xmlLogHandler;
}

void ClientThread::run()
{
	//
	// Construct client and subclasses
	//

	// components
	messageSessionHandler = new MessageSessionHandler(client, messageModel, rosterModel);
	vCardManager = new VCardManager(client, avatarStorage, rosterModel);
	rosterManager = new RosterManager(client, rosterModel, vCardManager);
	presenceHandler = new PresenceHandler(client);
	serviceDiscoveryManager = new ServiceDiscoveryManager(client, client->disco());
	xmlLogHandler = new XmlLogHandler(client);

	// Register Stanza Extensions
	client->registerStanzaExtension(new gloox::Receipt(gloox::Receipt::Request));
	client->registerStanzaExtension(new gloox::DelayedDelivery(gloox::JID(), std::string("")));
	client->registerStanzaExtension(new gloox::Forward());
	client->registerStanzaExtension(new gloox::Carbons());
	client->registerStanzaExtension(new gloox::VCardUpdate());

	// connect slots
	connect(this, &ClientThread::sendMessageRequested,
	        messageSessionHandler->getMessageHandler(), &MessageHandler::sendMessage);
Linus Jahn's avatar
Linus Jahn committed
124 125
	connect(this, &ClientThread::chatPartnerChanged,
	        messageSessionHandler->getMessageHandler(), &MessageHandler::setChatPartner);
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
	connect(this, &ClientThread::addContactRequested,
	        rosterManager, &RosterManager::addContact);
	connect(this, &ClientThread::removeContactRequested,
	        rosterManager, &RosterManager::removeContact);

	// timed fetching of packages
	connect(&workTimer, &QTimer::timeout, worker, &ClientWorker::updateClient);
	workTimer.start(KAIDAN_CLIENT_LOOP_INTERVAL);

	// enter event loop
	qDebug() << "[client] Entering main loop...";
	exec();
}

void ClientThread::setCredentials(Credentials creds)
{
	QMutexLocker locker(&mutex); // => locking mutex in this function

	this->creds = creds;

	client->setUsername(gloox::JID(creds.jid.toStdString()).username());
147 148
	client->setServer(gloox::JID(creds.jid.toStdString()).serverRaw());
	client->setJidServer(gloox::JID(creds.jid.toStdString()).server());
149 150 151 152
	client->setPassword(creds.password.toStdString());
	client->unbindResource(client->resource());
	client->bindResource(creds.jidResource.toStdString());

Linus Jahn's avatar
Linus Jahn committed
153
	emit messageModel->ownJidChanged(creds.jid);
154 155 156 157 158 159 160 161 162 163 164 165 166
}

void ClientThread::setConnectionState(ConnectionState state)
{
	connState = state;
	emit connectionStateChanged(state);
}

void ClientThread::setConnectionError(gloox::ConnectionError error)
{
	connError = error;
	emit disconnReasonChanged((DisconnReason) error);
}