aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2010-08-27 12:15:23 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2010-08-27 12:15:23 +0000
commitce3fc8a796f9ba14dac0c77e6d3c102c8552b172 (patch)
tree647f17a5d546568072680b72f96f33dc7b955989 /src
parentccf962560ca1178c543c091b2e36d9be49b2cf48 (diff)
downloadqxmpp-ce3fc8a796f9ba14dac0c77e6d3c102c8552b172.tar.gz
refactor QXmppServer extensions
Diffstat (limited to 'src')
-rw-r--r--src/QXmppServer.cpp157
-rw-r--r--src/QXmppServer.h23
-rw-r--r--src/QXmppServerExtension.cpp82
-rw-r--r--src/QXmppServerExtension.h51
-rw-r--r--src/QXmppServerPlugin.h2
-rw-r--r--src/src.pro2
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 \