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() {
36 //instanceptr->deleteLater();
46 if(!SqliteStorage::isAvailable()) {
47 qFatal("Sqlite is currently required! Please make sure your Qt library has sqlite support enabled.");
49 //SqliteStorage::init();
50 storage = new SqliteStorage();
51 connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
52 startListening(); // FIXME make configurable
57 //foreach(QTcpSocket *sock, validClients.keys()) {
64 CoreSession *Core::session(UserId uid) {
65 Core *core = instance();
66 if(core->sessions.contains(uid)) return core->sessions[uid];
70 CoreSession *Core::localSession() {
71 Core *core = instance();
72 if(core->guiUser && core->sessions.contains(core->guiUser)) return core->sessions[core->guiUser];
76 CoreSession *Core::createSession(UserId uid) {
77 Core *core = instance();
78 Q_ASSERT(!core->sessions.contains(uid));
79 CoreSession *sess = new CoreSession(uid, core->storage);
80 core->sessions[uid] = sess;
81 //connect(sess, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), core, SLOT(recvProxySignal(CoreSignal, QVariant, QVariant, QVariant)));
86 bool Core::startListening(uint port) {
87 if(!server.listen(QHostAddress::Any, port)) {
88 qWarning(QString(QString("Could not open GUI client port %1: %2").arg(port).arg(server.errorString())).toAscii());
91 qDebug() << "Listening for GUI clients on port" << server.serverPort();
95 void Core::stopListening() {
97 qDebug() << "No longer listening for GUI clients.";
100 void Core::incomingConnection() {
101 // TODO implement SSL
102 QTcpSocket *socket = server.nextPendingConnection();
103 connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
104 connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
105 blockSizes.insert(socket, (quint32)0);
106 qDebug() << "Client connected from " << socket->peerAddress().toString();
109 void Core::clientHasData() {
110 QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
111 Q_ASSERT(socket && blockSizes.contains(socket));
112 quint32 bsize = blockSizes.value(socket);
114 if(readDataFromDevice(socket, bsize, item)) {
115 /* this is probably obsolete now */
116 if(validClients.contains(socket)) {
118 //QList<QVariant> sigdata = item.toList();
119 //sessions[validClients[socket]]->processSignal((ClientSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
121 // we need to auth the client
123 processClientInit(socket, item);
124 } catch(Storage::AuthError) {
125 qWarning() << "Authentification error!"; // FIXME
128 } catch(Exception e) {
129 qWarning() << "Client init error:" << e.msg();
134 blockSizes[socket] = bsize = 0; // FIXME blockSizes aufräum0rn!
136 blockSizes[socket] = bsize;
139 void Core::clientDisconnected() {
140 QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
141 blockSizes.remove(socket);
142 validClients.remove(socket);
143 qDebug() << "Client disconnected.";
144 // TODO remove unneeded sessions - if necessary/possible...
147 QVariant Core::connectLocalClient(QString user, QString passwd) {
148 UserId uid = instance()->storage->validateUser(user, passwd);
149 QVariant reply = instance()->initSession(uid);
150 instance()->guiUser = uid;
151 qDebug() << "Local client connected.";
155 void Core::disconnectLocalClient() {
156 qDebug() << "Local client disconnected.";
157 instance()->guiUser = 0;
160 void Core::processClientInit(QTcpSocket *socket, const QVariant &v) {
161 QVariantMap msg = v.toMap();
162 if(msg["GuiProtocol"].toUInt() != GUI_PROTOCOL) {
163 //qWarning() << "Client version mismatch.";
164 throw Exception("GUI client version mismatch");
167 UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed
168 QVariant reply = initSession(uid);
169 validClients[socket] = uid; // still needed? FIXME
170 //QList<QVariant> sigdata;
171 //sigdata.append(CS_CORE_STATE); sigdata.append(reply); sigdata.append(QVariant()); sigdata.append(QVariant());
172 disconnect(socket, 0, this, 0);
173 sessions[uid]->addClient(socket);
174 writeDataToDevice(socket, reply);
177 QVariant Core::initSession(UserId uid) {
178 // Find or create session for validated user
180 if(sessions.contains(uid)) sess = sessions[uid];
182 sess = createSession(uid);
183 //validClients[socket] = uid;
186 reply["SessionState"] = sess->sessionState();
191 void Core::recvProxySignal(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
192 CoreSession *sess = qobject_cast<CoreSession*>(sender());
194 UserId uid = sess->userId();
195 QList<QVariant> sigdata;
196 sigdata.append(sig); sigdata.append(arg1); sigdata.append(arg2); sigdata.append(arg3);
197 //qDebug() << "Sending signal: " << sigdata;
198 foreach(QTcpSocket *socket, validClients.keys()) {
199 if(validClients[socket] == uid) writeDataToDevice(socket, QVariant(sigdata));