type=’unavailable’/>
6. When the user’s server receives the presence stanzas of type
"unsubscribed" and "unavailable", it MUST deliver them to the
user:
<presence
from=’contact@example.org’
to=’user@example.com’
type=’unsubscribed’/>
<presence
from=’contact@example.org/resource’
to=’user@example.com’
type=’unavailable’/>
7. Upon receiving the presence stanza of type "unsubscribed", the
user SHOULD acknowledge receipt of that subscription state
notification through either "affirming" it by sending a presence
stanza of type "unsubscribe" to the contact or "denying" it by
sending a presence stanza of type "subscribe" to the contact;
this step does not necessarily affect the subscription state (see
Subscription States (Section 9) for details), but instead lets
the user’s server know that it MUST no longer send notification
of the subscription state change to the user (see Section 9.4).
Note: Obviously this does not result in removal of the roster item
from the user’s roster, and the contact still has a subscription to
the user’s presence information. In order to both completely cancel
a mutual subscription and fully remove the roster item from the
user’s roster, the user SHOULD update the roster item with
subscription=’remove’ as defined under Removing a Roster Item and
Cancelling All Subscriptions (Section 8.6).
8.5. Cancelling a Subscription
At any time after approving a subscription request from a user, a
contact MAY cancel that subscription. While the XML that the contact
sends to make this happen is the same in all instances, the
subsequent subscription state is different depending on the
subscription state obtaining when the cancellation was sent. Both
possible scenarios are described below.
8.5.1. Case #1: Cancelling When Subscription is Not Mutual
In the first case, the user has a subscription to the contact’s
presence information but the contact does not have a subscription to
the user’s presence information (i.e., the subscription is not yet
mutual).
1. If the contact wants to cancel the user’s subscription, the
contact MUST send a presence stanza of type "unsubscribed" to the
user:
<presence to=’user@example.com’ type=’unsubscribed’/>
2. As a result, the contact’s server (1) MUST send a roster push to
all of the contact’s available resources that have requested the
roster, containing an updated roster item for the user with the
’subscription’ attribute set to a value of "none"; (2) MUST route
the presence stanza of type "unsubscribed" to the user, first
stamping the ’from’ address as the bare JID
(<contact@example.org>) of the contact; and (3) SHOULD send
unavailable presence from all of the contact’s available
resources to the user:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’user@example.com’
subscription=’none’
name=’SomeUser’>
<group>SomeGroup</group>
</item>
</query>
</iq>
<presence
from=’contact@example.org’
to=’user@example.com’
type=’unsubscribed’/>
<presence
from=’contact@example.org/resource’
to=’user@example.com’
type=’unavailable’/>
3. Upon receiving the presence stanza of type "unsubscribed"
addressed to the user, the user’s server (1) MUST initiate a
roster push to all of the user’s available resources that have
requested the roster, containing an updated roster item for the
contact with the ’subscription’ attribute set to a value of
"none" (if the user is unavailable or has not requested the
roster, the user’s server MUST modify the roster item and send
that modified item the next time the user requests the roster);
(2) MUST deliver the "unsubscribed" state change notification to
all of the user’s available resources; and (3) MUST deliver the
unavailable presence to all of the user’s available resources:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
subscription=’none’
name=’MyContact’>
<group>MyBuddies</group>
</item>
</query>
</iq>
<presence
from=’contact@example.org’
to=’user@example.com’
type=’unsubscribed’/>
<presence
from=’contact@example.org/resource’
to=’user@example.com’
type=’unavailable’/>
4. Upon receiving the presence stanza of type "unsubscribed", the
user SHOULD acknowledge receipt of that subscription state
notification through either "affirming" it by sending a presence
stanza of type "unsubscribe" to the contact or "denying" it by
sending a presence stanza of type "subscribe" to the contact;
this step does not necessarily affect the subscription state (see
Subscription States (Section 9) for details), but instead lets
the user’s server know that it MUST no longer send notification
of the subscription state change to the user (see Section 9.4).
8.5.2. Case #2: Cancelling When Subscription is Mutual
In the second case, the user has a subscription to the contact’s
presence information and the contact also has a subscription to the
user’s presence information (i.e., the subscription is mutual).
1. If the contact wants to cancel the user’s subscription, the
contact MUST send a presence stanza of type "unsubscribed" to the
user:
<presence to=’user@example.com’ type=’unsubscribed’/>
2. As a result, the contact’s server (1) MUST send a roster push to
all of the contact’s available resources that have requested the
roster, containing an updated roster item for the user with the
’subscription’ attribute set to a value of "to"; (2) MUST route
the presence stanza of type "unsubscribed" to the user, first
stamping the ’from’ address as the bare JID
(<contact@example.org>) of the contact; and (3) SHOULD send
unavailable presence from all of the contact’s available
resources to all of the user’s available resources:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’user@example.com’
subscription=’to’
name=’SomeUser’>
<group>SomeGroup</group>
</item>
</query>
</iq>
<presence
from=’contact@example.org’
to=’user@example.com’
type=’unsubscribed’/>
<presence
from=’contact@example.org/resource’
to=’user@example.com’
type=’unavailable’/>
3. Upon receiving the presence stanza of type "unsubscribed"
addressed to the user, the user’s server (1) MUST initiate a
roster push to all of the user’s available resources that have
requested the roster, containing an updated roster item for the
contact with the ’subscription’ attribute set to a value of
"from" (if the user is unavailable or has not requested the
roster, the user’s server MUST modify the roster item and send
that modified item the next time the user requests the roster);
and (2) MUST deliver the "unsubscribed" state change notification
to all of the user’s available resources; and (3) MUST deliver
the unavailable presence to all of the user’s available
resources:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
subscription=’from’
name=’MyContact’>
<group>MyBuddies</group>
</item>
</query>
</iq>
<presence
from=’contact@example.org’
to=’user@example.com’
type=’unsubscribed’/>
<presence
from=’contact@example.org/resource’
to=’user@example.com’
type=’unavailable’/>
4. Upon receiving the presence stanza of type "unsubscribed", the
user SHOULD acknowledge receipt of that subscription state
notification through either "affirming" it by sending a presence
stanza of type "unsubscribe" to the contact or "denying" it by
sending a presence stanza of type "subscribe" to the contact;
this step does not necessarily affect the subscription state (see
Subscription States (Section 9) for details), but instead lets
the user’s server know that it MUST no longer send notification
of the subscription state change to the user (see Section 9.4).
Note: Obviously this does not result in removal of the roster item
from the contact’s roster, and the contact still has a subscription
to the user’s presence information. In order to both completely
cancel a mutual subscription and fully remove the roster item from
the contact’s roster, the contact should update the roster item with
subscription=’remove’ as defined under Removing a Roster Item and
Cancelling All Subscriptions (Section 8.6).
8.6. Removing a Roster Item and Cancelling All Subscriptions
Because there may be many steps involved in completely removing a
roster item and cancelling subscriptions in both directions, the
roster management protocol includes a "shortcut" method for doing so.
The process may be initiated no matter what the current subscription
state is by sending a roster set containing an item for the contact
with the ’subscription’ attribute set to a value of "remove":
<iq type=’set’ id=’remove1’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
subscription=’remove’/>
</query>
</iq>
When the user removes a contact from his or her roster by setting the
’subscription’ attribute to a value of "remove", the user’s server
(1) MUST automatically cancel any existing presence subscription
between the user and the contact (both ’to’ and ’from’ as
appropriate); (2) MUST remove the roster item from the user’s roster
and inform all of the user’s available resources that have requested
the roster of the roster item removal; (3) MUST inform the resource
that initiated the removal of success; and (4) SHOULD send
unavailable presence from all of the user’s available resources to
the contact:
<presence
from=’user@example.com’
to=’contact@example.org’
type=’unsubscribe’/>
<presence
from=’user@example.com’
to=’contact@example.org’
type=’unsubscribed’/>
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
subscription=’remove’/>
</query>
</iq>
<iq type=’result’ id=’remove1’/>
<presence
from=’user@example.com/resource’
to=’contact@example.org’
type=’unavailable’/>
Upon receiving the presence stanza of type "unsubscribe", the
contact’s server (1) MUST initiate a roster push to all available
resources associated with the contact that have requested the roster,
containing an updated roster item for the user with the
’subscription’ attribute set to a value of "to" (if the contact is
unavailable or has not requested the roster, the contact’s server
MUST modify the roster item and send that modified item the next time
the contact requests the roster); and (2) MUST also deliver the
"unsubscribe" state change notification to all of the contact’s
available resources:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’user@example.com’
subscription=’to’
name=’SomeUser’>
<group>SomeGroup</group>
</item>
</query>
</iq>
<presence
from=’user@example.com’
to=’contact@example.org’
type=’unsubscribe’/>
Upon receiving the presence stanza of type "unsubscribed", the
contact’s server (1) MUST initiate a roster push to all available
resources associated with the contact that have requested the roster,
containing an updated roster item for the user with the
’subscription’ attribute set to a value of "none" (if the contact is
unavailable or has not requested the roster, the contact’s server
MUST modify the roster item and send that modified item the next time
the contact requests the roster); and (2) MUST also deliver the
"unsubscribe" state change notification to all of the contact’s
available resources:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’user@example.com’
subscription=’none’
name=’SomeUser’>
<group>SomeGroup</group>
</item>
</query>
</iq>
<presence
from=’user@example.com’
to=’contact@example.org’
type=’unsubscribed’/>
Upon receiving the presence stanza of type "unavailable" addressed to
the contact, the contact’s server MUST deliver the unavailable
presence to all of the user’s available resources:
<presence
from=’user@example.com/resource’
to=’contact@example.org’
type=’unavailable’/>
Note: When the user removes the contact from the user’s roster, the
end state of the contact’s roster is that the user is still in the
contact’s roster with a subscription state of "none"; in order to
completely remove the roster item for the user, the contact needs to
also send a roster removal request.
9. Subscription States
This section provides detailed information about subscription states
and server handling of subscription-related presence stanzas (i.e.,
presence stanzas of type "subscribe", "subscribed", "unsubscribe",
and "unsubscribed").
9.1. Defined States
There are nine possible subscription states, which are described here
from the user’s (not contact’s) perspective:
1. "None" = contact and user are not subscribed to each other, and
neither has requested a subscription from the other
2. "None + Pending Out" = contact and user are not subscribed to
each other, and user has sent contact a subscription request but
contact has not replied yet
3. "None + Pending In" = contact and user are not subscribed to each
other, and contact has sent user a subscription request but user
has not replied yet (note: contact’s server SHOULD NOT push or
deliver roster items in this state, but instead SHOULD wait until
contact has approved subscription request from user)
4. "None + Pending Out/In" = contact and user are not subscribed to
each other, contact has sent user a subscription request but user
has not replied yet, and user has sent contact a subscription
request but contact has not replied yet
5. "To" = user is subscribed to contact (one-way)
6. "To + Pending In" = user is subscribed to contact, and contact
has sent user a subscription request but user has not replied yet
7. "From" = contact is subscribed to user (one-way)
8. "From + Pending Out" = contact is subscribed to user, and user
has sent contact a subscription request but contact has not
replied yet
9. "Both" = user and contact are subscribed to each other (two-way)
9.2. Server Handling of Outbound Presence Subscription Stanzas
Outbound presence subscription stanzas enable the user to manage his
or her subscription to the contact’s presence information (via the
"subscribe" and "unsubscribe" types), and to manage the contact’s
access to the user’s presence information (via the "subscribed" and
"unsubscribed" types).
Because it is possible for the user’s server and the contact’s server
to lose synchronization regarding subscription states, the user’s
server MUST without exception route all outbound presence stanzas of
type "subscribe" or "unsubscribe" to the contact so that the user is
able to resynchronize his or her subscription to the contact’s
presence information if needed.
The user’s server SHOULD NOT route a presence stanza of type
"subscribed" or "unsubscribed" to the contact if the stanza does not
result in a subscription state change from the user’s perspective,
and MUST NOT make a state change. If the stanza results in a
subscription state change, the user’s server MUST route the stanza to
the contact and MUST make the appropriate state change. These rules
are summarized in the following tables.
Table 1: Recommended handling of outbound "subscribed" stanzas
+----------------------------------------------------------------+
| EXISTING STATE | ROUTE? | NEW STATE |
+----------------------------------------------------------------+
| "None" | no | no state change |
| "None + Pending Out" | no | no state change |
| "None + Pending In" | yes | "From" |
| "None + Pending Out/In" | yes | "From + Pending Out" |
| "To" | no | no state change |
| "To + Pending In" | yes | "Both" |
| "From" | no | no state change |
| "From + Pending Out" | no | no state change |
| "Both" | no | no state change |
+----------------------------------------------------------------+
Table 2: Recommended handling of outbound "unsubscribed" stanzas
+----------------------------------------------------------------+
| EXISTING STATE | ROUTE? | NEW STATE |
+----------------------------------------------------------------+
| "None" | no | no state change |
| "None + Pending Out" | no | no state change |
| "None + Pending In" | yes | "None" |
| "None + Pending Out/In" | yes | "None + Pending Out" |
| "To" | no | no state change |
| "To + Pending In" | yes | "To" |
| "From" | yes | "None" |
| "From + Pending Out" | yes | "None + Pending Out" |
| "Both" | yes | "To" |
+----------------------------------------------------------------+
9.3. Server Handling of Inbound Presence Subscription Stanzas
Inbound presence subscription stanzas request a subscription-related
action from the user (via the "subscribe" type), inform the user of
subscription-related actions taken by the contact (via the
"unsubscribe" type), or enable the contact to manage the user’s
access to the contact’s presence information (via the "subscribed"
and "unsubscribed" types).
When the user’s server receives a subscription request for the user
from the contact (i.e., a presence stanza of type "subscribe"), it
MUST deliver that request to the user for approval if the user has
not already granted the contact access to the user’s presence
information and if there is no pending inbound subscription request;
however, the user’s server SHOULD NOT deliver the new request if
there is a pending inbound subscription request, since the previous
subscription request will have been recorded. If the user has
already granted the contact access to the user’s presence
information, the user’s server SHOULD auto-reply to an inbound
presence stanza of type "subscribe" from the contact by sending a
presence stanza of type "subscribed" to the contact on behalf of the
user; this rule enables the contact to resynchronize the subscription
state if needed. These rules are summarized in the following table.
Table 3: Recommended handling of inbound "subscribe" stanzas
+------------------------------------------------------------------+
| EXISTING STATE | DELIVER? | NEW STATE |
+------------------------------------------------------------------+
| "None" | yes | "None + Pending In" |
| "None + Pending Out" | yes | "None + Pending Out/In" |
| "None + Pending In" | no | no state change |
| "None + Pending Out/In" | no | no state change |
| "To" | yes | "To + Pending In" |
| "To + Pending In" | no | no state change |
| "From" | no * | no state change |
| "From + Pending Out" | no * | no state change |
| "Both" | no * | no state change |
+------------------------------------------------------------------+
* Server SHOULD auto-reply with "subscribed" stanza
When the user’s server receives a presence stanza of type
"unsubscribe" for the user from the contact, if the stanza results in
a subscription state change from the user’s perspective then the
user’s server SHOULD auto-reply by sending a presence stanza of type
"unsubscribed" to the contact on behalf of the user, MUST deliver the
"unsubscribe" stanza to the user, and MUST change the state. If no
subscription state change results, the user’s server SHOULD NOT
deliver the stanza and MUST NOT change the state. These rules are
summarized in the following table.
Table 4: Recommended handling of inbound "unsubscribe" stanzas
+------------------------------------------------------------------+
| EXISTING STATE | DELIVER? | NEW STATE |
+------------------------------------------------------------------+
| "None" | no | no state change |
| "None + Pending Out" | no | no state change |