1 /***************************************************************************
2 * Copyright (C) 2005-07 by The Quassel IRC Development Team *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
22 #include "coresession.h"
23 #include "sqlitestorage.h"
26 Core *Core::instanceptr = 0;
28 Core * Core::instance() {
29 if(instanceptr) return instanceptr;
30 instanceptr = new Core();
35 void Core::destroy() {
45 if(!SqliteStorage::isAvailable()) {
46 qFatal("Sqlite is currently required! Please make sure your Qt library has sqlite support enabled.");
48 //SqliteStorage::init();
49 storage = new SqliteStorage();
50 connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
51 startListening(); // FIXME make configurable
60 CoreSession *Core::session(UserId uid) {
61 Core *core = instance();
62 if(core->sessions.contains(uid)) return core->sessions[uid];
66 CoreSession *Core::localSession() {
67 Core *core = instance();
68 if(core->guiUser && core->sessions.contains(core->guiUser)) return core->sessions[core->guiUser];
72 CoreSession *Core::createSession(UserId uid) {
73 Core *core = instance();
74 Q_ASSERT(!core->sessions.contains(uid));
75 CoreSession *sess = new CoreSession(uid, core->storage);
76 core->sessions[uid] = sess;
81 bool Core::startListening(uint port) {
82 if(!server.listen(QHostAddress::Any, port)) {
83 qWarning(QString(QString("Could not open GUI client port %1: %2").arg(port).arg(server.errorString())).toAscii());
86 qDebug() << "Listening for GUI clients on port" << server.serverPort();
90 void Core::stopListening() {
92 qDebug() << "No longer listening for GUI clients.";
95 void Core::incomingConnection() {
98 QTcpSocket *socket = server.nextPendingConnection();
99 connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
100 connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
101 blockSizes.insert(socket, (quint32)0);
102 qDebug() << "Client connected from " << socket->peerAddress().toString();
105 void Core::clientHasData() {
106 QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
107 Q_ASSERT(socket && blockSizes.contains(socket));
108 quint32 bsize = blockSizes.value(socket);
110 if(readDataFromDevice(socket, bsize, item)) {
111 // we need to auth the client
113 processClientInit(socket, item);
114 } catch(Storage::AuthError) {
115 qWarning() << "Authentification error!"; // FIXME: send auth error to client
118 } catch(Exception e) {
119 qWarning() << "Client init error:" << e.msg();
124 blockSizes[socket] = bsize = 0; // FIXME blockSizes aufräum0rn!
127 // FIXME: no longer called, since connection handling is now in SignalProxy
128 void Core::clientDisconnected() {
129 QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
130 blockSizes.remove(socket);
131 qDebug() << "Client disconnected.";
132 // TODO remove unneeded sessions - if necessary/possible...
135 QVariant Core::connectLocalClient(QString user, QString passwd) {
136 UserId uid = instance()->storage->validateUser(user, passwd);
137 QVariant reply = instance()->initSession(uid);
138 instance()->guiUser = uid;
139 qDebug() << "Local client connected.";
143 void Core::disconnectLocalClient() {
144 qDebug() << "Local client disconnected.";
145 instance()->guiUser = 0;
148 void Core::processClientInit(QTcpSocket *socket, const QVariant &v) {
149 QVariantMap msg = v.toMap();
150 if(msg["GuiProtocol"].toUInt() != GUI_PROTOCOL) {
151 //qWarning() << "Client version mismatch.";
152 throw Exception("GUI client version mismatch");
155 UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed
156 QVariant reply = initSession(uid);
157 disconnect(socket, 0, this, 0);
158 sessions[uid]->addClient(socket);
159 qDebug() << "Client initialized successfully.";
160 writeDataToDevice(socket, reply);
163 QVariant Core::initSession(UserId uid) {
164 // Find or create session for validated user
166 if(sessions.contains(uid)) sess = sessions[uid];
168 sess = createSession(uid);
171 reply["SessionState"] = sess->sessionState();