基于XMPP的发布订阅系统(二)
-
XmppServer
类图
-
XmppServer
XmppServer.h
#ifndef XMPPSERVER_H #define XMPPSERVER_H #include <QObject> class QXmppServer; class QXmppLogger; class QXmppPasswordChecker; class XmppPubSubManager; class PingManager; class XmppServer : public QObject { Q_OBJECT public: explicit XmppServer(QString const& logPath, QObject *parent = 0); void setPasswordChecker(QXmppPasswordChecker *checker); public slots: void start(); private slots: void clientConnected(const QString &jid); void clientDisconnected(const QString &jid); private: QXmppServer* server; QXmppLogger* logger; PingManager* pingManager; XmppPubSubManager* pubsubManager; }; #endif // XMPPSERVER_H
XmppServer.cpp
#include "XmppServer.h" #include "XmppPubSubManager.h" #include "PasswordChecker.h" #include "PingManager.h" #include <qxmpp/QXmppServer.h> #include <qxmpp/QXmppLogger.h> #include <QDebug> XmppServer::XmppServer(const QString &logPath, QObject *parent) : QObject(parent) , server(new QXmppServer(this)) , logger(new QXmppLogger(this)) , pingManager(new PingManager()) , pubsubManager(new XmppPubSubManager()) { connect(server, SIGNAL(clientConnected(QString)), this, SLOT(clientConnected(QString))); connect(server, SIGNAL(clientDisconnected(QString)), this, SLOT(clientDisconnected(QString))); logger->setLoggingType(QXmppLogger::FileLogging); logger->setLogFilePath(logPath); server->setLogger(logger); server->setDomain("pubsub.flysnow"); server->addExtension(pingManager); server->addExtension(pubsubManager); pubsubManager->initConnects(); server->listenForClients(); } void XmppServer::setPasswordChecker(QXmppPasswordChecker *checker) { server->setPasswordChecker(checker); } void XmppServer::start() { server->listenForClients(); } void XmppServer::clientConnected(const QString &jid) { qDebug() << "clientConnected: " << jid; } void XmppServer::clientDisconnected(const QString &jid) { qDebug() << "clientDisconnected: " << jid; }
-
XmppPubSubManager
XmppPubSubManager.h
#ifndef XMPPPUBSUBMANAGER_H #define XMPPPUBSUBMANAGER_H #include <qxmpp/QXmppServerExtension.h> #include <qxmpp/QXmppElement.h> class XmppPubSubManager : public QXmppServerExtension { Q_OBJECT Q_CLASSINFO("ExtensionName", "pubsub_manager") public: void initConnects(); QStringList discoveryFeatures() const; bool handleStanza(const QDomElement &stanza); private slots: void clientConnected(const QString &jid); void clientDisconnected(const QString &jid); private: void notifyToClients(QString const& jid, QXmppElement const& event); private: QList<QString> clientJids; }; #endif // XMPPPUBSUBMANAGER_H
XmppPubSubManager.cpp
#include "XmppPubSubManager.h" #include <qxmpp/QXmppServer.h> #include <qxmpp/QXmppMessage.h> #include <qxmpp/QXmppPubSubIq.h> #include <QDomElement> namespace { QXmppElement messageBody(QString const& node, QList<QXmppPubSubItem> const& pubSubItems) { QXmppElement items; items.setTagName("items"); items.setAttribute("node", node); foreach (QXmppPubSubItem pubSubitem, pubSubItems) { QXmppElement item; item.setTagName("item"); item.setAttribute("id", pubSubitem.id()); item.appendChild(pubSubitem.contents()); items.appendChild(item); } QXmppElement event; event.setTagName("event"); event.setAttribute("xmlns", "http://jabber.org/protocol/pubsub#event"); event.appendChild(items); return event; } } void XmppPubSubManager::initConnects() { connect(server(), SIGNAL(clientConnected(QString)), this, SLOT(clientConnected(QString))); connect(server(), SIGNAL(clientDisconnected(QString)), this, SLOT(clientDisconnected(QString))); } QStringList XmppPubSubManager::discoveryFeatures() const { return QStringList() << "http://jabber.org/protocol/pubsub"; } bool XmppPubSubManager::handleStanza(const QDomElement &stanza) { if(stanza.tagName() != "iq" || !QXmppPubSubIq::isPubSubIq(stanza)) return false; QXmppPubSubIq reqIq; reqIq.parse(stanza); if(reqIq.type() == QXmppIq::Set) { QXmppPubSubIq responseIq; responseIq.setType(QXmppIq::Result); responseIq.setId(reqIq.id()); responseIq.setTo(reqIq.from()); if(reqIq.queryType() == QXmppPubSubIq::PublishQuery) { responseIq.setQueryType(QXmppPubSubIq::PublishQuery); responseIq.setQueryNode(reqIq.queryNode()); QList<QXmppPubSubItem> items = reqIq.items(); if(!items.isEmpty()) { QXmppPubSubItem item; item.setId(items.first().id()); responseIq.setItems(QList<QXmppPubSubItem>() << item); } server()->sendPacket(responseIq); notifyToClients(reqIq.from(), messageBody(reqIq.queryNode(), items)); } } return true; } void XmppPubSubManager::notifyToClients(QString const& jid, QXmppElement const& event) { for(int i = 0; i < clientJids.size(); i++) { if(jid == clientJids[i]) continue; QXmppMessage message; message.setType(QXmppMessage::Normal); message.setFrom(server()->domain()); message.setTo(clientJids[i]); message.setExtensions(QXmppElementList() << event); server()->sendPacket(message); } } void XmppPubSubManager::clientConnected(const QString &jid) { clientJids << jid; } void XmppPubSubManager::clientDisconnected(const QString &jid) { clientJids.removeAll(jid); }
-
PingManager
PingManager.h
#ifndef PINGMANAGER_H #define PINGMANAGER_H #include <qxmpp/QXmppServerExtension.h> class PingManager : public QXmppServerExtension { Q_CLASSINFO("ExtensionName", "ping_manager") public: QStringList discoveryFeatures() const; bool handleStanza(const QDomElement &stanza); }; #endif // PINGMANAGER_H
PingManager.cpp
#include "PingManager.h" #include <qxmpp/QXmppPingIq.h> #include <qxmpp/QXmppServer.h> #include <QDomElement> QStringList PingManager::discoveryFeatures() const { return QStringList() << "urn:xmpp:ping"; } bool PingManager::handleStanza(const QDomElement &stanza) { if(stanza.tagName() != "iq" || !QXmppPingIq::isPingIq(stanza)) return false; QXmppPingIq pingIq; pingIq.parse(stanza); if(pingIq.type() == QXmppIq::Get) { QXmppPingIq responseIq; responseIq.setType(QXmppIq::Result); responseIq.setId(pingIq.id()); responseIq.setTo(pingIq.from()); server()->sendPacket(responseIq); } return true; }
-
PasswordChecker
PasswordChecker.h
#ifndef PASSWORDCHECKER_H #define PASSWORDCHECKER_H #include <qxmpp/QXmppPasswordChecker.h> class PasswordChecker : public QXmppPasswordChecker { public: PasswordChecker(); virtual ~PasswordChecker(); virtual bool hasGetPassword() const { return true; } protected: QXmppPasswordReply::Error getPassword(const QXmppPasswordRequest &request, QString &password); }; #endif // PASSWORDCHECKER_H
PasswordChecker.cpp
#include "PasswordChecker.h" PasswordChecker::PasswordChecker() { } PasswordChecker::~PasswordChecker() { } QXmppPasswordReply::Error PasswordChecker::getPassword( const QXmppPasswordRequest &request, QString &password) { QString user = request.username(); if(user == "publisher") { password = "publisher123"; return QXmppPasswordReply::NoError; } else if(user == "subscriber") { password = "subscriber123"; return QXmppPasswordReply::NoError; } else { return QXmppPasswordReply::AuthorizationError; } }
-
main
main.cpp
#include "XmppServer.h" #include "PasswordChecker.h" #include <QCoreApplication> #include <QDateTime> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); XmppServer server(QString("%1/log/%2.txt") .arg(a.applicationDirPath()) .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"))); PasswordChecker passwordChecker; server.setPasswordChecker(&passwordChecker); server.start(); return a.exec(); }
上一篇:基于XMPP的发布订阅系统(一) 下一篇:基于XMPP的发布订阅系统(三)
-