本文翻譯自 – 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保存到數據庫當中。