本文翻译自 – http://www.tigase.org/content/how-packets-are-processed-sm-and-plugins
理解插件是如何工做的对开发插件是很是重要的,在不一样的场景下由不一样类型的插件来负责处理packet。在开始正式的编码工做以前,建议你现阅读一下下面的文档。 html
在开始以前,先介绍一下什么是IQ。这个东西出如今后面的不少地方。Google了一下,IQ的意思是Info/Query:它是一种请求和应答机制,和http有一些相似的地方。 IQ的语意容许一个实体向另外一个实体发送请求,并从另外一个实体获取应答。请求和应答当中的数据在IQ元素的第一级子节点(命名空间的声明)当中被定义,请求方实体能够经过id标签来跟踪交互过程。如此一来,IQ交互的数据交换模式就相似于“get/result” 或者 “set/result”(在某些状况下,也多是get/error和set/error)。若有困惑请参考XMPP官方英文文档:http://xmpp.org/rfcs/rfc3920.html#stanzas-semantics-iq 算法
Requesting Responding Entity Entity ---------- ---------- | | | <iq type='get' id='1'> | | ------------------------> | | | | <iq type='result' id='1'> | | <------------------------ | | | | <iq type='set' id='2'> | | ------------------------> | | | | <iq type='error' id='2'> | | <------------------------ | | |
为了可以确保这种方式被执行,有以下规则须要遵照: 数据库
插件是一段负责处理特定XMPP stanza的代码。有专门负责处理消息的插件,有专门负责处理在线状态的插件,有专门负责处理iq通信录的插件,也有专门负责处理版本的插件。 服务器
插件经过xmlns和元素名来声明全部它“感兴趣”的那些在特定命名空间下的特定XML元素名,因此你能够建立一个对那些包含caps元素的packet“感兴趣”的插件。 session
对于那些没有插件“感兴趣”的stanza元素,它们会被直接传递到消息的目标地址。相反的,也有一些特定的stanza可能会被多个插件“感兴趣”,在这种状况下,多个插件可能会被多个线程同时进行处理,因此没法确保哪一个插件先进行处理哪一个插件后进行处理。 wordpress
每个stanza都会被session manager一步一步得进行处理,看看下面的图: 编码
就像图片里面展现的那样,stanza在session manager里面分四步进行处理: 插件
须要提醒两点: 线程
若是packet p1要向服务器外部发送(好比要发送给另一台服务器的一个用户,或者另一个组件 – MUC/PubSub/transport之类的),那么服务器中的第一个处理器必须为p1建立一个备份p2,而且正确设置好全部的全部的属性和目的地地址。当p1被SM在处理过程当中销毁,最终服务器中的插件还可以产生一个新的packet。
若是是组件向用户发送也是同样:
组件向用户发送
在来自组件的packet被销毁以前,服务器中的一个插件必须作好备份,并最终把备份投递给用户。固然了投递操做在packet没有被任何插件处理时会做为默认行为被执行。
这样设计的缘由是:输入packet-p1会在SM中被多个插件在多个线程中同时处理,因此packet的值在处理过程当中必定不能被改变。
最明显的处理过程是当一个用户向服务器发送一个指令并但愿从服务器得到一个应答:
这种设计产生惊人的结果。若是你看完下面两个用户之间的交互,你会发现,packet在投递到目的地以前被拷贝了两次:
一个用户向另外一个用户发送packet
就像图片所展现的那样,packet被SM处理了两次。第一次是做为用户A的传出packet进行处理,第二次是做为用户B的传入packet进行处理。
这样作的目的是为了首先肯定用户A有权限发送packet,而后是肯定用户B有权限接收数据。若是用户B不在线,那么离线消息处理器会把packet保存到数据库当中。