zoukankan      html  css  js  c++  java
  • openfire拦截数据包与发送广播

    openfrie官网插件开发人员指南,中文版:http://www.blogjava.net/jyleon/articles/254197.html

    分析了openfire的官方插件,插件的import里大概有4中包中的东西,

    openfire包,

    dom4j包(这个是解析xml的),

    tinder包(这个包里有一些xmpp packet的封装),

    slf4j包(这个包是logger相关的东西)

    看来这个···openfire还是用了很多别的开源插件的,tinder可以从官网上下到,稍微配置一下,吧包都导进去,就可一写插件了。


    这个,拦截数据包大概有4种方法

    1、Register a plugin as a Component。 Components可以接收一个特定子域(sub-domain)的所有包。比如test_componet.example.com。所以,一个发送 给joe@test_componet.example.com的包将被转发给这个componet.
    2、Register a plugin as an IQHandler。IQ handlers相应包中特定的元素名或命名空间。下面的代码展示了如何注册一个IQHandler.
    IQHandler myHandler = new MyIQHander();
    IQRouter iqRouter = XMPPServer.getInstance().getIQRouter();
    iqRouter.addHandler(myHandler);
    3、Register a plugin as a PacketInterceptor。 这种方式可以接收系统传输的所有包,并可以随意的丢弃它们。例如,一个interceptor 可以拦截并丢弃所有含有不健康信息的消息,或者将它们报告给系统管理员。
    4、使用JiveGlobals.getProperty(String) 和 JiveGlobals.setProperty(String, String) 方法将我们的插件设置为openfire的一个全局属性。通过实现 org.jivesoftware.util.PropertyEventListener方法可以将我们的 插件做成一个属性监听器监听任何属性的变化。通过 PropertyEventDispatcher.addListener(PropertyEventListener)方法可以注册监听。要注意的一 点是,一定要在destroyPlugin()方法中将注册的监听注销。


    官方带的,braodcast用的是第一种,component的方法。

    我尝试,第二种方法,发送一个自定义的IQ包

    1. public class Broadcasts extends IQ {      
    2.       
    3.     private String body;      
    4.     public String getElementName() {      
    5.         return "b";      
    6.     }      
    7.       
    8.     public String getNamespace() {      
    9.         return "com:message:broadcasts";      
    10.     }      
    11.       
    12.     public void setBody(String body) {      
    13.         this.body = body;      
    14.     }      
    15.       
    16.     public String getBody() {      
    17.         return body;      
    18.     }      
    19.       
    20.     @Override      
    21.     public String getChildElementXML() {      
    22.         if(getBody() == null){      
    23.             throw new RuntimeException("Broadcasts body is empty");      
    24.         }      
    25.         StringBuilder sb = new StringBuilder();      
    26.         sb.append("<").append(getElementName()).append(" xmlns="").append(getNamespace()).append("">").append(getBody()).append("</").append(getElementName()).append(">");      
    27.         return sb.toString();      
    28.     }      
    29.       
    30. }      

    通 过sendpacket方法,发到服务器上,会返回一个<error code="503" type="CANCEL"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>的包,

    IQHandler却没有捕捉到,这个包,有些奇怪。


    我用packetInterceptor拦截所有包,发现那个IQ包的确被服务器收到,而且可以对它进行处理。

    packerInterCeptor的关键代码

    1. private class SignatureInterceptor implements PacketInterceptor  
    2.   
    3.     {  
    4.   
    5.         @Override  
    6.         public void interceptPacket(Packet packet, Session session,  
    7.   
    8.         boolean incoming, boolean processed) throws PacketRejectedException  
    9.   
    10.         {  
    11.                 if(incoming && packet instanceof IQ){  
    12.                     IQ myIQ=(IQ)packet;  
    13.                     Element iq = myIQ.getElement();  
    14.                     Element b =iq.element("b");  
    15.                     System.out.println(b.getNamespaceURI());  
    16.                     if (b.getNamespaceURI().equals("com:message:broadcasts")){  
    17.                         System.out.println(myIQ.toXML());  
    18.                         XMPPServer.getInstance().getSessionManager().sendServerMessage(null"gogogo!");  
    19.                     }  
    20.                 }  
    21.         }  
    22.   
    23.     }  

    XMPPServer.getInstance().getSessionManager().sendServerMessage(null, "gogogo!");

    会构造一个message包,<message from="202.118.239.46"><body>gogogo!</body></message>

    不管用户在不在线,域中的客户端都可以捕捉到这条信息。

    后来发现这样一段代码

    1. IQ iq = new IQ(){    
    2.             @Override    
    3.             public String getChildElementXML() {    
    4.                   StringBuilder buf = new StringBuilder();    
    5.                   buf.append("<query xmlns="com:im:group"/>");    
    6.                   return buf.toString();    
    7.             }    
    8.                 
    9.         };    


    这里比较关键的一句话时是:buf.append("<query xmlns="com:im:group"/>");这句话指定了这个消息是发动到那个命名空间中。
    只有发送到openfire插件对应的命名空间中openfire插件才可以正确接收。 如果服务器找不到,处理包内的命名空间的插件,会返回一个serivce-unavailable错误。

  • 相关阅读:
    iOS跳转系统设置界面
    Swift中GCD与NSOperation相关
    将某字段按逗号分隔展示
    Java参考资料
    iOS消息推送相关
    [转]8 Regular Expressions You Should Know
    Oracle表锁住处理
    iframe自适应高度处理方案
    Mac常用软件推荐
    java代码块
  • 原文地址:https://www.cnblogs.com/rongxiang/p/3374658.html
Copyright © 2011-2022 走看看