openfire插件编写进阶,拦截数据包与发送广播
来源:互联网 发布:下载火车购票软件 编辑:程序博客网 时间:2024/06/06 07:03
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包
- public class Broadcastsextends IQ {
- private String body;
- public String getElementName() {
- return "b";
- }
- public String getNamespace() {
- return "com:message:broadcasts";
- }
- public void setBody(String body) {
- this.body = body;
- }
- public String getBody() {
- return body;
- }
- @Override
- public String getChildElementXML() {
- if(getBody() == null){
- throw new RuntimeException("Broadcasts body is empty");
- }
- StringBuilder sb = new StringBuilder();
- sb.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">").append(getBody()).append("</").append(getElementName()).append(">");
- return sb.toString();
- }
- }
public class Broadcasts extends IQ { private String body; public String getElementName() { return "b"; } public String getNamespace() { return "com:message:broadcasts"; } public void setBody(String body) { this.body = body; } public String getBody() { return body; } @Override public String getChildElementXML() { if(getBody() == null){ throw new RuntimeException("Broadcasts body is empty"); } StringBuilder sb = new StringBuilder(); sb.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">").append(getBody()).append("</").append(getElementName()).append(">"); return sb.toString(); } }通过sendpacket方法,发到服务器上,会返回一个<error code="503" type="CANCEL"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>的包,
IQHandler却没有捕捉到,这个包,有些奇怪。
我用packetInterceptor拦截所有包,发现那个IQ包的确被服务器收到,而且可以对它进行处理。
packerInterCeptor的关键代码
- private class SignatureInterceptorimplements PacketInterceptor
- {
- @Override
- public void interceptPacket(Packet packet, Session session,
- boolean incoming, boolean processed)throws PacketRejectedException
- {
- if(incoming && packetinstanceof IQ){
- IQ myIQ=(IQ)packet;
- Element iq = myIQ.getElement();
- Element b =iq.element("b");
- System.out.println(b.getNamespaceURI());
- if (b.getNamespaceURI().equals("com:message:broadcasts")){
- System.out.println(myIQ.toXML());
- XMPPServer.getInstance().getSessionManager().sendServerMessage(null,"gogogo!");
- }
- }
- }
- }
private class SignatureInterceptor implements PacketInterceptor{@Overridepublic void interceptPacket(Packet packet, Session session,boolean incoming, boolean processed) throws PacketRejectedException{if(incoming && packet instanceof IQ){IQ myIQ=(IQ)packet;Element iq = myIQ.getElement();Element b =iq.element("b");System.out.println(b.getNamespaceURI());if (b.getNamespaceURI().equals("com:message:broadcasts")){System.out.println(myIQ.toXML());XMPPServer.getInstance().getSessionManager().sendServerMessage(null, "gogogo!");}}}}XMPPServer.getInstance().getSessionManager().sendServerMessage(null, "gogogo!");
会构造一个message包,<message from="202.118.239.46"><body>gogogo!</body></message>
不管用户在不在线,域中的客户端都可以捕捉到这条信息。
后来发现这样一段代码
- IQ iq = new IQ(){
- @Override
- public String getChildElementXML() {
- StringBuilder buf = new StringBuilder();
- buf.append("<query xmlns=\"com:im:group\"/>");
- return buf.toString();
- }
- };
IQ iq = new IQ(){ @Override public String getChildElementXML() { StringBuilder buf = new StringBuilder(); buf.append("<query xmlns=\"com:im:group\"/>"); return buf.toString(); } };
这里比较关键的一句话时是:buf.append("<query xmlns=\"com:im:group\"/>");这句话指定了这个消息是发动到那个命名空间中。
只有发送到openfire插件对应的命名空间中openfire插件才可以正确接收。
如果服务器找不到,处理包内的命名空间的插件,会返回一个serivce-unavailable错误。
- openfire插件编写进阶,拦截数据包与发送广播
- openfire插件编写进阶,拦截数据包与发送广播
- openfire插件编写进阶,拦截数据包与发送广播
- openfire 插件编写
- smack+openfire插件实现广播。向所有在线用户发送消息。
- 广播发送与接收
- C++编写发送自定义TCP数据包程序
- 网卡发送与接收数据包
- Android开发之发送有序广播+拦截广播
- 编写监听端口的Openfire插件
- 广播发送者与广播接收者
- Android 发送系统广播与自定义广播
- Android 广播发送者与广播接收者
- 广播接收者与广播发送者复习
- Android发送广播与接收广播
- Android广播发送者与广播接收者
- Android_广播发送者与广播接收者
- jpcap安装与配置、数据包拦截
- 1.pthread_create()初体验
- mysql密码管理
- php判断是否为ajax请求摘自thinkphp
- Kryo、msgpack、protobuf、Hessian、Avro、Thrift等序列化框架比较
- 程序崩掉后 自动重启的shell脚本
- openfire插件编写进阶,拦截数据包与发送广播
- MVC框架是什么
- OC开发基本常识
- ERROR 1148 (42000): The used command is not allowed with this MySQL versio
- JS获取当前时间戳的方法
- 找出符合规则为ABAB,ABCABC的QQ号码
- 如何成为Python高手
- SD卡检测
- js parseInt