RFC 4662

A Session Initiation Protocol (SIP) Event Notification Extension for Resource Lists

๐Ÿ“… published August 2006, from ietf

A Session Initiation Protocol (SIP) Event Notification Extension for Resource Lists โœจ

RFC 4662 ๐ŸŽ€ is from the Network Working Group and it's a Standards Track doc, which means it's a real protocol spec. It was written by A. B. Roach and B. Campbell (both at Estacado Systems) and J. Rosenberg (at Cisco Systems) in August 2006. The title block doesn't list any RFCs that it obsoletes or updates, so it stands on its own ๐Ÿ’….

Status of This Memo ๐Ÿ“œ

okay so this doc is an Internet standards track protocol for the Internet community. It's inviting discussion and suggestions for improvements ๐Ÿซถ. If you want to know where this protocol stands in terms of standardization, check the current edition of the "Internet Official Protocol Standards" (STD 1). And the distribution of this memo is unlimited, so share it with everyone ๐ŸŒˆ.

Copyright (C) The Internet Society (2006). That's the legal bit, bestie ๐Ÿ˜Œ.

Abstract ๐ŸŒธ

this doc extends the SIP-Specific Event Notification mechanism so you can subscribe to a whole homogeneous list of resources at once ๐Ÿงš. Instead of sending a SUBSCRIBE for every single resource one by one (ugh, so much work), you subscribe to the entire list. Then you get notifications whenever the state of any resource in that list changes. It's giving efficiency ๐Ÿ”ฅ.

Table of Contents ๐Ÿ“‘

1. Introduction ....................................................3
2. Terminology .....................................................4
3. Overview of Operation ...........................................4
4. Operation of List Subscriptions .................................5
   4.1. Negotiation of Support for Resource Lists ..................6
   4.2. Subscription Duration ......................................7
   4.3. NOTIFY Bodies ..............................................7
   4.4. RLS Processing of SUBSCRIBE Requests .......................7
   4.5. RLS Generation of NOTIFY Requests ..........................7
   4.6. Subscriber Processing of NOTIFY Requests ...................9
   4.7. Handling of Forked Requests ...............................10
   4.8. Rate of Notifications .....................................10
5. Using multipart/related to Convey Aggregate State ..............10
   5.1. XML Syntax ................................................11
   5.2. List Attributes ...........................................13
   5.3. Resource Attributes .......................................14
   5.4. Name Attributes ...........................................14
   5.5. Instance Attributes .......................................14
   5.6. Constructing Coherent Resource State ......................16
        5.6.1. Processing Full State Notifications ................17
        5.6.2. Processing Partial State Notifications .............17
6. Example ........................................................18
7. Security Considerations ........................................31
   7.1. Authentication ............................................31
        7.1.1. RLS and Subscriber in the Same Domain ..............31
        7.1.2. RLS and Subscriber in Different Domains ............32
   7.2. Risks of Improper Aggregation .............................33
   7.3. Signing and Sealing .......................................33
   7.4. Infinite Loops ............................................34
8. IANA Considerations ............................................34
   8.1. New SIP Option Tag: eventlist .............................34
   8.2. New MIME type for Resource List Meta-Information ..........34
   8.3. URN Sub-Namespace .........................................35
9. Acknowledgements ...............................................36
10. References ....................................................36
   10.1. Normative References .....................................36
   10.2. Informative References ...................................37

1. Introduction โœจ

so the SIP-specific event notification mechanism [2] lets a user (the subscriber) ask to be told when a particular resource changes state ๐Ÿ‘€. The subscriber sends a SUBSCRIBE request for that resource, and a notifier representing the resource handles it.

But here's the thing: subscribers often care about a whole list of resources ๐Ÿ“‹. Without some way to aggregate them, the subscriber has to send a SUBSCRIBE for every resource they want info on. That's a big problem when bandwidth is tight, like on wireless networks ๐Ÿ“ถ. Some specific issues:

  • Doing this creates a ton of message traffic ๐ŸŒŠ. You get the initial SUBSCRIBE requests for each resource, plus the refreshes for every individual subscription.
  • The notifier might insist on short refresh intervals so it doesn't keep long-lived subscription state around ๐Ÿ˜ฉ. That means the subscriber may have to refresh SUBSCRIBE faster than it wants to, or faster than it has the capacity for.
  • The notifier might send NOTIFY requests more often than the subscriber wants, so the NOTIFY traffic gets way louder than the subscriber is happy with ๐Ÿ”Š.

To fix all of this, the doc defines an extension to RFC 3265 [2] that lets you request and convey notifications for lists of resources ๐ŸŽ€. A resource list is identified by a URI, and it represents a list of zero or more URIs. Each of those URIs identifies one resource the subscriber wants info about. A lot of the time, the URI for the resource list will be a SIP URI [1], but other schemes like pres: [10] are also expected to work ๐ŸŒˆ.

The notifier for the list is called a "resource list server", or RLS ๐Ÿงšโ€โ™€๏ธ. To figure out the state of the entire list, the RLS acts as if it has subscribed to each resource in the list.

Also, the resource list doesn't have to live inside the subscriber's domain, and the resources on the list don't have to live inside the RLS's domain either. Anything goes, lowkey iconic ๐Ÿฆ‹.

2. Terminology ๐Ÿ“–

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [5]. (Those are the official BCP 14 key words, so they carry real weight here ๐Ÿ’–.)

These terms get used all the way through the rest of the doc, so let's get them straight:

  • Back-End Subscription: any subscription (SIP or otherwise) that an RLS creates to learn the state of a resource ๐Ÿ”™. An RLS creates back-end subscriptions for resources it isn't the authority on. For back-end subscriptions, RLSes act as a subscriber.
  • List Subscription: a subscription to a resource list ๐Ÿ“ƒ. In list subscriptions, RLSes act as the notifier.
  • Resource: any logical entity that has a state (or states) that can be subscribed to ๐Ÿ“. Resources are identified by URIs.
  • Resource List: a list of zero or more resources whose individual states can be subscribed to with a single subscription ๐Ÿงบ.
  • RLMI: Resource List Meta-Information ๐Ÿ—‚๏ธ. RLMI is a document that describes the state of the virtual subscriptions tied to a list subscription.
  • RLS: Resource List Server ๐Ÿ‘‘. RLSes accept subscriptions to resource lists and send notifications to update subscribers on the state of the resources in a resource list.
  • Virtual Subscription: a logical construct inside an RLS that represents subscriptions to the resources in a resource list ๐Ÿชž. For each list subscription it services, an RLS creates at least one virtual subscription for every resource in the list being subscribed to. Sometimes, like when the RLS isn't the authority for a resource's state, that virtual subscription is linked to a back-end subscription. Other times, like when the RLS is the authority for the state, the virtual subscription has no corresponding back-end subscription ๐ŸŒธ.

3. Overview of Operation ๐Ÿฆ‹

This section is an overview of the typical way this extension works, so it's not normative ๐Ÿ™ˆ. The actual rules are in the rest of the doc.

when users want to subscribe to a list of resources, they can use the mechanisms in this spec ๐Ÿซถ. Step one is creating a resource list, which is represented by a SIP URI. The list holds a set of URIs, and each one represents a resource the subscriber wants info about. The resource list can live in any domain. You could manage the list through a web page, a voice response system, or some other protocol ๐Ÿ“ฑ. How the list gets created and maintained is outside the scope of this spec, so no need to stress about it ๐Ÿ’….

To find out the state of everything on the list, the user sends a single SUBSCRIBE request aimed at the list's URI โœจ. That request gets routed to an RLS for that URI. The RLS acts as the notifier, authenticates the subscriber, and accepts the subscription ๐Ÿ”.

The RLS might already have direct info about some or all of the resources on the list. If it doesn't, it can subscribe to any non-local resources specified by the list resource ๐Ÿ”ญ.

Heads up that subscriptions to non-local resources might or might not be SIP subscriptions. Any mechanism for figuring out that info can be used ๐Ÿงฉ. This doc uses the term "back-end subscription" for these, no matter whether SIP is used to set them up and keep them going.

As the state of the resources on the list changes, the RLS generates notifications for the list subscribers ๐Ÿ””. The RLS can, if it wants, buffer the resource-change notifications and send the resource info to the subscriber in batches instead of one at a time ๐Ÿ“ฆ. That lets the RLS do rate limiting for the subscriber, which is honestly such a mood ๐Ÿ˜ญ.

The list notifications contain a body of type multipart/related ๐ŸŽ. The root section of that multipart/related content is an XML document that provides meta-information about each resource in the list. The remaining sections hold the actual state info for each resource ๐Ÿ’œ.

4. Operation of List Subscriptions โœจ

okay so the event list extension is lowkey giving event template package energy ๐ŸŽ€. The big rule is that any single list subscription has to be homogeneous with respect to the underlying event package. Translation: one list subscription can only apply ONE event package to every resource on the list ๐Ÿ’…

Also, it is totally fine for an RLS to let multiple subscriptions to the same list use different event packages ๐Ÿฆ‹

The real main character difference between list subscriptions and templates in general is that supporting list subscriptions means you support arbitrary nesting of list subscriptions ๐ŸŒˆ Elements inside a list can be atomic elements, or they can be lists themselves. Lists all the way down, bestie ๐Ÿงš

So when you subscribe to a URI that represents a list, you actually end up with a bunch of virtual subscriptions to a whole tree of resources ๐ŸŒธ The leaf nodes of that tree are virtual subscriptions of the event type given in the Event header field. Every other node in the tree is a list subscription, and those get handled the way this section and its subsections describe ๐Ÿ’œ

Keep in mind that these virtual subscriptions are not literal SIP subscriptions ๐Ÿ™ˆ They might result in SIP subscriptions, depending on how the RLS is implemented, so don't mix them up!

4.1. Negotiation of Support for Resource Lists

This spec uses the SIP option tag mechanism to negotiate support for the extension ๐Ÿซถ For the normative stuff on how the Supported and Require header fields get processed, and what the 421 (Extension Required) response code means, go check RFC 3261 [1]. That's the source of truth, periodt ๐Ÿ’…

A non-normative description of what option tags imply is coming up next. It's not the official rulebook, just the vibe check ๐ŸŒท

Any client that supports the event list extension will put an option tag of eventlist in a Supported header field of every SUBSCRIBE message for a subscription it's willing to process a list for โœจ If the subscription goes to a URI that represents a list, the RLS will put eventlist in a Require header field of the response to that SUBSCRIBE, and in every NOTIFY message within that subscription ๐ŸŽ€

Now, why would the notifier put Require: eventlist in NOTIFY messages? Because of the RFC 3261 rule that a UAC MUST insert a Require header field into a request if it wants to insist that the UAS understands an extension in order to process that request ๐Ÿ”ฅ The NOTIFY is literally not usable without the eventlist option, so the notifier is obligated to include it. No choice, bestie ๐Ÿ˜ญ

Putting eventlist in a Require header field of a SUBSCRIBE request serves no purpose except to break interoperability in certain cases ๐Ÿ’€ So it is NOT RECOMMENDED. Don't do it!!

Sending Supported: eventlist in a NOTIFY message is meaningless and silly ๐Ÿ™„ Implementations SHOULD NOT include Supported: eventlist in any requests except for SUBSCRIBE ๐Ÿ“

Here's the tea โ˜• A SIP URI has nothing in it that tells you whether it represents a list of resources or a single resource. So if a subscriber sends a request to a list URI without a Supported header field listing the eventlist token, the notifier will typically return a 421 (Extension Required) response code ๐Ÿ™ˆ RFC 3261 [1] advises servers to avoid returning a 421 and to just try processing the request without the extension. But in this case the URI fundamentally represents a list resource, so the subscription genuinely cannot proceed without this extension. No cap ๐Ÿงข

4.2. Subscription Duration

Since the whole point of the resource list server is to cut down the overall messaging volume to a subscriber ๐Ÿ’– it is RECOMMENDED that the subscription duration to a list be reasonably long โณ If no duration is specified, the default comes from the underlying event package. The standard techniques [2] can be used to make that amount longer or shorter, if you need it ๐Ÿฆ‹

4.3. NOTIFY Bodies

Any implementation compliant with this spec MUST support the multipart/related and application/rlmi+xml MIME types ๐ŸŽ€ These types MUST be included in an Accept header sent in a SUBSCRIBE message, on top of any other types the client supports (including any types the event package being used requires) ๐Ÿซถ

4.4. RLS Processing of SUBSCRIBE Requests

Once the subscriber is authenticated, the RLS does authorization according to its local policy ๐Ÿ” A lot of the time, each resource list belongs to one particular user (the one who created it and manages the elements in it), and only that user gets to subscribe ๐Ÿ‘‘ That's not something baked into resource lists, though. An RLS can use whatever authorization policy it wants โœจ

4.5. RLS Generation of NOTIFY Requests

This spec leaves it up to the implementor how and when NOTIFY requests get generated ๐ŸŒˆ Honestly, this is where RLS implementations flex on each other: how they aggregate, rate-limit, or optimize notifications is the big differentiator ๐Ÿ’… As a baseline, the RLS MAY generate a NOTIFY to the RLS subscriber whenever the state of any resource on the list changes ๐Ÿงš

Okay, pay attention, this part is important ๐Ÿ‘€ Any given subscription is either a subscription to a single resource or a subscription to a list of resources. That nature (single resource versus list of resources) can NOT change during the life of one subscription ๐Ÿ™…โ€โ™€๏ธ So RLSes MUST NOT send NOTIFY messages that don't contain RLMI for a subscription if they've already sent NOTIFY messages containing RLMI in that subscription. And the flip side: RLSes MUST NOT send NOTIFY messages that DO contain RLMI for a subscription if they've previously sent NOTIFY messages in it that didn't. Consistency is everything ๐Ÿ’œ

Quick lore drop: list representations always contain RLMI documents, and there are two reasons why ๐Ÿ’ก First, they identify the resource that the event state corresponds to. This matters because a lot of state syntaxes don't fully identify the resource they apply to, or they identify it differently than the list does. PIDF documents, for example, can have resource URIs that aren't identical to the URI used to fetch them ๐Ÿ™ˆ Second, RLMI documents disambiguate multiple instances of a single resource ๐Ÿซถ

Check out Section 5 for the detailed syntax used to convey the state of resource lists ๐Ÿ“œ For what's coming next, the key thing to know is that the overall list holds zero or more resources, and each resource holds zero or more instances. Every instance has a state attached to it (pending, active, or terminating), which represents the state of the virtual subscription ๐Ÿฆ‹

Notifications contain a multipart document. The first part ALWAYS has meta-information about the list (like membership and the state of the virtual subscription to each resource) ๐ŸŽ€ The remaining parts carry the actual state of the resources listed in that meta-information ๐ŸŒธ

The state attribute of each instance of a resource in the meta-information is set according to the state of the virtual subscription ๐Ÿ’– What those state attribute values mean is described in RFC 3265 [2] ๐Ÿ“–

Now, if an instance of a resource was reported to the subscriber earlier but is no longer available (meaning the virtual subscription to that instance has been terminated), the resource list server SHOULD include that resource instance in the meta-information in the first NOTIFY message sent to the subscriber after the instance went unavailable ๐Ÿซ  The RLS MAY keep doing that in future notifications too ๐Ÿ“

When sending info about a terminated resource instance, the RLS sets a state of terminated and an appropriate reason value ๐Ÿ’€ Valid reason values and what they mean are in RFC 3265 [2]. If the RLS is going to try to recover that resource state again later (for example, when the reason in the meta-information is probation), then the instance SHOULD stay in the meta-information until its state is available, or until the RLS gives up on making that state available ๐ŸŒˆ

When the very first SUBSCRIBE message for a particular subscription hits an RLS, the RLS often won't know the state of every resource in the resource list yet ๐Ÿฅบ For any resource whose state isn't known, the corresponding uri attribute gets set appropriately, and there are NO <instance> elements present for that resource โœจ

For an initial notification, sections for resources the RLS does have state for get filled in with the appropriate data (subject, of course, to local policy decisions) ๐ŸŽ€ This often happens when the resource list server is co-located with the server for one or more of the resources on the list ๐Ÿงš

Immediate notifications triggered by later SUBSCRIBE messages SHOULD include an RLMI document that shows the full state ๐Ÿ’œ The RLS SHOULD also include state info for every resource in the list that it has state for, subject to policy restrictions ๐ŸŒธ This lets the subscriber refresh their state and recover from lost notifications, which is honestly so iconic of it ๐Ÿซถ

4.6. Subscriber Processing of NOTIFY Requests

Notifications for a resource list can carry info about just a subset of the list elements ๐Ÿงฉ So there needs to be an explicit algorithm for building coherent, consistent state on the subscriber's side ๐Ÿ”ฅ

The XML document in the root of the multipart/related document has a <resource> element for some or all of the resources in the list ๐Ÿ“œ Each <resource> element contains a URI that uniquely identifies the resource that section corresponds to ๐Ÿฆ‹ When a NOTIFY arrives, it can contain full or partial state, which is indicated by the fullState attribute on the top-level <list> element ๐ŸŽ€ If full state is indicated, the recipient replaces ALL state associated with the list with the entities in the NOTIFY body ๐Ÿ’… If full state is NOT indicated, the recipient updates the information for each identified resource ๐ŸŒˆ Info for any resource that isn't identified in the NOTIFY stays unchanged, even if it showed up in earlier NOTIFY messages ๐Ÿ™Œ See Section 5.6 for more info โœจ

Full state only applies to the RLMI document it appears in!! One of the <resource> elements in that document might point to another list of resources. Any sub-lists get detailed in their own RLMI documents, which may or may not have full state indicated ๐Ÿงš
Also, the underlying event package might have its own rules for compositing partial state notifications ๐Ÿ’… When you're processing data for those packages, their rules apply. Being reported as part of a list doesn't change their partial notification semantics ๐Ÿซถ
Last but not least: because of how resource list subscriptions work, polling resource state may not be super useful ๐Ÿ™ˆ Polls will retrieve the resource list, but they won't necessarily include state for some or all of the resources on it ๐Ÿ’€

4.7. Handling of Forked Requests ๐Ÿด

okay so forking is kinda weird for list subscriptions ๐Ÿ’… because the whole point of a list is that it's ONE central place sending out notifications. so a subscriber to a list MUST NOT install multiple subscriptions when the initial request gets forked ๐Ÿ™…โ€โ™€๏ธ and if multiple responses come back, they get handled with the techniques in Section 4.4.9 of RFC 3265 [2] โœจ

4.8. Rate of Notifications โฑ๏ธ

the RLS can totally act as a bouncer for the subscriber and do rate limiting for them ๐Ÿšง but this spec doesn't force any particular rate limit. it just leaves that up to the implementation, so do you bestie ๐Ÿ’–

to show the state of a bunch of resources at once, the list extension uses the "multipart/related" mime type ๐Ÿ“ฆ the syntax for that lives in "The MIME Multipart/Related Content-type" [4], so go check that out if you want the full tea ๐Ÿซ–

5.1. XML Syntax ๐Ÿงฉ

the root document of the multipart/related body MUST be a Resource List Meta-Information (RLMI) document ๐Ÿ“„ it's of the type "application/rlmi+xml" and it holds the meta-information for all the resources in the notification. here's the schema, bestie ๐Ÿ‘‘

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema targetNamespace="urn:ietf:params:xml:ns:rlmi"
           elementFormDefault="qualified"
           xmlns="urn:ietf:params:xml:ns:rlmi"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
           schemaLocation="http://www.w3.org/2001/xml.xsd"/>
  <xs:element name="list">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="name" minOccurs="0"
                    maxOccurs="unbounded" />
        <xs:element ref="resource" minOccurs="0"
                    maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="uri" type="xs:anyURI" use="required" />
      <xs:attribute name="version" type="xs:unsignedInt"
                    use="required" />
      <xs:attribute name="fullState" type="xs:boolean"
                    use="required" />
      <xs:attribute name="cid" type="xs:string" use="optional" />
      <xs:anyAttribute processContents="lax" />
    </xs:complexType>
  </xs:element>
  <xs:element name="resource">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="name" minOccurs="0"
                    maxOccurs="unbounded" />
        <xs:element ref="instance" minOccurs="0"
                    maxOccurs="unbounded" />
      </xs:sequence>
      <xs:attribute name="uri" type="xs:anyURI" use="required" />
      <xs:anyAttribute processContents="lax" />
    </xs:complexType>
  </xs:element>
  <xs:element name="instance">
    <xs:complexType>
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded"

                processContents="lax" />
      </xs:sequence>
      <xs:attribute name="id" type="xs:string" use="required" />
      <xs:attribute name="state" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="active" />
            <xs:enumeration value="pending" />
            <xs:enumeration value="terminated" />
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="reason" type="xs:string"
                    use="optional" />
      <xs:attribute name="cid" type="xs:string" use="optional" />
      <xs:anyAttribute processContents="lax" />
    </xs:complexType>
  </xs:element>
  <xs:element name="name">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute ref="xml:lang" use="optional"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>

and here's an example of a document that follows that schema ๐ŸŒธ

<?xml version="1.0"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
      uri="sip:adam-friends@lists.vancouver.example.com"
      version="7" fullState="true">
  <name xml:lang="en">Buddy List</name>
  <name xml:lang="fr">Liste d'amis</name>
  <resource uri="sip:bob@vancouver.example.com">
    <name>Bob Smith</name>
    <instance id="juwigmtboe" state="active"
              cid="12345.aaa@vancouver.example.com"/>
  </resource>
  <resource uri="sip:dave@vancouver.example.com">
    <name>Dave Jones</name>
    <instance id="hqzsuxtfyq" state="active"
              cid="12345.aab@vancouver.example.com"/>
  </resource>
  <resource uri="sip:jim@vancouver.example.com">

    <name>Jim</name>
    <instance id="oflzxqzuvg" state="terminated"
              reason="rejected" />
  </resource>
  <resource uri="sip:ed@vancouver.example.com">
    <name>Ed</name>
    <instance id="grqhzsppxb" state="pending"/>
  </resource>
</list>

5.2. List Attributes ๐Ÿ“‹

the <list> element in a list notification MUST contain three attributes, no cap ๐Ÿงพ

the first mandatory one is "uri" ๐Ÿ”— it holds the uri for the list, and usually that's the URI the SUBSCRIBE request was sent to.

the second mandatory one is "version" ๐Ÿ”ข it's a number from 0 to 2^32-1. the version MUST be 0 for the first NOTIFY sent in a subscription, and it MUST increase by exactly one for every NOTIFY after that. very orderly, very iconic ๐Ÿ’…

the third mandatory one is "fullState" ๐ŸŒˆ it tells you whether the NOTIFY has info for every single resource in the list. if it does, the value is true (or 1); if not, it's false (or 0). the first NOTIFY in a subscription MUST contain full state, and so must the first NOTIFY sent after a SUBSCRIBE request for the subscription is received ๐Ÿซถ

finally, <list> elements MAY contain a "cid" attribute ๐Ÿฆ‹ if it's there, it points at a section inside the multipart/related body that has the aggregate state for the resources in the list. what that aggregate info actually looks like is outside the scope of this doc and will be defined per package, as needed. the cid is the Content-ID of that matching section in the multipart body.

the cid attribute MUST refer only to top-level parts of the multipart/related document that the RLMI document it's in is the root of. Section 5.5 has an example if you wanna see it in action ๐Ÿ“

5.3. Resource Attributes ๐Ÿง

the resource list has one <resource> element for each resource being reported in the notification. these elements carry attributes that hold the meta-data for each resource โœจ

the "uri" attribute says which resource that <resource> element is about. usually it's a SIP URI that, if you subscribed to it, would give you back that resource's state ๐Ÿ“ก this attribute MUST be present, no exceptions bestie ๐Ÿ™…โ€โ™€๏ธ

5.4. Name Attributes ๐Ÿท๏ธ

each list and resource element can have zero or more name elements. these hold human-readable names or descriptions for the list or resource, kinda like the "Display Name" in a SIP name-addr element ๐Ÿ’œ

name elements can optionally carry the standard XML "xml:lang" attribute ๐ŸŒ if it's there, it says what language the human-readable name is in. when it's present, it MUST contain a valid language tag. language tags are defined in RFC 3066 [6], and they help apps figure out which of several name elements to show the user ๐ŸŽ€

5.5. Instance Attributes ๐Ÿฆ‹

Okay so each resource element can hold zero or more instance elements โœจ Each instance element represents a single notifier for the resource. For event packages that allow forking, there can be multiple virtual subscriptions for one resource, and each one shows up as its own instance element inside that resource element. For subscriptions where forking doesn't happen, there's at most one instance per resource.

The "id" attribute is an opaque string that uniquely identifies the instance of the resource. It only has to be unique within its resource, not globally. How you build that string is totally an implementation decision ๐Ÿ’… Any mechanism works, as long as uniqueness within the resource is assured.

The "state" attribute holds the subscription state for that instance. It's one of "active", "pending", or "terminated", and the meanings match the "Subscription-State" header field from RFC 3265 [2] ๐ŸŒธ

If the "state" attribute says "terminated", then a "reason" attribute MUST also be present. It has the same values and meanings as the "reason" parameter on the "Subscription-State" header field in RFC 3265 [2]. Just so you know, the "reason" attribute is only there for informational purposes. The list subscriber is not expected to take any automated actions based on the reason value ๐Ÿ™ˆ

Finally, the "cid" attribute MUST be present if the "state" attribute is "active" ๐ŸŽ€ It identifies the section within the multipart/related body that contains the actual resource state. That state is expressed in the content type the event package defines for conveying state. The "cid" attribute is the Content-ID for the corresponding section in the multipart body.

The "cid" attribute MUST refer only to top-level parts of the multipart/related document for which the RLMI document in which it appears is the root.

Here's an example to make it click ๐Ÿงš Picture a multipart/related document with three parts: A, B, and C. Part A is type application/rlmi+xml, part B is type multipart/related, and part C is type application/pidf+xml. Part B is its own document with three parts: D, E, and F. Part D is type application/rlmi+xml, and parts E and F are both type application/pidf+xml.

   +-------------------------------------------+
   | Top Level Document: multipart/related     |
   |                                           |
   | +---------------------------------------+ |
   | | Part A: application/rlmi+xml          | |
   | +---------------------------------------+ |
   | | Part B: multipart/related             | |
   | |                                       | |
   | | +-----------------------------------+ | |
   | | | Part D: application/rlmi+xml      | | |
   | | +-----------------------------------+ | |
   | | | Part E: application/pidf+xml      | | |
   | | +-----------------------------------+ | |
   | | | Part F: application/pidf+xml      | | |
   | | +-----------------------------------+ | |
   | |                                       | |
   | +---------------------------------------+ |
   | | Part C: application/pidf+xml          | |
   | +---------------------------------------+ |
   |                                           |
   +-------------------------------------------+

So any "cid" attributes in document A must refer only to parts B or C. Referring to parts D, E, or F would be illegal. Similarly, any "cid" attributes in document D must refer only to parts E or F, and referring to any other parts would be illegal.

Also note that the subscription durations of any back-end subscriptions are not propagated into the meta-information state in any way. Those timers stay behind the scenes ๐Ÿคซ

5.6. Constructing Coherent Resource State ๐Ÿ’–

The resource list subscriber keeps a table for each resource list. That table has a row for each resource in the list, and each row is indexed by the URI for that resource. The URI comes from the "uri" attribute on each <resource> element. The contents of each row hold the state of that resource as conveyed in the resource document.

For resources that provide versioning information (which is mandated by [2] for any formats that allow partial notification), each row also holds a resource state version number. The version number for the row gets initialized with the version specified in the first document received, as defined by the corresponding event package. That value is used when comparing versions of partial notifications for a resource ๐Ÿ”ฅ

How the resource list notification gets processed depends on whether it contains full or partial state.

5.6.1. Processing Full State Notifications ๐Ÿ‘‘

If a notification contains full state, which is indicated by the <list> attribute "fullState" set to "true", the notification is used to update the table. First, a check is made to make sure that the "version" attribute of the <list> attribute in the received message is greater than the local version number. If it isn't, the received document is discarded without any further processing. Otherwise, the contents of the resource-list table get flushed and repopulated from the contents of the document. A new row gets created in the table for each "resource" element โœจ

5.6.2. Processing Partial State Notifications ๐ŸŒˆ

If a notification contains partial state, which is indicated by the <list> attribute "fullState" set to "false", a check is made to make sure no list notifications have been lost. The value of the local version number (the "version" attribute of the <list> element) is compared to the version number of the new document.

  • If the value in the new document is exactly one higher than the local version number, the local version number goes up by one, and the document is processed as described below.
  • If the version in the document is more than one higher than the local version number, the local version number is set to the value in the new document, and the document is processed as described below. The list subscriber SHOULD also generate a refresh request to trigger a full state notification ๐Ÿซถ
  • If the version in the document is less than or equal to the local version, the document is discarded without any further processing.

For each resource listed in the document, the subscriber checks whether a row exists for that resource. This check is done by comparing the Resource-URI value with the URI associated with the row. If the resource doesn't exist in the table, a row is added, and its state is set to the information from that "resource" element. If the resource does exist, its state is updated to be the information from that "resource" element, as described in the definition of the event package. If a row is updated or created so that its state is now "terminated," that entry MAY be removed from the table at any time ๐Ÿฆ‹


6. Example ๐Ÿงš

This section gives an example call flow. It is not normative. If a conflict arises between this call flow and the normative behavior described in this or any other document, the normative descriptions are to be followed.

In this particular example, we request a subscription to a nested presence list. The subscriber's address-of-record is "sip:adam@vancouver.example.com", and the name of the nested list resource we're subscribing to is "sip:adam-buddies@pres.vancouver.example.com". The underlying event package is "presence", described by [8].

In this example, the RLS has information to service some of the resources on the list, but it has to consult other servers to get information for others. The implementation of the RLS in this example uses the SIP SUBSCRIBE/NOTIFY mechanism to retrieve that information ๐Ÿ’…

   Terminal   pres.vancouver.example.com   pres.stockholm.example.org
     |                |        pres.dallas.example.net  |
   1 |---SUBSCRIBE--->|                |                |
   2 |<-----200-------|                |                |
   3 |<----NOTIFY-----|                |                |
   4 |------200------>|                |                |
   5 |                |---SUBSCRIBE--->|                |
   6 |                |<-----200-------|                |
   7 |                |<----NOTIFY-----|                |
   8 |                |------200------>|                |
   9 |                |------------SUBSCRIBE----------->|
  10|                |<--------------200---------------|
  11|                |<-------------NOTIFY-------------|
  12|                |---------------200-------------->|
  13|<----NOTIFY-----|                |                |
  14|------200------>|                |                |
  1. We start the subscription by sending a SUBSCRIBE message to our local RLS. (There's no reason the RLS we contact has to be in our domain, of course ๐ŸŒธ) Note that we must advertise support for application/rlmi+xml and multipart/related because we support the eventlist extension, and that we must advertise application/pidf+xml because we are requesting a subscription to presence ๐Ÿ’œ

Terminal -> Local RLS

SUBSCRIBE sip:adam-buddies@pres.vancouver.example.com SIP/2.0
Via: SIP/2.0/TCP terminal.vancouver.example.com;
  branch=z9hG4bKwYb6QREiCL
Max-Forwards: 70
To: <sip:adam-buddies@pres.vancouver.example.com>
From: <sip:adam@vancouver.example.com>;tag=ie4hbb8t
Call-ID: cdB34qLToC@terminal.vancouver.example.com
CSeq: 322723822 SUBSCRIBE
Contact: <sip:terminal.vancouver.example.com>
Event: presence
Expires: 7200
Supported: eventlist
Accept: application/pidf+xml
Accept: application/rlmi+xml
Accept: multipart/related
Accept: multipart/signed
Accept: application/pkcs7-mime
Content-Length: 0
  1. The Local RLS completes the SUBSCRIBE transaction ๐Ÿ“ Authentication and authorization would normally happen at this point in the call flow, but those steps are omitted for brevity.

Local RLS -> Terminal

SIP/2.0 200 OK
Via: SIP/2.0/TCP terminal.vancouver.example.com;
  branch=z9hG4bKwYb6QREiCL
To: <sip:adam-buddies@pres.vancouver.example.com>;tag=zpNctbZq
From: <sip:adam@vancouver.example.com>;tag=ie4hbb8t
Call-ID: cdB34qLToC@terminal.vancouver.example.com
CSeq: 322723822 SUBSCRIBE
Contact: <sip:pres.vancouver.example.com>
Expires: 7200
Require: eventlist
Content-Length: 0
  1. As RFC 3265 [2] requires, the RLS sends a NOTIFY immediately upon accepting the subscription โญ In this example, we're assuming the local RLS is also an authority for presence information for the users in the "vancouver.example.com" domain. The NOTIFY contains an RLMI document describing the entire buddy list (initial notifies require full state), as well as presence information for the users the RLS already knows about. Since the RLS hasn't retrieved information yet for some of the entries on the list, those <resource> elements contain no <instance> elements ๐Ÿฆ‹

Local RLS -> Terminal

Okay so the NOTIFY is literally the main event ๐Ÿ˜ญ๐Ÿฆ‹ The terminal gets a multipart body that has the list (RLMI) and two presence docs, and it's giving organized. ๐Ÿ’…

NOTIFY sip:terminal.vancouver.example.com SIP/2.0
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bKMgRenTETmm
Max-Forwards: 70
From: <sip:adam-buddies@pres.vancouver.example.com>;tag=zpNctbZq
To: <sip:adam@vancouver.example.com>;tag=ie4hbb8t
Call-ID: cdB34qLToC@terminal.vancouver.example.com
CSeq: 997935768 NOTIFY
Contact: <sip:pres.vancouver.example.com>
Event: presence
Subscription-State: active;expires=7200
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";
    start="<nXYxAE@pres.vancouver.example.com>";
    boundary="50UBfW7LSCVLtggUPe5z"
Content-Length: 1560
--50UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <nXYxAE@pres.vancouver.example.com>
Content-Type: application/rlmi+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
      uri="sip:adam-friends@pres.vancouver.example.com"
      version="1" fullState="true">
  <name xml:lang="en">Buddy List at COM</name>
  <name xml:lang="de">Liste der Freunde an COM</name>
  <resource uri="sip:bob@vancouver.example.com"">
    <name>Bob Smith</name>
    <instance id="juwigmtboe" state="active"
              cid="bUZBsM@pres.vancouver.example.com"/>
  </resource>
  <resource uri="sip:dave@vancouver.example.com">
    <name>Dave Jones</name>
    <instance id="hqzsuxtfyq" state="active"
              cid="ZvSvkz@pres.vancouver.example.com"/>
  </resource>
  <resource uri="sip:ed@dallas.example.net">
    <name>Ed at NET</name>
  </resource>
  <resource uri="sip:adam-friends@stockholm.example.org">
    <name xml:lang="en">My Friends at ORG</name>
    <name xml:lang="de">Meine Freunde an ORG</name>
  </resource>
</list>

--50UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <bUZBsM@pres.vancouver.example.com>
Content-Type: application/pidf+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
    entity="sip:bob@vancouver.example.com">
  <tuple id="sg89ae">
    <status>
      <basic>open</basic>
    </status>
    <contact priority="1.0">sip:bob@vancouver.example.com</contact>
  </tuple>
</presence>

--50UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <ZvSvkz@pres.vancouver.example.com>
Content-Type: application/pidf+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
    entity="sip:dave@vancouver.example.com">
  <tuple id="slie74">
    <status>
      <basic>closed</basic>
    </status>
  </tuple>
</presence>

--50UBfW7LSCVLtggUPe5z--

4. The terminal wraps up the transaction. ๐ŸŽ€ Bestie, it's giving "send the 200 and move on" โœจ

Terminal -> Local RLS

SIP/2.0 200 OK
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bKMgRenTETmm
From: <sip:adam-buddies@pres.vancouver.example.com>;tag=zpNctbZq
To: <sip:adam@vancouver.example.com>;tag=ie4hbb8t
Call-ID: cdB34qLToC@terminal.vancouver.example.com
CSeq: 997935768 NOTIFY
Contact: <sip:terminal.vancouver.example.com>
Content-Length: 0

5. Now the local RLS goes shopping for info ๐Ÿ›๏ธ๐Ÿ’œ It needs to subscribe to the state of the resources so it can actually service the subscription. In this step it tries to subscribe to the presence state of sip:ed@dallas.example.net. Since the local RLS knows how to receive notifications for list subscriptions, it puts Supported: eventlist in its request. Ngl, the link between this subscription and the one the terminal sent is left up to the application, but this message is lowkey iconic because it lists Accept header fields for every body type it knows the subscriber (Terminal) supports. And it's safe to do, bestie, because the local RLS only passes these formats through to the subscriber and doesn't need to actually understand them ๐Ÿซถ

Local RLS -> Presence Server in dallas.example.net

SUBSCRIBE sip:ed@dallas.example.net SIP/2.0
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bKMEyGjdG1LH

Max-Forwards: 70
To: <sip:ed@dallas.example.net>
From: <sip:adam@vancouver.example.com>;tag=aM5icQu9
Call-ID: Ugwz5ARxNw@pres.vancouver.example.com
CSeq: 870936068 SUBSCRIBE
Contact: <sip:pres.vancouver.example.com>
Identity: Tm8sIHRoaXMgaXNuJ3QgYSByZWFsIGNlcnQuIFlvdSBvn
          Zpb3VzbHkgaGF2ZSB0aW1lIHRvIGtpbGwuIEkKc3VnZ2V
          zdCBodHRwOi8vd3d3LmhvbWVzdGFycnVubmVyLmNvbS8K
Identity-Info: https://vancouver.example.com/cert
Event: presence
Expires: 3600
Supported: eventlist
Accept: application/pidf+xml
Accept: application/rlmi+xml
Accept: multipart/related
Accept: multipart/signed
Accept: application/pkcs7-mime
Content-Length: 0

6. The Presence Server in dallas.example.net finishes the SUBSCRIBE transaction. ๐Ÿ™ˆ Authentication would normally happen right about here, but we're skipping it for brevity, so no drama.

Presence Server in dallas.example.net -> Local RLS

SIP/2.0 200 OK
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bKMEyGjdG1LH
To: <sip:ed@dallas.example.net>;tag=e45TmHTh
From: <sip:adam@vancouver.example.com>;tag=aM5icQu9
Call-ID: Ugwz5ARxNw@pres.vancouver.example.com
CSeq: 870936068 SUBSCRIBE
Contact: <sip:dallas.example.net>
Expires: 3600
Content-Length: 0

7. Plot twist ๐ŸŒˆ In this example, the server at dallas.example.net doesn't have enough authorization info to say yes or no to our subscription. So the initial NOTIFY carries a Subscription-State of "pending" ๐Ÿ‘€ Presumably whoever decides on authorization for the resource gets notified of this change, but those steps are skipped in this call flow for brevity. Not me being dramatic about it being pending... well, a little ๐Ÿ’€

Presence Server in dallas.example.net -> Local RLS

NOTIFY sip:pres.vancouver.example.com SIP/2.0
Via: SIP/2.0/TCP pres.dallas.example.net;
  branch=z9hG4bKfwpklPxmrW
Max-Forwards: 70
From: <sip:ed@dallas.example.net>;tag=e45TmHTh
To: <sip:adam@vancouver.example.com>;tag=aM5icQu9
Call-ID: Ugwz5ARxNw@pres.vancouver.example.com
CSeq: 1002640632 NOTIFY
Contact: <sip:dallas.example.net>
Subscription-State: pending;expires=3600
Event: presence
Require: eventlist
Content-Length: 0

8. The local RLS finishes the NOTIFY transaction โœจ At this point the Local RLS has new info to tell the subscriber, and whether it reports right away or saves it up for later is totally up to the application. For this example, we pretend the RLS waits a little bit before sending, so the subscriptions it sent out have time to actually bring back useful data ๐Ÿฆ‹

Local RLS -> Presence Server in dallas.example.net

SIP/2.0 200 OK
Via: SIP/2.0/TCP pres.dallas.example.net;
  branch=z9hG4bKfwpklPxmrW
From: <sip:ed@dallas.example.net>;tag=e45TmHTh
To: <sip:adam@vancouver.example.com>;tag=aM5icQu9
Call-ID: Ugwz5ARxNw@pres.vancouver.example.com
CSeq: 1002640632 NOTIFY
Contact: <sip:pres.vancouver.example.com>
Content-Length: 0

9. The Local RLS subscribes to the state of the other non-local resource ๐ŸŒธ

Local RLS -> RLS in stockholm.example.org

SUBSCRIBE sip:adam-friends@stockholm.example.org SIP/2.0
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bKFSrAF8CZFL
Max-Forwards: 70
To: <sip:adam-friends@stockholm.example.org>
From: <sip:adam@vancouver.example.com>;tag=a12eztNf
Call-ID: kBq5XhtZLN@pres.vancouver.example.com
CSeq: 980774491 SUBSCRIBE
Contact: <sip:pres.vancouver.example.com>
Identity: Tm90IGEgcmVhbCBzaWduYXR1cmUsIGVpdGhlci4gQ2VydGFp
          bmx5IHlvdSBoYXZlIGJldHRlcgp0aGluZ3MgdG8gYmUgZG9p
          bmcuIEhhdmUgeW91IGZpbmlzaGVkIHlvdXIgUkxTIHlldD8K
Identity-Info: https://vancouver.example.com/cert
Event: presence
Expires: 3600
Supported: eventlist
Accept: application/pidf+xml
Accept: application/rlmi+xml
Accept: multipart/related
Accept: multipart/signed
Accept: application/pkcs7-mime
Content-Length: 0

10. The RLS in stockholm.example.org finishes the SUBSCRIBE transaction ๐ŸŽ€ Again, authentication would normally happen at this point, but it's omitted here for brevity.

RLS in stockholm.example.org -> Local RLS

SIP/2.0 200 OK
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bKFSrAF8CZFL
To: <sip:adam-friends@stockholm.example.org>;tag=JenZ40P3
From: <sip:adam@vancouver.example.com>;tag=a12eztNf
Call-ID: kBq5XhtZLN@pres.vancouver.example.com
CSeq: 980774491 SUBSCRIBE
Contact: <sip:stockholm.example.org>
Expires: 3600
Content-Length: 0

11. Okay, the RLS in stockholm.example.org is also an authority for presence info for users in the "stockholm.example.org" domain ๐Ÿ‘‘ So its NOTIFY has an RLMI document describing the buddy list, plus presence info for those users. Here the RLS has chosen to sign [14] the body of the NOTIFY. As described in RFC 3851, signing creates a multipart/signed document with two parts. The first part is the thing being signed (in this example, the multipart/related document describing the list resource states), and the second part is the actual signature. It's giving security glow-up ๐Ÿ”ฅ

RLS in stockholm.example.org -> Local RLS

NOTIFY sip:pres.vancouver.example.com SIP/2.0
Via: SIP/2.0/TCP pres.stockholm.example.org;
  branch=z9hG4bKmGL1nyZfQI
Max-Forwards: 70
From: <sip:adam-friends@stockholm.example.org>;tag=JenZ40P3
To: <sip:adam@vancouver.example.com>;tag=a12eztNf
Call-ID: kBq5XhtZLN@pres.vancouver.example.com
CSeq: 294444656 NOTIFY
Contact: <sip:stockholm.example.org>
Event: presence
Subscription-State: active;expires=3600
Require: eventlist
Content-Type: multipart/signed;
    protocol="application/pkcs7-signature";
    micalg=sha1;boundary="l3WMZaaL8NpQWGnQ4mlU"
Content-Length: 2038

--l3WMZaaL8NpQWGnQ4mlU
Content-Transfer-Encoding: binary
Content-ID: <ZPvJHL@stockholm.example.org>
Content-Type: multipart/related;type="application/rlmi+xml";
    start="<Cvjpeo@stockholm.example.org>";
    boundary="tuLLl3lDyPZX0GMr2YOo"

--tuLLl3lDyPZX0GMr2YOo
Content-Transfer-Encoding: binary
Content-ID: <Cvjpeo@stockholm.example.org>
Content-Type: application/rlmi+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
      uri="sip:adam-friends@stockholm.example.org" version="1"
      fullState="true">
  <name xml:lang="en">Buddy List at COM</name>
  <name xml:lang="de">Liste der Freunde an COM</name>
  <resource uri="sip:joe@stockholm.example.org">
    <name>Joe Thomas</name>
    <instance id="1" state="active"
              cid="mrEakg@stockholm.example.org"/>
  </resource>
  <resource uri="sip:mark@stockholm.example.org">
    <name>Mark Edwards</name>
    <instance id="1" state="active"
              cid="KKMDmv@stockholm.example.org"/>
  </resource>
</list>
--tuLLl3lDyPZX0GMr2YOo
Content-Transfer-Encoding: binary
Content-ID: <mrEakg@stockholm.example.org>
Content-Type: application/pidf+xml;charset="UTF-8"

12. Okay, the Local RLS wraps up the NOTIFY transaction with a 200 OK, and it's giving tidy handshake vibes ๐Ÿงš

Local RLS -> RLS in stockholm.example.org

SIP/2.0 200 OK
Via: SIP/2.0/TCP pres.stockholm.example.org;
  branch=z9hG4bKmGL1nyZfQI
From: <sip:adam-friends@stockholm.example.org>;tag=JenZ40P3
To: <sip:adam@vancouver.example.com>;tag=a12eztNf
Call-ID: kBq5XhtZLN@pres.vancouver.example.com
CSeq: 294444656 NOTIFY
Contact: <sip:pres.vancouver.example.com>
Content-Length: 0

13. Now the Local RLS has collected enough extra info to justify sending a new notification to the user ๐Ÿ’… A full notification would also be totally fine, but this RLS picks a partial notification instead. The RLMI document only has info for the resources that changed, which is why fullState is set to "false". Here's the cute part: to avoid messing up the S/MIME signature on the data from the RLS in stockholm.example.org, the local RLS copies the entire multipart/signed body exactly as-is into the notification it sends. No edits, no drama ๐Ÿซถ

Local RLS -> Terminal

NOTIFY sip:terminal.vancouver.example.com SIP/2.0
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bK4EPlfSFQK1
Max-Forwards: 70
From: <sip:adam-buddies@pres.vancouver.example.com>;tag=zpNctbZq
To: <sip:adam@vancouver.example.com>;tag=ie4hbb8t
Call-ID: cdB34qLToC@terminal.vancouver.example.com
CSeq: 997935769 NOTIFY
Contact: <sip:pres.vancouver.example.com>
Event: presence
Subscription-State: active;expires=7200
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";
    start="<2BEI83@pres.vancouver.example.com>";
    boundary="TfZxoxgAvLqgj4wRWPDL"
Content-Length: 2862

--TfZxoxgAvLqgj4wRWPDL
Content-Transfer-Encoding: binary
Content-ID: <2BEI83@pres.vancouver.example.com>
Content-Type: application/rlmi+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
      uri="sip:adam-friends@pres.vancouver.example.com" version="2"
      fullState="false">
  <name xml:lang="en">Buddy List at COM</name>
  <name xml:lang="de">Liste der Freunde an COM</name>
  <resource uri="sip:ed@dallas.example.net">
    <name>Ed at NET</name>
    <instance id="sdlkmeopdf" state="pending"/>
  </resource>
  <resource uri="sip:adam-friends@stockholm.example.org">
    <name xml:lang="en">My Friends at ORG</name>
    <name xml:lang="de">Meine Freunde an ORG</name>
    <instance id="cmpqweitlp" state="active"
              cid="1KQhyE@pres.vancouver.example.com"/>
  </resource>
</list>

--TfZxoxgAvLqgj4wRWPDL
Content-Transfer-Encoding: binary
Content-ID: <1KQhyE@pres.vancouver.example.com>
Content-Type: multipart/signed;
    protocol="application/pkcs7-signature";
    micalg=sha1;boundary="l3WMZaaL8NpQWGnQ4mlU"

--l3WMZaaL8NpQWGnQ4mlU
Content-Transfer-Encoding: binary
Content-ID: <ZPvJHL@stockholm.example.org>
Content-Type: multipart/related;type="application/rlmi+xml";
    start="<Cvjpeo@stockholm.example.org>";
    boundary="tuLLl3lDyPZX0GMr2YOo"

--tuLLl3lDyPZX0GMr2YOo
Content-Transfer-Encoding: binary
Content-ID: <Cvjpeo@stockholm.example.org>
Content-Type: application/rlmi+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
      uri="sip:adam-friends@stockholm.example.org" version="1"
      fullState="true">
  <name xml:lang="en">Buddy List at ORG</name>
  <name xml:lang="de">Liste der Freunde an ORG</name>
  <resource uri="sip:joe@stockholm.example.org">
    <name>Joe Thomas</name>
    <instance id="1" state="active"
              cid="mrEakg@stockholm.example.org"/>
  </resource>
  <resource uri="sip:mark@stockholm.example.org">

    <name>Mark Edwards</name>
    <instance id="1" state="active"
              cid="KKMDmv@stockholm.example.org"/>
  </resource>
</list>

--tuLLl3lDyPZX0GMr2YOo
Content-Transfer-Encoding: binary
Content-ID: <mrEakg@stockholm.example.org>
Content-Type: application/pidf+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
    entity="sip:joe@stockholm.example.org">
  <tuple id="x823a4">
    <status>
      <basic>open</basic>
    </status>
    <contact priority="1.0">sip:joe@stockholm.example.org</contact>
  </tuple>
</presence>

--tuLLl3lDyPZX0GMr2YOo
Content-Transfer-Encoding: binary
Content-ID: <KKMDmv@stockholm.example.org>
Content-Type: application/pidf+xml;charset="UTF-8"

<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
    entity="sip:mark@stockholm.example.org">
  <tuple id="z98075">
    <status>
      <basic>closed</basic>
    </status>
  </tuple>
</presence>
--tuLLl3lDyPZX0GMr2YOo--

--l3WMZaaL8NpQWGnQ4mlU
Content-Transfer-Encoding: binary
Content-ID: <K9LB7k@stockholm.example.org>
Content-Type: application/pkcs7-signature

[PKCS #7 signature here]

--l3WMZaaL8NpQWGnQ4mlU--

--TfZxoxgAvLqgj4wRWPDL--

14. Last step, and it's so satisfying โœจ The terminal finishes the NOTIFY transaction by sending back a 200 OK ๐ŸŽ€

Terminal -> Local RLS

SIP/2.0 200 OK
Via: SIP/2.0/TCP pres.vancouver.example.com;
  branch=z9hG4bK4EPlfSFQK1
From: <sip:adam-buddies@pres.vancouver.example.com>;tag=zpNctbZq
To: <sip:adam@vancouver.example.com>;tag=ie4hbb8t
Call-ID: cdB34qLToC@terminal.vancouver.example.com
CSeq: 997935769 NOTIFY
Contact: <sip:terminal.vancouver.example.com>
Content-Length: 0

7. Security Considerations ๐Ÿ”

Okay bestie, this part is serious, so let's get into it ๐Ÿฅบ The way RLS state gets collected is mostly up to whoever builds the RLS. Some of the security issues below only show up when a SIP back-end subscription is being used for that. Non-SIP ways of getting resource state will usually come with their own security issues too ๐Ÿ˜ฌ Listing every possible access method isn't something this document can do, so if you're using one of those, you must analyze your chosen access method for security issues yourself.

7.1. Authentication ๐Ÿ”‘

If back-end subscriptions are needed to get resource state, the end user is no longer the one directly subscribing to the resource state. So direct authentication of the user is no longer possible ๐Ÿ’€

7.1.1. RLS and Subscriber in the Same Domain ๐Ÿ 

The most common setup is going to be the RLS and its subscribers living in the same domain ๐Ÿ’– When that's the case, the RLS can act as an authentication service. That role is defined in "Enhancements for Authenticated Identity Management in the Session Initiation Protocol (SIP)" [7].

Here's the high-level version. The RLS authenticates the subscriber, then puts an Identity header field into every back-end subscription it makes on that user's behalf. That Identity header field cryptographically asserts that the request was authorized to be made for the user named in the From header field ๐Ÿ”โœจ

Authenticating requests is super central to the network working properly, so any RLS that uses SIP back-end subscriptions to get information about the resources in a resource list MUST be able to act as an authentication service as defined in [7], provided that local administrative policy allows it to do so.

In other words, every RLS implementation that supports SIP back-end subscriptions also has to include the ability to be configured as an authentication service. Whether an admin actually turns that on is totally up to them ๐Ÿ’… And if an RLS can't act as an identity server, then it's going to behave like the next section describes, because it's basically acting like it's in a different domain from the user.

7.1.2. RLS and Subscriber in Different Domains ๐ŸŒ

In the general case, the SIP Authenticated Identity extensions don't give the RLS a way to securely say that subscriptions are being made on the end user's behalf ๐Ÿ˜ญ So when the subscriber and the RLS are in different domains, the RLS has no way to vouch for the user's identity. How back-end subscriptions get authenticated in that situation is left for future study ๐Ÿ”ฎ

Until general solutions show up, RLSes in a different domain from the subscriber they're making back-end subscriptions for SHOULD subscribe to the resources using their own identity. Doing that means the RLS will generally only get the resource information that's publicly available ๐Ÿซ 

Until those general solutions exist, implementations of subscriber user agents MAY try direct subscriptions to the resources in the resource list when they're subscribing to an RLS outside their domain (either directly or through another resource list subscription). The resources to subscribe to are the ones in the uri attribute of the <resource> elements in the RLMI document the RLS returns. Subscribing directly lets the user get properly authenticated, which generally means they'll be authorized to get more complete state information ๐ŸŽ€ Implementations that choose to do direct subscriptions SHOULD use the data they retrieve instead of any information about the resource they got through the list subscription ๐ŸŒธ

7.2. Risks of Improper Aggregation ๐Ÿ’…

Okay bestie, so a resource list server (RLS) usually serves info to a bunch of subscribers at the same time ๐ŸŒธ. Resources can show up in several lists, and it's super possible that two users subscribe to the same list.

In these cases, misguided RLS implementations might try to save network load by keeping just one back-end subscription to a resource in a list and handing that one result to more than one user ๐Ÿ™ˆ. But that totally works around whatever authorization policy the notifier keeps for the resource ๐Ÿ’€. Authorization is so much more than "allowed/not allowed" ๐Ÿ˜ญ. A resource can show totally different (even conflicting!) states depending on who's asking ๐Ÿซถ.

To make sure event info only goes to the intended recipient, implementations MUST NOT present the result of one back-end subscription to more than one user, unless:

a. The RLS has adequate access to the complete authorization policy associated with the resource to which the back-end subscription has been made, AND

b. The RLS can and has determined that presenting the information to more than one user does not violate such policy.

Note that this is a very difficult problem to solve correctly ๐ŸŒˆ. Even in the cases where such access is believed possible, this mode of operation is NOT RECOMMENDED. ๐Ÿšซ

7.3. Signing and Sealing ๐Ÿ”

Implementors should keep in mind that any section of the MIME body may be signed and/or encrypted as necessary โœจ. Resource List Servers should take care not to modify any MIME bodies they receive from any back-end subscriptions, and should not generally rely on being able to read them ๐ŸŽ€.

In order to facilitate security, resource list servers SHOULD pass along indication for support of multipart/signed and application/pkcs7-mime content types to any SIP back-end subscriptions, if the subscriber includes them in the initial SUBSCRIBE message ๐Ÿฆ‹. Not doing so may actually result in resources refusing to divulge state (if notifier policy requires encryption, but the RLS fails to convey support), or subscribers discarding valid state (if subscriber policy requires a signature, but the RLS fails to convey support). Yikes, that's a mess ๐Ÿ˜ฌ.

Note that actual implementation of encryption and signing by the RLS is not necessary to be able to pass through signed and/or encrypted bodies ๐Ÿ’œ.

7.4. Infinite Loops ๐Ÿ”

One risk introduced by the ability to nest resource lists is the possibility of creating lists that ultimately contain themselves as a sub-list ๐Ÿ™ƒ. Detection and handling of such a case is trivial when the RLS services all the virtual subscriptions internally. When back-end subscriptions are created to service virtual subscriptions, however, detection of such situations becomes a more difficult problem ๐Ÿ˜ตโ€๐Ÿ’ซ.

Implementors of RLSes that create back-end subscriptions MUST implement safeguards to prevent such nestings from creating an infinite loop of subscriptions. Typically, such mechanisms will require support in the back-end subscription protocol. In particular, applying filters to the back-end subscriptions can be an effective way to preclude such problems ๐Ÿ‘‘.


8. IANA Considerations ๐Ÿฆ‹

8.1. New SIP Option Tag: eventlist

This section defines a new option tag for the registry established by Section 27.1 of RFC 3261[1] ๐Ÿงš.

Option Tag Name:  eventlist

Description:  Extension to allow subscriptions to lists of resources.

Published specification:  RFC 4662

8.2. New MIME type for Resource List Meta-Information ๐Ÿ“

MIME Media Type Name:  application

MIME subtype name:  rlmi+xml

Required parameters:  None

Optional parameters:  charset

   See RFC 3023 [12] for a discussion of the charset parameter on
   XML-derived MIME types.  Since this MIME type is used exclusively
   in SIP, the use of UTF-8 encoding is strongly encouraged.

Encoding considerations:  8-bit text
Security considerations:  Security considerations specific to uses of
   this MIME type are discussed in RFC 4662.  RFC 1874 [11] and RFC
   3023 [12] discuss security issues common to all uses of XML.

Interoperability considerations:  The use of this MIME body is
   intended to be generally interoperable.  No unique considerations
   have been identified.

Published specification:  RFC 4662

Applications that use this media type:  This media type is used to
   convey meta-information for the state of lists of resources within
   a Session Initiation Protocol (SIP) subscription.

Additional information:
   Magic Number(s):  None.
   File Extension(s):  None.
   Macintosh File Type Code(s):  None.
   Object Identifier(s) or OID(s):  None.

Intended usage:  Limited Use

Other Information/General Comment:  None.

Person to contact for further information:
   Name:  Adam Roach
   E-Mail:  adam@estacado.net
   Author/Change Controller:  The specification of this MIME type is
      a work product of the SIMPLE working group and was authored by
      Adam Roach, Jonathan Rosenberg, and Ben Campbell.  The IETF has
      change control over its specification.

8.3. URN Sub-Namespace ๐ŸŒธ

URI:  urn:ietf:params:xml:ns:rlmi

Description:  This is the XML namespace URI for XML elements defined
   by RFC 4662 to describe information about subscriptions when such
   subscriptions are aggregated within a single SIP subscription.  It
   is used in the application/rlmi+xml body type.

Registrant Contact:
   Name:  Adam Roach
   E-Mail:  adam@estacado.net
   Author/Change Controller:  The specification of this MIME type is
      a work product of the SIMPLE working group and was authored by
      Adam Roach, Jonathan Rosenberg, and Ben Campbell.  The IETF has
      change control over its specification.

XML:
   BEGIN
     <?xml version="1.0"?>
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
         "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
     <html xmlns="http://www.w3.org/1999/xhtml">
     <head>
       <meta http-equiv="content-type"
          content="text/html;charset=utf-8"/>
       <title>Namespace for SIP Event Resource List
              Meta-Information</title>
     </head>
     <body>
       <h1>Namespace for SIP Event Resource List
           Meta-Information</h1>
       <h2>application/rlmi+xml</h2>
       <p>See <a href="[http://www.rfc-editor.org/rfc/rfc4662.txt]">
          RFC4662</a>.</p>
     </body>
     </html>
   END

9. Acknowledgements ๐Ÿซถ

Huge thanks to Sean Olson for reviewing and correcting how XML is used in this protocol ๐Ÿ’–.

Thanks also to Hisham Khartabil, Paul Kyzivat, Keith Drage, and Robert Sparks for their careful reviews of and comments on this document ๐ŸŒŸ.

10. References ๐Ÿ“š

10.1. Normative References

  • [1] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, June 2002.
  • [2] Roach, A. B., "Session Initiation Protocol (SIP)-Specific Event Notification", RFC 3265, June 2002.
  • [3] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
  • [4] Levinson, E., "The MIME Multipart/Related Content-type", RFC 2387, August 1998.
  • [5] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [6] Alvestrand, H., "Tags for the Identification of Languages", BCP 47, RFC 3066, January 2001.
  • [7] Peterson, J. and C. Jennings, "Enhancements for Authenticated Identity Management in the Session Initiation Protocol (SIP)", RFC 4474, August 2006.

10.2. Informative References

  • [8] Rosenberg, J., "A Presence Event Package for the Session Initiation Protocol (SIP)", RFC 3856, August 2004.
  • [9] Burger, E., "A Mechanism for Content Indirection in Session Initiation Protocol (SIP) Messages", RFC 4483, May 2006.
  • [10] Peterson, J., "Common Profile for Presence (CPP)", RFC 3859, August 2004.
  • [11] Levinson, E., "SGML Media Types", RFC 1874, December 1995.
  • [12] Murata, M., St. Laurent, S., and D. Kohn, "XML Media Types", RFC 3023, January 2001.
  • [13] Ramsdell, B., "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.1 Message Specification", RFC 3851, July 2004.
  • [14] Galvin, J., Murphy, S., Crocker, S., and N. Freed, "Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted", RFC 1847, October 1995.
  • [15] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.

Authors' Addresses ๐Ÿ’Œ

Adam Roach
Estacado Systems
US

EMail: adam@estacado.net


Ben Campbell
Estacado Systems
US

EMail: ben@estacado.net


Jonathan Rosenberg
Cisco Systems
600 Lanidex Plaza
Parsippany, NJ  07054-2711
US

EMail: jdrosen@cisco.com

Copyright (C) The Internet Society (2006).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Intellectual Property ๐Ÿง 

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.

Acknowledgement ๐ŸŒท

Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA). ๐Ÿ’•

๐Ÿ“ฆ where this page comes from