RFC 4975

The Message Session Relay Protocol (MSRP)

๐Ÿ“… published September 2007, from ietf

RFC 4975: The Message Session Relay Protocol (MSRP) ๐Ÿ’–

  • Number: RFC 4975 ๐ŸŒธ
  • Working group: Network Working Group
  • Category: Standards Track โœจ
  • Date: September 2007 ๐Ÿ—“๏ธ
  • Authors (all editors): B. Campbell (Estacado Systems), R. Mahy (Plantronics), and C. Jennings (Cisco Systems, Inc.) ๐Ÿซถ

Status of This Memo โœจ

This is an Internet standards track protocol for the Internet community, and it's open for discussion and suggestions for improvements ๐Ÿ’ฌ. For the standardization state and status, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š. Distribution of this memo is unlimited ๐ŸŒˆ.

Abstract ๐Ÿฆ‹

Okay so this document describes the Message Session Relay Protocol, a protocol for sending a bunch of related instant messages as part of a session ๐Ÿ’Œ. When message sessions get set up through a rendezvous or session creation protocol like the Session Initiation Protocol, they get treated like any other media stream, which is so iconic ๐Ÿ‘‘.

Table of Contents ๐Ÿ“‹

   1. Introduction ....................................................4
   2. Conventions .....................................................5
   3. Applicability of MSRP ...........................................5
   4. Protocol Overview ...............................................6
   5. Key Concepts ....................................................9
      5.1. MSRP Framing and Message Chunking ..........................9
      5.2. MSRP Addressing ...........................................10
      5.3. MSRP Transaction and Report Model .........................11
      5.4. MSRP Connection Model .....................................12
   6. MSRP URIs ......................................................14
      6.1. MSRP URI Comparison .......................................15
      6.2. Resolving MSRP Host Device ................................16
   7. Method-Specific Behavior .......................................17
      7.1. Constructing Requests .....................................17
           7.1.1. Sending SEND Requests ..............................18
           7.1.2. Sending REPORT Requests ............................21
           7.1.3. Generating Success Reports .........................22
           7.1.4. Generating Failure Reports .........................23
      7.2. Constructing Responses ....................................24
      7.3. Receiving Requests ........................................25
           7.3.1. Receiving SEND Requests ............................25
           7.3.2. Receiving REPORT Requests ..........................27
   8. Using MSRP with SIP and SDP ....................................27
      8.1. SDP Connection and Media-Lines ............................28
      8.2. URI Negotiations ..........................................29
      8.3. Path Attributes with Multiple URIs ........................30
      8.4. Updated SDP Offers ........................................31
      8.5. Connection Negotiation ....................................31
      8.6. Content Type Negotiation ..................................32
      8.7. Example SDP Exchange ......................................34
      8.8. MSRP User Experience with SIP .............................35
      8.9. SDP Direction Attribute and MSRP ..........................35
   9. Formal Syntax ..................................................36
   10. Response Code Descriptions ....................................38
      10.1. 200 ......................................................38
      10.2. 400 ......................................................38
      10.3. 403 ......................................................38
      10.4. 408 ......................................................39
      10.5. 413 ......................................................39
      10.6. 415 ......................................................39
      10.7. 423 ......................................................39
      10.8. 481 ......................................................39
      10.9. 501 ......................................................39
      10.10. 506 .....................................................40

   11. Examples ......................................................40
      11.1. Basic IM Session .........................................40
      11.2. Message with XHTML Content ...............................42
      11.3. Chunked Message ..........................................43
      11.4. Chunked Message with Message/CPIM Payload ................43
      11.5. System Message ...........................................44
      11.6. Positive Report ..........................................44
      11.7. Forked IM ................................................45
   12. Extensibility .................................................48
   13. CPIM Compatibility ............................................48
   14. Security Considerations .......................................49
      14.1. Secrecy of the MSRP URI ..................................50
      14.2. Transport Level Protection ...............................50
      14.3. S/MIME ...................................................51
      14.4. Using TLS in Peer-to-Peer Mode ...........................52
      14.5. Other Security Concerns ..................................53
   15. IANA Considerations ...........................................55
      15.1. MSRP Method Names ........................................55
      15.2. MSRP Header Fields .......................................55
      15.3. MSRP Status Codes ........................................56
      15.4. MSRP Port ................................................56
      15.5. URI Schema ...............................................56
           15.5.1. MSRP Scheme .......................................56
           15.5.2. MSRPS Scheme ......................................57
      15.6. SDP Transport Protocol ...................................57
      15.7. SDP Attribute Names ......................................58
           15.7.1. Accept Types ......................................58
           15.7.2. Wrapped Types .....................................58
           15.7.3. Max Size ..........................................58
           15.7.4. Path ..............................................58
   16. Contributors and Acknowledgments ..............................59
   17. References ....................................................59
      17.1. Normative References .....................................59
      17.2. Informative References ...................................60

1. Introduction โœจ

Okay so a series of related instant messages between two or more people can be seen as a "message session" ๐Ÿ’ฌ. It's a conversation with a definite beginning and end, which is different from individual messages that each get sent on their own. Messaging that only keeps track of single messages is called "page-mode" messaging, and messaging that's part of a "session" with a clear start and finish is called "session-mode" messaging ๐ŸŽ€.

SIP already does page-mode messaging through the SIP [4] MESSAGE method [22] ๐Ÿ“จ. Session-mode messaging has a bunch of perks though, like explicit rendezvous, tighter integration with other media types, direct client-to-client operation, and brokered privacy and security ๐Ÿ”. It's giving main character energy ๐Ÿ’….

This document defines a session-oriented instant message transport protocol called the Message Session Relay Protocol (MSRP) ๐Ÿฆ‹. Its sessions can be negotiated with an offer or answer [3] using the Session Description Protocol (SDP) [2], and the exchange is carried by some signaling protocol, such as SIP [4]. That means a communication user agent can offer a messaging session as one of the possible media types in a session ๐Ÿงš.

Here's an example. Alice wants to talk to Bob, but she doesn't know if he has his phone or his IM client handy, and she's happy to use either ๐Ÿ™ˆ. She sends an invitation to the address of record she has for Bob, sip:bob@example.com. Her invitation offers both voice and an IM session ๐Ÿ“ž. The SIP services at example.com forward the invite to Bob's currently registered clients. Bob accepts it on his IM client, and they start a threaded chat conversation ๐Ÿ’œ.

When a user uses an Instant Messaging (IM) URL, RFC 3861 [32] defines how DNS can be used to map that to a particular protocol that establishes the session, such as SIP ๐Ÿ—บ๏ธ. SIP can use an offer/answer model to carry the MSRP URIs for the media in SDP. This document defines how the offer/answer exchange works to set up MSRP connections and how messages get sent across MSRP. It doesn't cover mapping an IM URL to a session establishment protocol, though ๐Ÿ™ƒ.

This session model lets message sessions plug into advanced communications apps with little to no extra protocol development ๐ŸŒธ. For example, during that chat, Bob decides Alice really needs to be talking to Carol ๐Ÿ‘€. Bob can transfer [21] Alice to Carol, which introduces them into their own messaging session. Message sessions can then slot right into call-center and dispatch setups using third-party call control [20] and conferencing [19] apps ๐Ÿ“žโœจ.

This document only specifies MSRP behavior for peer-to-peer sessions, meaning sessions that cross just a single hop. MSRP relay devices [23] (called "relays" in this doc) are specified in a separate document ๐Ÿšง.

An endpoint that implements this specification but not the relay specification won't be able to put relays into the message path. It can still interoperate with peers that do use relays ๐Ÿซถ.

2. Conventions ๐Ÿ“

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] ๐Ÿ”‘.

This document consistently refers to a "message" as a complete unit of MIME or text content ๐Ÿ’–. Sometimes a message gets split up and delivered in more than one MSRP request. Each of those portions of the complete message is called a "chunk" ๐Ÿ“.


Part 1 of 13 is done, bestie! ๐Ÿงš๐Ÿ’– Part 2 is coming next, so stay tuned ๐Ÿ’…โœจ

3. Applicability of MSRP โœจ

okay so MSRP is NOT a standalone protocol, bestie ๐Ÿ˜ญ it can't just vibe solo. It MUST be used only in the context of a rendezvous mechanism that meets the following requirements:

  • The rendezvous mechanism MUST provide both MSRP URIs associated with an MSRP session to each of the participating endpoints. The rendezvous mechanism MUST implement mechanisms to protect the confidentiality of these URIs -- they MUST NOT be made available to an untrusted third party or be easily discoverable. ๐Ÿ”’
  • The rendezvous mechanism MUST provide mechanisms for the negotiation of any supported MSRP extensions that are not backwards compatible. ๐Ÿงฉ
  • The rendezvous mechanism MUST be able to natively transport im: URIs or automatically translate im: URIs [27] into the addressing identifiers of the rendezvous protocol. ๐ŸŽ€

If you wanna use a rendezvous mechanism with MSRP, an RFC MUST be prepared that describes how it swaps MSRP URIs and meets these requirements. The good news? This document already does that for the use of MSRP with SIP and SDP ๐Ÿ’–

SIP meets these requirements for a rendezvous mechanism. The MSRP URIs are exchanged using SDP in an offer/answer exchange via SIP. It's giving very organized energy ๐Ÿ’…

The exchanged SDP can also be used to negotiate MSRP extensions. This SDP can be secured using any of the mechanisms available in SIP, including using the sips mechanism to ensure transport security across intermediaries and Secure/Multipurpose Internet Mail Extensions (S/MIME) for end-to-end protection of the SDP body. SIP can carry arbitrary URIs (including im: URIs) in the Request-URI, and procedures are available to map im: URIs to sip: or sips: URIs. It is expected that initial deployments of MSRP will use SIP as its rendezvous mechanism. SIP is basically the main character here ๐Ÿ‘‘


4. Protocol Overview

okay so MSRP is a text-based, connection-oriented protocol for exchanging arbitrary (binary) MIME [8] content, especially instant messages ๐Ÿ’ฌ this section is a non-normative overview of how it works and how it gets used with SIP. Think of it as the friend who explains the whole plot before the movie starts ๐Ÿฟ

MSRP sessions are usually set up with SIP the same way you'd set up a session of audio or video media ๐ŸŽง one SIP user agent (Alice) sends the other (Bob) a SIP invitation with an offered session-description that includes a session of MSRP. The receiving SIP user agent can accept the invitation and include an answer session-description that acknowledges the choice of media. Alice's session description has an MSRP URI that says where she's willing to receive MSRP requests from Bob, and vice versa. (Note: Some lines in the examples are removed for clarity and brevity.) โœ‚๏ธ

Alice sends to Bob:

INVITE sip:bob@biloxi.example.com SIP/2.0
To: <sip:bob@biloxi.example.com>
From: <sip:alice@atlanta.example.com>;tag=786
Call-ID: 3413an89KU
Content-Type: application/sdp

c=IN IP4 atlanta.example.com
m=message 7654 TCP/MSRP *
a=accept-types:text/plain
a=path:msrp://atlanta.example.com:7654/jshA7weztas;tcp

Bob sends to Alice:

SIP/2.0 200 OK
To: <sip:bob@biloxi.example.com>;tag=087js
From: <sip:alice@atlanta.example.com>;tag=786
Call-ID: 3413an89KU
Content-Type: application/sdp

c=IN IP4 biloxi.example.com
m=message 12763 TCP/MSRP *
a=accept-types:text/plain
a=path:msrp://biloxi.example.com:12763/kjhd37s2s20w2a;tcp

Alice sends to Bob:

ACK sip:bob@biloxi SIP/2.0
To: <sip:bob@biloxi.example.com>;tag=087js
From: <sip:alice@atlanta.example.com>;tag=786
Call-ID: 3413an89KU

Figure 1: Session Setup

MSRP has two request types, aka methods ๐Ÿง SEND requests deliver a complete message or a chunk (a portion of a complete message), and REPORT requests report on the status of a previously sent message, or a range of bytes inside a message. When Alice gets Bob's answer, she checks whether she already has a connection to Bob. If not, she opens a new one using the URI he gave her in the SDP. Then she sends Bob a SEND request with her first message, and Bob replies to say it came through successfully ๐Ÿฅฐ

Alice sends to Bob:

MSRP a786hjs2 SEND
To-Path: msrp://biloxi.example.com:12763/kjhd37s2s20w2a;tcp
From-Path: msrp://atlanta.example.com:7654/jshA7weztas;tcp
Message-ID: 87652491
Byte-Range: 1-25/25
Content-Type: text/plain

Hey Bob, are you there?
-------a786hjs2$

Bob sends to Alice:

MSRP a786hjs2 200 OK
To-Path: msrp://atlanta.example.com:7654/jshA7weztas;tcp
From-Path: msrp://biloxi.example.com:12763/kjhd37s2s20w2a;tcp
-------a786hjs2$

Figure 2: Example MSRP Exchange

Alice's request starts with the MSRP start line, which has a transaction identifier that also does the request framing. Next she puts the path of URIs to the destination in the To-Path header field, and her own URI in the From-Path header field. In this typical case there's just one "hop", so there's only one URI in each path header field. ๐Ÿ›ค๏ธ She also adds a message ID, which she can use to match status reports with the original message. Then comes the actual content. Last, she closes the request with an end-line of seven hyphens, the transaction identifier, and a "$" to show this request has the end of a complete message. Iconic closing move ๐Ÿซถ

If Alice wants to send a really big message, she can split it into chunks and send each chunk in its own SEND request. The message ID is for the whole message, so the receiver can use it to put the pieces back together and tell which chunks belong to which message. Chunking is explained in more detail in Section 5.1. The Byte-Range header field tells you which part of the message is in this chunk and how big the whole message is ๐Ÿ“ฆ

Alice can also pick what kind of reporting she wants for her request. If Alice requests positive acknowledgments, Bob sends a REPORT request to Alice confirming delivery of her complete message. This is especially handy if Alice sent a bunch of SEND requests with chunks of one message. More on requesting types of reports and errors is in Section 5.3. ๐Ÿ“

Alice and Bob pick their MSRP URIs so the exact URI is hard to guess ๐Ÿ•ต๏ธโ€โ™€๏ธ Alice and Bob can reject requests to URIs they aren't expecting to serve, and they can match the specific URI with the likely sender. Alice and Bob can also use TLS [1] to protect the channel over this hop. To receive MSRP requests over a TLS protected connection, Alice or Bob could advertise URIs with the "msrps" scheme instead of "msrp". security glow-up unlocked ๐Ÿ”โœจ

MSRP is designed with the expectation that it can carry URIs for nodes on the far side of relays. Because of that, a URI with the "msrps" scheme makes no claim about the security properties of other hops, just the next hop. The user agent knows the URI for each hop, so it can check that each URI has the security properties it wants. ๐Ÿง

MSRP URIs get the full breakdown in Section 6.

An adjacent pair of busy MSRP nodes (for example, two relays) can easily have several sessions and carry traffic for several users at once ๐Ÿšฆ The nodes can reuse existing connections to carry new traffic with the same destination host, port, transport protocol, and scheme. MSRP nodes can keep track of how many sessions are using a connection, and close it when no sessions have used it for a while. Connection management is covered in more detail in Section 5.4. ๐Ÿงน


5. Key Concepts

5.1. MSRP Framing and Message Chunking

okay so MSRP messages can be HUGE ๐Ÿ˜ and they can be delivered across several SEND requests, where each SEND request carries one chunk of the whole message. Long chunks may get interrupted mid-transmission so everyone sharing a transport connection gets a fair turn ๐Ÿค To make this work, MSRP uses a boundary-based framing mechanism. The start line of an MSRP request has a unique identifier that's also used to mark the end of the request. At the end of the end-line there's a flag that says whether this is the last chunk for the message or whether more chunks are coming in a later one. There's also a Byte-Range header field in the request that shows where this chunk sits inside the complete message ๐Ÿ—บ๏ธ

For example, this little snippet of two SEND requests shows a message with the text "abcdEFGH" sent as two chunks:

 MSRP dkei38sd SEND
 Message-ID: 4564dpWd
 Byte-Range: 1-*/8
 Content-Type: text/plain

 abcd
 -------dkei38sd+

 MSRP dkei38ia SEND
 Message-ID: 4564dpWd
 Byte-Range: 5-8/8
 Content-Type: text/plain

 EFGH
 -------dkei38ia$

Figure 3: Breaking a Message into Chunks

This chunking lets a sender pause a chunk partway through sending it. Being able to interrupt messages is what lets several sessions share one TCP connection, and lets big messages go out efficiently without blocking other messages on the same connection, or even other messages in the same MSRP session. Any chunk that is larger than 2048 octets MUST be interruptible. โšก Sure, MSRP would be simpler to build if every MSRP session had its own TCP connection, but there are big reasons to save connections. For example, the TCP peer might be a relay device that talks to lots of other peers. That kind of device scales way better if each peer doesn't make a ton of connections ๐Ÿ“‰ (Note that in the example above, the first chunk was interruptible just for the sake of the example, even though it's way under the size limit where interruptibility is required.)

The chunking mechanism only applies to the SEND method, since it's the only method used to transfer message content. ๐Ÿ“จ

5.2. MSRP Addressing

MSRP entities are addressed using URIs. The MSRP URI schemes are defined in Section 6. The syntax of the To-Path and From-Path header fields each allows for a list of URIs. This was done so the protocol can work with relays, which are defined in a separate document, to give a complete path to the end recipient ๐Ÿงญ When two MSRP nodes talk directly, they only need one URI in the To-Path list and one URI in the From-Path list. Simple, clean, no drama ๐ŸŒธ

5.3. MSRP Transaction and Report Model โœจ

okay so a sender sends MSRP requests to a receiver, and the receiver MUST quickly accept or reject the request ๐Ÿ’… but here's the lowkey tea: if it initially accepted, it still may then do stuff that takes significant time to succeed or fail ๐Ÿ˜ญ like, if the receiver is an MSRP to Extensible Messaging and Presence Protocol (XMPP) [30] gateway, it may forward the message over XMPP. then the XMPP side may later go "nope, that didn't work" ๐Ÿ’€ and at that point the MSRP receiver may need to indicate that the request did not succeed.

there are two important concepts here, bestie ๐Ÿซถ first, the hop-by-hop delivery of the request may succeed or fail. second, the end result of the request may or may not be successfully processed. the first kind of status is called "transaction status" and may be returned in response to a request. the second kind is called "delivery status" and may be returned in a REPORT transaction. keeping them separate is literally main character energy ๐Ÿ‘‘

the original sender of a request can say whether they want reports for requests that fail, and can independently say whether they want reports for requests that succeed ๐ŸŽ€ a receiver only sends a success REPORT if it knows that the request was successfully delivered and the sender requested a success report. a receiver only sends a failure REPORT if the request failed to be delivered and the sender requested failure reports.

๐Ÿ“ This document describes the behavior of MSRP endpoints. MSRP relays will introduce additional conditions that indicate a failure REPORT should be sent, such as the failure to receive a positive response from the next hop.

two header fields control the sender's desire to receive reports ๐Ÿฆ‹ the Success-Report header field can have a value of "yes" or "no", and the Failure-Report header field can have a value of "yes", "no", or "partial".

the combinations of reporting exist to meet the different scenarios of IM systems that are actually out there right now ๐ŸŒˆ Success-Report might be "no" in many public systems to reduce load, but might be "yes" in certain enterprise systems, like ones used for securities trading ๐Ÿ“ˆ a Failure-Report value of "no" is useful for system messages like "the system is going down in 5 minutes" without causing a response explosion to the sender ๐Ÿ™ˆ a Failure-Report of "yes" is used by lots of systems that want to notify the user if the message failed ๐Ÿ’Œ and a Failure-Report of "partial" is a way to report errors other than timeouts โœจ timeout error reporting requires the sending hop to run a timer and the receiving hop to send an acknowledgment to stop the timer. some systems don't want that overhead, so "partial" lets them skip it but still allows error responses to be sent in many cases ๐Ÿ“

๐Ÿ“ The term "partial" denotes that the hop-by-hop acknowledgment mechanism that would be required with a Failure-Report value of "yes" is not invoked. Thus, each device uses only "part" of the set of error detection tools available to them. This allows a compromise between no reporting of failures at all, and reporting every possible failure. For example, with "partial", a sending device does not have to keep transaction state around waiting for a positive acknowledgment. But it still allows devices to report other types of errors. The receiving device could still report a policy violation such as an unacceptable content-type, or an ICMP error trying to connect to a downstream device.

5.4. MSRP Connection Model ๐Ÿ”Œ

when an MSRP endpoint wants to send a request to a peer identified by an MSRP URI, it first needs a transport connection, with the appropriate security properties, to the host specified in the URI ๐Ÿงš if the sender already has such a connection, meaning one associated with the same host, port, and URI scheme, then it SHOULD reuse that connection โ™ป๏ธ

when a new MSRP session is created, the initiating endpoint MUST act as the "active" endpoint, meaning it's responsible for opening the transport connection to the answerer, if a new connection is required ๐Ÿ’ช however, this requirement MAY be weakened if standardized mechanisms for negotiating the connection direction become available and are implemented by both parties to the connection.

likewise, the active endpoint MUST immediately issue a SEND request ๐Ÿš€ this initial SEND request MAY have a body if the sender has content to send, or it MAY have no body at all.

๐Ÿ“ The first SEND request serves to bind a connection to an MSRP session from the perspective of the passive endpoint. If the connection is not authenticated with TLS, and the active endpoint did not send an immediate request, the passive endpoint would have no way to determine who had connected, and would not be able to safely send any requests towards the active party until after the active party sends its first request.

when an element needs to form a new connection, it looks at the URI to decide on the type of connection (TLS, TCP, etc.), then connects to the host indicated by the URI, following the URI resolution rules in Section 6.2 ๐Ÿ—บ๏ธ connections using the msrps scheme MUST use TLS ๐Ÿ” the SubjectAltName in the received certificate MUST match the hostname part of the URI, and the certificate MUST be valid according to RFC 3280 [16], including having a date that is valid and being signed by an acceptable certification authority. at that point, the device that initiated the connection can assume that this connection is with the correct host ๐ŸŽฏ

the rules on certificate name matching and CA signing MAY be relaxed when using TLS peer-to-peer ๐Ÿค in this case, a mechanism to ensure that the peer used a correct certificate MUST be used. see Section 14.4 for details.

if the connection used mutual TLS authentication, and the TLS client presented a valid certificate, then the element accepting the connection can verify the identity of the connecting device by comparing the hostname part of the target URI in the SDP provided by the peer device against the SubjectAltName in the client certificate ๐Ÿชช

when mutual TLS authentication is not used, the listening device MUST wait until it receives a request on the connection, at which point it infers the identity of the connecting device from the associated session description ๐Ÿ‘€

when the first request arrives, its To-Path header field should contain a URI that the listening element provided in the SDP for a session. the element that accepted the connection looks up the URI in the received request and determines which session it matches ๐Ÿ” if a match exists, the node MUST assume that the host that formed the connection is the host to which this URI was given. if no match exists, the node MUST reject the request with a 481 response. the node MUST also check to make sure the session is not already in use on another connection. if the session is already in use, it MUST reject the request with a 506 response. ๐Ÿšซ

๐Ÿ“ If it were legal to have multiple connections associated with the same session, a security problem would exist. If the initial SEND request is not protected, an eavesdropper might learn the URI, and use it to insert messages into the session via a different connection. ๐Ÿ˜ฑ this is serious, so keep your sessions locked down!

if a connection fails for any reason, then an MSRP endpoint MUST consider any sessions associated with the connection as also having failed ๐Ÿ’” when either endpoint notices such a failure, it MAY attempt to re-create any such sessions. if it chooses to do so, it MUST use a new SDP exchange, for example in a SIP re-INVITE ๐Ÿ”„ if a replacement session is successfully created, endpoints MAY attempt to resend any content for which delivery on the original session could not be confirmed. if it does this, the Message-ID values for the resent messages MUST match those used in the initial attempts. if the receiving endpoint receives more than one message with the same Message-ID, it SHOULD assume that the messages are duplicates ๐Ÿ‘ฏ the specific action an endpoint takes when it receives a duplicate message is a matter of local policy, except that it SHOULD NOT present the duplicate messages to the user without warning of the duplication. note that acknowledgments, as needed based on the Failure-Report and Success-Report settings, are still necessary even for requests containing duplicate content ๐Ÿงพ

when endpoints create a new session in this fashion, the chunks for a given logical message MAY be split across the sessions. however, endpoints SHOULD NOT split chunks between sessions under non-failure circumstances ๐Ÿงฉ

if an endpoint attempts to re-create a failed session in this manner, it MUST NOT assume that the MSRP URIs in the SDP will be the same as the old ones ๐Ÿ™…โ€โ™€๏ธ

a connection SHOULD NOT be closed while there are sessions associated with it ๐Ÿซถ๐Ÿ’œ

6. MSRP URIs โœจ

okay so MSRP URIs are the "msrp" and "msrps" scheme addresses ๐Ÿฆ‹ they identify a session of instant messages at a specific MSRP device, and they also identify an MSRP relay in general. this document covers the first usage, and the relay one lives in the MSRP relay spec [23] ๐Ÿงš session URIs are super ephemeral, so each distinct session gets its own MSRP URI, and a session URI means absolutely nothing outside its own session ๐Ÿ’…

an MSRP URI follows a subset of the URI syntax in Appendix A of RFC 3986 [10], with a scheme of "msrp" or "msrps" ๐ŸŒธ the full syntax is in Section 9

MSRP URIs are mostly generated and swapped between machines, not read by humans, so they're encoded entirely in US-ASCII ๐Ÿค–

the "authority", "userinfo", and "unreserved" constructions are all detailed in RFC 3986 [10] ๐Ÿ’œ and URIs for MSRP over TCP MUST include the "tcp" transport parameter ๐Ÿ”ฅ

Since this document only specifies MSRP over TCP, all MSRP URIs herein use the "tcp" transport parameter. Documents that provide bindings on other transports should define respective parameters for those transports.

the authority field tells you which participant is in a particular MSRP session ๐Ÿ‘‘ if the authority has a numeric IP address, it MUST also have a port ๐Ÿ’– the session-id part picks out a specific session of that participant, and if it's missing, you're pointing at the MSRP host device itself, not a particular session there ๐ŸŽ€ a session-id only makes sense next to its authority, so the authority basically runs the namespace the session-id lives in. it's giving namespace energy ๐ŸŒˆ

a scheme of "msrps" means the underlying connection MUST be protected with TLS ๐Ÿ”’

MSRP has an IANA-registered recommended port, defined in Section 15.4 โญ it is not a default, because the URI negotiation process described here always includes explicit port numbers. still, URIs SHOULD be set up so the recommended port gets used whenever that makes sense, because it makes life way easier for network admins managing firewall policy for MSRP ๐Ÿ™ˆ

the authority component usually won't have a userinfo component, but it MAY have one to say which user account the session is valid for ๐Ÿง just know that's not the same thing as identifying the session itself. and a userinfo part MUST NOT contain password information ๐Ÿšซ

here's an example of a typical MSRP URI:

msrp://host.example.com:8493/asfd34;tcp

6.1. MSRP URI Comparison

okay comparing MSRP URIs is a whole thing, so in the MSRP context, the comparisons MUST be performed according to these rules ๐Ÿง

  1. the scheme MUST match. scheme comparison is case insensitive ๐ŸŒท
  2. if the authority component has an explicit IP address and/or port, those get compared for address and port equivalence. percent-encoding normalization [10] applies, so if any percent-encoded nonreserved characters show up in the authority component, they must be decoded before comparing. userinfo parts don't count at all for URI comparison ๐Ÿ™…โ€โ™€๏ธ otherwise, the authority component is compared as a case-insensitive character string ๐Ÿ“
  3. if a port exists explicitly in either URI, then it MUST match exactly. a URI with an explicit port is never equivalent to one with no port specified ๐Ÿ’…
  4. the session-id part is compared as case sensitive ๐Ÿฆ‹ and a URI without a session-id part is never equivalent to one that has one โœจ
  5. URIs with different "transport" parameters never match ๐Ÿ’€ two URIs that are identical except for transport are not equivalent, and the transport parameter itself is case insensitive ๐Ÿซถ

path normalization [10] is not relevant for MSRP URIs, so you can skip that step entirely ๐ŸŒธ


6.2. Resolving MSRP Host Device

an MSRP host device is identified by the authority component of an MSRP URI ๐ŸŽ€

if the authority component has a numeric IP address and port, those MUST be used as listed ๐Ÿ”ฅ

if the authority component has a host name and a port, the connecting device MUST work out a host address by doing an A or AAAA DNS query, and it uses the port as listed ๐Ÿ’œ

if a connection attempt fails, the device SHOULD try the addresses returned in any additional A or AAAA records, in the order the records were presented ๐Ÿงš

This process assumes the connection port is always known before resolution. That's always true for the MSRP URI uses described in this document, which means URIs exchanged in the SDP offer and answer. Relays are where things get messy, since they make it so that's not always the case. For example, when a user sets up her client to use a relay, it's desirable for the relay's MSRP URI to be easy to remember and pass along to humans, and that URI often leaves out the port number. So the relay specification [23] describes extra steps for resolving the port number ๐ŸŒˆ

MSRP devices MAY use other methods for discovering other such devices, when that's appropriate ๐Ÿฆ‹ for instance, MSRP endpoints may use other mechanisms to discover relays, but those are beyond the scope of this document โœจ


7. Method-Specific Behavior ๐Ÿ’–

7.1. Constructing Requests

okay so to form a new request, the sender makes a transaction identifier and uses that plus the method name to build an MSRP request start line ๐ŸŽ€ the transaction identifier MUST NOT collide with other transactions that exist at the same time, so it MUST contain at least 64 bits of randomness. no cap, that's a lot of randomness ๐Ÿ”ฅ

next, the sender puts the target path in a To-Path header field, and its own URI in a From-Path header field ๐Ÿ’… if there are multiple URIs in the To-Path, the leftmost one is the first URI visited, and the rightmost one is the last URI visited ๐Ÿงš then processing becomes method specific, and any extra method-specific header fields get added as described in the following sections ๐ŸŒธ

after any method-specific header fields are added, processing moves on to handling a body, if there is one ๐Ÿ“ if the request has a body, it MUST contain a Content-Type header field. it may have other MIME-specific header fields too. the Content-Type header field MUST be the last field in the message header section ๐Ÿ’œ and the body MUST be separated from the header fields with an extra CRLF ๐Ÿซถ

non-SEND requests aren't meant to carry message content, so they're not interruptible ๐Ÿ™ˆ non-SEND request bodies MUST NOT be larger than 10240 octets ๐Ÿ›‘

Although this document doesn't discuss any particular use of bodies in non-SEND requests, they might be useful later for carrying security or identity information, information about a message in progress, and so on. The 10K size limit was picked to be big enough for most of those applications, but small enough to avoid the fairness issues that come from sending arbitrarily large content in non-interruptible method bodies ๐ŸŒˆ

a request with no body MUST NOT include a Content-Type or any other MIME-specific header fields ๐Ÿ™…โ€โ™€๏ธ and a request without a body MUST contain an end-line after the final header field. there's no extra CRLF between the header section and the end-line in that case โœจ

Requests with no bodies are useful when a client wants to send "traffic" but doesn't want to send content to be rendered to the peer user. For example, the active endpoint sends a SEND request right after a connection is established. If it has nothing to say at the moment, it can send a request with no body. Bodiless requests may also be used in certain applications to keep Network Address Translation (NAT) bindings alive, and so on ๐Ÿฆ‹ Bodiless requests are different from requests with empty bodies. A request with an empty body will have a Content-Type header field value and will generally be rendered to the recipient according to the rules for that type ๐Ÿ’€

the end-line that terminates the request MUST be made up of seven "-" (minus sign) characters, the transaction ID as used in the start line, and a flag character ๐Ÿง if a body is present, the end-line MUST be preceded by a CRLF that is not part of the body ๐Ÿ’– if the chunk holds the data that forms the end of the complete message, the flag value MUST be a "$" ๐Ÿ if the sender is aborting an incomplete message and doesn't plan to send any more chunks in it, the flag MUST be a "#" ๐Ÿ›‘ otherwise, the flag MUST be a "+" ๐ŸŒธ

if the request has a body, the sender MUST make sure the end-line (seven hyphens, the transaction identifier, and a continuation flag) is not present in the body ๐Ÿ” if the end-line does show up in the body, the sender MUST choose a new transaction identifier that's not present in the body, add a CRLF if needed, and then the end-line, including the "$", "#", or "+" character ๐Ÿซถ

some implementations might scan for the closing sequence as they send the body, and if they hit it, they just interrupt the chunk right there and start a new transaction with a different transaction identifier to carry the rest of the body โœจ other implementations might scan the data first and make sure the body doesn't contain the transaction identifier before they start sending the transaction ๐ŸŽ€

once a request is ready for delivery, the sender follows the connection management (Section 5.4) rules to forward the request over an existing open connection or to create a new connection ๐Ÿฆ‹๐Ÿ‘‘

7.1.1. Sending SEND Requests โœจ

Okay so when an endpoint has a message to deliver ๐Ÿ’Œ, the very first thing it does is generate a brand new Message-ID. The value MUST be highly unlikely to be repeated by another endpoint instance, or by the same instance in the future. If the message is big, the endpoint chops it into chunks ๐Ÿ”ช, then makes a SEND request for each chunk, following the procedures for constructing requests (Section 7.1).

The Message-ID header field is a unique ID for one particular version of one particular message ๐Ÿ†”. "Message" here just means the stuff the sender wants to convey to the recipient. Even if that message gets broken into chunks, the Message-ID refers to the entire message, not a single chunk.

The uniqueness is guaranteed by whichever host generates the ID ๐Ÿ”. It's meant for machines to read, not really for humans to make sense of. Each message ID belongs to exactly one version of a message, so if the message gets revised, the revision gets a fresh ID. Endpoints can make sure their IDs are unique in lots of ways, and picking the method is an implementation choice ๐Ÿ› ๏ธ. For example, an endpoint could smush together an instance identifier like a MAC address, its idea of the number of seconds since the epoch, a process ID, and a monotonically increasing 16-bit integer, then base-64 encode the whole thing ๐Ÿง. Or, if an endpoint doesn't have an on-board clock, it could just use a 64-bit random number ๐ŸŽฒ.

Each chunk of a message MUST contain a Message-ID header field containing the Message-ID ๐Ÿท๏ธ. If the sender wants status reporting that isn't the default, it MUST insert a Failure-Report and/or Success-Report header field with an appropriate value ๐Ÿ“ฃ. All chunks of the same message MUST use the same Failure-Report and Success-Report values in their SEND requests, no mixing and matching ๐Ÿ™…โ€โ™€๏ธ.

If success reports are requested (so the Success-Report header field is "yes"), the sending device MAY wish to run a timer of some value that makes sense for its application, and take action if a success report doesn't show up in that time โฑ๏ธ. There's no universal value for this timer. For lots of IM apps it might be 2 minutes, while for some trading systems it could be under a second ๐Ÿ“ˆ. Whether or not a timer gets used, if the success report hasn't arrived by the time the session ends, the device SHOULD inform the user ๐Ÿ‘€.

If the Failure-Report value is "yes", the sender of the request runs a timer โณ. If a 200 response to the transaction isn't received within 30 seconds from the time the last byte of the transaction is sent, or submitted to the operating system for sending, the element MUST inform the user that the request probably failed ๐Ÿ˜ฌ. If the value is "partial", the element sending the transaction doesn't have to run a timer, but it MUST inform the user if it receives a non-recoverable error response to the transaction ๐Ÿšจ. No matter what the Failure-Report value is, there's no requirement to wait for a response before sending the next request ๐Ÿƒโ€โ™€๏ธ.

The timers for success reports and failure reports are intentionally inconsistent, and that's on purpose ๐Ÿง . An explicit timeout makes sense for failure reports, since they usually point at a message "chunk" that gets acknowledged on a hop-by-hop basis. Success reports are different. They're end-to-end and might refer to the entire message content, which can be arbitrarily large ๐Ÿ˜.

If no Success-Report header field is present in a SEND request, it MUST be treated the same as a Success-Report header field with a value of "no" ๐Ÿ™…. If no Failure-Report header field is present, it MUST be treated the same as a Failure-Report header field with a value of "yes" โœ…. If an MSRP endpoint receives a REPORT for a Message-ID it doesn't recognize, it SHOULD silently ignore the REPORT ๐Ÿคซ.

The Byte-Range header field value has a starting value (range-start), followed by a "-", then an ending value (range-end), followed by a "/", and finally the total length ๐Ÿ“. The first octet in the message has a position of one, not zero, so no starting from 0 here, bestie ๐Ÿ™…โ€โ™€๏ธ.

The first chunk of the message SHOULD include a Byte-Range header field, and all subsequent chunks MUST include one ๐Ÿงฉ. The range-start field MUST indicate the position of the first byte in the body within the overall message (for the first chunk this field will have a value of one) ๐ŸŽฏ. The range-end field SHOULD indicate the position of the last byte in the body, if it's known ๐Ÿ”š. It MUST take the value of "*" if the position is unknown, or if the request needs to be interruptible โธ๏ธ. The total field SHOULD contain the total size of the message, if known ๐Ÿงฎ. The total field MAY contain a "*" if the total size of the message isn't known in advance ๐Ÿคทโ€โ™€๏ธ. The sender MUST send all chunks in Byte-Range order ๐Ÿ“ฆ. (However, the receiver can't assume the requests will be delivered in order, because intervening relays may have changed the order ๐Ÿ”€.)

Sometimes an endpoint might choose to send an empty SEND request ๐Ÿซ™. For the sake of consistency, a Byte-Range header field referring to nonexistent or zero-length content MUST still have a range-start value of 1. For example, 1-0/0 ๐ŸŒธ.

Now the fairness part ๐Ÿซง. To keep things fair over a connection, senders MUST NOT send chunks with a body larger than 2048 octets unless they're prepared to interrupt them. That means any chunk with a body bigger than 2048 octets will have a "*" character in the range-end field. A sender can satisfy this in one of two ways ๐Ÿ› ๏ธ. The sender is STRONGLY RECOMMENDED to send messages larger than 2048 octets using as few chunks as possible, and to interrupt chunks (which are at least 2048 octets long) only when other traffic is waiting to use the same connection ๐Ÿšฆ. Or, the sender MAY simply send chunks in 2048-octet increments until the final chunk ๐Ÿงฑ. Heads up: the first strategy is way more efficient use of the connection, so it's the one to go for ๐Ÿ’…. All MSRP nodes MUST be able to receive chunks of any size, from zero octets up to the maximum number of octets they can receive for a complete message ๐Ÿ“ฅ. Senders SHOULD NOT break messages into chunks smaller than 2048 octets, except for the final chunk of a complete message ๐Ÿ™.

A SEND request gets interrupted while its body is being written to the connection. The sender just notes how much of the message has already been written, then writes out the end-line to end the chunk โœ‚๏ธ. It can be resumed in another chunk with the same Message-ID and a Byte-Range header field whose range-start contains the position of the first byte after the interruption ๐Ÿ”.

SEND requests larger than 2048 octets MUST be interrupted if the sender needs to send pending responses or REPORT requests ๐Ÿšจ. If multiple SEND requests from different sessions are being sent over the same connection at the same time, the device SHOULD implement some scheme to alternate between them, so each concurrent request gets a fair portion of data at regular intervals that suit the application ๐ŸŽ .

The sender MUST NOT assume that the peer received a message with the same chunk allocation it was sent with ๐Ÿซ . An intervening relay could break SEND requests into smaller chunks, or combine multiple chunks into bigger ones, so chunk sizes can change in transit ๐ŸŽญ.

The default disposition of messages is to be rendered to the user ๐Ÿ–ผ๏ธ. If the sender wants a different disposition, it MAY insert a Content-Disposition [9] header field ๐ŸŽ€. Values MAY include any from RFC 2183 [9] or the IANA registry it defines ๐Ÿ“‹. MSRP can carry unencoded binary payloads, so transfer encoding is always "binary", and transfer-encoding parameters MUST NOT be present ๐Ÿ”ข.


7.1.2. Sending REPORT Requests ๐Ÿ“ฌ

REPORT requests are basically SEND requests' chill sibling ๐Ÿฆ‹, but with a few differences. REPORT requests MUST NOT include Success-Report or Failure-Report header fields, and they MUST contain a Status header field ๐Ÿท๏ธ. REPORT requests MUST contain the Message-ID header field from the original SEND request ๐Ÿ”—.

If an MSRP element receives a REPORT for a Message-ID it doesn't recognize, it SHOULD silently ignore the REPORT ๐Ÿ™ˆ.

An MSRP endpoint MUST be able to generate success REPORT requests ๐ŸŽ‰.

REPORT requests will normally not include a body, since the REPORT request header fields can carry enough info in most cases ๐Ÿงพ. However, REPORT requests MAY include a body with additional info about the status of the associated SEND request ๐Ÿ“. That body is informational only, and the sender of the REPORT request SHOULD NOT assume the recipient pays any attention to it ๐Ÿ˜…. REPORT requests are not interruptible ๐Ÿšซ.

Success-Report and Failure-Report header fields MUST NOT be present in REPORT requests ๐Ÿ™…โ€โ™€๏ธ. MSRP nodes MUST NOT send REPORT requests in response to REPORT requests ๐Ÿ”๐Ÿšซ. MSRP nodes MUST NOT send MSRP responses to REPORT requests ๐Ÿ’€. Keep the report drama to a minimum, periodt ๐Ÿ’….

Endpoints SHOULD NOT send REPORT requests if they have reason to believe the request won't be delivered ๐Ÿ“ญ. For example, they SHOULD NOT send a REPORT request for a session that's no longer valid ๐Ÿšชโœจ.

7.1.3. Generating Success Reports ๐Ÿ’–

Okay so, when an endpoint gets a message in one or more chunks and the Success-Report value is "yes", it MUST send a success report (or reports) covering all the bytes it received successfully ๐Ÿซถ. These go out as REPORT requests, following the normal procedures in Section 7.1, with a few extra rules on top โœจ.

The receiver MAY wait until it gets the last chunk of a message, then send one success report that covers the whole thing ๐ŸŽ€. Alternately, it MAY send incremental success REPORTs as the chunks come in. These can go out periodically and cover every byte received so far, or they can go out after a chunk arrives and cover just the part from that chunk ๐Ÿฆ‹.

It's helpful to think of a success REPORT as reporting on a particular range of bytes, not on a particular chunk the client sent ๐Ÿ’…. The sending client can't count on the Byte-Range header field in a success report matching one of its SEND requests. For example, an intervening MSRP relay might break chunks into smaller chunks, or glue multiple chunks into bigger ones. Because of that, even when no relay is used, the receiving client might report on byte ranges that don't exactly match the original chunks the sender sent ๐Ÿ™ˆ. It can wait until every byte in a message is in and report on the whole thing, it can report as each chunk lands, or it can report on any other received range. Reporting on ranges smaller than the entire message gives the sender some nice experiences, like showing incremental status of which byte ranges the receiver has acknowledged ๐Ÿ“ˆ. But whether to report incrementally is totally up to the receiving client ๐Ÿ‘‘. There is no mechanism for the sender to ask for incremental reports or to ask for none, and honestly that kind of mechanism would be of questionable value, since a relay can make the receiver see a very different chunk allocation than the sender did ๐Ÿ’€.

When generating a REPORT request, the endpoint inserts a To-Path header field containing the From-Path value from the original request ๐Ÿงš. It also inserts a From-Path header field containing the URI that identifies itself in the session. Then it inserts a Status header field with a namespace of 000, a status-code of 200, and an implementation-defined comment phrase โœจ. Last but not least, it inserts a Message-ID header field containing the value from the original request ๐ŸŒธ.

The namespace field tells you the context of the status-code field. A namespace value of 000 means the status-code should be read the same way as the matching MSRP transaction response code ๐Ÿ“. If a future specification ever uses the status-code field for some other purpose, it MUST define a new namespace field value. Iconic behavior, honestly ๐Ÿ‘‘.

The endpoint MUST NOT send a success report for a SEND request that either had no Success-Report header field or had one with a value of "no" ๐Ÿ™…โ€โ™€๏ธ. And yes, if there's no Success-Report header field at all, it gets treated exactly the same as a value of "no" ๐Ÿ’œ.

7.1.4. Generating Failure Reports ๐ŸŒˆ

So if an MSRP endpoint gets a SEND request it can't process for some reason, and the Failure-Report header field was either missing from the original request or set to "yes", it SHOULD just put the right error code in the transaction response ๐Ÿ’…. BUT, there might be situations where the error can't be figured out quickly, like when the endpoint is a gateway waiting on a downstream network to report an error โณ. In that case, it MAY send a 200 OK response to the request and then send a failure REPORT request once the error is detected ๐Ÿฆ‹.

If the endpoint gets a SEND request with a Failure-Report value of "no", then it MUST NOT send a failure REPORT request, and it MUST NOT send a transaction response ๐Ÿšซ. If the value is "partial", it MUST NOT send a 200 transaction response to the request, but it SHOULD send an appropriate non-200 class response if a failure happens ๐Ÿซ .

As mentioned above, if no Failure-Report header field is present, it MUST be treated the same as a Failure-Report header field with a value of "yes" ๐Ÿ’–.

Building a failure REPORT request is basically identical to building a success REPORT request, except the Status header field's code field MUST contain the appropriate error code โŒ. Any error response code defined in this specification MAY also be used in failure reports ๐ŸŽ€.

If a failure REPORT request gets sent in response to a SEND request that contained a chunk, it MUST include a Byte-Range header field that shows the actual range being reported on ๐Ÿ“. It can take the range-start and total values from the original SEND request, but it MUST calculate the range-end field from the actual body data ๐Ÿงฎ.

This section only describes failure report generation for MSRP endpoints. Relay behavior is out of scope for this document and will be handled in a separate document [23] ๐Ÿ‘€. We expect failure reports to be generated by relays more often than by endpoints, so that's one to watch ๐Ÿ”ฅ.

7.2. Constructing Responses ๐ŸŽ€

If an MSRP endpoint gets a request that either has a Failure-Report value of "yes" or has no Failure-Report header field at all, it MUST immediately generate a response ๐Ÿƒโ€โ™€๏ธ. Likewise, if an MSRP endpoint gets a request with a Failure-Report value of "partial" and the receiver can't process it, it SHOULD immediately generate a response ๐Ÿ’ซ.

To build the response, the endpoint first creates the response start line, putting in the appropriate response code and, optionally, a comment ๐Ÿ“. The transaction identifier in the response start line MUST match the transaction identifier from the original request ๐Ÿ”‘.

Then the endpoint inserts an appropriate To-Path header field. If the request that triggered the response was a SEND request, the To-Path header field is formed by copying the first (leftmost) URI in the request's From-Path header field. (Responses to SEND requests only go back to the previous hop, so no full trip back for them ๐Ÿงš.) For responses to all other request methods, the To-Path header field has the full path back to the original sender ๐Ÿ›ค๏ธ. That full path comes from copying the list of URIs in the original request's From-Path into the response's To-Path. (Legal REPORT requests don't request responses, so this spec doesn't actually exercise the behavior I just described. Still, we expect extensions for gateways and relays to need it ๐Ÿ‘€.)

Finally, the endpoint inserts a From-Path header field containing the URI that identifies it in the context of the session, and then ends with the end-line after the last header field ๐Ÿ. Since a response is never chunked, the continuation flag in the end-line will always be a dollar sign ($) ๐Ÿ’…. The response MUST be sent back on the same connection the original request arrived on ๐Ÿ”.

7.3. Receiving Requests ๐Ÿ“ฌ

The receiving endpoint MUST first check the URI in the To-Path to make sure the request belongs to an existing session ๐Ÿ”. When the request arrives, the To-Path will have exactly one URI, and that URI MUST map to an existing session that's associated with the connection the request came in on ๐Ÿชข. If that isn't true, the receiver MUST generate a 481 error and ignore the request ๐Ÿšจ. Note that if the Failure-Report header field had a value of "no", then no error report would be sent ๐Ÿคซ.

Any further request processing by the receiver is method specific ๐Ÿงฉ.

7.3.1. Receiving SEND Requests ๐Ÿ’Œ

okay so when the receiving endpoint gets a SEND request, the first thing it checks is whether it's holding a complete message or just a chunk of a bigger one ๐Ÿ‘€. If the request has no Byte-Range header field, or it has one whose range-start value is "1" and its closing line continuation flag is "$", then the request carried the entire message ๐Ÿ’–. Otherwise the receiver uses the Message-ID value to stitch chunks back together into the original message. It sets up a virtual buffer for the message and keeps track of which bytes have arrived and which are still missing ๐Ÿงฉ. Then it takes the data from the request and drops it into the right spot in that buffer. The receiver SHOULD determine the actual length of each chunk by inspecting the payload itself, because the body can be shorter than the range-end field says ๐Ÿ™ˆ. That happens if the sender interrupted a SEND request unexpectedly. Also, the chunk with the "$" termination character is the one that defines the total length of the message โœจ.

Side tea: it's technically illegal for the sender to interrupt a request early if the last-byte position of the Byte-Range header field held anything other than "*". But having the receiver work out the chunk length from the actual content adds resilience when senders mess up. Since this should never happen with compliant senders, this only has a "SHOULD" strength.

Receivers MUST not assume that chunks arrive in order, and they can't count on getting every + chunk before the $ one ๐Ÿ™…โ€โ™€๏ธ. In certain connection failures, information can get duplicated. If new chunk data overlaps data already received for the same message, the last chunk received SHOULD take precedence (even if it wasn't the last one sent ๐Ÿคท). For example, bytes 1 to 100 are already in, then a chunk shows up with bytes 50 to 150. That second chunk overwrites bytes 50 to 100 โœ๏ธ. Other schemes work too, but this one is the easiest for the receiver and keeps clients behaving consistently ๐Ÿ’….

Sometimes the receiver can't give precedence to the last chunk when they overlap. Say the app is rendering chunks as they arrive. Once a conflicting chunk has been rendered, it's too late to "take back" that data. So the most-recent-chunk rule is only at a "SHOULD" strength, and it's not meant to block apps where that behavior doesn't make sense ๐Ÿซถ.

The seven - in the end-line exist so the receiver can search for the value ---- 32 bits at a time to find the probable location of the end-line ๐Ÿ”. Most processors can locate the boundaries and copy memory at about the same speed as a normal memory copy. This is just as fast as framing based on a body length in the header fields, but it still allows messages to be interrupted ๐ŸŽ๏ธ.

What happens to the body is outside the scope of MSRP and is largely decided by the MIME Content-Type and Content-Disposition ๐ŸŽ€. The body MAY be rendered after the whole message is received, or partially rendered as it's being received.

If the SEND request contained a Content-Type header field with an unsupported media-type, and the Failure-Report value is not "no", the receiver MUST generate a response with a status code of 415 ๐Ÿšซ. All MSRP endpoints MUST be able to receive the multipart/mixed [15] and multipart/alternative [15] media-types ๐ŸŒˆ.

If the Success-Report header field was set to "yes", the receiver must construct and send one or more success reports, as described in Section 7.1.3 ๐Ÿ“ฌ.

7.3.2. Receiving REPORT Requests ๐Ÿ“ฃ

When an endpoint receives a REPORT request, it matches the report to the original SEND request using the Message-ID and the Byte-Range, if present ๐Ÿงท. If it asked for success reports, then it SHOULD keep enough state about each outstanding sent message so it can match REPORT requests to the original messages ๐Ÿ—‚๏ธ.

An endpoint that receives a REPORT request with a Status header field whose namespace field is "000" MUST interpret the report in exactly the same way it would interpret an MSRP transaction response with a response code matching the status-code field ๐Ÿง .

It's possible to receive a failure report, or a failure transaction response, for a chunk that's currently being delivered. In that case, the entire message corresponding to that chunk SHOULD be aborted by including the "#" character in the continuation field of the end-line ๐Ÿ›‘.

It's also possible that an endpoint receives a REPORT request on a session that's no longer valid. What the endpoint does then is a matter of local policy ๐Ÿค“. The endpoint is not required to take any steps to facilitate that late delivery. In other words, it isn't expected to keep a connection active in case late REPORTs show up ๐Ÿ˜Œ.

When an endpoint that sent a SEND request receives a failure REPORT saying a particular byte range was not received, it MUST treat the session as failed ๐Ÿ’”. If it wants to recover, it MUST first re-negotiate the URIs at the signaling level, then resend that range of bytes of the message on the resulting new session ๐Ÿ”.

MSRP nodes MUST NOT send MSRP REPORT requests in response to other REPORT requests. no reports about reports, bestie, that's a whole loop ๐Ÿ™ƒโ™พ๏ธ


8. Using MSRP with SIP and SDP ๐Ÿ“ž

MSRP sessions are typically initiated using the Session Description Protocol (SDP) [2] via the SIP offer/answer mechanism [3] ๐ŸŽถ.

This document defines a handful of new SDP parameters for setting up MSRP sessions. They're detailed below and in the IANA Considerations section ๐Ÿ“‹.

An MSRP media-line (that is, a media-line proposing MSRP) in the session description comes with a mandatory "path" attribute ๐Ÿ›ค๏ธ. This attribute holds a space-separated list of URIs to visit to reach the user agent that advertised the session description. If there's more than one URI, the leftmost one is the first stop on the way to the target resource. (The path list can hold multiple URIs so gateways or relays can be added in the future ๐ŸŒ‰.) MSRP implementations that can accept incoming connections without relays will usually only give a single URI here ๐ŸŽฏ.

An MSRP media line also comes with an "accept-types" attribute, and optionally an "accept-wrapped-types" attribute ๐Ÿ’…. These are used to specify the media-types the endpoint is willing to accept.

8.1. SDP Connection and Media-Lines ๐ŸŽ€

An SDP connection-line looks like this:

c=<network type> <address type> <connection address>

Figure 4: Standard SDP Connection Line

The network type and address type fields are used the normal SDP way. The connection address field MUST be set to the IP address or fully qualified domain name from the MSRP URI that identifies the endpoint in its path attribute ๐ŸŒ.

The general format of an SDP media-line is:

m=<media> <port> <protocol> <format list>

Figure 5: Standard SDP Media Line

An offered or accepted media-line for MSRP over TCP MUST include a protocol field value of "TCP/MSRP", or "TCP/TLS/MSRP" for TLS ๐Ÿ”. The media field value MUST be "message". The format list field MUST be set to "*" โœจ.

The port field value MUST match the port value used in the endpoint's MSRP URI in the path attribute. The exception is described in [3]: a user agent that wants to accept an offer, but not a specific media-line, MUST set that media-line's port number to zero (0) in the response ๐Ÿ™‹โ€โ™€๏ธ. Since MSRP lets multiple sessions share the same TCP connection, several m-lines in one SDP document may share the same port field value. MSRP devices MUST NOT assume any particular relationship between m-lines just because their port field values match ๐Ÿšซ.

MSRP devices don't use the c-line address field, or the m-line port and format list fields, to figure out where to connect ๐Ÿ—บ๏ธ. They use the attributes defined in this specification instead. The connection information gets copied into the c-line and m-line for backwards compatibility with conventional SDP usages. MSRP could theoretically carry any media-type, but "message" is the right fit ๐Ÿ’ฌ.

8.2. URI Negotiations ๐Ÿ”—

Each endpoint in an MSRP session is identified by a URI, and these URIs get negotiated in the SDP exchange ๐Ÿค. Each SDP offer or answer that proposes MSRP MUST contain a "path" attribute with one or more MSRP URIs. The path attribute lives in an SDP a-line and has this syntax:

path = path-label ":" path-list
path-label = "path"
path-list= MSRP-URI *(SP MSRP-URI)

Figure 6: Path Attribute

where MSRP-URI is an "msrp" or "msrps" URI as defined in Section 6 ๐Ÿชช. MSRP URIs included in an SDP offer or answer MUST include explicit port numbers ๐Ÿ”ข.

An MSRP device uses the URI to figure out the host address, port, transport, and protection level when connecting, and to identify the target when sending requests and responses ๐ŸŽฏ.

The offerer and answerer each pick a URI to represent themselves and send it to their peer in the SDP document ๐Ÿ“จ. Each peer stores the path value it got from the other side and uses that value as the target for requests inside the resulting session ๐Ÿ’Œ. If the path attribute from the peer has more than one URI, the target URI is the rightmost one, while the leftmost entry is the adjacent hop. If only one entry is there, it's both the peer and the adjacent hop URI ๐Ÿช„. The target path is the entire path attribute value received from the peer.

The following example shows an SDP offer with a session URI of "msrp://alice.example.com:7394/2s93i9ek2a;tcp" ๐Ÿง

v=0
o=alice 2890844526 2890844527 IN IP4 alice.example.com
s= -
c=IN IP4 alice.example.com
t=0 0
m=message 7394 TCP/MSRP *
a=accept-types:text/plain
a=path:msrp://alice.example.com:7394/2s93i9ek2a;tcp

Figure 7: Example SDP with Path Attribute

The rightmost URI in the path attribute MUST identify the endpoint that generated the SDP document, or some other location where that endpoint wants to receive requests for the session ๐Ÿ . It MUST be assigned for this particular session, and it MUST NOT duplicate any URI in use for any other session the endpoint is currently part of ๐Ÿ™…โ€โ™€๏ธ. It SHOULD be hard to guess, and protected from eavesdroppers ๐Ÿ•ต๏ธโ€โ™€๏ธ. This is discussed in more detail in Section 14 ๐Ÿ”โœจ.

8.3. Path Attributes with Multiple URIs โœจ

okay so as I said before, this doc is all about MSRP for peer-to-peer scenarios, aka when NO relays are involved ๐Ÿซถ. Relays get their own separate doc [23]. But an MSRP device that only does the core spec still has to play nice with devices that DO use relays, so this doc has to make a few assumptions about how relays work ๐Ÿฆ‹

An endpoint that uses one or more relays says so by putting a URI for every device in the relay chain into the SDP path attribute. The last entry points at the endpoint itself. Everything before it lists each proposed relay, in order. The first entry is the first relay in the chain from the peer's point of view, meaning the relay the peer device (or a relay acting on its behalf) should connect to ๐Ÿงš

Endpoints that don't want to insert a relay, including the ones that don't support relays at all, put exactly one URI in the path attribute. That one URI is both the endpoint for the session and the connection point โœจ

Even though endpoints that implement only this spec will never introduce a relay, they still need to interoperate with endpoints that do. So they MUST be prepared to receive more than one URI in the SDP path attribute. When an endpoint gets more than one URI, only the first entry matters for resolving the address and port and establishing the network connection, because it describes the first adjacent hop ๐Ÿ’…

If an endpoint puts more than one URI in a path attribute, the final URI (the peer URI) identifies the session, and it MUST not duplicate the URI of any other session the endpoint is currently participating in. Uniqueness requirements for the other entries are out of scope for this document ๐ŸŒธ

8.4. Updated SDP Offers ๐Ÿ”„

sometimes MSRP endpoints need to send extra SDP exchanges for a session that already exists ๐Ÿ’ซ Maybe they need periodic exchanges with no change, just to refresh state in the network (think SIP session timers or the SIP UPDATE [24] request). Maybe they want to change some other stream in the session without touching the MSRP stream, or change the MSRP stream without touching the other stream. All valid vibes ๐Ÿ’–

Either peer can start an updated exchange at any time. Whoever sends the new offer takes on the role of offerer for all purposes ๐Ÿ‘‘ The answerer MUST respond with a path attribute that represents a valid path to itself at the time of the updated exchange. That new path can be the same as its old one, or it can be different. The new offerer MUST NOT assume the peer will answer with the same path it used last time ๐Ÿ™ˆ

If either party wants to send an SDP document that changes nothing at all, then it MUST use the same o-line as in the previous exchange ๐ŸŽ€

8.5. Connection Negotiation ๐Ÿ”Œ

ok history lesson ๐Ÿ“š Previous versions of this document had a mechanism for negotiating the direction of any required TCP connection. It was loosely based on the Connection-Oriented Media (COMEDIA) [26] work from the MMUSIC working group. The whole point was to let MSRP sessions succeed when the offerer couldn't accept connections but the answerer could. Like, the offerer might be stuck behind a NAT, while the answerer has a globally routable address ๐ŸŒ

The SIMPLE working group said bye bye to that mechanism, because it added a ton of complexity to connection management ๐Ÿ’€ Instead, MSRP now specifies a default connection direction: the party that sent the original offer is responsible for connecting to its peer โœจ

8.6. Content Type Negotiation ๐Ÿ“

okay this section is a whole thing, so let's go ๐Ÿง An SDP media-line proposing MSRP MUST be accompanied by an accept-types attribute.

An entry of "*" in the accept-types attribute means the sender may try to send content with media-types that weren't explicitly listed. Likewise, an entry with an explicit type and a "*" as the subtype means the sender may try to send content with any subtype of that type. If the receiver gets an MSRP request and can process the media-type, it does. If not, it responds with a 415 response. Also, all explicit entries SHOULD be considered preferred over any non-listed types. This is needed because otherwise the list of formats for rich IM devices could be prohibitively large ๐Ÿ˜ญ

This spec requires support for certain data formats. Mandatory formats MUST be signaled like any other, either explicitly or with a "*".

The accept-types attribute may include container types, meaning MIME formats that contain other types inside them ๐Ÿ“ฆ If compound types are used, the types listed in accept-types may be used as the root payload, or they may be wrapped in a listed container type. Any container types MUST also be listed in the accept-types attribute.

Sometimes an endpoint needs to specify a MIME media-type that can only be used when it's wrapped inside a listed container type. For that, endpoints MAY specify media-types that are only allowed when wrapped inside compound types, using the "accept-wrapped-types" attribute in an SDP a-line ๐ŸŽ

The semantics for accept-wrapped-types are identical to those of the accept-types attribute, with one exception: the specified types may only be used when wrapped inside container types that are listed in the accept-types attribute. Only types listed in accept-types may be used as the "root" type for the entire body. Since any type listed in accept-types may be used both as a root body and wrapped in other bodies, format entries from accept-types SHOULD NOT be repeated in this attribute ๐Ÿ”

This approach doesn't allow distinct lists of acceptable wrapped types for different types of containers. If an endpoint understands a media-type in the context of one wrapper, it's assumed to understand it in the context of any other acceptable wrappers, subject to any constraints the wrapper types themselves define ๐Ÿงฉ

The reason for keeping types that are only allowed inside containers separate from the primary payload types is so an endpoint can force the use of certain wrappers ๐ŸŽ€ For example, a Common Presence and Instant Messaging (CPIM) [12] gateway might require every message to be wrapped inside message/cpim bodies, but allow several content types inside that wrapper. If the gateway listed the wrapped types in accept-types, its peer might try to use those types without the wrapper ๐Ÿ’€

If the recipient of an offer doesn't understand any of the payload types in the offered SDP, it SHOULD indicate that using the appropriate mechanism of the rendezvous protocol. For example, in SIP, it SHOULD return a SIP 488 response ๐Ÿ™…โ€โ™€๏ธ

An MSRP endpoint MUST NOT send content of a type that the peer hasn't signaled in either an accept-types or an accept-wrapped-types attribute. Furthermore, it MUST NOT send a top-level (i.e., not wrapped) MIME document of a type that isn't signaled in the accept-types attribute. In either case, the signaling could be explicit, or implicit through the use of the "*" character ๐Ÿซถ

An endpoint MAY indicate the maximum size message it wants to receive using the max-size a-line attribute. Max-size refers to the complete message in octets, not the size of any one chunk ๐Ÿ“ Senders SHOULD NOT exceed the max-size limit for any message sent in the resulting session. However, the receiver should consider the max-size value as a hint ๐Ÿ’œ

Media format entries may include parameters. How those parameters are interpreted depends on the media-type. For the purposes of media-type negotiation, a format-entry with one or more parameters is assumed to match the same format-entry with no parameters ๐ŸŒˆ

The formal syntax for these attributes is below ๐Ÿ‘‡

accept-types = accept-types-label ":" format-list
accept-types-label = "accept-types"
accept-wrapped-types = wrapped-types-label ":" format-list
wrapped-types-label = "accept-wrapped-types"
format-list = format-entry *( SP format-entry)
format-entry = ( ( (type "/" subtype)
                 / (type "/" "*") )
                 *( ";" type-param ) )
                / ("*")

type = token
subtype = token
type-param = parm-attribute "=" parm-value
parm-attribute = token
parm-value = token / quoted-string

max-size = max-size-label ":" max-size-value
max-size-label = "max-size"
max-size-value = 1*(DIGIT) ; max size in octets

                   Figure 8: Attribute Syntax

8.7. Example SDP Exchange ๐ŸŽฌ

okay, the classic scenario ๐Ÿ’– Endpoint A wants to invite Endpoint B to an MSRP session, so A offers this session description:

 v=0
 o=usera 2890844526 2890844527 IN IP4 alice.example.com
 s= -
 c=IN IP4 alice.example.com
 t=0 0
 m=message 7394 TCP/MSRP *
 a=accept-types:message/cpim text/plain text/html
 a=path:msrp://alice.example.com:7394/2s93i93idj;tcp

                   Figure 9: SDP from Endpoint A

B responds with its own URI ๐Ÿฆ‹

 v=0
 o=userb 2890844530 2890844532 IN IP4 bob.example.com
 s= -
 c=IN IP4 bob.example.com
 t=0 0
 m=message 8493 TCP/MSRP *
 a=accept-types:message/cpim text/plain
 a=path:msrp://bob.example.com:8493/si438dsaodes;tcp

                   Figure 10: SDP from Endpoint B

8.8. MSRP User Experience with SIP ๐Ÿ“ฑ

so in typical SIP apps, when an endpoint gets an INVITE, it alerts the user and waits for input before responding ๐Ÿ”” It's basically the phone-call vibe, where the callee "answers" the call ๐Ÿ“ž

Instant messaging apps are different ๐Ÿ’ฌ The first message you get just pops up right away, without you having to "join" the conversation first. So the principle of least surprise would suggest that MSRP endpoints using SIP signaling SHOULD allow a mode where the endpoint quietly accepts the session and starts displaying messages ๐Ÿซถ

This guideline might not make sense for every situation, like mixed-media apps where both MSRP and audio sessions are offered in the same INVITE. Overall, good application design should win out ๐ŸŒธ

ok last bit, the forking drama ๐Ÿฟ A SIP proxy can fork SIP INVITE requests, so more than one endpoint might get the same INVITE. SIP early media [29] techniques can set up a preliminary session with each endpoint, so the initial message(s) show up on every endpoint ๐Ÿ’… Then, any endpoints that don't send MSRP traffic after some period of time get their INVITE transaction canceled, so they stop receiving MSRP traffic from the inviter ๐Ÿงš

8.9. SDP Direction Attribute and MSRP ๐Ÿ’…โœจ

okay so SDP has these direction attributes that change which way media flows: "sendonly", "recvonly", "inactive", and "sendrecv" ๐ŸŽ€. bestie, these are the four you need to know ๐Ÿซถ

if a "sendonly" or "recvonly" attribute is on an MSRP media description line, it tells you which direction the MSRP SEND requests carrying regular message payloads go ๐Ÿฆ‹. unless it's specified otherwise, these attributes don't change the direction of other request types, like REPORT ๐ŸŒธ. and SEND requests that carry a control or reporting protocol instead of a regular message payload (think Instant Message Delivery Notification (IMDN) reports ๐Ÿ’–) SHOULD be generated by the protocol rules as if no direction attribute were there at all ๐Ÿ˜ญ

9. Formal Syntax ๐ŸŽ€

okay this part is the grammar, and it is LONG, so grab a snack ๐Ÿ“ MSRP is a text protocol and it uses the UTF-8 [14] transformation format ๐Ÿ’œ

the syntax is written in augmented Backus-Naur Form (BNF) as described in RFC 4234 [6] ๐Ÿงš

msrp-req-or-resp = msrp-request / msrp-response
msrp-request = req-start headers [content-stuff] end-line
msrp-response = resp-start headers end-line

req-start  = pMSRP SP transact-id SP method CRLF
resp-start = pMSRP SP transact-id SP status-code [SP comment] CRLF
comment = utf8text

pMSRP = %x4D.53.52.50 ; MSRP in caps
transact-id = ident
method = mSEND / mREPORT / other-method
mSEND = %x53.45.4e.44 ; SEND in caps
mREPORT = %x52.45.50.4f.52.54; REPORT in caps

other-method = 1*UPALPHA
status-code = 3DIGIT ; any code defined in this document
                     ; or an extension document

MSRP-URI = msrp-scheme "://" authority
    ["/" session-id] ";" transport *( ";" URI-parameter)
                     ; authority as defined in RFC3986

msrp-scheme = "msrp" / "msrps"
session-id = 1*( unreserved / "+" / "=" / "/" )
                     ; unreserved as defined in RFC3986
transport = "tcp" / 1*ALPHANUM
URI-parameter = token ["=" token]

headers = To-Path CRLF From-Path CRLF 1*( header CRLF )
header  =   Message-ID
 / Success-Report
 / Failure-Report
 / Byte-Range
 / Status
 / ext-header

To-Path = "To-Path:" SP MSRP-URI *( SP MSRP-URI )
From-Path = "From-Path:" SP MSRP-URI *( SP MSRP-URI )
Message-ID = "Message-ID:" SP ident
Success-Report = "Success-Report:" SP ("yes" / "no" )
Failure-Report = "Failure-Report:" SP ("yes" / "no" / "partial" )
Byte-Range = "Byte-Range:" SP range-start "-" range-end "/" total
range-start = 1*DIGIT
range-end   = 1*DIGIT / "*"
total       = 1*DIGIT / "*"

Status = "Status:" SP namespace SP status-code [SP comment]
namespace = 3(DIGIT); "000" for all codes defined in this document.

ident = ALPHANUM  3*31ident-char
ident-char = ALPHANUM / "." / "-" / "+" / "%" / "="

content-stuff = *(Other-Mime-header CRLF)
                Content-Type 2CRLF data CRLF

Content-Type = "Content-Type:" SP media-type
media-type = type "/" subtype *( ";" gen-param )
type = token
subtype = token

gen-param = pname [ "=" pval ]
pname = token
pval  = token / quoted-string

token = 1*(%x21 / %x23-27 / %x2A-2B / %x2D-2E
           / %x30-39 / %x41-5A / %x5E-7E)
           ; token is compared case-insensitive

quoted-string = DQUOTE *(qdtext / qd-esc) DQUOTE
qdtext = SP / HTAB / %x21 / %x23-5B / %x5D-7E
            / UTF8-NONASCII
qd-esc = (BACKSLASH BACKSLASH) / (BACKSLASH DQUOTE)
BACKSLASH = "\"
UPALPHA  = %x41-5A
ALPHANUM = ALPHA / DIGIT
Other-Mime-header = (Content-ID
 / Content-Description
 / Content-Disposition
 / mime-extension-field)

    ; Content-ID, and Content-Description are defined in RFC2045.
    ; Content-Disposition is defined in RFC2183
    ; MIME-extension-field indicates additional MIME extension
    ; header fields as described in RFC2045

data = *OCTET
end-line = "-------" transact-id continuation-flag CRLF
continuation-flag = "+" / "$" / "#"

ext-header = hname ":" SP hval CRLF
hname = ALPHA *token
hval = utf8text

utf8text = *(HTAB / %x20-7E / UTF8-NONASCII)

UTF8-NONASCII = %xC0-DF 1UTF8-CONT
              / %xE0-EF 2UTF8-CONT
              / %xF0-F7 3UTF8-CONT
              / %xF8-Fb 4UTF8-CONT
              / %xFC-FD 5UTF8-CONT
UTF8-CONT     = %x80-BF

                        Figure 11: MSRP ABNF

10. Response Code Descriptions ๐ŸŒˆ

this section is the vibe check on the response codes ๐Ÿ’… they can show up in MSRP transaction responses, and they can also go in the Status header field in REPORT requests โœจ

10.1. 200 ๐Ÿ’–

the 200 response code means the transaction went through successfully ๐ŸŽ‰

10.2. 400 ๐Ÿ™ˆ

a 400 means the request was unintelligible ๐Ÿ˜ต the sender MAY retry the request after fixing the error. (bestie, MAY means it's optional, so this is a "you're allowed to" ๐Ÿซถ)

10.3. 403 ๐Ÿšซ

a 403 means the action is not allowed ๐Ÿ™…โ€โ™€๏ธ the sender SHOULD NOT try the request again ๐Ÿ’€

10.4. 408 โฐ

a 408 means a downstream transaction didn't finish in time โŒ› no element described in this spec ever sends it ๐Ÿ˜ญ BUT it's used in the MSRP relay extension, so endpoints MAY still get one ๐Ÿงš. an endpoint MUST treat a 408 the same way it would treat a local timeout ๐Ÿ’…

10.5. 413 โœ‹

a 413 means the receiver wants the sender to stop sending that particular message ๐Ÿ›‘ usually a 413 shows up in response to a chunk of a message the receiver doesn't want ๐Ÿ“

if a message sender gets a 413 in a response, or in a REPORT request, it MUST NOT send any more chunks of that message, meaning any more chunks with the same Message-ID value ๐Ÿ™…โ€โ™€๏ธ and if the sender gets the 413 while it's in the middle of sending a chunk, and that chunk is interruptible, the sender MUST interrupt it ๐Ÿ”ฅ

10.6. 415 ๐ŸŽต

a 415 means the SEND request had a media type the receiver doesn't understand ๐Ÿคทโ€โ™€๏ธ the sender SHOULD NOT send any more messages with that same content-type for the rest of the session ๐ŸŒธ

10.7. 423 ๐Ÿ“

a 423 means one of the requested parameters is out of bounds ๐Ÿ˜ฌ the relay extensions to this document use it ๐Ÿ’œ

10.8. 481 ๐Ÿ‘ป

a 481 means the session doesn't exist ๐Ÿ‘‹ the sender SHOULD terminate the session ๐Ÿฆ‹

10.9. 501 ๐Ÿค”

a 501 means the recipient doesn't understand the request method ๐Ÿซ 

The 501 response code exists to allow some degree of method extensibility. It is not intended as a license to ignore methods defined in this document; rather, it is a mechanism to report lack of support of extension methods.

(okay this bit is a big deal, so read it twice ๐Ÿ‘€ the 501 code exists so methods can be extended a little bit ๐Ÿงฉ it is NOT permission to ignore methods defined in this document ๐Ÿšซ it's just a way to say "I don't support this extension method" ๐Ÿซถ)

10.10. 506 ๐Ÿ”’

a 506 means a request came in on a session that's already tied to another network connection ๐Ÿ”— the sender SHOULD stop sending messages for that session on this connection ๐Ÿ›‘

11. Examples ๐Ÿ“š

11.1. Basic IM Session ๐Ÿ’ฌ

this section shows the most common flow ๐ŸŒŸ the example assumes SIP carries the SDP exchange ๐Ÿ“ž the SIP message details and proxy stuff are left out to keep it short ๐Ÿ™ˆ in the example, the offerer is sip:alice@example.com and the answerer is sip:bob@example.com ๐Ÿ’–

        Alice                     Bob
          |                        |
          |                        |
          |(1) (SIP) INVITE        |
          |----------------------->|
          |(2) (SIP) 200 OK        |
          |<-----------------------|
          |(3) (SIP) ACK           |
          |----------------------->|
          |(4) (MSRP) SEND         |
          |----------------------->|
          |(5) (MSRP) 200 OK       |
          |<-----------------------|
          |(6) (MSRP) SEND         |
          |<-----------------------|
          |(7) (MSRP) 200 OK       |
          |----------------------->|
          |(8) (SIP) BYE           |
          |----------------------->|
          |(9) (SIP) 200 OK        |
          |<-----------------------|
          |                        |
          |                        |

                     Figure 12: Basic IM Session Example
  1. okay Alice builds a local URI of msrp://alicepc.example.com:7777/iau39soe2843z;tcp โœจ

Alice->Bob (SIP): INVITE sip:bob@example.com

v=0
o=alice 2890844557 2890844559 IN IP4 alicepc.example.com
s= -
c=IN IP4 alicepc.example.com
t=0 0
m=message 7777 TCP/MSRP *
a=accept-types:text/plain
a=path:msrp://alicepc.example.com:7777/iau39soe2843z;tcp
  1. Bob listens on port 8888 and sends this response ๐ŸŽ€

Bob->Alice (SIP): 200 OK

v=0
o=bob 2890844612 2890844616 IN IP4 bob.example.com
s= -
c=IN IP4 bob.example.com
t=0 0
m=message 8888 TCP/MSRP *
a=accept-types:text/plain
a=path:msrp://bob.example.com:8888/9di4eae923wzd;tcp
  1. Alice->Bob (SIP): ACK sip:bob@example.com ๐Ÿซถ
  2. (Alice opens a connection to Bob ๐Ÿ”Œ) Alice->Bob (MSRP):
MSRP d93kswow SEND
To-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
From-Path: msrp://alicepc.example.com:7777/iau39soe2843z;tcp
Message-ID: 12339sdqwer
Byte-Range: 1-16/16
Content-Type: text/plain

Hi, I'm Alice!
-------d93kswow$
  1. Bob->Alice (MSRP): ๐Ÿ’Œ
MSRP d93kswow 200 OK
To-Path: msrp://alicepc.example.com:7777/iau39soe2843z;tcp
From-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
-------d93kswow$
  1. Bob->Alice (MSRP): ๐Ÿ“
MSRP dkei38sd SEND
To-Path: msrp://alicepc.example.com:7777/iau39soe2843z;tcp
From-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
Message-ID: 456s9wlk3
Byte-Range: 1-21/21
Content-Type: text/plain

Hi, Alice!  I'm Bob!
-------dkei38sd$
  1. Alice->Bob (MSRP): ๐ŸŒธ
MSRP dkei38sd 200 OK
To-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
From-Path: msrp://alicepc.example.com:7777/iau39soe2843z;tcp
-------dkei38sd$
  1. Alice->Bob (SIP): BYE sip:bob@example.com ๐Ÿ‘‹

Alice invalidates her local session state ๐Ÿงน

  1. Bob invalidates his local state for the session ๐Ÿงน

Bob->Alice (SIP): 200 OK ๐Ÿ’–

11.2. Message with XHTML Content ๐ŸŒ

MSRP dsdfoe38sd SEND
To-Path: msrp://alice.example.com:7777/iau39soe2843z;tcp
From-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
Message-ID: 456so39s
Byte-Range: 1-374/374
Content-Type: application/xhtml+xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"_http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd_">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>FY2005 Results</title>
</head>
  <body>
   <p>See the results at <a
href="http://example.org/">example.org</a>.</p>
  </body>
</html>
-------dsdfoe38sd$

Figure 13: Example Message with XHTML

11.3. Chunked Message ๐Ÿงฉ

for an example of a chunked message, check out the example in Section 5.1 ๐Ÿซถ

11.4. Chunked Message with Message/CPIM Payload โœจ

okay so this example is a chunked message that wraps a CPIM message around a text/plain payload ๐Ÿ“ฆ the important bit: MSRP builds the whole CPIM message first and only chops it up after, so the CPIM headers only show up in the first chunk ๐Ÿ’… both chunks still carry the MSRP Content-Type and Byte-Range headers, and those refer to the whole CPIM message, not just the slice ๐Ÿฆ‹

MSRP d93kswow SEND
To-Path: msrp://bobpc.example.com:8888/9di4eae923wzd;tcp
From-Path: msrp://alicepc.example.com:7654/iau39soe2843z;tcp
Message-ID: 12339sdqwer
Byte-Range: 1-137/148
Content-Type: message/cpim

To: Bob <sip:bob@example.com>
From: Alice <sip:alice@example.com>
DateTime: 2006-05-15T15:02:31-03:00
Content-Type: text/plain

ABCD
-------d93kswow+

Figure 14: First Chunk ๐ŸŒธ

Alice sends the second and last chunk ๐Ÿซถ

MSRP op2nc9a SEND
To-Path: msrp://bobpc.example.com:8888/9di4eae923wzd;tcp
From-Path: msrp://alicepc.example.com:7654/iau39soe2843z;tcp
Message-ID: 12339sdqwer
Byte-Range: 138-148/148
Content-Type: message/cpim

1234567890
-------op2nc9a$

Figure 15: Second Chunk ๐Ÿ’œ

11.5. System Message ๐Ÿ“ข

sysadmin is pinging Alice, and this one is a super plain text message ๐Ÿ™ˆ

Sysadmin->Alice (MSRP):

MSRP d93kswow SEND
To-Path: msrp://alicepc.example.com:8888/9di4eae923wzd;tcp
From-Path: msrp://example.com:7777/iau39soe2843z;tcp
Message-ID: 12339sdqwer
Byte-Range: 1-38/38
Failure-Report: no
Success-Report: no
Content-Type: text/plain

This conference will end in 5 minutes
-------d93kswow$

11.6. Positive Report ๐ŸŒˆ

here Alice sends Bob a text/html message with a link, and she asks for a success report back ๐Ÿ”—

Alice->Bob (MSRP):

MSRP d93kswow SEND
To-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
From-Path: msrp://alicepc.example.com:7777/iau39soe2843z;tcp
Message-ID: 12339sdqwer
Byte-Range: 1-106/106
Success-Report: yes
Failure-Report: no
Content-Type: text/html
<html><body>
<p>Here is that important link...
<a href="http://www.example.com/foobar">foobar</a>
</p>
</body></html>
-------d93kswow$

Figure 16: Initial SEND Request โญ

Bob replies with the success report ๐ŸŽ‰

Bob->Alice (MSRP):

MSRP dkei38sd REPORT
To-Path: msrp://alicepc.example.com:7777/iau39soe2843z;tcp
From-Path: msrp://bob.example.com:8888/9di4eae923wzd;tcp
Message-ID: 12339sdqwer
Byte-Range: 1-106/106
Status: 000 200 OK
-------dkei38sd$

Figure 17: Success Report ๐Ÿ‘‘

11.7. Forked IM ๐Ÿงš

ngl traditional IM systems are kinda bad at handling the same person being online on multiple clients at once ๐Ÿ˜ญ it works okay for some of them, but the whole multi-client thing is pretty clunky. It gets even messier now that we've got always-on phones, because you'd really only want to ping the phone if the main client isn't around ๐Ÿ“ฑ

SIP makes these rendezvous decisions explicit, predictable, and super flexible ๐Ÿ’– "page-mode" IM systems do it with hidden, implementation-specific choices that clients can't really influence ๐Ÿ™ƒ With SIP session-mode messaging, the client can steer rendezvous in a predictable, interoperable way for any host that supports callee capabilities [31]. So the rendezvous policy stays consistent for each address of record ๐ŸŽ€

Now meet Juliet ๐ŸŒน she has several IM clients where she can be reached. Each one has its own SIP contact and MSRP session. The example uses SIP's ability to "fork" an invitation to several contacts at once, one after another, or in a mix of both โœจ Juliet has registered from her chamber, the balcony, her PDA, and, as a last resort, her nurse (you can leave a message there). Her contacts are listed in the diagram below, and the q-values show relative preference, where q=1.0 is the highest ๐Ÿ‘‘

When Romeo opens his IM program, he picks Juliet and types "art thou hither?" (not "you there?" ๐Ÿ’…). His client sends a SIP invitation to sip:juliet@thecapulets.example.com. The proxy tries the balcony and the chamber at the same time ๐Ÿฆ‹ A client runs on each of those, and both set up early MSRP sessions with Romeo's client. The client automatically sends the message over MSRP to the two MSRP URIs involved ๐Ÿ’Œ After a few seconds with no reply or activity from Juliet, the proxy cancels the invitation at those first two contacts and forwards it to her PDA ๐Ÿ“ฑ Since her dad is talking to her about the wedding, she hits "Do Not Disturb," which sends a "Busy Here" response ๐Ÿ˜ญ The proxy then tries the nurse, who answers and fills Romeo in on what's going on ๐Ÿซถ

Romeo       Juliet's     Juliet/      Juliet/     Juliet/     Nurse
             Proxy       balcony      chamber       PDA
  |            |            |            |           |           |
  |--INVITE--->|            |            |           |           |
  |            |--INVITE--->|            |            |           |
  |            |<----180----|            |           |           |
  |<----180----|            |            |           |           |
  |---PRACK---------------->|            |           |           |
  |<----200-----------------|            |           |           |
  |<===Early MSRP Session==>| art thou hither?       |           |
  |            |            |            |           |           |
  |            |--INVITE---------------->|           |           |
  |            |<----180-----------------|           |           |
  |<----180----|            |            |           |           |
  |---PRACK----------------------------->|           |           |
  |<----200------------------------------|           |           |
  |<========Early MSRP Session==========>| art thou hither?      |
  |            |            |            |           |           |
  |            |            |            |           |           |
  |            | .... Time Passes ....   |           |           |
  |            |            |            |           |           |
  |            |            |            |           |           |
  |            |--CANCEL--->|            |           |           |
  |            |<---200-----|            |           |           |
  |            |<---487-----|            |           |           |
  |            |----ACK---->|            |           |           |
  |            |--CANCEL---------------->|           |           |
  |            |<---200------------------|           |           |
  |            |<---487------------------|           |           |
  |            |----ACK----------------->|           |           |
  |            |--INVITE---------------------------->|  romeo wants
  |            |            |            |           |  to IM w/ you
  |            |<---486 Busy Here--------------------|           |
  |            |----ACK----------------------------->|           |
  |            |            |            |           |           |
  |            |--INVITE---------------------------------------->|
  |            |<---200 OK---------------------------------------|
  |<--200 OK---|            |            |           |           |
  |---ACK------------------------------------------------------->|
  |<================MSRP Session================================>|
  |            |            |            |           |           |
  |                                         Hi Romeo, Juliet is  |
  |                                         with her father now  |
  |                                         can I take a message?|
  |                                                              |
  |  Tell her to go to confession tomorrow....                   |

Figure 18: Forking Example ๐Ÿ™ˆ

12. Extensibility ๐Ÿ”ฎ

MSRP was built to be only minimally extensible ๐Ÿค New MSRP methods, header fields, and status codes can be defined in standards-track RFCs. There's no version number and no negotiation mechanism to require or discover new features. If an extension comes along that needs negotiation, its spec will have to describe how it gets negotiated in the encapsulating signaling protocol. And if a non-interoperable update or extension ever shows up, it will be treated as a new protocol and MUST describe how its use will be signaled ๐Ÿšจ

To keep extension header fields from breaking interoperability, an MSRP device that gets a request or response with a header field it doesn't understand MUST ignore that header field and process the request or response as if the header field weren't there ๐Ÿซง If an MSRP device gets a request with an unknown method, it MUST return a 501 response ๐Ÿ’€

MSRP uses lists of URIs in the To-Path and From-Path header fields instead of a single URI, since relay or gateway functionality might get added later ๐ŸŒ‰ Also, "msrp" and "msrps" URIs can carry parameters that are extensible ๐Ÿงฉ

13. CPIM Compatibility ๐Ÿ’Œ

MSRP sessions may go through a gateway to other Common Profile for Instant Messaging (CPIM) [27] compatible protocols ๐ŸŒ If that happens, the gateway MUST maintain session state, and MUST translate between MSRP session semantics and CPIM semantics, which have no concept of sessions ๐Ÿ” When one endpoint of the session is a CPIM gateway, instant messages SHOULD be wrapped in "message/cpim" [12] bodies. Such a gateway MUST include "message/cpim" as the first entry in its SDP accept-types attribute ๐ŸŽ€ MSRP endpoints sending instant messages to a peer that has put "message/cpim" first in its accept-types attribute SHOULD encapsulate all instant message bodies in message/cpim wrappers. All MSRP endpoints MUST support the message/cpim type, and SHOULD support the S/MIME[7] features of that format ๐Ÿ”

If a message is going into a message/cpim envelope, the wrapping MUST be done before the message gets broken into chunks, if chunking is needed ๐Ÿง

All MSRP endpoints MUST recognize the From, To, DateTime, and Require header fields as defined in RFC 3862 ๐Ÿ“‹ Such applications SHOULD recognize the CC header field, and MAY recognize the Subject header field. Any MSRP application that recognizes any message/cpim header field MUST understand the NS (name space) header field ๐ŸŒธ

All message/cpim body parts sent by an MSRP endpoint MUST include the From and To header fields. If the message/cpim body part is protected using S/MIME, then it MUST also include the DateTime header field ๐Ÿ’œ

The NS, To, and CC header fields may occur multiple times. Other header fields defined in RFC 3862 MUST NOT occur more than once in a given message/cpim body part in an MSRP message ๐Ÿšซ The Require header field MAY include multiple values. The NS header field MAY occur zero or more times, depending on how many name spaces are being referenced โœจ

Extension header fields MAY occur more than once, depending on how those header fields are defined ๐Ÿงš

Using message/cpim envelopes is also handy if an MSRP device wants to send a message on behalf of some other identity ๐Ÿช„ The device can add a message/cpim envelope with the appropriate From header field value ๐Ÿฆ‹

14. Security Considerations ๐Ÿ”โœจ

Okay so instant messaging is literally everywhere ๐Ÿ’ฌ people swap personal convos, corporate confidential stuff, account numbers, and financial trading info through it. Individuals, corporations, AND governments all use IM to communicate important info, so IM systems NEED to be serious about a few things ๐Ÿ˜ค. They need integrity and confidentiality for the exchanged info, they need you to know you're talking to the correct party, and they need to allow the possibility of anonymous communication ๐ŸŽญ. MSRP pushes a lot of the hard problems over to SIP when SIP sets up the session, but some of the problems are still ours to handle. Spam and Denial of Service (DoS) attacks are also very relevant to IM systems ๐Ÿšซ.

MSRP needs to provide confidentiality and integrity for the messages it transfers ๐Ÿ”’. It also needs to provide assurances that the connected host is the host it meant to connect to, and that the connection has not been hijacked ๐Ÿซถ.

14.1. Secrecy of the MSRP URI

Okay this one is giving secret agent ๐Ÿ•ต๏ธโ€โ™€๏ธ. When an endpoint sends an MSRP URI to its peer in a rendezvous protocol, that URI is basically a secret shared between the two peers ๐Ÿคซ. If an attacker learns or guesses the URI before session setup is done, it may be able to impersonate one of the peers ๐Ÿ’€.

Assuming the URI exchange in the rendezvous protocol is sufficiently protected, it is critical that the URI stays difficult to "guess" with brute force methods ๐Ÿง . Most parts of the URI, like the scheme and the authority components, are common knowledge, so the secrecy is entirely provided by the session-id component ๐Ÿ”‘.

So, when an MSRP device generates an MSRP URI to use when starting an MSRP session, the session-id component MUST contain at least 80 bits of randomness โœจ. No cap, this is the main event.

14.2. Transport Level Protection

Real talk, when you're only using TCP connections, MSRP security is fairly weak ๐Ÿ˜ฌ. If host A is contacting host B, B passes its hostname and a secret to A using a rendezvous protocol. MSRP does require a rendezvous protocol that can protect this exchange, but there's no guarantee the protection will actually be used all the time ๐Ÿ™ˆ. If it isn't, anyone can see that secret. Host A then connects to the provided hostname and passes the secret in the clear across the connection to B. Host A assumes it's talking to B based on where it sent the SYN packet, and then delivers the secret in plain text. Host B assumes it's talking to A because the host on the other end delivered the secret. An attacker who could ACK the SYN packet could insert itself as a man-in-the-middle in the connection ๐Ÿ˜ฑ.

When using TLS connections, the security is way better ๐ŸŽ€. We assume the host accepting the connection has a certificate from a well-known certification authority. We also assume the signaling to set up the session is protected by the rendezvous protocol. In this case, when host A contacts host B, the secret is passed through a confidential channel to A. A connects with TLS to B. B presents a valid certificate, so A knows it really is connected to B. A then delivers the secret B provided, so B can verify it's connected to A ๐Ÿซถ. Still, a rogue SIP Proxy can see the secret in the SIP signaling traffic and could potentially insert itself as a man-in-the-middle ๐Ÿ‘€.

Realistically though, using TLS with certificates from well-known certification authorities is hard for peer-to-peer connections ๐Ÿ˜ญ. The kinds of hosts end clients use to send instant messages are unlikely to have long-term stable IP addresses or DNS names for the certificates to bind to. On top of that, server certificates from well-known certification authorities are currently expensive enough to discourage using them for each client ๐Ÿ’ธ. Using TLS in a peer-to-peer mode without well-known certificates is discussed in Section 14.4 ๐Ÿงš.

TLS becomes way more practical once some form of relay is introduced ๐ŸŒธ. Clients can then form TLS connections to relays, which are much more likely to have TLS certificates. This specification does not address such relays, but a companion document [23] describes them. That document makes extensive use of TLS to protect traffic between clients and relays, and between one relay and another ๐Ÿ’–.

TLS is used to authenticate devices and to provide integrity and confidentiality for the header fields being transported ๐Ÿ”. MSRP elements MUST implement TLS and MUST also implement the TLS ClientExtendedHello extended hello information for server name indication, as described in [11] ๐Ÿซถ. A TLS cipher-suite of TLS_RSA_WITH_AES_128_CBC_SHA [13] MUST be supported, and other cipher-suites MAY also be supported ๐Ÿ’….

14.3. S/MIME

Okay so the only strong security for non-TLS connections comes from S/MIME ๐Ÿ”.

Since MSRP carries arbitrary MIME content, it can trivially carry S/MIME protected messages too ๐ŸŽ. All MSRP implementations MUST support the multipart/signed media-type, even if they don't support S/MIME ๐Ÿ“. Since SIP can carry a session key, S/MIME messages in the context of a session could also be protected using a key-wrapped shared secret [28] that's provided in the session setup ๐Ÿ”‘. MSRP can carry unencoded binary payloads, so MIME bodies MUST be transferred with a transfer encoding of binary ๐Ÿงฉ. If a message is both signed and encrypted, it SHOULD be signed first, then encrypted โœ๏ธ. If S/MIME is supported, SHA-1, SHA-256, RSA, and AES-128 MUST be supported. For RSA, implementations MUST support key sizes of at least 1024 bits, and SHOULD support key sizes of 2048 bits or more ๐Ÿ’ช.

This does not actually require the endpoint to have certificates from a well-known certification authority ๐Ÿ™Œ. When MSRP is used with SIP, the Identity [17] and Certificates [25] mechanisms provide S/MIME-based delivery of a secret between A and B. No SIP intermediary except the explicitly trusted authentication service (one per user) can see the secret ๐Ÿ›ก๏ธ. The S/MIME encryption of the SDP can also be used by SIP to exchange keying material that can be used in MSRP ๐Ÿ—๏ธ.

The MSRP session can then use S/MIME with this keying material to sign and encrypt messages sent over MSRP โœจ. The connection can still be hijacked, since the secret is sent in clear text to the other end of the TCP connection, but the consequences are mitigated if all the MSRP content is signed and encrypted with S/MIME ๐ŸŒˆ. Although it's out of scope for this document, the SIP negotiation of an MSRP session can negotiate symmetric keying material to be used with S/MIME for integrity and privacy ๐Ÿฆ‹.

14.4. Using TLS in Peer-to-Peer Mode

Okay this section is my favorite ๐Ÿฅน. TLS can be used with a self-signed certificate, as long as there's a mechanism for both sides to ascertain that the other side used the correct certificate ๐ŸŽ€. When used with SDP and SIP, the correct certificate can be verified by passing a fingerprint of the certificate in the SDP and making sure the SDP has suitable integrity protection. When SIP is used to transport the SDP, the integrity can be provided by the SIP Identity mechanism [17]. The rest of this section describes the details of this approach ๐Ÿ’œ.

If self-signed certificates are used, the content of the subjectAltName attribute inside the certificate MAY use the URI of the user. In SIP, this URI of the user is the User's Address of Record (AOR). This is useful for debugging purposes only, and is not required to bind the certificate to one of the communication endpoints ๐Ÿ”. Unlike normal TLS operations in this protocol, when doing peer-to-peer TLS, the subjectAltName is not an important component of the certificate verification ๐Ÿ™ƒ. If the endpoint is also able to make anonymous sessions, a distinct, unique certificate MUST be used for this purpose ๐ŸŽญ. For a client that works with multiple users, each user SHOULD have its own certificate ๐Ÿ‘‘. Because generating public/private key pairs is relatively expensive, endpoints are not required to generate certificates for each session ๐Ÿ’ธ.

A certificate fingerprint is the output of a one-way hash function computed over the Distinguished Encoding Rules (DER) form of the certificate ๐Ÿ”ข. The endpoint MUST use the certificate fingerprint attribute as specified in [18], and MUST include this in the SDP ๐Ÿ“œ. The certificate presented during the TLS handshake needs to match the fingerprint exchanged via the SDP. If the fingerprint does not match the hashed certificate, then the endpoint MUST tear down the media session immediately ๐Ÿšจ.

When using SIP, the integrity of the fingerprint can be ensured through the SIP Identity mechanism [17]. When a client wants to use SIP to set up a secure MSRP session with another endpoint, it sends an SDP offer in a SIP message to the other endpoint ๐Ÿ“จ. This offer includes, as part of the SDP payload, the fingerprint of the certificate the endpoint wants to use ๐Ÿงพ. The SIP message containing the offer is sent to the offerer's SIP proxy, which will add an Identity header according to the procedures outlined in [17] โœ๏ธ. When the far endpoint receives the SIP message, it can verify the identity of the sender using the Identity header ๐Ÿชช. Since the Identity header is a digital signature across several SIP headers, in addition to the body or bodies of the SIP message, the receiver can also be certain the message has not been tampered with after the digital signature was added ๐Ÿ›ก๏ธ.

An example of SDP with a fingerprint attribute is shown in the following figure. Note the fingerprint is shown spread over two lines due to formatting consideration, but should all be on one line ๐Ÿ™ˆ.

c=IN IP4 atlanta.example.com
m=message 7654 TCP/TLS/MSRP *
a=accept-types:text/plain
a=path:msrps://atlanta.example.com:7654/jshA7weso3ks;tcp
a=fingerprint:SHA-1 \
      4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
              Figure 19: SDP with Fingerprint Attribute

14.5. Other Security Concerns ๐ŸŽ€

Okay bestie, this last bit is about the sneaky stuff that doesn't fit anywhere else ๐Ÿ‘€. MSRP can't be used as an amplifier for DoS attacks, but it can be used to build a distributed attack that eats up TCP connection resources on servers ๐Ÿ˜ญ. Here's how it goes: Mallory sends a SIP INVITE with no offer to Alice. Alice replies with a 200 that includes an offer, and Mallory answers with SDP saying his MSRP address is actually Tom's address ๐Ÿ’€. Since Alice sent the offer, Alice starts a connection to Tom and uses up resources on Tom's server. With so many IM clients out there and so few TCP connections most servers can handle, this is a pretty straightforward attack ๐Ÿ˜ค.

SIP is already trying to deal with spam ๐Ÿ™„. Honestly, the spam problem is probably best handled at the SIP level when an MSRP session gets set up, not at the MSRP level ๐Ÿ’….

If a sender chooses to use S/MIME to protect a message, every S/MIME operation applies to the complete message, before the message gets broken up into chunks ๐Ÿงฉ.

The signaling will have set up the session to or from specific URIs, which often use the "im:" or "sip:" URI schemes ๐Ÿฆ‹. When signaling was set up with a specific end user and S/MIME is implemented, the client needs to verify that the SubjectAltName of the certificate contains an entry matching the URI that was used for the other end in the signaling. Some cases, like IM conferencing, won't match up, because the S/MIME certificate name and the signaled identity are different things. In those cases the client should make sure the user knows the message came from whoever is identified in the certificate, and not assume it came from the party they signaled with ๐Ÿ‘€โœจ.

Sometimes a sending device needs to attribute a message to some other identity, and it might use different identities for different messages in the same session. For example, a conference server might send messages on behalf of several users in the same session ๐ŸŽช. Instead of adding new header fields to MSRP for this, MSRP relies on the message/cpim format. The sender can wrap such a message in a message/cpim body and put the actual sender's identity in the From field ๐Ÿ’Œ. How much you can trust that attribution depends on the security properties of the session, the same way it depends on the identity of the actual peer. There's also the extra question of whether the recipient trusts the sender to make that claim in the first place ๐Ÿค”.

This approach can lead to nested message/cpim envelopes ๐Ÿช†. Say a message comes from a CPIM gateway and then a conference server forwards it onto a new session. Both the gateway and the conference server add an envelope. In that case the recipient client SHOULD show the user the whole chain of identity assertions, so the user doesn't just assume the gateway or the conference server wrote the message ๐Ÿซฃ.

A recipient might also get messages attributed to the same sender through different MSRP sessions ๐ŸŒˆ. For example, Alice might be chatting with Bob over an MSRP session on a TLS-protected channel. Then she gets a different message from Bob over another session, maybe through a conference server that asserts Bob's identity in a message/cpim envelope signed by the server ๐Ÿ“จ.

MSRP doesn't prohibit multiple simultaneous sessions between the same pair of identities ๐Ÿ‘ฏ. It also doesn't prohibit an endpoint from sending a message on behalf of another identity, which is the case for a conference server ๐ŸŽ€. The recipient's endpoint should decide how much it trusts the authenticity of the sender independently for each session. Trusting the sender on one session should not change how much it trusts what looks like the same sender on a different session ๐Ÿง .

When MSRP clients form or acquire a certificate, they SHOULD make sure the subjectAltName has a GeneralName entry of type uniformResourceIdentifier for each URI that belongs to this client, and they should always include an "im:" URI ๐Ÿ“œ. It's fine if the certificate also has other URIs, like "sip:" or "xmpp:" URIs ๐Ÿ’–.

โš ๏ธ MSRP implementors, watch out! There's a potential attack on MSRP devices that puts very large values in the byte-range header field. That can make the device allocate huge memory buffers to hold the message ๐Ÿ˜ฑ. Implementations SHOULD apply some degree of sanity checking on byte-range values before allocating those buffers ๐Ÿ›ก๏ธ.

15. IANA Considerations ๐Ÿ“š

This specification tells IANA to create a new registry for MSRP parameters ๐Ÿ—‚๏ธ. The MSRP Parameter registry is a container for sub-registries. This section introduces sub-registries for MSRP method names, status codes, and header field names ๐Ÿ’œ.

Also, Section 15.4 through Section 15.7 register new parameters in existing IANA registries ๐Ÿงš.

15.1. MSRP Method Names ๐Ÿ’ซ

This specification sets up the Methods sub-registry under MSRP Parameters and starts filling it in like this. New parameters in this sub-registry must be published in an RFC (either as an IETF submission or RFC Editor submission) ๐Ÿ“.

   SEND - [RFC4975]
   REPORT - [RFC4975]

To register a new MSRP method, the following information MUST be provided in an RFC publication:

  • The method name.
  • The RFC number in which the method is registered.

15.2. MSRP Header Fields ๐Ÿ“

This specification sets up the header field-Field sub-registry under MSRP Parameters. New parameters in this sub-registry must be published in an RFC (either as an IETF submission or RFC Editor submission). The initial population is defined as follows ๐ŸŒธ:

   To-Path - [RFC4975]
   From-Path - [RFC4975]
   Message-ID - [RFC4975]
   Success-Report - [RFC4975]
   Failure-Report - [RFC4975]
   Byte-Range - [RFC4975]
   Status - [RFC4975]

To register a new MSRP header field, the following information MUST be provided in an RFC publication:

  • The header field name.
  • The RFC number in which the method is registered.

15.3. MSRP Status Codes ๐Ÿšฆ

This specification sets up the Status-Code sub-registry under MSRP Parameters. New parameters in this sub-registry must be published in an RFC (either as an IETF submission or RFC Editor submission). Its initial population is defined in Section 10 ๐Ÿ”ฅ. It takes the following format:

   Code [RFC Number]

To register a new MSRP status code, the following information MUST be provided in an RFC publication:

  • The status code number.
  • The RFC number in which the method is registered.

15.4. MSRP Port ๐Ÿ”Œ

MSRP uses TCP port 2855, from the "registered" port range. Usage of this value is described in Section 6 ๐Ÿ’–.

15.5. URI Schema ๐Ÿฆ‹

This document requests permanent registration of the URI schemes "msrp" and "msrps" โœจ.

15.5.1. MSRP Scheme ๐Ÿ’…

   URI Scheme Name:  "msrp"
   URI Scheme Syntax:  See the ABNF construction for "MSRP-URI" in
      Section 9 of RFC 4975.
   URI Scheme Semantics:  See Section 6 of RFC 4975.
   Encoding Considerations:  See Section 6 of RFC 4975.

   Applications/Protocols that use this URI Scheme:  The Message Session
      Relay Protocol (MSRP).
   Interoperability Considerations:  MSRP URIs are expected to be used
      only by implementations of MSRP.  No additional interoperability
      issues are expected.
   Security Considerations:  See Section 14.1 of RFC 4975 for specific
      security considerations for MSRP URIs, and Section 14 of RFC 4975
      for security considerations for MSRP in general.
   Contact:  Ben Campbell (ben@estacado.net).
   Author/Change Controller:  This is a permanent registration request.
      Change control does not apply.

15.5.2. MSRPS Scheme ๐ŸŒˆ

   URI Scheme Name:  "msrps"
   URI Scheme Syntax:  See the ABNF construction for "MSRP-URI" in
      Section 9 of RFC 4975.
   URI Scheme Semantics:  See Section 6 of RFC 4975.
   Encoding Considerations:  See Section 6 of RFC 4975.
   Applications/Protocols that use this URI Scheme:  The Message Session
      Relay Protocol (MSRP).
   Interoperability Considerations:  MSRP URIs are expected to be used
      only by implementations of MSRP.  No additional interoperability
      issues are expected.
   Security Considerations:  See Section 14.1 of RFC 4975 for specific
      security considerations for MSRP URIs, and Section 14 of RFC 4975
      for security considerations for MSRP in general.
   Contact:  Ben Campbell (ben@estacado.net).
   Author/Change Controller:  This is a permanent registration request.
      Change control does not apply.

15.6. SDP Transport Protocol ๐Ÿ“ก

MSRP defines the new SDP protocol field values "TCP/MSRP" and "TCP/TLS/MSRP", which should be registered in the sdp-parameters registry under "proto". The first value indicates the MSRP protocol when TCP is used as the underlying transport. The second indicates that TLS over TCP is used ๐ŸŽ€.

Specifications defining new protocol values must define the rules for the associated media format namespace. The "TCP/MSRP" and "TCP/TLS/MSRP" protocol values allow only one value in the format field (fmt), which is a single occurrence of "*". Actual format determination is made using the "accept-types" and "accept-wrapped-types" attributes ๐Ÿง.

15.7. SDP Attribute Names ๐Ÿซถ

This document registers the following SDP attribute parameter names in the sdp-parameters registry. These names are to be used in the SDP att-name field ๐Ÿ’œ.

15.7.1. Accept Types ๐ŸŒธ

   Contact Information:  Ben Campbell (ben@estacado.net)
   Attribute-name:   accept-types
   Long-form Attribute Name:  Acceptable media types
   Type:  Media level
   Subject to Charset Attribute:  No
   Purpose and Appropriate Values:  The "accept-types" attribute
      contains a list of media types that the endpoint is willing to
      receive.  It may contain zero or more registered media-types, or
      "*" in a space-delimited string.

15.7.2. Wrapped Types ๐ŸŽ€

   Contact Information:  Ben Campbell (ben@estacado.net)
   Attribute-name:   accept-wrapped-types
   Long-form Attribute Name:  Acceptable media types Inside Wrappers
   Type:  Media level
   Subject to Charset Attribute:  No
   Purpose and Appropriate Values:  The "accept-wrapped-types" attribute
      contains a list of media types that the endpoint is willing to
      receive in an MSRP message with multipart content, but may not be
      used as the outermost type of the message.  It may contain zero or
      more registered media-types, or "*" in a space-delimited string.

15.7.3. Max Size ๐Ÿ“

   Contact Information:  Ben Campbell (ben@estacado.net)
   Attribute-name:   max-size
   Long-form Attribute Name:  Maximum message size
   Type:  Media level
   Subject to Charset Attribute:  No
   Purpose and Appropriate Values:  The "max-size" attribute indicates
      the largest message an endpoint wishes to accept.  It may take any
      whole numeric value, specified in octets.

15.7.4. Path ๐Ÿงš

   Contact Information:  Ben Campbell (ben@estacado.net)
   Attribute-name:   path
   Long-form Attribute Name:  MSRP URI Path
   Type:  Media level
   Subject to Charset Attribute:  No
   Purpose and Appropriate Values:  The "path" attribute indicates a
      series of MSRP devices that must be visited by messages sent in
      the session, including the final endpoint.  The attribute contains
      one or more MSRP URIs, delimited by the space character.

16. Contributors and Acknowledgments ๐ŸŽ€

okay bestie, big shoutout time ๐Ÿ“ฃ Chris Boulton, Paul Kyzivat, Orit Levin, Hans Persson, Adam Roach, Jonathan Rosenberg, and Robert Sparks all put in extensive work on this document, in addition to the editors. they literally carried ๐Ÿซถ

the people who gave substantial discussion and feedback to this ongoing effort are Eric Burger, Allison Mankin, Jon Peterson, Brian Rosen, Dean Willis, Aki Niemi, Hisham Khartabil, Pekka Pessi, Miguel Garcia, Peter Ridler, Sam Hartman, and Jean Mahoney. the group chat would not be the same without y'all ๐Ÿ’œ


17. References ๐Ÿ“š

17.1. Normative References

  • [1] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.1", RFC 4346, April 2006.
  • [2] Handley, M., Jacobson, V., and C. Perkins, "SDP: Session Description Protocol", RFC 4566, July 2006.
  • [3] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, June 2002.
  • [4] 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.
  • [5] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [6] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 4234, October 2005.
  • [7] Ramsdell, B., "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.1 Message Specification", RFC 3851, July 2004.
  • [8] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
  • [9] Troost, R., Dorner, S., and K. Moore, "Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field", RFC 2183, August 1997.
  • [10] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.
  • [11] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J., and T. Wright, "Transport Layer Security (TLS) Extensions", RFC 4366, April 2006.
  • [12] Klyne, G. and D. Atkins, "Common Presence and Instant Messaging (CPIM): Message Format", RFC 3862, August 2004.
  • [13] Chown, P., "Advanced Encryption Standard (AES) Ciphersuites for Transport Layer Security (TLS)", RFC 3268, June 2002.
  • [14] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
  • [15] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, November 1996.
  • [16] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3280, April 2002.
  • [17] Peterson, J. and C. Jennings, "Enhancements for Authenticated Identity Management in the Session Initiation Protocol (SIP)", RFC 4474, August 2006.
  • [18] Lennox, J., "Connection-Oriented Media Transport over the Transport Layer Security (TLS) Protocol in the Session Description Protocol (SDP)", RFC 4572, July 2006.

17.2. Informative References

  • [19] Johnston, A. and O. Levin, "Session Initiation Protocol (SIP) Call Control - Conferencing for User Agents", BCP 119, RFC 4579, August 2006.
  • [20] Rosenberg, J., Peterson, J., Schulzrinne, H., and G. Camarillo, "Best Current Practices for Third Party Call Control (3pcc) in the Session Initiation Protocol (SIP)", BCP 85, RFC 3725, April 2004.
  • [21] Sparks, R., Johnston, A., and D. Petrie, "Session Initiation Protocol Call Control - Transfer", Work in Progress, October 2006.
  • [22] Campbell, B., Rosenberg, J., Schulzrinne, H., Huitema, C., and D. Gurle, "Session Initiation Protocol (SIP) Extension for Instant Messaging", RFC 3428, December 2002.
  • [23] Jennings, C., Mahy, R., and A. Roach, "Relay Extensions for the Message Session Relay Protocol (MSRP)", RFC 4976, September 2007.
  • [24] Rosenberg, J., "The Session Initiation Protocol (SIP) UPDATE Method", RFC 3311, October 2002.
  • [25] Jennings, C., Peterson, J., and J. Fischl, "Certificate Management Service for SIP", Work in Progress, July 2007.
  • [26] Yon, D. and G. Camarillo, "TCP-Based Media Transport in the Session Description Protocol (SDP)", RFC 4145, September 2005.
  • [27] Peterson, J., "Common Profile for Instant Messaging (CPIM)", RFC 3860, August 2004.
  • [28] Housley, R., "Triple-DES and RC2 Key Wrapping", RFC 3217, December 2001.
  • [29] Camarillo, G. and H. Schulzrinne, "Early Media and Ringing Tone Generation in the Session Initiation Protocol (SIP)", RFC 3960, December 2004.
  • [30] Saint-Andre, P., "Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence", RFC 3921, October 2004.
  • [31] Rosenberg, J., Schulzrinne, H., and P. Kyzivat, "Indicating User Agent Capabilities in the Session Initiation Protocol (SIP)", RFC 3840, August 2004.
  • [32] Peterson, J., "Address Resolution for Instant Messaging and Presence", RFC 3861, August 2004.

Authors' Addresses ๐Ÿ“ฎ

meet the editors, bestie ๐Ÿงš

Ben Campbell (editor)
Estacado Systems
17210 Campbell Road
Suite 250
Dallas, TX  75252
USA

EMail: ben@estacado.net
Rohan Mahy (editor)
Plantronics
345 Encincal Street
Santa Cruz, CA  95060
USA

EMail: rohan@ekabal.com
Cullen Jennings (editor)
Cisco Systems, Inc.
170 West Tasman Dr.
MS: SJC-21/2
San Jose, CA  95134
USA

Phone: +1 408 421-9990
EMail: fluffy@cisco.com

okay the legal stuff, but make it cute ๐Ÿ™ˆ

Copyright (C) The IETF Trust (2007).

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, THE IETF TRUST 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 on whether 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 are valid or in scope, or on whether any license under such rights might or might not be available. it also doesn't claim it has made any independent effort to identify any such rights. info on how rights in RFC documents are handled lives in BCP 78 and BCP 79.

copies of IPR disclosures made to the IETF Secretariat, any assurances of licenses to be made available, or the result of an attempt to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be found in 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. send that info to the IETF at ietf-ipr@ietf.org. โœจ

๐Ÿ“ฆ where this page comes from