- }
- qDebug() << "Listening for GUI clients on port" << server.serverPort();
- return true;
-}
-
-void Core::stopListening() {
- server.close();
- qDebug() << "No longer listening for GUI clients.";
-}
-
-void Core::incomingConnection() {
- // TODO implement SSL
- QTcpSocket *socket = server.nextPendingConnection();
- connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
- connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData()));
- blockSizes.insert(socket, (quint32)0);
- qDebug() << "Client connected from " << socket->peerAddress().toString();
-}
-
-void Core::clientHasData() {
- QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
- Q_ASSERT(socket && blockSizes.contains(socket));
- quint32 bsize = blockSizes.value(socket);
- QVariant item;
- while(readDataFromDevice(socket, bsize, item)) {
- if(validClients.contains(socket)) {
- QList<QVariant> sigdata = item.toList();
- if((ClientSignal)sigdata[0].toInt() == GS_UPDATE_GLOBAL_DATA) {
- processClientUpdate(socket, sigdata[1].toString(), sigdata[2]);
- } else {
- sessions[validClients[socket]]->processSignal((ClientSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
- }
- } else {
- // we need to auth the client
- try {
- processClientInit(socket, item);
- } catch(Storage::AuthError) {
- qWarning() << "Authentification error!"; // FIXME
- socket->close();
- return;
- } catch(Exception e) {
- qWarning() << "Client init error:" << e.msg();
- socket->close();
- return;
- }
- }
- blockSizes[socket] = bsize = 0;
- }
- blockSizes[socket] = bsize;
-}
-
-void Core::clientDisconnected() {
- QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender());
- blockSizes.remove(socket);
- validClients.remove(socket);
- qDebug() << "Client disconnected.";
- // TODO remove unneeded sessions - if necessary/possible...
-}
-
-void Core::processClientInit(QTcpSocket *socket, const QVariant &v) {
- VarMap msg = v.toMap();
- if(msg["GUIProtocol"].toUInt() != GUI_PROTOCOL) {
- //qWarning() << "Client version mismatch.";
- throw Exception("GUI client version mismatch");
- }
- // Auth
- UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed
-
- // Find or create session for validated user
- CoreSession *sess;
- if(sessions.contains(uid)) sess = sessions[uid];
- else {
- sess = createSession(uid);
- validClients[socket] = uid;
- }
- VarMap reply;
- VarMap coreData;
- // FIXME
- QStringList dataKeys = Global::keys(uid);
- QString key;
- foreach(key, dataKeys) {
- coreData[key] = Global::data(key);
- }
- reply["CoreData"] = coreData;
- reply["SessionState"] = sess->sessionState();
- QList<QVariant> sigdata;
- sigdata.append(CS_CORE_STATE); sigdata.append(QVariant(reply)); sigdata.append(QVariant()); sigdata.append(QVariant());
- writeDataToDevice(socket, QVariant(sigdata));
- sess->sendServerStates();
-}
-
-void Core::processClientUpdate(QTcpSocket *socket, QString key, const QVariant &data) {
- UserId uid = validClients[socket];
- Global::updateData(uid, key, data);
- QList<QVariant> sigdata;
- sigdata.append(CS_UPDATE_GLOBAL_DATA); sigdata.append(key); sigdata.append(data); sigdata.append(QVariant());
- foreach(QTcpSocket *s, validClients.keys()) {
- if(validClients[s] == uid && s != socket) writeDataToDevice(s, QVariant(sigdata));
- }
-}
-
-void Core::updateGlobalData(UserId uid, QString key) {
- QVariant data = Global::data(uid, key);
- QList<QVariant> sigdata;
- sigdata.append(CS_UPDATE_GLOBAL_DATA); sigdata.append(key); sigdata.append(data); sigdata.append(QVariant());
- foreach(QTcpSocket *socket, validClients.keys()) {
- if(validClients[socket] == uid) writeDataToDevice(socket, QVariant(sigdata));
- }
-}
-
-void Core::recvProxySignal(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
- CoreSession *sess = qobject_cast<CoreSession*>(sender());
- Q_ASSERT(sess);
- UserId uid = sess->userId();
- QList<QVariant> sigdata;
- sigdata.append(sig); sigdata.append(arg1); sigdata.append(arg2); sigdata.append(arg3);
- //qDebug() << "Sending signal: " << sigdata;
- foreach(QTcpSocket *socket, validClients.keys()) {
- if(validClients[socket] == uid) writeDataToDevice(socket, QVariant(sigdata));
- }
-}
-
-/*
- // Read global settings from config file
- QSettings s;
- s.beginGroup("Global");
- QString key;
- foreach(key, s.childKeys()) {
- global->updateData(key, s.value(key));
- }
-
- global->updateData("CoreReady", true);
- // Now that we are in sync, we can connect signals to automatically store further updates.
- // I don't think we care if global data changed locally or if it was updated by a client.
- connect(global, SIGNAL(dataUpdatedRemotely(QString)), SLOT(globalDataUpdated(QString)));
- connect(global, SIGNAL(dataPutLocally(QString)), SLOT(globalDataUpdated(QString)));
-
-}
- */
-
-CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_storage) {
- coreProxy = new CoreProxy();
-
- connect(coreProxy, SIGNAL(send(CoreSignal, QVariant, QVariant, QVariant)), this, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)));
- connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
- connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
- connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGui(BufferId, QString)));
- connect(coreProxy, SIGNAL(gsImportBacklog()), storage, SLOT(importOldBacklog()));
- connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
- connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
- connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
- connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
- connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
- connect(storage, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
- connect(Global::instance(), SIGNAL(dataUpdatedRemotely(UserId, QString)), this, SLOT(globalDataUpdated(UserId, QString)));
- connect(Global::instance(), SIGNAL(dataPutLocally(UserId, QString)), this, SLOT(globalDataUpdated(UserId, QString)));
-}
-
-CoreSession::~CoreSession() {
-
-}
-
-UserId CoreSession::userId() {
- return user;
-}
-
-void CoreSession::processSignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
- coreProxy->recv(sig, arg1, arg2, arg3);
-}
+#endif
+}
+
+
+bool Core::reloadCerts()
+{
+#ifdef HAVE_SSL
+ SslServer *sslServer = qobject_cast<SslServer *>(&instance()->_server);
+ return sslServer->reloadCerts();
+#else
+ // SSL not supported, don't mark configuration reload as failed
+ return true;
+#endif
+}
+
+
+bool Core::startListening()
+{
+ // in mono mode we only start a local port if a port is specified in the cli call
+ if (Quassel::runMode() == Quassel::Monolithic && !Quassel::isOptionSet("port"))
+ return true;
+
+ bool success = false;
+ uint port = Quassel::optionValue("port").toUInt();
+
+ const QString listen = Quassel::optionValue("listen");
+ const QStringList listen_list = listen.split(",", QString::SkipEmptyParts);
+ if (listen_list.size() > 0) {
+ foreach(const QString listen_term, listen_list) { // TODO: handle multiple interfaces for same TCP version gracefully
+ QHostAddress addr;
+ if (!addr.setAddress(listen_term)) {
+ qCritical() << qPrintable(
+ tr("Invalid listen address %1")
+ .arg(listen_term)
+ );
+ }
+ else {
+ switch (addr.protocol()) {
+ case QAbstractSocket::IPv6Protocol:
+ if (_v6server.listen(addr, port)) {
+ quInfo() << qPrintable(
+ tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3")
+ .arg(addr.toString())
+ .arg(_v6server.serverPort())
+ .arg(Quassel::buildInfo().protocolVersion)
+ );
+ success = true;
+ }
+ else
+ quWarning() << qPrintable(
+ tr("Could not open IPv6 interface %1:%2: %3")
+ .arg(addr.toString())
+ .arg(port)
+ .arg(_v6server.errorString()));
+ break;
+ case QAbstractSocket::IPv4Protocol:
+ if (_server.listen(addr, port)) {
+ quInfo() << qPrintable(
+ tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3")
+ .arg(addr.toString())
+ .arg(_server.serverPort())
+ .arg(Quassel::buildInfo().protocolVersion)
+ );
+ success = true;
+ }
+ else {
+ // if v6 succeeded on Any, the port will be already in use - don't display the error then
+ if (!success || _server.serverError() != QAbstractSocket::AddressInUseError)
+ quWarning() << qPrintable(
+ tr("Could not open IPv4 interface %1:%2: %3")
+ .arg(addr.toString())
+ .arg(port)
+ .arg(_server.errorString()));
+ }
+ break;
+ default:
+ qCritical() << qPrintable(
+ tr("Invalid listen address %1, unknown network protocol")
+ .arg(listen_term)
+ );
+ break;
+ }
+ }
+ }
+ }
+ if (!success)
+ quError() << qPrintable(tr("Could not open any network interfaces to listen on!"));