diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-27 12:15:23 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-27 12:15:23 +0000 |
| commit | ce3fc8a796f9ba14dac0c77e6d3c102c8552b172 (patch) | |
| tree | 647f17a5d546568072680b72f96f33dc7b955989 /src | |
| parent | ccf962560ca1178c543c091b2e36d9be49b2cf48 (diff) | |
| download | qxmpp-ce3fc8a796f9ba14dac0c77e6d3c102c8552b172.tar.gz | |
refactor QXmppServer extensions
Diffstat (limited to 'src')
| -rw-r--r-- | src/QXmppServer.cpp | 157 | ||||
| -rw-r--r-- | src/QXmppServer.h | 23 | ||||
| -rw-r--r-- | src/QXmppServerExtension.cpp | 82 | ||||
| -rw-r--r-- | src/QXmppServerExtension.h | 51 | ||||
| -rw-r--r-- | src/QXmppServerPlugin.h | 2 | ||||
| -rw-r--r-- | src/src.pro | 2 |
6 files changed, 269 insertions, 48 deletions
diff --git a/src/QXmppServer.cpp b/src/QXmppServer.cpp index 947add18..9c9e0a45 100644 --- a/src/QXmppServer.cpp +++ b/src/QXmppServer.cpp @@ -33,6 +33,7 @@ #include "QXmppOutgoingServer.h" #include "QXmppPingIq.h" #include "QXmppServer.h" +#include "QXmppServerExtension.h" #include "QXmppServerPlugin.h" #include "QXmppUtils.h" @@ -40,6 +41,9 @@ class QXmppServerPrivate { public: QXmppServerPrivate(); + void start(QXmppServer *server); + void info(const QString &message); + void warning(const QString &message); QString domain; QList<QXmppServerExtension*> extensions; @@ -52,14 +56,44 @@ public: QList<QXmppIncomingClient*> incomingClients; // server-to-server + QList<QXmppIncomingServer*> incomingServers; QList<QXmppOutgoingServer*> outgoingServers; QXmppSslServer *serverForServers; + + bool started; }; QXmppServerPrivate::QXmppServerPrivate() : logger(0), - passwordChecker(0) + passwordChecker(0), + started(false) +{ +} + +void QXmppServerPrivate::info(const QString &message) +{ + if (logger) + logger->log(QXmppLogger::InformationMessage, message); +} + +void QXmppServerPrivate::warning(const QString &message) { + if (logger) + logger->log(QXmppLogger::WarningMessage, message); +} + +/// Start the server's extensions. +/// + +void QXmppServerPrivate::start(QXmppServer *server) +{ + if (!started) + { + foreach (QXmppServerExtension *extension, extensions) + if (!extension->start(server)) + warning(QString("Could not start extension %1").arg(extension->extensionName())); + started = true; + } } /// Constructs a new XMPP server instance. @@ -80,6 +114,7 @@ QXmppServer::QXmppServer(QObject *parent) this, SLOT(slotServerConnection(QSslSocket*))); Q_ASSERT(check); + // load static plugins QObjectList plugins = QPluginLoader::staticInstances(); foreach (QObject *object, plugins) { @@ -87,7 +122,7 @@ QXmppServer::QXmppServer(QObject *parent) if (plugin) { foreach (const QString &key, plugin->keys()) - addExtension(plugin->create(key, this)); + addExtension(plugin->create(key)); } } } @@ -97,6 +132,7 @@ QXmppServer::QXmppServer(QObject *parent) QXmppServer::~QXmppServer() { + close(); delete d; } @@ -106,10 +142,20 @@ QXmppServer::~QXmppServer() void QXmppServer::addExtension(QXmppServerExtension *extension) { + if (d->extensions.contains(extension)) + return; extension->setParent(this); d->extensions << extension; } +/// Returns the list of loaded extensions. +/// + +QList<QXmppServerExtension*> QXmppServer::loadedExtensions() +{ + return d->extensions; +} + /// Returns the server's domain. /// @@ -168,7 +214,7 @@ void QXmppServer::setPasswordChecker(QXmppPasswordChecker *checker) void QXmppServer::addCaCertificates(const QString &path) { if (!path.isEmpty() && !QFileInfo(path).isReadable()) - qWarning() << "SSL CA certificates are not readable" << path; + d->warning(QString("SSL CA certificates are not readable %1").arg(path)); d->serverForClients->addCaCertificates(path); d->serverForServers->addCaCertificates(path); } @@ -180,7 +226,7 @@ void QXmppServer::addCaCertificates(const QString &path) void QXmppServer::setLocalCertificate(const QString &path) { if (!path.isEmpty() && !QFileInfo(path).isReadable()) - qWarning() << "SSL certificate is not readable" << path; + d->warning(QString("SSL certificate is not readable %1").arg(path)); d->serverForClients->setLocalCertificate(path); d->serverForServers->setLocalCertificate(path); } @@ -192,7 +238,7 @@ void QXmppServer::setLocalCertificate(const QString &path) void QXmppServer::setPrivateKey(const QString &path) { if (!path.isEmpty() && !QFileInfo(path).isReadable()) - qWarning() << "SSL key is not readable" << path; + d->warning(QString("SSL key is not readable %1").arg(path)); d->serverForClients->setPrivateKey(path); d->serverForServers->setPrivateKey(path); } @@ -206,14 +252,41 @@ bool QXmppServer::listenForClients(const QHostAddress &address, quint16 port) { if (!d->serverForClients->listen(address, port)) { - if (logger()) - logger()->log(QXmppLogger::WarningMessage, - QString("Could not start listening for C2S on port %1").arg(QString::number(port))); + d->warning(QString("Could not start listening for C2S on port %1").arg(QString::number(port))); return false; } + + // start extensions + d->start(this); return true; } +/// Closes the server. +/// + +void QXmppServer::close() +{ + // prevent new connections + d->serverForClients->close(); + d->serverForServers->close(); + + // stop extensions in reverse order + if (d->started) + { + for (int i = d->extensions.size() - 1; i >= 0; --i) + d->extensions[i]->stop(); + d->started = false; + } + + // close XMPP streams + foreach (QXmppIncomingClient *stream, d->incomingClients) + stream->disconnectFromHost(); + foreach (QXmppIncomingServer *stream, d->incomingServers) + stream->disconnectFromHost(); + foreach (QXmppOutgoingServer *stream, d->outgoingServers) + stream->disconnectFromHost(); +} + /// Listen for incoming XMPP server connections. /// /// \param address @@ -223,11 +296,12 @@ bool QXmppServer::listenForServers(const QHostAddress &address, quint16 port) { if (!d->serverForServers->listen(address, port)) { - if (logger()) - logger()->log(QXmppLogger::WarningMessage, - QString("Could not start listening for S2S on port %1").arg(QString::number(port))); + d->warning(QString("Could not start listening for S2S on port %1").arg(QString::number(port))); return false; } + + // start extensions + d->start(this); return true; } @@ -241,7 +315,15 @@ QXmppOutgoingServer* QXmppServer::connectToDomain(const QString &domain) stream->configuration().setDomain(domain); stream->configuration().setHost(domain); stream->configuration().setPort(5269); + + bool check = connect(stream, SIGNAL(disconnected()), + this, SLOT(slotServerDisconnected())); + Q_ASSERT(check); + Q_UNUSED(check); + + // add stream d->outgoingServers.append(stream); + emit streamAdded(stream); // connect to remote server stream->connectToHost(); @@ -457,7 +539,9 @@ void QXmppServer::slotClientConnection(QSslSocket *socket) this, SLOT(slotElementReceived(QDomElement))); Q_ASSERT(check); + // add stream d->incomingClients.append(stream); + emit streamAdded(stream); } /// Handle a successful client authentication. @@ -478,8 +562,6 @@ void QXmppServer::slotClientConnected() conn->disconnectFromHost(); } } - - // FIXME : update statistics } /// Handle a disconnection from a client. @@ -503,10 +585,11 @@ void QXmppServer::slotClientDisconnected() sendPacket(presence); } } + + // remove stream d->incomingClients.removeAll(stream); + emit streamRemoved(stream); stream->deleteLater(); - - // FIXME : update statistics } void QXmppServer::slotDialbackRequestReceived(const QXmppDialback &dialback) @@ -557,7 +640,7 @@ void QXmppServer::slotServerConnection(QSslSocket *socket) stream->setLogger(d->logger); bool check = connect(stream, SIGNAL(disconnected()), - stream, SLOT(deleteLater())); + this, SLOT(slotServerDisconnected())); Q_ASSERT(check); check = connect(stream, SIGNAL(dialbackRequestReceived(QXmppDialback)), @@ -567,30 +650,36 @@ void QXmppServer::slotServerConnection(QSslSocket *socket) check = connect(stream, SIGNAL(elementReceived(QDomElement)), this, SLOT(slotElementReceived(QDomElement))); Q_ASSERT(check); -} - -/// Handles an incoming XMPP stanza. -/// -/// Return true if no further processing should occur, false otherwise. -/// -/// \param stream The QXmppStream on which the stanza was received. -/// \param stanza The received stanza. -bool QXmppServerExtension::handleStanza(QXmppStream *stream, const QDomElement &stanza) -{ - Q_UNUSED(stream); - Q_UNUSED(stanza); - return false; + // add stream + d->incomingServers.append(stream); + emit streamAdded(stream); } -/// Returns the list of subscribers for the given JID. +/// Handle a disconnection from a server. /// -/// \param jid -QStringList QXmppServerExtension::presenceSubscribers(const QString &jid) +void QXmppServer::slotServerDisconnected() { - Q_UNUSED(jid); - return QStringList(); + // handle incoming streams + QXmppIncomingServer *incoming = qobject_cast<QXmppIncomingServer *>(sender()); + if (incoming && d->incomingServers.contains(incoming)) + { + d->incomingServers.removeAll(incoming); + emit streamRemoved(incoming); + incoming->deleteLater(); + return; + } + + // handle outgoing streams + QXmppOutgoingServer *outgoing = qobject_cast<QXmppOutgoingServer *>(sender()); + if (outgoing && d->outgoingServers.contains(outgoing)) + { + d->outgoingServers.removeAll(outgoing); + emit streamRemoved(outgoing); + outgoing->deleteLater(); + return; + } } class QXmppSslServerPrivate diff --git a/src/QXmppServer.h b/src/QXmppServer.h index 36032cd0..39ee64e8 100644 --- a/src/QXmppServer.h +++ b/src/QXmppServer.h @@ -52,6 +52,7 @@ public: ~QXmppServer(); void addExtension(QXmppServerExtension *extension); + QList<QXmppServerExtension*> loadedExtensions(); QString domain() const; void setDomain(const QString &domain); @@ -66,12 +67,20 @@ public: void setLocalCertificate(const QString &sslCertificate); void setPrivateKey(const QString &sslKey); + void close(); bool listenForClients(const QHostAddress &address = QHostAddress::Any, quint16 port = 5222); bool listenForServers(const QHostAddress &address = QHostAddress::Any, quint16 port = 5269); bool sendElement(const QDomElement &element); bool sendPacket(const QXmppStanza &stanza); +signals: + /// This signal is emitted when an XMPP stream is added. + void streamAdded(QXmppStream *stream); + + /// This signal is emitted when an XMPP stream is removed. + void streamRemoved(QXmppStream *stream); + private slots: void slotClientConnection(QSslSocket *socket); void slotClientConnected(); @@ -79,6 +88,7 @@ private slots: void slotDialbackRequestReceived(const QXmppDialback &dialback); void slotElementReceived(const QDomElement &element); void slotServerConnection(QSslSocket *socket); + void slotServerDisconnected(); private: QXmppOutgoingServer *connectToDomain(const QString &domain); @@ -88,19 +98,6 @@ private: QXmppServerPrivate * const d; }; -/// \brief The QXmppServerExtension class is the base class for QXmppServer -/// extensions. -/// - -class QXmppServerExtension : public QObject -{ - Q_OBJECT - -public: - virtual bool handleStanza(QXmppStream *stream, const QDomElement &stanza); - virtual QStringList presenceSubscribers(const QString &jid); -}; - class QXmppSslServerPrivate; /// \brief The QXmppSslServer class represents an SSL-enabled TCP server. diff --git a/src/QXmppServerExtension.cpp b/src/QXmppServerExtension.cpp new file mode 100644 index 00000000..f1f25e6b --- /dev/null +++ b/src/QXmppServerExtension.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + +#include <QMetaClassInfo> +#include <QStringList> + +#include "QXmppServerExtension.h" + +/// Returns the extension's name. +/// + +QString QXmppServerExtension::extensionName() const +{ + int index = metaObject()->indexOfClassInfo("ExtensionName"); + if (index < 0) + return QString(); + const char *name = metaObject()->classInfo(index).value(); + return QString::fromLatin1(name); +} + +/// Handles an incoming XMPP stanza. +/// +/// Return true if no further processing should occur, false otherwise. +/// +/// \param stream The QXmppStream on which the stanza was received. +/// \param stanza The received stanza. + +bool QXmppServerExtension::handleStanza(QXmppStream *stream, const QDomElement &stanza) +{ + Q_UNUSED(stream); + Q_UNUSED(stanza); + return false; +} + +/// Returns the list of subscribers for the given JID. +/// +/// \param jid + +QStringList QXmppServerExtension::presenceSubscribers(const QString &jid) +{ + Q_UNUSED(jid); + return QStringList(); +} + +/// Starts the extension for the given server. +/// +/// Return true if the extension was started, false otherwise. +/// +/// \param server The QXmppServer which started the extension. + +bool QXmppServerExtension::start(QXmppServer *server) +{ + Q_UNUSED(server); + return true; +} + +/// Stops the extension. + +void QXmppServerExtension::stop() +{ +} + diff --git a/src/QXmppServerExtension.h b/src/QXmppServerExtension.h new file mode 100644 index 00000000..372448b9 --- /dev/null +++ b/src/QXmppServerExtension.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPSERVEREXTENSION_H +#define QXMPPSERVEREXTENSION_H + +#include <QObject> + +class QDomElement; +class QStringList; + +class QXmppServer; +class QXmppStream; + +/// \brief The QXmppServerExtension class is the base class for QXmppServer +/// extensions. +/// + +class QXmppServerExtension : public QObject +{ + Q_OBJECT + +public: + QString extensionName() const; + virtual bool handleStanza(QXmppStream *stream, const QDomElement &stanza); + virtual QStringList presenceSubscribers(const QString &jid); + virtual bool start(QXmppServer *server); + virtual void stop(); +}; + +#endif diff --git a/src/QXmppServerPlugin.h b/src/QXmppServerPlugin.h index defa05d6..6338d3d3 100644 --- a/src/QXmppServerPlugin.h +++ b/src/QXmppServerPlugin.h @@ -35,7 +35,7 @@ class QXmppServerExtension; class QXmppServerPluginInterface { public: - virtual QXmppServerExtension *create(const QString &key, QXmppServer *server) = 0; + virtual QXmppServerExtension *create(const QString &key) = 0; virtual QStringList keys() const = 0; }; diff --git a/src/src.pro b/src/src.pro index d8bb5ed4..ee3cf582 100644 --- a/src/src.pro +++ b/src/src.pro @@ -52,6 +52,7 @@ HEADERS += QXmppUtils.h \ QXmppRosterIq.h \ QXmppRosterManager.h \ QXmppServer.h \ + QXmppServerExtension.h \ QXmppServerPlugin.h \ QXmppSessionIq.h \ QXmppSocks.h \ @@ -102,6 +103,7 @@ SOURCES += QXmppUtils.cpp \ QXmppRosterIq.cpp \ QXmppRosterManager.cpp \ QXmppServer.cpp \ + QXmppServerExtension.cpp \ QXmppSessionIq.cpp \ QXmppSocks.cpp \ QXmppStanza.cpp \ |
