基于XMPP的发布订阅系统(二)

基于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的发布订阅系统(三)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flysnow010

你的鼓励就是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值