to one contact (not those from whom an error was received or to whom
the user sent directed presence):
<presence
from=’romeo@example.net/orchard’
to=’juliet@example.com’
xml:lang=’en’>
<show>away</show>
<status>I shall return!</status>
<priority>1</priority>
</presence>
Example 9: Contact’s server delivers updated presence information to
all of the contact’s available resources:
[to "balcony" resource...]
<presence
from=’romeo@example.net/orchard’
to=’juliet@example.com’
xml:lang=’en’>
<show>away</show>
<status>I shall return!</status>
<priority>1</priority>
</presence>
[to "chamber" resource...]
<presence
from=’romeo@example.net/orchard’
to=’juliet@example.com’
xml:lang=’en’>
<show>away</show>
<status>I shall return!</status>
<priority>1</priority>
</presence>
Example 10: One of the contact’s resources broadcasts final presence:
<presence from=’juliet@example.com/balcony’ type=’unavailable’/>
Example 11: Contact’s server sends unavailable presence information
to user:
<presence
type=’unavailable’
from=’juliet@example.com/balcony’
to=’romeo@example.net/orchard’/>
Example 12: User sends final presence:
<presence from=’romeo@example.net/orchard’
type=’unavailable’
xml:lang=’en’>
<status>gone home</status>
</presence>
Example 13: User’s server broadcasts unavailable presence information
to contact as well as to the person to whom the user sent directed
presence:
<presence
type=’unavailable’
from=’romeo@example.net/orchard’
to=’juliet@example.com’
xml:lang=’en’>
<status>gone home</status>
</presence>
<presence
from=’romeo@example.net/orchard’
to=’nurse@example.com’
xml:lang=’en’>
<status>gone home</status>
</presence>
6. Managing Subscriptions
In order to protect the privacy of instant messaging users and any
other entities, presence and availability information is disclosed
only to other entities that the user has approved. When a user has
agreed that another entity may view its presence, the entity is said
to have a subscription to the user’s presence information. A
subscription lasts across sessions; indeed, it lasts until the
subscriber unsubscribes or the subscribee cancels the
previously-granted subscription. Subscriptions are managed within
XMPP by sending presence stanzas containing specially-defined
attributes.
Note: There are important interactions between subscriptions and
rosters; these are defined under Integration of Roster Items and
Presence Subscriptions (Section 8), and the reader must refer to that
section for a complete understanding of presence subscriptions.
6.1. Requesting a Subscription
A request to subscribe to another entity’s presence is made by
sending a presence stanza of type "subscribe".
Example: Sending a subscription request:
<presence to=’juliet@example.com’ type=’subscribe’/>
For client and server responsibilities regarding presence
subscription requests, refer to Presence Subscriptions (Section
5.1.6).
6.2. Handling a Subscription Request
When a client receives a subscription request from another entity, it
MUST either approve the request by sending a presence stanza of type
"subscribed" or refuse the request by sending a presence stanza of
type "unsubscribed".
Example: Approving a subscription request:
<presence to=’romeo@example.net’ type=’subscribed’/>
Example: Refusing a presence subscription request:
<presence to=’romeo@example.net’ type=’unsubscribed’/>
6.3. Cancelling a Subscription from Another Entity
If a user would like to cancel a previously-granted subscription
request, it sends a presence stanza of type "unsubscribed".
Example: Cancelling a previously granted subscription request:
<presence to=’romeo@example.net’ type=’unsubscribed’/>
6.4. Unsubscribing from Another Entity’s Presence
If a user would like to unsubscribe from the presence of another
entity, it sends a presence stanza of type "unsubscribe".
Example: Unsubscribing from an entity’s presence:
<presence to=’juliet@example.com’ type=’unsubscribe’/>
7. Roster Management
In XMPP, one’s contact list is called a roster, which consists of any
number of specific roster items, each roster item being identified by
a unique JID (usually of the form <contact@domain>). A user’s roster
is stored by the user’s server on the user’s behalf so that the user
may access roster information from any resource.
Note: There are important interactions between rosters and
subscriptions; these are defined under Integration of Roster Items
and Presence Subscriptions (Section 8), and the reader must refer to
that section for a complete understanding of roster management.
7.1. Syntax and Semantics
Rosters are managed using IQ stanzas, specifically by means of a
<query/> child element qualified by the ’jabber:iq:roster’ namespace.
The <query/> element MAY contain one or more <item/> children, each
describing a unique roster item or "contact".
The "key" or unique identifier for each roster item is a JID,
encapsulated in the ’jid’ attribute of the <item/> element (which is
REQUIRED). The value of the ’jid’ attribute SHOULD be of the form
<user@domain> if the item is associated with another (human) instant
messaging user.
The state of the presence subscription in relation to a roster item
is captured in the ’subscription’ attribute of the <item/> element.
Allowable values for this attribute are:
o "none" -- the user does not have a subscription to the contact’s
presence information, and the contact does not have a subscription
to the user’s presence information
o "to" -- 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
o "from" -- the contact has a subscription to the user’s presence
information, but the user does not have a subscription to the
contact’s presence information
o "both" -- both the user and the contact have subscriptions to each
other’s presence information
Each <item/> element MAY contain a ’name’ attribute, which sets the
"nickname" to be associated with the JID, as determined by the user
(not the contact). The value of the ’name’ attribute is opaque.
Each <item/> element MAY contain one or more <group/> child elements,
for use in collecting roster items into various categories. The XML
character data of the <group/> element is opaque.
7.2. Business Rules
A server MUST ignore any ’to’ address on a roster "set", and MUST
treat any roster "set" as applying to the sender. For added safety,
a client SHOULD check the "from" address of a "roster push" (incoming
IQ of type "set" containing a roster item) to ensure that it is from
a trusted source; specifically, the stanza MUST either have no ’from’
attribute (i.e., implicitly from the server) or have a ’from’
attribute whose value matches the user’s bare JID (of the form
<user@domain>) or full JID (of the form <user@domain/resource>);
otherwise, the client SHOULD ignore the "roster push".
7.3. Retrieving One’s Roster on Login
Upon connecting to the server and becoming an active resource, a
client SHOULD request the roster before sending initial presence
(however, because receiving the roster may not be desirable for all
resources, e.g., a connection with limited bandwidth, the client’s
request for the roster is OPTIONAL). If an available resource does
not request the roster during a session, the server MUST NOT send it
presence subscriptions and associated roster updates.
Example: Client requests current roster from server:
<iq from=’juliet@example.com/balcony’ type=’get’ id=’roster_1’>
<query xmlns=’jabber:iq:roster’/>
</iq>
Example: Client receives roster from server:
<iq to=’juliet@example.com/balcony’ type=’result’ id=’roster_1’>
<query xmlns=’jabber:iq:roster’>
<item jid=’romeo@example.net’
name=’Romeo’
subscription=’both’>
<group>Friends</group>
</item>
<item jid=’mercutio@example.org’
name=’Mercutio’
subscription=’from’>
<group>Friends</group>
</item>
<item jid=’benvolio@example.org’
name=’Benvolio’
subscription=’both’>
<group>Friends</group>
</item>
</query>
</iq>
7.4. Adding a Roster Item
At any time, a user MAY add an item to his or her roster.
Example: Client adds a new item:
<iq from=’juliet@example.com/balcony’ type=’set’ id=’roster_2’>
<query xmlns=’jabber:iq:roster’>
<item jid=’nurse@example.com’
name=’Nurse’>
<group>Servants</group>
</item>
</query>
</iq>
The server MUST update the roster information in persistent storage,
and also push the change out to all of the user’s available resources
that have requested the roster. This "roster push" consists of an IQ
stanza of type "set" from the server to the client and enables all
available resources to remain in sync with the server-based roster
information.
Example: Server (1) pushes the updated roster information to all
available resources that have requested the roster and (2) replies
with an IQ result to the sending resource:
<iq to=’juliet@example.com/balcony’
type=’set’
id=’a78b4q6ha463’>
<query xmlns=’jabber:iq:roster’>
<item jid=’nurse@example.com’
name=’Nurse’
subscription=’none’>
<group>Servants</group>
</item>
</query>
</iq>
<iq to=’juliet@example.com/chamber’
type=’set’
id=’a78b4q6ha464’>
<query xmlns=’jabber:iq:roster’>
<item jid=’nurse@example.com’
name=’Nurse’
subscription=’none’>
<group>Servants</group>
</item>
</query>
</iq>
<iq to=’juliet@example.com/balcony’ type=’result’ id=’roster_2’/>
As required by the semantics of the IQ stanza kind as defined in
[XMPP-CORE], each resource that received the roster push MUST reply
with an IQ stanza of type "result" (or "error").
Example: Resources reply with an IQ result to the server:
<iq from=’juliet@example.com/balcony’
to=’example.com’
type=’result’
id=’a78b4q6ha463’/>
<iq from=’juliet@example.com/chamber’
to=’example.com’
type=’result’
id=’a78b4q6ha464’/>
7.5. Updating a Roster Item
Updating an existing roster item (e.g., changing the group) is done
in the same way as adding a new roster item, i.e., by sending the
roster item in an IQ set to the server.
Example: User updates roster item (added group):
<iq from=’juliet@example.com/chamber’ type=’set’ id=’roster_3’>
<query xmlns=’jabber:iq:roster’>
<item jid=’romeo@example.net’
name=’Romeo’
subscription=’both’>
<group>Friends</group>
<group>Lovers</group>
</item>
</query>
</iq>
As with adding a roster item, when updating a roster item the server
MUST update the roster information in persistent storage, and also
initiate a roster push to all of the user’s available resources that
have requested the roster.
7.6. Deleting a Roster Item
At any time, a user MAY delete an item from his or her roster by
sending an IQ set to the server and making sure that the value of the
’subscription’ attribute is "remove" (a compliant server MUST ignore
any other values of the ’subscription’ attribute when received from a
client).
Example: Client removes an item:
<iq from=’juliet@example.com/balcony’ type=’set’ id=’roster_4’>
<query xmlns=’jabber:iq:roster’>
<item jid=’nurse@example.com’ subscription=’remove’/>
</query>
</iq>
As with adding a roster item, when deleting a roster item the server
MUST update the roster information in persistent storage, initiate a
roster push to all of the user’s available resources that have
requested the roster (with the ’subscription’ attribute set to a
value of "remove"), and send an IQ result to the initiating resource.
For further information about the implications of this command, see
Removing a Roster Item and Cancelling All Subscriptions (Section
8.6).
8. Integration of Roster Items and Presence Subscriptions
8.1. Overview
Some level of integration between roster items and presence
subscriptions is normally expected by an instant messaging user
regarding the user’s subscriptions to and from other contacts. This
section describes the level of integration that MUST be supported
within XMPP instant messaging applications.
There are four primary subscription states:
o None -- the user does not have a subscription to the contact’s
presence information, and the contact does not have a subscription
to the user’s presence information
o To -- 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
o From -- the contact has a subscription to the user’s presence
information, but the user does not have a subscription to the
contact’s presence information
o Both -- both the user and the contact have subscriptions to each
other’s presence information (i.e., the union of ’from’ and ’to’)
Each of these states is reflected in the roster of both the user and
the contact, thus resulting in durable subscription states.
Narrative explanations of how these subscription states interact with
roster items in order to complete certain defined use cases are
provided in the following sub-sections. Full details regarding
server and client handling of all subscription states (including
pending states between the primary states listed above) is provided
in Subscription States (Section 9).
The server MUST NOT send presence subscription requests or roster
pushes to unavailable resources, nor to available resources that have
not requested the roster.
The ’from’ and ’to’ addresses are OPTIONAL in roster pushes; if
included, their values SHOULD be the full JID of the resource for
that session. A client MUST acknowledge each roster push with an IQ
stanza of type "result" (for the sake of brevity, these stanzas are
not shown in the following examples but are required by the IQ
semantics defined in [XMPP-CORE]).
8.2. User Subscribes to Contact
The process by which a user subscribes to a contact, including the
interaction between roster items and subscription states, is
described below.
1. In preparation for being able to render the contact in the user’s
client interface and for the server to keep track of the
subscription, the user’s client SHOULD perform a "roster set" for
the new roster item. This request consists of sending an IQ
stanza of type=’set’ containing a <query/> element qualified by
the ’jabber:iq:roster’ namespace, which in turn contains an
<item/> element that defines the new roster item; the <item/>
element MUST possess a ’jid’ attribute, MAY possess a ’name’
attribute, MUST NOT possess a ’subscription’ attribute, and MAY
contain one or more <group/> child elements:
<iq type=’set’ id=’set1’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
name=’MyContact’>
<group>MyBuddies</group>
</item>
</query>
</iq>
2. As a result, the user’s server (1) MUST initiate a roster push
for the new roster item to all available resources associated
with this user that have requested the roster, setting the
’subscription’ attribute to a value of "none"; and (2) MUST reply
to the sending resource with an IQ result indicating the success
of the roster set:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
subscription=’none’
name=’MyContact’>
<group>MyBuddies</group>
</item>
</query>
</iq>
<iq type=’result’ id=’set1’/>
3. If the user wants to request a subscription to the contact’s
presence information, the user’s client MUST send a presence
stanza of type=’subscribe’ to the contact:
<presence to=’contact@example.org’ type=’subscribe’/>
4. As a result, the user’s server MUST initiate a second roster push
to all of the user’s available resources that have requested the
roster, setting the contact to the pending sub-state of the
’none’ subscription state; this pending sub-state is denoted by
the inclusion of the ask=’subscribe’ attribute in the roster
item:
<iq type=’set’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’contact@example.org’
subscription=’none’
ask=’subscribe’
name=’MyContact’>
<group>MyBuddies</group>
</item>
</query>
</iq>
Note: If the user did not create a roster item before sending the
subscription request, the server MUST now create one on behalf of the
user, then send a roster push to all of the user’s available
resources that have requested the roster, absent the ’name’ attribute
and the <group/> child shown above.
5. The user’s server MUST also stamp the presence stanza of type
"subscribe" with the user’s bare JID (i.e., <user@example.com>)
as the ’from’ address (if the user provided a ’from’ address set
to the user’s full JID, the server SHOULD remove the resource
identifier). If the contact is served by a different host than
the user, the user’s server MUST route the presence stanza to the
contact’s server for delivery to the contact (this case is
assumed throughout; however, if the contact is served by the same
host, then the server can simply deliver the presence stanza
directly):
<presence
from=’user@example.com’
to=’contact@example.org’
type=’subscribe’/>
Note: If the user’s server receives a presence stanza of type "error"
from the contact’s server, it MUST deliver the error stanza to the
user, whose client MAY determine that the error is in response to the
outgoing presence stanza of type "subscribe" it sent previously
(e.g., by tracking an ’id’ attribute) and then choose to resend the
"subscribe" request or revert the roster to its previous state by
sending a presence stanza of type "unsubscribe" to the contact.
6. Upon receiving the presence stanza of type "subscribe" addressed
to the contact, the contact’s server MUST determine if there is
at least one available resource from which the contact has
requested the roster. If so, it MUST deliver the subscription
request to the contact (if not, the contact’s server MUST store
the subscription request offline for delivery when this condition
is next met; normally this is done by adding a roster item for
the contact to the user’s roster, with a state of "None + Pending
In" as defined under Subscription States (Section 9), however a
server SHOULD NOT push or deliver roster items in that state to
the contact). No matter when the subscription request is
delivered, the contact must decide whether or not to approve it
(subject to the contact’s configured preferences, the contact’s
client MAY approve or refuse the subscription request without
presenting it to the contact). Here we assume the "happy path"
that the contact approves the subscription request (the alternate
flow of declining the subscription request is defined in Section
8.2.1). In this case, the contact’s client (1) SHOULD perform a
roster set specifying the desired nickname and group for the user
(if any); and (2) MUST send a presence stanza of type
"subscribed" to the user in order to approve the subscription
request.
<iq type=’set’ id=’set2’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’user@example.com’
name=’SomeUser’>
<group>SomeGroup</group>
</item>
</query>
</iq>
<presence to=’user@example.com’ type=’subscribed’/>
7. As a result, the contact’s server (1) MUST initiate a roster push
to all available resources associated with the contact that have
requested the roster, containing a roster item for the user with
the subscription state set to ’from’ (the server MUST send this
even if the contact did not perform a roster set); (2) MUST
return an IQ result to the sending resource indicating the
success of the roster set; (3) MUST route the presence stanza of
type "subscribed" to the user, first stamping the ’from’ address
as the bare JID (<contact@example.org>) of the contact; and (4)
MUST send available presence from all of the contact’s available
resources to the user:
<iq type=’set’ to=’contact@example.org/resource’>
<query xmlns=’jabber:iq:roster’>
<item
jid=’user@example.com’
subscription=’from’
name=’SomeUser’>
<group>SomeGroup</group>
</item>
</query>
</iq>
<iq type=’result’ to=’contact@example.org/resource’ id=’set2’/>
<presence
from=’contact@example.org’
to=’user@example.com’
type=’subscribed’/>
<presence
from=’contact@example.org/resource’
to=’user@example.com’/>
Note: If the contact’s server receives a presence stanza of type
"error" from the user’s server, it MUST deliver the error stanza to
the contact, whose client MAY determine that the error is in response
to the outgoing presence stanza of type "subscribed" it sent
previously (e.g., by tracking an ’id’ attribute) and then choose to
resend the "subscribed" notification or revert the roster to its
previous state by sending a presence stanza of type "unsubscribed" to
the user.
8. Upon receiving the presence stanza of type "subscribed" addressed
to the user, the user’s server MUST first verify that the contact
is in the user’s roster with either of the following states: (a)
subscription=’none’ and ask=’subscribe’ or (b)
subscription=’from’ and ask=’subscribe’. If the contact is not
in the user’s roster with either of those states, the user’s
server MUST silently ignore the presence stanza of type
"subscribed" (i.e., it MUST NOT route it to the user, modify the
user’s roster, or generate a roster push to the user’s available