MUC

以上屬性存儲在MUCPersistenceManager
private staticConcurrentHashMap<String,MUCServiceProperties> propertyMaps=newConcurrentHashMap<String,MUCServiceProperties>();
用戶端建立房間案例
第一:用戶端發出查詢請求
[html] view plain copy
<iq id="wcCqI-57" to="[email protected]" type="get">
<query xmlns="http://jabber.org/protocol/disco#info"/>
</iq>
伺服器将資料包發送到托管在該伺服器元件來處理。
routed = routeToComponent(jid,packet, routed);
伺服器需要在記憶體中判斷房間是否存在,其次呢,傳回外部元件的配置。為确切請求子域的查詢将會作出修改。如果沒有被發現和使用通配符請求,然後再查詢将被提出,在使用通配符這個時候。
然後檢查元件是否被托管在此JVM
擷取MUC元件的資訊
該MUC服務将接收的域MUC的域相比對的所有資料包服務。這意味着,例如,disco 請求應該由服務本身作出回應,而不是依賴在伺服器上處理請求。
根據命名空間找到相應處理——>IQDiscoInfoHandler。
尋找與所請求的實體相關的DiscoInfoProvider。
我們認為該資料包為機關的接收者的JID的主機。這是DiscoInfoProvider責任提供有關的JID的姓名資訊一起用任何可能的請求節點。
所查詢的房間節點不存在,按照正常的流程伺服器傳回錯誤資訊
<iq type="error" id="wcCqI-57" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<error code="404" type="cancel">
<item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
用戶端第二輪發送:
<presence id="wcCqI-59" to="[email protected]/test2">
<x xmlns="http://jabber.org/protocol/muc"/>
</presence>
伺服器處理:
1.将使用者發送的定向存在的實體
(通知方式發送到該處理程式,當使用者發送了一個指向存在的實體。如果存在的發件人是本地的(這個伺服器)和目标實體不屬于使用者的花名冊,然後發送更新派駐執導的使用者系統資料庫。)
2.廣播到所有連接配接的資源
(獲得由XMPPAddress聊天的使用者。僅傳回已連接配接到該JVM的使用者。)
伺服器傳回消息:
<message type="groupchat" from="[email protected]">
<body>确認配置之前已鎖住該房間,禁止進入。</body>
</message>
配置錢鎖定房間,一面别的用建立一樣的,或者申請加入這個房間
<presence id="wcCqI-59" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"
from="[email protected]/test2">
<x xmlns="http://jabber.org/protocol/muc#user">
<item jid="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"
affiliation="owner" role="moderator"/>
<status code="201"/>
</x>
用戶端發送IQ:
<iq id="wcCqI-60" to="[email protected]" type="get">
<query xmlns="http://jabber.org/protocol/muc#owner"/>
查詢房間擁有者。
伺服器傳回1:
<message type="groupchat" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<body>确認配置之前已鎖住該房間,禁止進入。</body>
伺服器傳回2:
<iq type="error" id="wcCqI-60" from="[email protected]"
to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<query xmlns="http://jabber.org/protocol/muc#owner"/>
<error code="401" type="auth">
<not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
======================================================================
總的對話
用戶端發送C2S - RECV (32671720):
<iq id="wcCqI-61" to="[email protected]" type="get">
<query xmlns="http://jabber.org/protocol/disco#info">
</query>
伺服器傳回
<iq type="error" id="wcCqI-61"
from="[email protected]"
to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<query xmlns="http://jabber.org/protocol/disco#info"/>
<error code="404" type="cancel">
<item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
以上循環兩次對話,這可能由于debug逾時原因,消息重複發送。
用戶端發送
<presence id="wcCqI-63" to="[email protected]/test2">
<x xmlns="http://jabber.org/protocol/muc">
出席消息。
1.當使用者發送一個 directed presence的時候将發送給directedPresenceSent()來處理。如果存在的發件人是本地的(這個伺服器)和目标實體不屬于使用者的花名冊,然後發送更新派駐執導的使用者系統資料庫。
跟蹤所有訓示派駐人員名冊,如果服務被禁用
這裡有兩塊記憶體記錄消息:
private Cache<String,Collection<DirectedPresence>>directedPresencesCache;
跟蹤發送指向派駐到其他實體。
在這個Cache上我們跟蹤每一個 directed presence存在,無論發送者是否托管在這個JVM或其他群集節點。
另一個
private Map<String,Collection<DirectedPresence>>localDirectedPresences;
發送相同directedPresencesCache但隻有不斷派駐指導
使用者連接配接到該JVM。
在方法directedPresenceSent()中主要對兩個變量開始操作,這裡有一個開鎖和解鎖的過程。
updateHandler.directedPresenceSent(packet, jid, recipientJID.toString());
2.路由消息包
被發送到XMPP域的元件路由資料包(這是XMPP域的子域)
首先檢查元件是否被托管在此JVM
存在,交由component.processPacket(packet);出資料包
該MUC服務将接收的域MUC服務的域相比對的所有資料包。
這意味着,例如,disco請求應該由服務本身作出回應,而不是依賴在伺服器上處理請求。
在getChatRoom()方法中會從資料庫中加載了房間的配置(如果房間是持久性的,但被添加到資料庫伺服器啟動或房間可能是舊的房間,這是不存在于記憶體後)
這裡OF伺服器檢查到房間需要重新建立的情況下,它沒有預先建立(或已被删除不知何故,預計委托存在)。
因為房間不存在,是以接下來就該檢測擁有者的建立權限了。依次添加room到記憶體中,以免其他建立者沖突。
開始建立房間事件——>通知其他叢集節點,一個新的空間可用.
檢查用戶端建立密碼或用戶端對MUC的支援
(注:擷取房間元件的基本資訊
Long serviceID = XMPPServer.getInstance().getMultiUserChatManager().
getMultiUserChatServiceID(room.getMUCService().getServiceName());)
<presence id="wcCqI-63" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"
from="[email protected]/test2">
<x xmlns="http://jabber.org/protocol/muc#user">
<item jid="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"
affiliation="owner" role="moderator"/>
<status code="201"/>
</x>
給自己發送出席
<message type="groupchat" from="[email protected]"
to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
用戶端發送:
<iq id="wcCqI-64" to="[email protected]" type="get">
<query xmlns="http://jabber.org/protocol/muc#owner">
</query>
</iq >
根據namespace伺服器将有IQOwnerHandler來處理
refreshConfigurationFormValues()房間配置資訊
伺服器傳回:
<iq type="result" id="wcCqI-64" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<query xmlns="http://jabber.org/protocol/muc#owner">
<x xmlns="jabber:x:data" type="form">
<title>房間配置</title>
<instructions>
已建立房間“room2”。要接受預設配置,請單擊“确定”按鈕。
或填寫以下表單以完成設定:
</instructions>
<field var="FORM_TYPE" type="hidden">
<value>http://jabber.org/protocol/muc#roomconfig</value>
</field>
<field var="muc#roomconfig_roomname" type="text-single"
label="房間名稱">
<value>room2</value>
<field var="muc#roomconfig_roomdesc" type="text-single"
label="描述">
<field var="muc#roomconfig_changesubject" type="boolean"
label="允許占有者更改主題">
<value>1</value>
<field var="muc#roomconfig_maxusers" type="list-single"
label="最大房間占有者人數">
<option label="10">
<value>10</value>
</option>
<option label="20">
<value>20</value>
<option label="30">
<value>30</value>
<option label="40">
<value>40</value>
<option label="50">
<value>50</value>
<option label="無">
<value>0</value>
<value>30</value>
<field var="muc#roomconfig_presencebroadcast" type="list-multi"
label="其 Presence 是 Broadcast 的角色">
<option label="主持者">
<value>moderator</value>
<option label="參與者">
<value>participant</value>
<option label="訪客">
<value>visitor</value>
<value>moderator</value>
<value>participant</value>
<value>visitor</value>
</field>
<field var="muc#roomconfig_publicroom" type="boolean"
label="列出目錄中的房間">
<value>1</value>
<field var="muc#roomconfig_persistentroom" type="boolean"
label="房間是持久的">
<value>1</value></field>
<field var="muc#roomconfig_moderatedroom" type="boolean"
label="房間是适度的">
<field var="muc#roomconfig_membersonly" type="boolean"
label="房間僅對成員開放">
<field type="fixed">
<value>注意:預設情況下,隻有管理者才可以在僅用于邀請的房間中發送邀請。</value>
<field var="muc#roomconfig_allowinvites" type="boolean"
label="允許占有者邀請其他人">
<field var="muc#roomconfig_passwordprotectedroom" type="boolean"
label="需要密碼才能進入房間">
<value>0</value>
<value>如果需要密碼才能進入房間,則您必須在下面指定密碼。</value>
<field var="muc#roomconfig_roomsecret" type="text-private"
label="密碼"/>
<field var="muc#roomconfig_whois" type="list-single"
label="能夠發現占有者真實 JID 的角色">
<option label="主持者">
<value>moderators</value>
</option>
<option label="任何人">
<value>anyone</value>
<value>anyone</value>
<field var="muc#roomconfig_enablelogging" type="boolean"
label="登入房間對話">
<value>1</value>
<field var="x-muc#roomconfig_reservednick" type="boolean"
label="僅允許注冊的昵稱登入">
</field>
<field var="x-muc#roomconfig_canchangenick" type="boolean"
label="允許使用者修改昵稱">
<value>允許使用者注冊房間</value>
<field var="x-muc#roomconfig_registration" type="boolean"
label="允許使用者注冊房間">
<value>您可以指定該房間的管理者。請在每行提供一個 JID。</value>
<field var="muc#roomconfig_roomadmins" type="jid-multi"
label="房間管理者"/>
<value>您可以指定該房間的其他擁有者。請在每行提供一個 JID。</value>
<field var="muc#roomconfig_roomowners" type="jid-multi"
label="房間擁有者">
<value>test2@8ntmorv1ep4wgcy</value>
</query>
用戶端發送1
<iq id="wcCqI-65" to="[email protected]" type="set">
<query xmlns="http://jabber.org/protocol/muc#owner">
<x xmlns="jabber:x:data" type="submit">
<field var="FORM_TYPE" type="hidden">
<value>http://jabber.org/protocol/muc#roomconfig</value>
</field>
<field var="muc#roomconfig_roomname" type="text-single">
<value>room2</value>
<field var="muc#roomconfig_roomdesc" type="text-single">
<value>測試2</value>
<field var="muc#roomconfig_roomowners" type="jid-multi">
<value>test2@8ntmorv1ep4wgcy</value>
</x>
</query>
在這一步操作,是用戶端來設定房間的一些配置資訊,并且儲存到DB(在類LoaclMUCRomm.saveToDB()方法中)
然後儲存使用者(普通使用者,管理者).
服務端傳回1
<message type="groupchat" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<body>該房間現在已解鎖。
</body>
服務端傳回2
<iq type="result" id="wcCqI-65" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"/>
<iq id="wcCqI-66" to="[email protected]" type="get">
<query xmlns="http://jabber.org/protocol/disco#info">
處理類:IQDiscoInfoHandler
服務端傳回
<iq type="result" id="wcCqI-66" from="[email protected]"
to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<identity category="conference" name="room2" type="text"/>
<feature var="http://jabber.org/protocol/muc"/>
<feature var="muc_public"/><feature var="muc_membersonly"/>
<feature var="muc_moderated"/>
<feature var="muc_nonanonymous"/>
<feature var="muc_unsecured"/>
<feature var="muc_persistent"/>
<feature var="http://jabber.org/protocol/disco#info"/>
<x xmlns="jabber:x:data" type="result">
<value>http://jabber.org/protocol/muc#roominfo</value>
<field var="muc#roominfo_description" label="描述">
<field var="muc#roominfo_subject" label="主題">
<value></value>
<field var="muc#roominfo_occupants" label="占有者人數">
<value>1</value>
<field var="x-muc#roominfo_creationdate" label="建立日期">
<value>20131202T02:22:08</value>
</field>
用戶端加入房間,首先擷取房間資訊
<iq id="BfI3V-47" to="[email protected]" type="get">
服務端通過查找伺服器元件擷取房間資訊并傳回如下封包
<iq type="result" id="BfI3V-55" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android">
<query xmlns="http://jabber.org/protocol/disco#info">
<identity category="conference" name="room2" type="text"/>
<feature var="http://jabber.org/protocol/muc"/>
<feature var="muc_public"/>
<feature var="muc_open"/>
<feature var="muc_unmoderated"/>
<feature var="muc_nonanonymous"/>
<feature var="muc_unsecured"/>
<feature var="muc_persistent"/>
<feature var="http://jabber.org/protocol/disco#info"/>
<x xmlns="jabber:x:data" type="result">
<value>http://jabber.org/protocol/muc#roominfo</value>
<value>測試房間2</value>
<value></value>
<value>20131202T07:08:32</value>
</query>
用戶端再次發送狀态
<presence id="BfI3V-57" to="[email protected]/test2"><x xmlns="http://jabber.org/protocol/muc"></x></presence>
服務端傳回:
<presence id="BfI3V-57" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android" from="[email protected]/test2"><x xmlns="http://jabber.org/protocol/muc#user"><item jid="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android" affiliation="owner" role="moderator"/></x></presence>
<message type="groupchat" from="[email protected]" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android"><body>該房間不是匿名的。</body><x xmlns="http://jabber.org/protocol/muc#user"><status code="100"/></x></message>
請求使用者發送消息内容
<message id="BfI3V-64" to="[email protected]">
<x xmlns="http://jabber.org/protocol/muc#user">
<invite to="test1@8ntmorv1ep4wgcy">
<reason>請把我加入會議中。</reason>
</invite>
</x>
元件将消息發送給用戶端test1,如圖:
Test1接收邀請
發送消息:
<presence id="6808K-48" to="[email protected]/test1">
服務端将發送如下消息
<presence id="6808K-48" to="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android" from="[email protected]/test1">
<item jid="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" affiliation="none" role="participant"/>
<presence id="BfI3V-57" to="test1@8ntmorv1ep4wgcy/Spark 2.6.3#android" from="[email protected]/test2">
<item jid="test2@8ntmorv1ep4wgcy/Spark 2.6.3#android" affiliation="owner" role="moderator"/>
OK,關于會議室這塊就到次結束。這裡讀起來很難了解很正常。基于xmpp協定的通訊消息太繁瑣了。但是隻要讀者細心debug調試,還是不難的。
我在上面中的jid,如:jid="test2@8ntmorv1ep4wgcy/Spark 2.6.3#Android,這裡面有個#号。而實際上在openfire正常的通訊是沒的
這是本人調試測試多加了個jid屬性。關于jid部分,本人會單獨拿出來寫博文的。歡迎閱讀,不對之處請聯系本人指正。