述语:
TLS 传输层安全协议 SASL简单验证和安全层
层的顺序:TCPTLSSASLXMPP
XML节通过XML流来发送,XMPP定义了三种顶级XML节
XMPP给这三种节定义了五种通用属性 to from id type xml:lang
to属性指定接收节的JID。
from属性指定发送者的JID。
id属性是可选的。并且,在接收应用(通常是一个服务器)中是唯一的。注意:流ID可能是严格安全的,并且因此必须是即不能预测也不能重复的
type属性指定目的或消息上下文,出席或IQ节的详细信息。 iq节的type属性有: Type 值 Error Get Result Set 描述 如果一个实体接收了一个类型\"get\"或\"set\"的IQ节包含一个不理解的子元素, 这个实体应该返回一个类型为\"error\"的
presence节的type属性有: Type 值 Available 描述
Subscribe Subscribed Unsubscribe Unsubscribed Unavailable Probe Error Invisible Presence 节的子元素 子元素节点
Show节点的取值:
away -- 实体或资源临时离开. chat -- 实体或资源在聊天中是激活的. dnd -- 实体或资源是忙(dnd = \"不要打扰\"). xa -- 实体或资源是长时间的离开(xa = \"长时间离开\")
如果没有提供
message节的type属性有: 类型值 Chat 描述 消息是在一对一聊天会话的语境被发送. 一个兼容的客户端应该在一个允许两个实体进行一对一聊天的界面中显示消息,包括适当的会话历史 发生了一个和上次发送者发送的消息有关的错误(关于节错误语法的详细信息,一个兼容客户端应该在一个适当的界面展示它以通知发送者这个错误的种类 Error
GroupChat 消息是在一个多用户聊天环境的语境下发送的(类似[IRC]). 一个兼容客户端应该在允许多对多聊天的界面显示这个消息,包括, 包括这个聊天室的名册和适当的会话历史. 基于XMPP的群聊协议的完整定义超出了本文的范围 一个消息可能是由一个递送或广播内容的自动化服务生成的(新闻, 体育, 市场信息, RSS feeds, 等等.). 这个消息是不需要回复的, 一个兼容客户端应该在一个适当的和单独消息,聊天会话,或群聊会话不同的界面显示这个消息(例如, 不给接收者提供回复能力) 这个消息是一个在一对一会话或群聊会话之外的单独消息, 并且它希望接收者能够回复.一个兼容客户端应该在一个允许接收者回复的界面显示这个消息, 但不需要会话历史 元素描述 主题 主体 线索 Headline Normal Message 子元素 元素节点
名册管理
一个名册项相的presence信息订阅状态从 Subscription属性值 值 none 值描述 这个用户(A)没有对这个(item行中的)联系人(B)出席信息的订阅, 这个联系人(B)也没有订阅用户(A)的presence信息,即A,B没有任何订阅关系 这个用户订阅了这个联系人的presence信息, 但是这个联系人没有订阅用户的presence信息。即B是A的好友,但A不是B的好友 这个联系人订阅了用户的presence信息, 但是这个用户没有订阅这个联系人的presence信息。即A是B的好友,但B不是A的好友。 to from both 用户和联系人互相订阅了对方的出席信息 A,B互为好友 每个 每个 xml:lang属性值指定任意可读XML字符数据的缺省语言 订阅状态 从用户的角度,已定义的发种可能的订阅状态。 状态 None None + Pending Out 描述 联系人和用户互相没有被对方订阅, 并且也都没有从对方那里请求一个订阅 联系人和用户互相没有被对方订阅, 用户已经向联系人发送了一个订阅请求但还没有收到回复 联系人和用户互相没有被对方订阅, 联系人已经向用户发送了一个订阅请求但还没有收到回复(注意: 在这种状态下联系人的服务器None + Pending In 不应该推送或递送名册条目, 但是应该等待,直到联系人的订阅请求已经从用户那里得到批准) None + Pending Out/In 联系人和用户互相没有被对方订阅, 联系人已经向用户发送了一个订阅请求但还没有收到回复, 用户已经向联系人发送了一个订阅请求但还没有收到回复 用户已订阅联系人(单向) 用户已订阅联系人, 联系人已经向用户发送了一个订阅请求但还没有收到回复 联系人已订阅用户(单向) 联系人已订阅用户(单向), 用户已经向联系人发送了一个订阅请求但还没有收到回复 用户和联系人互相被对方订阅了(双向) To To + Pending In From From + Pending Out Both 对上述9种状态,用户进行subscribed(授予订阅权限)节处理后,用户的状态变化 以下描述里A为用户,B为联系人 出站:用户即收到服务器发来的消息用户做出响应后向服务器发出的动作。 入站:用户服务器收到联系人发来的消息后,转后给用户的所有资源的动作。 消息发出方(出站) 当前状态 None None+Pending Out 是否路由发过来? 否 否 新状态 状态不变 状态不变 描述 A,B无订阅关系,故状态不变 A当前为发出订阅请求,但B还没有响应,故状态不变 B向A发送一个订阅请求,这时A进行subscribed处理之后,状态变为From(即A同为成为B的好友) 收到B发来订部A的请求,A进行subscribed处理后,A将成为B的好友,但A发出的订阅请求,B还没有作回应 B已是A的好友,没有消息请求,故状态不变 在B已是A好友的情况下,B向A发来订阅A的请求,当A进None+Pending In 是 From None+Pending Out/In 是 Form+Pending Out To 否 状态不变 To+Pending In 是 Both 行subscribed处理后,A也同意成为B的好友。故状态变为both From 否 状态不变 A已是B的好友,没有由到路由发来的请求,故不变 在A已是B好友的情况下,向B发了订阅请求,但B没有应答,所以也没有路由消息要处理,故不变 From+Pending Out 否 状态不变 Both 否 状态不变 (出站)用户作拒绝处理(unsubscribed) 当前状态 None None+Pending Out 是否路由发过来? 否 否 新状态 状态不变 状态不变 描述 A,B无订阅关系,故状态不变 A当前为发出订阅请求,但B还没有响应,故状态不变 B发来订阅A的请求,A作拒绝处理后状态变为None A发出的请求未得到B的请求,这时收到B发来的订阅A的请求,A进行拒绝(unsubscribed)处理后,状态变为None+Pending Out B已同意成为A的好友 在B已是A的好友的情况下,收到B发来的订阅请求,A拒绝后,状态变为To A已经同意成为B的情况下,A选择取消授权(unsubscribed)之后,A,B之间没有任何关系,即变为None A成为B的好友情况下,A发出订阅请求None+Pending In 是 None None+Pending Out/In 是 None+Pending Out To To+Pending In 否 是 状态不变 To From 是 None From+Pending Out 是 None+Pending Out 给B后,进行拒绝 Both 是 To 在,AB互为好友的情况,A取消授权给B,哪么就回到了单方好友,即A将不再成为B的好友,但B还是A的好友。 用户收到presence订阅消息(入站)时服务器处理 A:用户 B:联系人 入站subscribe节处理 当前状态 None 是否路由发过来? 是 新状态 None+Pending in 描述 当B发送订阅(subscribe)请求给A,A服务器收到后,状态变为None+Pending In 此时A的状态为发送订阅B的请求但未得到回应,这个时侯A的服务器收到B发来的subscribe请求,所以状态变为None+Pending Out/In B发来订阅A未作回应,故不变 B发来订阅A未作回应,故不变 此时状态为B是A的好友,B发来订阅请求给A的服务器,服务器将状态改为to+pending In A在此状态下服务器没有接收subscribe消息,故不变 A在此状态下服务器没有接收subscribe消息,故不变 A在此状态下服务器没有接收subscribe消息,故不变 A在此状态下服务器None+Pending Out 是 None+Pending Out/In None+Pending In None+Pending Out/In To 否 否 是 状态不变 状态不变 To+Pending In To+Pending In 否 状态不变 From 否 状态不变 From+Pending Out 否 状态不变 Both 否 状态不变 没有接收subscribe消息,故不变 处理入站unsubscribe A:用户 B:联系人 当前状态 None 是否路由发过来? 否 新状态 状态不变 描述 A,B没有任何关系,所以A服务器收到unsubscribe时,状态不需要改变。 A,B没有任何关系,所以A服务器收到unsubscribe时,状态不需要改变。 B发出订阅消息给A,在A未作回应的时候,B又发出了unsubscribe进行取消,A的服务器收到后,将状态改为None A在None+Pending Out/In状态下,B发送unsubscribe进行取消后,A的服务器将状态改为None+Pending Out B已是A的好友,但B没有订阅过A,所以B进行取消订阅,没有改变状态。 B目前已是A的好友,并且B发送订阅请求给A,在A未作回应情况下,B发出了unsubscribe来取消,所以状态又变回了To A已是B的好友,现在B不想再订阅A了,发出unsubscribe进行取消后,状态改为None A已是B的好友,现None+Pending Out 否 状态不变 None+Pending In 是 None None+Pending Out/In 是 None+Pending Out To 否 状态不变 To+Pending In 是 To From 是 None From+Pending Out 是 None+Pending Out 在B不想再订阅A了,发出unsubscribe进行取消后,状态改为None+Pending Out Both 是 To 双方为好友的情况下,B取消对A的订阅,即解决关系,这里回到了,B是A的好友,但A不再是B的好友了。 处理入站subscribed(订阅授权) A:用户 B:联系人 当前状态 None None+Pending Out 是否路由发过来? 否 是 新状态 状态不变 To 描述 A,B没有关系,所以状态不变 A此时已经发送订阅给B,现在B进行同意后,A的服务器将变为To A没有发任何订阅B的请求,所以B发授权状态也不会变 A在None+Pending Out状态下,收到subscribed后变为to所以这里的状态为To+Pending In A没有发任何订阅请求,所以不变 A没有发任何订阅请求,所以不变 A没有发任何订阅请求,所以不变 此时A已是B的好友,在A发出订阅请求后,B同意(subscribed)之后就变为Both A没有发任何订阅请求,所以不变 None+Pending In 否 状态不变 None+Pending Out/In 是 To+Pending In To To+Pending In From From+Pending Out 否 否 否 是 状态不变 状态不变 状态不变 Both Both 否 状态不变 入站处理 unsubscribed A:用户 B:联系人 当前状态 None None+Pending Out None+Pending In None+Pending Out/In To 是否路由发过来? 否 是 否 是 是 新状态 状态不变 None 状态不变 None+Pending In None 描述 遇到B的拒绝,所以变为None 遇到B的拒绝,所以变为None A订阅B,B同意后状态变为To,但B想取消同意的订阅,所以又变回了None A订阅B,B同意后状态变为To,但B想取消同意的订阅,所以又变回了None A没有发出订阅请求,所以不变 A发出请求被B拒绝,又变回了From B解除了A的订阅,但A没有解解B的订阅,成单方好友。 To+Pending In 是 None+Pending In From From+Pending Out Both 否 是 是 状态不变 From From 订阅状态变更通知 节类型 Subscribe Subscribed Unsubscribe Unsubscribed 客户端:(支持多终端) 多个终端登录,使用resource 如: Example@fsh.com/PC example@fsh.com/Iphone example@fsh.com/android 红色的地方为资源。 接受 Subscribed Subscribe Unsubscribed Unsubscribe 禁止 Unsubscribed unsubscribe Subscribed subscribe JID 合法的JID应包括:域名(domain),节点名(node),资源名(resource) 且长度不能超过1023字节。 jid = [ node \"@\" ] domain [ \"/\" resource ] domain = fqdn / address-literal fqdn = (sub-domain 1*(\".\" sub-domain)) sub-domain = (internationalized domain label) address-literal = IPv4address / IPv6address stream 属性 to from id 初始化方发给接收方 接收方发给初始化方 接收方的主机名 忽略 忽略 忽略 接收方的主机名 会话键值 缺省语言 支持XMPP 1.0 xml:lang 缺省语言 version 支持XMPP 1.0 流错误的条件。 条件标签 'version'属性的值所指定的版本不被服务器支持;服务器可以在 SASL错误条件定义 条件节点 TLS握手过程 客户端-----服务端 步骤 1: 客户端初始化流给服务器 步骤 2: 服务器发送一个流标签给客户端作为应答 步骤 3: 服务器发送 STARTTLS 范围给客户端(包括验证机制和任何其他流特性) 步骤 4: 客户端发送 STARTTLS 命令给服务器 步骤 5: 服务器通知客户端可以继续进行 步骤 5 (或者): 服务器通知客户端 TLS 握手失败并关闭流和TCP连接 步骤 6: 客户端和服务器尝试通过已有的TCP连接完成 TLS 握手. 步骤 7: 如果 TLS 握手成功, 客户端初始化一个新的流给服务器 步骤 7 (或者): 如果 TLS 握手不成功, 服务器关闭 TCP 连接. 步骤 8: 服务器发送一个流头信息应答客户端,其中包括任何可用的流特性 服务端------服务端 步骤 1: Server1 初始化流给 Server2 步骤 2: Server2 发送一个流标签给 Server1 作为应答 步骤 3: Server2 发送 STARTTLS 范围给 Server1 ,包括验证机制和任何其他流特性 步骤 4: Server1 发送 STARTTLS 命令给 Server2 步骤 5: Server2 通知 Server1 允许继续进行 步骤 5 (或者): Server2 通知 Server1 TLS握手失败并关闭流 步骤 6: Server1 和 Server2 尝试通过 TCP 完成 TLS 握手. 步骤 7: 如果 TLS 握手成功, Server1 初始化一个新的流给 Server2 步骤 7 (或者): 如果 TLS 握手不成功, Server2 关闭 TCP 连接. 步骤 8: Server2 发送一个包含任何可用流特性的流头信息给 Server1 SASL握手过程 客户端-----服务端 步骤 1: 客户端初始化流给服务器 步骤 2: 服务器向客户端发送流标签作为应答 步骤 3: 服务器通知客户端可用的验证机制 步骤 4: 客户端选择一个验证机制 cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg== 解码后的挑战信息是 realm=\"somerealm\ qop=\"auth\ 步骤 5 (替代): 服务器返回一个错误给客户端 步骤 6: 客户端发送一个[BASE64]编码的回应这个挑战 dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo YXJzZXQ9dXRmLTgK 解码后的回应信息是 username=\"somenode\ nonce=\"OA6MG9tEQGm2hh\ nc=00000001,qop=auth,digest-uri=\"xmpp/example.com\ response=d388dad90d4bbd760a152321f2143af7,charset=utf-8 步骤 7: 服务器发送另一个[BASE64]编码的挑战给客户端 cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo= 解码后的挑战信息是 rspauth=ea40f60335c427b5527b84dbabcdfffd 步骤 7 (或者): 服务器返回一个错误给客户端 步骤 8: 客户端应答这个挑战 步骤 9: 服务器通知客户端验证成功 步骤 10: 客户端发起一个新的流给服务器 步骤 11: 服务器发送一个流头信息回应客户端,并附上任何可用的特性(或空的features元素): 服务端-------服务端 步骤 1: 服务器1 发起一个流给 服务器2 步骤 2: 服务器2 回应一个流标签给 服务器1 步骤 3: 服务器2 通知 服务器1 可用的验证机制 步骤 4: 服务器1 选择一个验证机制 步骤 5: 服务器2 发送一个[BASE64]编码的挑战给 服务器1 cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9 ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz 解码后的挑战信息是 realm=\"somerealm\ qop=\"auth\ 步骤 5 (替代): 服务器2 返回一个错误给 服务器1 步骤 6: 服务器1 发送一个[BASE64]编码的回应这个挑战 dXNlcm5hbWU9ImV4YW1wbGUub3JnIixyZWFsbT0ic29tZXJlYWxtIixub25j ZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5j PTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5v cmciLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3 LGNoYXJzZXQ9dXRmLTgK 解码后的应答信息是 username=\"example.org\ nonce=\"OA6MG9tEQGm2hh\ nc=00000001,qop=auth,digest-uri=\"xmpp/example.org\ response=d388dad90d4bbd760a152321f2143af7,charset=utf-8 步骤 7: 服务器2 发送另外一个[BASE64]编码的挑战给 服务器1 cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo= 解码后的挑战信息是 rspauth=ea40f60335c427b5527b84dbabcdfffd 步骤 7 (或者): 服务器2 返回一个错误给 服务器1 步骤 8: 服务器1 回应挑战 步骤 8 (或者): 服务器1 中止协商 步骤 9: 服务器2 通知 服务器1 验证成功 步骤 9 (或者): 服务器2 通知 服务器1 验证失败 步骤 10: 服务器1 重新发起一个新的流给 服务器2 步骤 11: 服务器2 发送一个流头信息应答 服务器1 ,并附上任何可用的特性(或一个空的features元素) 服务器回拨 发起服务器 接收服务器 ----------- --------- | | | 建立连接 | | ----------------------> | | | | 发stream头 | | ----------------------> | | | | 发stream头 | | <---------------------- | | | | 发回拨key | 授权服务器 | ----------------------> | ------------- | | | | 建立连接 | | ----------------------> | | | | 发stream头 | | ----------------------> | | | | 发stream头 | | <---------------------- | | | | 发验证请求 | | ----------------------> | | | | 发验证响应 | | <---------------------- | | | 报告回拨结果 | | <---------------------- | | | 服务器之间互动的细节协议如下: 1. 发起服务器和接受服务器建立TCP连接. 2. 发起服务器发送流头信息给接收服务器 3. 接收服务器应该(SHOULD)回送一个流头信息给发起服务器,为这次交互生成一个唯一性的ID 4. 发起服务器发送一个回拨密钥给接收服务器 5. 接收服务器向发起服务器声明的那个域建立一个 TCP 连接,作为结果它连接到授权服务器. (注意: 为了优化性能, 在这里一个实现可以(MAY)重用现有的连接.) 6. 接收服务器发送一个流头信息给授权服务器 7. 授权服务器发送流头信息给接收服务器 8. 接收服务器发送一个密钥检查请求给授权服务器 9. 授权服务器检查密钥是否合法 或 10. 接收服务器通知发起服务器结果 会话的建立 1. 流验证 -- 客户端在尝试建立一个会话或发送任何XML节之前必须完成 2. 资源绑定 -- 完成流验证之后, 一个客户端必须绑定一个资源到流上,使得客户端的地址符合 服务器向客户端声明会话确定特性 xmlns:stream='http://etherx.jabber.org/streams' id='c2s_345' from='example.com' version='1.0'> 收到需要会话确立的通知之后(并且是在完成资源绑定之后), 客户端如果想使用即时消息和出席信息功能必须建立一个会话; 它向服务器发送一个符合'urn:ietf:params:xml:ns:xmpp-session'名字空间的类型为\"set\"并包含空的 步骤 1: 客户端向服务器请求会话 步骤 2: 服务器通知客户端会话已经建立 建立会话之后, 一个 已连接的资源就被称为一个 激活的资源\"active resource\". 许多错误条件是可能的. 例如, 服务器可能遭遇一个内部条件阻碍了它建立会话, 用户名或授权身份可能缺乏建立会话的许可, 或同一个名字相关的这个资源ID已经有一个激活的资源. 如果服务器遭到一个内部条件阻碍了它建立会话, 它必须返回一个错误 步骤2返回的错误情况。 情况一、服务器应答一个错误(内部服务器错误) 情况二、服务器应答错误(用户名或资源不被允许建立一个会话) 情况三、服务器通知现有的激活的资源 资源冲突(1) 信息交流(message) from='juliet@example.com/balcony' type='chat' xml:lang='en'> B的JID: b@example.com/PC 当A没有主动发信息到B的情况下B要发信息到A,哪么在message节中的to属性将使用纯JID。如果A发过一次信息给B并且会话还没有断开的情况下。B回复A,这个时候to属性使用的必须为全JID 呈现信息交流(presence) 初始化呈现信息 个人信息发布例子 A用户:A@example.net, 他有一个可用的资源, 资源ID为 \"orchard\" A服务器中联系人(花名册)列表中存在的用户: B@example.com (subscription=\"both\" 并且她有两个可用的资源, 一个资源名为\"PC\" 而另一个资源名为 \"IPHONE\") C@example.org (subscription=\"to\") D@example.org (subscription=\"from\") 步骤 1: 用户A发送初始化presence信息: 步骤2: 用户A的服务器代替用户A发送presence信息调查(探索)给 subscription=\"to\" 和 subscription=\"both\" 的联系人的可用资源: from='A@example.net/orchard' to='B@example.com'/> from='A@example.net/orchard' to='C@example.org'/> 步骤3: 用户A的服务器代替用户A发送初始化presence信息给 subscription=\"from\" 和 subscription=\"both\"的联系人的可用资源: 步骤4: 联系人的服务器代替所有可用的资源应答presence信息调查: to='A@example.net/orchard'> 步骤5: 联系人的服务器递送用户的初始化presence信息给所有可用的资源或返回错误给用户: from='D@example.org' to='A@example.net/orchard'> 发送presence给不在花名册中的用户 用户直接发送presence信息给另一个不在他的名册中的用户: 更新presence 用户发送更新的可用出席presence用于广播: 用户A的服务器仅向一个联系人广播更新的presence信息 (不是那些返回错误的联系人,也不是那些用户直接向其发送presence信息的联系人): 联系人的服务器递送更新的presence信息给联系人所有可用的资源: [to \"IPHONE\" resource...] [to \"PC\" resource...] 联系人的资源之一广播最后presence信息: from='juliet@example.com/balcony' to='romeo@example.net/orchard'/> 用户发送最后presence信息: 用户的服务器广播不可用的presence信息给联系人,包括用户直接向其发送presence信息的那个人: from='romeo@example.net/orchard' to='juliet@example.com' xml:lang='en'> 管理订阅 A发送一个订阅请求给B。(A请求订阅B的presence) B同意订阅请求: 如果B已经同意了A的订阅请求,现在B想取消曾允许的订阅请求 Roster 获取联系人列表 在即时聊天 (IM) 应用中,客户端登录服务器后做的第一个操作通常是获取联系人列表。获取联系人列表需要发送 get 类型的 Iq 数据包。 客户端: 该请求的意义为:名为 juliet 的用户 (登录资源为 balcony) 向 example.com 服务器请求获得 (get) roster 表。 服务器收到请求后,返回 roster 表。 服务端: 可以看到,juliet 的 roster 表内有3个联系人,分别名为 Romeo,Mercutio,Benvolio,都属于 Friends 分组。Roster 列表中的 JID 信息将会用在稍候客户端发送信息包的目的地址中。 Item 中的 subscription 关系到联系人状态信息的传输,有 none,both,from,to 四种。 添加联系人到好友列表(花名册) 添加成功后,服务器将会下发成功后的列表给各个资源终端进行同步。 当各终端接到名单添加成功要求同步的下发列表后,再行应答服务器。 更新联系人 没发现跟添加联系人有哪些不同之处? 删除联系人 不管是添加,修改,删除联系人,服务器都要通知(同一JID,不同资源)各个终端进行同步。 订阅联系人(A订阅B) 当A的服务器收到A的订阅联系人的请求,(服务器将向A的所有资源[可能是iphone,PC登录的]进行下发) 请求联系人的presence信息的订阅(A订阅B的presence信息) A的服务器将向A的其它资源广播: 屏蔽通信 语法: action='[allow|deny]' order='unsignedInt'> [ [ 说明:如果type为Jid的时候,value的属性值必须为一个合法的JID,此JID应该满足如下 顺序: 1. 4. 如果type为group的时候,此时value的属性值为用户花名册(好友列表)中的一个JID,如果这个JID不存在,此时服务器应该返回给客户端一个 如果type为”subscription”时,value的属性值为:”both”,”to”,”from”,”none” 如果没有带type属性,哪么这个规则将返回”fall-through”错误。 Action 属性值只能是”allow”允许或”deny”禁止 Order属性值必须是唯一并且大于0的整数,如果不唯一的值建立或更新时,服务器将返回 在\"jabber:iq:privacy'名字空间之内, 一个\"set\"类型的IQ节的 当一个客户端增加或更新一个隐私列表, 例子说明: 查找服务器中存在的隐私列表的名字 客户端向服务器发送查询请求消息 服务器发送隐私列表给客户端。 当查询到隐私列表后,逐个取列表的例子: 取public隐私列表 服务器下发public列表给客户端 请求private聊私列表 服务器下发private隐私列表 请求special隐私列表 服务器下发special列表 上述说明: (1) 'public', 它允许所有人的通信,除了一个指定的实体(这是缺省列表); (2) 'private', 它只允许和这个用户有双向订阅的联系人的通信(这是激活的列表); 还有 (3) 'special', 它只允许三个指定的实体通信 如果客户端请求一个列表不存在名字,服务器必须返回 用户一次只能接收一个列表,如果请求中带多个列表,将会收到服务器发来的 管理激活列表 客户端请求激活列表变更 如果激活成功服务器将下发 如果要激活的名字不存在将下发 客户取消使用激活列表 服务器下发取消成功 变更缺省列表 服务器下发成功消息。 如果请求变更的列表正在被其它客户端资源占用哪么将下发冲突。 取消使用缺省列表 服务器下发成功取消消息。 修改隐私列表 如果修改成功,服务器下发 当修改成功后,服务器同时推送给该客户端的正在连接的各个资源。比如:A@fsh.com/PC进行修改聊私列表,同时也有一个A@fsh.com/IPHONE和A@fsh.com/Android 哪么服务器将推送修改消息到另外的资源。 推送消息 各资源收到服务端发来的消息后必须做出响应 添加一个新的隐私列表,如果名字和服务器的相同,将复盖掉服务器上的,这跟修改相同。 注意新增或修改是都必须有ITEM节,删除的时候不带ITEM节 删除一个隐私列表 成功移除后消息 屏蔽消息 基于JID的用户屏蔽 屏蔽后,用户将不会接收到从特定JID发来的消息 基于花名册的用户屏蔽 基于订阅状态的用户屏蔽 全局的用户屏蔽 屏蔽进来的presence信息通知 基于JID的presence入站屏蔽 基于名册组的用户屏蔽presence信息进入 基于订阅状态的用户屏蔽 全局的用户屏蔽 屏蔽发出的presence信息通知 对于JID的 对于Group的 对于订阅状态 对于全局的 对于IQ节的屏蔽也一样,有基于JID,基于GROUP,基于订阅,基于全局。 其它与前面的类似,这里不再详写。 屏蔽所有通信 基于JID 基于组 基于订阅 基于全局用户屏蔽 已被屏蔽的实体尝试和用户通信 已被屏蔽的实体尝试发送 IQ get from='tybalt@example.com/pda' id='probing1'> 服务器返回一个错误给已被屏蔽的实体 高级启发 当建立一个高级隐私启发的表达式的时候, 客户端应该(SHOULD)使用尽可能简单的表达式. 例如, 启发 \"屏蔽不在我名册中的任何用户的通信\" 可以使用以下任何一种方式来构造: 允许任何来自我的名册中的JID的通信 (换言之, 列出每个JID成为单独的列 表条目), 但是屏蔽和其他任何人的通信 允许任何来自我的名册的某个组中的用户的通信(换言之, 列出每个组作为单 独的条目), 但是屏蔽和任何其他人的通信 允许任何我的他(她)之间的订阅状态为'both'或'to'或'from'的用户的通信 (换言之, 单独列出每个订阅状态值), 但是屏蔽和任何其他人的通信 屏蔽和任何订阅状态为'none'的用户的通信 最后一个表达式是最简单的并且应该(SHOULD)被使用; 这种情形下将被发送的XML如下: 因篇幅问题不能全部显示,请点此查看更多更全内容
元素),如果违反了这个规则,服务器将返回一个
元素应该包含至少一个
元素不能包含任何