C++:gloox库进行协议扩展(使用自定义标签)

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_29542611/article/details/87736734

前言

直接使用gloox库源码中examples下面的示例,采用开源的openfire搭建的xmpp的服务器,是可以直接进行连接、注册和消息推送。 使用AndroidPN作为xmpp服务器可以可以直接使用 gloox的示例进行注册,但是连接 和 消息推送不行。连接的问题咋们就不说了,咋们直接说 消息推送的问题。

因为AndroidPN作为服务器 给客户端推送的消息是扩展了协议,所以直接使用示例代码是不行。笔者也是看官方文档查看 gloox源代码,将这个问题调通了。其实就是Protocol Extensions 协议扩展问题,如果你仔细去看stanzaextension.h也能解决。自己在网上没有找到一个完整的示例,所以在这里本着奉献自我的精神,写一个使用 gloox 进行协议扩展的案例。

下面是AndroidPN服务器给的消息推送报文结构

<iq type='set' id='193-0' to='[email protected]/gloox'>
    <notification xmlns='androidpn:iq:notification'>
        <id>65d24038</id><apiKey>1234567890</apiKey>
        <title>Dokdo Island</title>
        <message>Dokdo is a Korean island, the far east of the Korean territory. No doubt! No question! Don&apos;t mention it any more!</message>
        <uri>www.baidu.com</uri>
    </notification>
</iq>

我们需要的title、message和uri,我们通过协议扩展来获取到我们想要的信息。

这里额外说下gloox使用的是1.0.22版本AndroidPN服务器使用的是androidpn-server-0.5.0-bin

代码

定义我们自己的扩展类

myextension.h

#pragma once

#include "stanzaextension.h"
#include <string>
using namespace gloox;

class MyExtension :public StanzaExtension
{
public:
	  MyExtension();
	  MyExtension( const Tag* tag );
	  //MyExtension( const MyExtension& one );
      virtual ~MyExtension();

      /**
       * This function returns the embedded Stanza, if any.
       * You only have to reimplement it if your protocol flow contains embedded Stanzas.
       *
       * @return The embedded Stanza. May be 0.
       */
      virtual Stanza* embeddedStanza() const { return 0; }

      /**
       * This function returns the embedded Tag that the embedded Stanza is based on, if any.
       * You only have to reimplement it if your protocol flow contains embedded Stanzas.
       *
       * @return The embedded Tag. May be 0.
       */
      virtual Tag* embeddedTag() const { return 0; }

      /**
       * Returns an XPath expression that describes a path to child elements of a
       * stanza that an extension handles.
       *
       * @return The extension's filter string.
       */
      virtual const std::string& filterString() const;

      /**
       * Returns a new Instance of the derived type. Usually, for a derived class FooExtension,
       * the implementation of this function looks like:
       * @code
       * StanzaExtension* FooExtension::newInstance( const Tag* tag ) const
       * {
       *   return new FooExtension( tag );
       * }
       * @endcode
       * @return The derived extension's new instance.
       */
      virtual StanzaExtension* newInstance( const Tag* tag ) const;

      /**
       * Returns a Tag representation of the extension.
       * @return A Tag representation of the extension.
       */
      virtual Tag* tag() const;

      /**
       * Returns an identical copy of the current StanzaExtension.
       * @return An identical copy of the current StanzaExtension.
       */
      virtual StanzaExtension* clone() const;

	  std::string getTitle();
	  std::string getMsg();
	  std::string getUrl();

private:
	std::string m_title;
	std::string m_msg;
	std::string m_url;
};

myextension.cpp

#include "myextension.h"
#include "tag.h"
#include "gloox.h"
#include <stdlib.h>
using namespace gloox;

#define OPEN_TEST 0

MyExtension::MyExtension():StanzaExtension(ExtUser)
{
#if OPEN_TEST
	printf("MyExtension() \n");
#endif
}	

MyExtension::MyExtension( const Tag* tag ):StanzaExtension(ExtUser)
{
	/*
	<notification xmlns='androidpn:iq:notification'>
		<id>65d24038</id>
		<apiKey>1234567890</apiKey>
		<title>Dokdo Island</title>
		<message>Dokdo is a Korean island, the far east of the Korean territory.</message>
		<url>www.baidu.com</url>
	</notification>
	*/
	#if OPEN_TEST
		printf("MyExtension( const Tag* tag ) enter \n");
	#endif

	Tag* titleTag = tag->findChild("title");
	if( NULL != titleTag )
	{
		m_title = titleTag->cdata();
	}

	Tag* msgTag = tag->findChild("message");
	if( NULL != titleTag )
	{
		m_msg = msgTag->cdata();
	}

	Tag* urlTag = tag->findChild("uri");
	if( NULL != urlTag )
	{
		m_url = urlTag->cdata();
	}
}

MyExtension::~MyExtension() 
{
#if OPEN_TEST
	printf("~MyExtension() \n");
#endif
}

// 返回自定义协议的xmlns进行过滤匹配
const std::string& MyExtension::filterString() const
{
	#if OPEN_TEST
		printf("filterString() enter \n");
	#endif
	static const std::string filter = "/iq/notification[\@xmlns='androidpn:iq:notification']";
	return filter;
}

StanzaExtension* MyExtension::newInstance( const Tag* tag ) const
{
	#if OPEN_TEST
		printf("newInstance( const Tag* tag ) enter \n");
	#endif
	StanzaExtension* ret = new MyExtension( tag );
	return ret;
}

Tag*  MyExtension::tag() const
{
	/*
	<notification xmlns='androidpn:iq:notification'>
		<id>65d24038</id>
		<apiKey>1234567890</apiKey>
		<title>Dokdo Island</title>
		<message>Dokdo is a Korean island, the far east of the Korean territory.</message>
		<url>www.baidu.com</url>
	</notification>
	*/
	#if OPEN_TEST
		printf("MyExtension::tag() enter \n");
	#endif

	Tag* root = new Tag("notification");
	root->addAttribute("xmlns","androidpn:iq:notification");

	Tag* titleTag = new Tag("title");
	Tag* msgTag = new Tag("message");
	Tag* urlTag = new Tag("uri");
	titleTag->setCData(m_title);
	msgTag->setCData(m_msg);
	urlTag->setCData(m_url);
	
	root->addChild(titleTag);
	root->addChild(msgTag);
	root->addChild(urlTag);

	return root;
}

StanzaExtension* MyExtension::clone() const
{
	StanzaExtension* ret = new MyExtension(*this);
	return ret;
}

std::string MyExtension::getTitle()
{
	return m_title;
}

std::string MyExtension::getMsg()
{
	return m_msg;
}

std::string MyExtension::getUrl()
{
	return m_url;
}

在使用的地方进行注册,并且继承 IqHandler并重写对应的纯虚函数。

	  MyExtension* ex = new MyExtension(); // 自定义xmpp协议扩展
	  j->registerIqHandler(this,ExtUser);
	  j->registerStanzaExtension(ex);

重写

virtual bool handleIq( const IQ& iq ) 
	{
		MyExtension* ex = (MyExtension*)iq.findExtension(ExtUser);
		if( NULL == ex )
		{
			return false;
		}
		std::cout <<"title:" << ex->getTitle() << std::endl;
		std::cout << "msg:" << ex->getMsg() << std::endl; 
		std::cout << "url:" << ex->getUrl() << std::endl;
		return true;
	}
	virtual void handleIqID( const IQ& iq, int context )
	{
		return;
	}

效果截图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_29542611/article/details/87736734