RFC 4975
The Message Session Relay Protocol (MSRP)
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 aFailure-Reportvalue 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 ๐ง
- the scheme MUST match. scheme comparison is case insensitive ๐ท
- 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 ๐
- 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 ๐
- 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 โจ
- 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
- 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
- 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
Alice->Bob (SIP): ACK sip:bob@example.com๐ซถ- (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$
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$
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$
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$
Alice->Bob (SIP): BYE sip:bob@example.com๐
Alice invalidates her local session state ๐งน
- 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
Full Copyright Statement โ๏ธ
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
- ietf: rfc4975 2007-09
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms