5. Exchanging Presence Information
Exchanging presence information is made relatively straightforward within XMPP by using presence stanzas. However, we see here a contrast to the handling of messages: although a client MAY send directed presence information to another entity by including a 'to' address, normally presence notifications (i.e., presence stanzas with no 'type' or of type "unavailable" and with no 'to' address) are sent from a client to its server and then broadcasted by the server to any entities that are subscribed to the presence of the sending entity (in the terminology of RFC 2778 [IMP-MODEL], these entities are subscribers). This broadcast model does not apply to subscription-related presence stanzas or presence stanzas of type "error", but to presence notifications only as defined above. (Note: While presence information MAY be provided on a user's behalf by an automated service, normally it is provided by the user's client.) For information regarding the syntax of presence stanzas as well as their defined attributes and child elements, refer to [XMPP-CORE].5.1. Client and Server Presence Responsibilities
5.1.1. Initial Presence
After establishing a session, a client SHOULD send initial presence to the server in order to signal its availability for communications. As defined herein, the initial presence stanza (1) MUST possess no 'to' address (signalling that it is meant to be broadcasted by the server on behalf of the client) and (2) MUST possess no 'type' attribute (signalling the user's availability). After sending initial presence, an active resource is said to be an "available resource". Upon receiving initial presence from a client, the user's server MUST do the following if there is not already one or more available resources for the user (if there is already one or more available resources for the user, the server obviously does not need to send the presence probes, since it already possesses the requisite information): 1. Send presence probes (i.e., presence stanzas whose 'type' attribute is set to a value of "probe") from the full JID (e.g., <user@example.com/resource>) of the user to all contacts to which the user is subscribed in order to determine if they are available; such contacts are those for which a JID is present in the user's roster with the 'subscription' attribute set to a value of "to" or "both". (Note: The user's server MUST NOT send presence probes to contacts from which the user is blocking
inbound presence notifications, as described under Blocking Inbound Presence Notifications (Section 10.10).) 2. Broadcast initial presence from the full JID (e.g., <user@example.com/resource>) of the user to all contacts that are subscribed to the user's presence information; such contacts are those for which a JID is present in the user's roster with the 'subscription' attribute set to a value of "from" or "both". (Note: The user's server MUST NOT broadcast initial presence to contacts to which the user is blocking outbound presence notifications, as described under Blocking Outbound Presence Notifications (Section 10.11).) In addition, the user's server MUST broadcast initial presence from the user's new available resource to any of the user's existing available resources (if any). Upon receiving initial presence from the user, the contact's server MUST deliver the user's presence stanza to the full JIDs (<contact@example.org/resource>) associated with all of the contact's available resources, but only if the user is in the contact's roster with a subscription state of "to" or "both" and the contact has not blocked inbound presence notifications from the user's bare or full JID (as defined under Blocking Inbound Presence Notifications (Section 10.10)). If the user's server receives a presence stanza of type "error" in response to the initial presence that it sent to a contact on behalf of the user, it SHOULD NOT send further presence updates to that contact (until and unless it receives a presence stanza from the contact).5.1.2. Presence Broadcast
After sending initial presence, the user MAY update its presence information for broadcasting at any time during its session by sending a presence stanza with no 'to' address and either no 'type' attribute or a 'type' attribute with a value of "unavailable". (Note: A user's client SHOULD NOT send a presence update to broadcast information that changes independently of the user's presence and availability.) If the presence stanza lacks a 'type' attribute (i.e., expresses availability), the user's server MUST broadcast the full XML of that presence stanza to all contacts (1) that are in the user's roster with a subscription type of "from" or "both", (2) to whom the user
has not blocked outbound presence notifications, and (3) from whom the server has not received a presence error during the user's session (as well as to any of the user's other available resources). If the presence stanza has a 'type' attribute set to a value of "unavailable", the user's server MUST broadcast the full XML of that presence stanza to all entities that fit the above description, as well as to any entities to which the user has sent directed available presence during the user's session (if the user has not yet sent directed unavailable presence to that entity).5.1.3. Presence Probes
Upon receiving a presence probe from the user, the contact's server SHOULD reply as follows: 1. If the user is not in the contact's roster with a subscription state of "From", "From + Pending Out", or "Both" (as defined under Subscription States (Section 9)), the contact's server MUST return a presence stanza of type "error" in response to the presence probe (however, if a server receives a presence probe from a subdomain of the server's hostname or another such trusted service, it MAY provide presence information about the user to that entity). Specifically: * if the user is in the contact's roster with a subscription state of "None", "None + Pending Out", or "To" (or is not in the contact's roster at all), the contact's server MUST return a <forbidden/> stanza error in response to the presence probe. * if the user is in the contact's roster with a subscription state of "None + Pending In", "None + Pending Out/In", or "To + Pending In", the contact's server MUST return a <not-authorized/> stanza error in response to the presence probe. 2. Else, if the contact is blocking presence notifications to the user's bare JID or full JID (using either a default list or active list as defined under Blocking Outbound Presence Notifications (Section 10.11)), the server MUST NOT reply to the presence probe. 3. Else, if the contact has no available resources, the server MUST either (1) reply to the presence probe by sending to the user the full XML of the last presence stanza of type "unavailable" received by the server from the contact, or (2) not reply at all.
4. Else, if the contact has at least one available resource, the server MUST reply to the presence probe by sending to the user the full XML of the last presence stanza with no 'to' attribute received by the server from each of the contact's available resources (again, subject to privacy lists in force for each session).5.1.4. Directed Presence
A user MAY send directed presence to another entity (i.e., a presence stanza with a 'to' attribute whose value is the JID of the other entity and with either no 'type' attribute or a 'type' attribute whose value is "unavailable"). There are three possible cases: 1. If the user sends directed presence to a contact that is in the user's roster with a subscription type of "from" or "both" after having sent initial presence and before sending unavailable presence broadcast, the user's server MUST route or deliver the full XML of that presence stanza (subject to privacy lists) but SHOULD NOT otherwise modify the contact's status regarding presence broadcast (i.e., it SHOULD include the contact's JID in any subsequent presence broadcasts initiated by the user). 2. If the user sends directed presence to an entity that is not in the user's roster with a subscription type of "from" or "both" after having sent initial presence and before sending unavailable presence broadcast, the user's server MUST route or deliver the full XML of that presence stanza to the entity but MUST NOT modify the contact's status regarding available presence broadcast (i.e., it MUST NOT include the entity's JID in any subsequent broadcasts of available presence initiated by the user); however, if the available resource from which the user sent the directed presence become unavailable, the user's server MUST broadcast that unavailable presence to the entity (if the user has not yet sent directed unavailable presence to that entity). 3. If the user sends directed presence without first sending initial presence or after having sent unavailable presence broadcast (i.e., the resource is active but not available), the user's server MUST treat the entities to which the user sends directed presence in the same way that it treats the entities listed in case #2 above.
5.1.5. Unavailable Presence
Before ending its session with a server, a client SHOULD gracefully become unavailable by sending a final presence stanza that possesses no 'to' attribute and that possesses a 'type' attribute whose value is "unavailable" (optionally, the final presence stanza MAY contain one or more <status/> elements specifying the reason why the user is no longer available). However, the user's server MUST NOT depend on receiving final presence from an available resource, since the resource may become unavailable unexpectedly or may be timed out by the server. If one of the user's resources becomes unavailable for any reason (either gracefully or ungracefully), the user's server MUST broadcast unavailable presence to all contacts (1) that are in the user's roster with a subscription type of "from" or "both", (2) to whom the user has not blocked outbound presence, and (3) from whom the server has not received a presence error during the user's session; the user's server MUST also send that unavailable presence stanza to any of the user's other available resources, as well as to any entities to which the user has sent directed presence during the user's session for that resource (if the user has not yet sent directed unavailable presence to that entity). Any presence stanza with no 'type' attribute and no 'to' attribute that is sent after sending directed unavailable presence or broadcasted unavailable presence MUST be broadcasted by the server to all subscribers.5.1.6. Presence Subscriptions
A subscription request is a presence stanza whose 'type' attribute has a value of "subscribe". If the subscription request is being sent to an instant messaging contact, the JID supplied in the 'to' attribute SHOULD be of the form <contact@example.org> rather than <contact@example.org/resource>, since the desired result is normally for the user to receive presence from all of the contact's resources, not merely the particular resource specified in the 'to' attribute. A user's server MUST NOT automatically approve subscription requests on the user's behalf. All subscription requests MUST be directed to the user's client, specifically to one or more available resources associated with the user. If there is no available resource associated with the user when the subscription request is received by the user's server, the user's server MUST keep a record of the subscription request and deliver the request when the user next creates an available resource, until the user either approves or denies the request. If there is more than one available resource associated with the user when the subscription request is received by the user's server, the user's server MUST broadcast that subscription request to all available resources in accordance with Server Rules for Handling XML Stanzas (Section 11). (Note: If an active resource
has not provided initial presence, the server MUST NOT consider it to be available and therefore MUST NOT send subscription requests to it.) However, if the user receives a presence stanza of type "subscribe" from a contact to whom the user has already granted permission to see the user's presence information (e.g., in cases when the contact is seeking to resynchronize subscription states), the user's server SHOULD auto-reply on behalf of the user. In addition, the user's server MAY choose to re-send an unapproved pending subscription request to the contact based on an implementation-specific algorithm (e.g., whenever a new resource becomes available for the user, or after a certain amount of time has elapsed); this helps to recover from transient, silent errors that may have occurred in relation to the original subscription request.5.2. Specifying Availability Status
A client MAY provide further information about its availability status by using the <show/> element (see Show (Section 2.2.2.1)). Example: Availability status: <presence> <show>dnd</show> </presence>5.3. Specifying Detailed Status Information
In conjunction with the <show/> element, a client MAY provide detailed status information by using the <status/> element (see Status (Section 2.2.2.2)). Example: Detailed status information: <presence xml:lang='en'> <show>dnd</show> <status>Wooing Juliet</status> <status xml:lang='cz'>Ja dvořím Juliet</status> </presence>
5.4. Specifying Presence Priority
A client MAY provide a priority for its resource by using the <priority/> element (see Priority (Section 2.2.2.3)). Example: Presence priority: <presence xml:lang='en'> <show>dnd</show> <status>Wooing Juliet</status> <status xml:lang='cz'>Ja dvořím Juliet</status> <priority>1</priority> </presence>5.5. Presence Examples
The examples in this section illustrate the presence-related protocols described above. The user is romeo@example.net, he has an available resource whose resource identifier is "orchard", and he has the following individuals in his roster: o juliet@example.com (subscription="both" and she has two available resources, one whose resource is "chamber" and another whose resource is "balcony") o benvolio@example.org (subscription="to") o mercutio@example.org (subscription="from") Example 1: User sends initial presence: <presence/> Example 2: User's server sends presence probes to contacts with subscription="to" and subscription="both" on behalf of the user's available resource: <presence type='probe' from='romeo@example.net/orchard' to='juliet@example.com'/> <presence type='probe' from='romeo@example.net/orchard' to='benvolio@example.org'/>
Example 3: User's server sends initial presence to contacts with subscription="from" and subscription="both" on behalf of the user's available resource: <presence from='romeo@example.net/orchard' to='juliet@example.com'/> <presence from='romeo@example.net/orchard' to='mercutio@example.org'/> Example 4: Contacts' servers reply to presence probe on behalf of all available resources: <presence from='juliet@example.com/balcony' to='romeo@example.net/orchard' xml:lang='en'> <show>away</show> <status>be right back</status> <priority>0</priority> </presence> <presence from='juliet@example.com/chamber' to='romeo@example.net/orchard'> <priority>1</priority> </presence> <presence from='benvolio@example.org/pda' to='romeo@example.net/orchard' xml:lang='en'> <show>dnd</show> <status>gallivanting</status> </presence> Example 5: Contacts' servers deliver user's initial presence to all available resources or return error to user: <presence from='romeo@example.net/orchard' to='juliet@example.com/chamber'/>
<presence from='romeo@example.net/orchard' to='juliet@example.com/balcony'/> <presence type='error' from='mercutio@example.org' to='romeo@example.net/orchard'> <error type='cancel'> <gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </presence> Example 6: User sends directed presence to another user not in his roster: <presence from='romeo@example.net/orchard' to='nurse@example.com' xml:lang='en'> <show>dnd</show> <status>courting Juliet</status> <priority>0</priority> </presence> Example 7: User sends updated available presence information for broadcasting: <presence xml:lang='en'> <show>away</show> <status>I shall return!</status> <priority>1</priority> </presence> Example 8: User's server broadcasts updated presence information only 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 resources). If the contact is in the user's roster with either of those states, the user's server (1) MUST deliver the presence stanza of type "subscribed" from the contact to the user; (2) 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 "to"; and (3) MUST deliver the available presence stanza received from each of the contact's available resources to each of the user's available resources: <presence to='user@example.com' from='contact@example.org' type='subscribed'/> <iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='contact@example.org' subscription='to' name='MyContact'> <group>MyBuddies</group> </item> </query> </iq> <presence from='contact@example.org/resource' to='user@example.com/resource'/> 9. Upon receiving the presence stanza of type "subscribed", the user SHOULD acknowledge receipt of that subscription state notification through either "affirming" it by sending a presence stanza of type "subscribe" to the contact or "denying" it by sending a presence stanza of type "unsubscribe" 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). From the perspective of the user, there now exists a subscription to the contact's presence information; from the perspective of the contact, there now exists a subscription from the user.8.2.1. Alternate Flow: Contact Declines Subscription Request
The above activity flow represents the "happy path" regarding the user's subscription request to the contact. The main alternate flow occurs if the contact refuses the user's subscription request, as described below.
1. If the contact wants to refuse the request, the contact's client MUST send a presence stanza of type "unsubscribed" to the user (instead of the presence stanza of type "subscribed" sent in Step 6 of Section 8.2): <presence to='user@example.com' type='unsubscribed'/> 2. As a result, the contact's server 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: <presence from='contact@example.org' to='user@example.com' type='unsubscribed'/> Note: If the contact's server previously added the user to the contact's roster for tracking purposes, it MUST remove the relevant item at this time. 3. Upon receiving the presence stanza of type "unsubscribed" addressed to the user, the user's server (1) MUST deliver that presence stanza to the user and (2) 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" and with no 'ask' attribute: <presence from='contact@example.org' to='user@example.com' type='unsubscribed'/> <iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='contact@example.org' subscription='none' name='MyContact'> <group>MyBuddies</group> </item> </query> </iq> 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). As a result of this activity, the contact is now in the user's roster with a subscription state of "none", whereas the user is not in the contact's roster at all.8.3. Creating a Mutual Subscription
The user and contact can build on the "happy path" described above to create a mutual subscription (i.e., a subscription of type "both"). The process is described below. 1. If the contact wants to create a mutual subscription, the contact MUST send a subscription request to the user (subject to the contact's configured preferences, the contact's client MAY send this automatically): <presence to='user@example.com' type='subscribe'/> 2. 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, with the user still in the 'from' subscription state but with a pending 'to' subscription denoted by the inclusion of the ask='subscribe' attribute in the roster item; and (2) MUST route the presence stanza of type "subscribe" to the user, first stamping the 'from' address as the bare JID (<contact@example.org>) of the contact: <iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='user@example.com' subscription='from' ask='subscribe' name='SomeUser'> <group>SomeGroup</group> </item> </query> </iq>
<presence from='contact@example.org' to='user@example.com' type='subscribe'/> 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 "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 user. 3. Upon receiving the presence stanza of type "subscribe" addressed to the user, the user's server must determine if there is at least one available resource for which the user has requested the roster. If so, the user's server MUST deliver the subscription request to the user (if not, it MUST store the subscription request offline for delivery when this condition is next met). No matter when the subscription request is delivered, the user must then decide whether or not to approve it (subject to the user's configured preferences, the user's client MAY approve or refuse the subscription request without presenting it to the user). Here we assume the "happy path" that the user approves the subscription request (the alternate flow of declining the subscription request is defined in Section 8.3.1). In this case, the user's client MUST send a presence stanza of type "subscribed" to the contact in order to approve the subscription request. <presence to='contact@example.org' type='subscribed'/> 4. As a result, the user's server (1) MUST initiate a roster push to all of the user's available resources that have requested the roster, containing a roster item for the contact with the 'subscription' attribute set to a value of "both"; (2) MUST route the presence stanza of type "subscribed" to the contact, first stamping the 'from' address as the bare JID (<user@example.com>) of the user; and (3) MUST send to the contact the full XML of the last presence stanza with no 'to' attribute received by the server from each of the user's available resources (subject to privacy lists in force for each session):
<iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='contact@example.org' subscription='both' name='MyContact'> <group>MyBuddies</group> </item> </query> </iq> <presence from='user@example.com' to='contact@example.org' type='subscribed'/> <presence from='user@example.com/resource' to='contact@example.org'/> 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 "subscribed" it sent previously (e.g., by tracking an 'id' attribute) and then choose to resend the subscription request or revert the roster to its previous state by sending a presence stanza of type "unsubscribed" to the contact. 5. Upon receiving the presence stanza of type "subscribed" addressed to the contact, the contact's server MUST first verify that the user is in the contact's roster with either of the following states: (a) subscription='none' and ask='subscribe' or (b) subscription='from' and ask='subscribe'. If the user is not in the contact's roster with either of those states, the contact's server MUST silently ignore the presence stanza of type "subscribed" (i.e., it MUST NOT route it to the contact, modify the contact's roster, or generate a roster push to the contact's available resources). If the user is in the contact's roster with either of those states, the contact's server (1) MUST deliver the presence stanza of type "subscribed" from the user to the contact; (2) 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 "both"; and (3) MUST deliver the available presence stanza received from each of the user's available resources to each of the contact's available resources:
<presence from='user@example.com' to='contact@example.org' type='subscribed'/> <iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='user@example.com' subscription='both' name='SomeUser'> <group>SomeGroup</group> </item> </query> </iq> <presence from='user@example.com/resource' to='contact@example.org/resource'/> 6. Upon receiving the presence stanza of type "subscribed", the contact SHOULD acknowledge receipt of that subscription state notification through either "affirming" it by sending a presence stanza of type "subscribe" to the user or "denying" it by sending a presence stanza of type "unsubscribe" to the user; this step does not necessarily affect the subscription state (see Subscription States (Section 9) for details), but instead lets the contact's server know that it MUST no longer send notification of the subscription state change to the contact (see Section 9.4). The user and the contact now have a mutual subscription to each other's presence -- i.e., the subscription is of type "both".8.3.1. Alternate Flow: User Declines Subscription Request
The above activity flow represents the "happy path" regarding the contact's subscription request to the user. The main alternate flow occurs if the user refuses the contact's subscription request, as described below. 1. If the user wants to refuse the request, the user's client MUST send a presence stanza of type "unsubscribed" to the contact (instead of the presence stanza of type "subscribed" sent in Step 3 of Section 8.3): <presence to='contact@example.org' type='unsubscribed'/>
2. As a result, the user's server MUST route the presence stanza of type "unsubscribed" to the contact, first stamping the 'from' address as the bare JID (<user@example.com>) of the user: <presence from='user@example.com' to='contact@example.org' type='unsubscribed'/> 3. Upon receiving the presence stanza of type "unsubscribed" addressed to the contact, the contact's server (1) MUST deliver that presence stanza to the contact; and (2) 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 "from" and with no 'ask' attribute: <presence from='user@example.com' to='contact@example.org' type='unsubscribed'/> <iq type='set'> <query xmlns='jabber:iq:roster'> <item jid='user@example.com' subscription='from' name='SomeUser'> <group>SomeGroup</group> </item> </query> </iq> 4. Upon receiving the presence stanza of type "unsubscribed", the contact SHOULD acknowledge receipt of that subscription state notification through either "affirming" it by sending a presence stanza of type "unsubscribe" to the user or "denying" it by sending a presence stanza of type "subscribe" to the user; this step does not necessarily affect the subscription state (see Subscription States (Section 9) for details), but instead lets the contact's server know that it MUST no longer send notification of the subscription state change to the contact (see Section 9.4). As a result of this activity, there has been no change in the subscription state; i.e., the contact is in the user's roster with a subscription state of "to" and the user is in the contact's roster with a subscription state of "from".