RFC 7395

An Extensible Messaging and Presence Protocol (XMPP) Subprotocol for WebSocket

πŸ“… published October 2014, from ietf

RFC 7395: An Extensible Messaging and Presence Protocol (XMPP) Subprotocol for WebSocket πŸŽ€ (Part 1 of 3)

Okay bestie, the title block is giving πŸ’…. This is an IETF doc, written by L. Stout, Ed. (&yet), J. Moffitt (Mozilla), and E. Cestari (cstar industries). It's a Standards Track document, published in October 2014, with ISSN 2070-1721. The title block doesn't list anything it obsoletes or updates.

Abstract 🌸

This doc defines a binding for the Extensible Messaging and Presence Protocol (XMPP) over a WebSocket transport layer. A WebSocket binding for XMPP gives you way higher performance than the current HTTP binding for XMPP πŸš€.

Status of This Memo 🧚

This is an Internet Standards Track document. πŸ’–

It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). For more on Internet Standards, check Section 2 of RFC 5741 πŸ“š.

For the current status, any errata, and how to give feedback, go to http://www.rfc-editor.org/info/rfc7395 πŸ”—.

Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved ©️.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as in effect on the publication date. Please read these carefully, because they spell out your rights and restrictions for this document πŸ“œ. Code Components pulled out of this document must include the Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Simplified BSD License 🫢.

Table of Contents πŸ¦‹

1. Introduction ....................................................2
2. Terminology .....................................................3
3. XMPP Subprotocol ................................................3
   3.1. Handshake ..................................................3
   3.2. WebSocket Messages .........................................4
   3.3. XMPP Framing ...............................................5
        3.3.1. Framed XML Stream ...................................5
        3.3.2. Framed Stream Namespace .............................5
        3.3.3. Stream Frames .......................................5
   3.4. Stream Initiation ..........................................6
   3.5. Stream Errors ..............................................7
   3.6. Closing the Connection .....................................7
        3.6.1. see-other-uri .......................................8
   3.7. Stream Restarts ............................................9
   3.8. Pings and Keepalives .......................................9
   3.9. Use of TLS .................................................9
   3.10. Stream Management ........................................10
4. Discovering the WebSocket Connection Method ....................10
5. IANA Considerations ............................................11
   5.1. WebSocket Subprotocol Name ................................11
   5.2. URN Sub-namespace .........................................11
6. Security Considerations ........................................12
7. References .....................................................14
   7.1. Normative References ......................................14
   7.2. Informative References ....................................14
Appendix A. XML Schema ............................................16
Acknowledgements ..................................................17
Authors' Addresses ................................................18

1. Introduction ✨

So, apps using XMPP (see [RFC6120] and [RFC6121]) on the Web have been using Bidirectional-streams Over Synchronous HTTP (BOSH) (see [XEP-0124] and [XEP-0206]), which is an XMPP binding to HTTP πŸ™ˆ. BOSH is built on the HTTP "long polling" technique, and it has way more transport overhead than XMPP's native binding to TCP. There are also a bunch of other known issues with long polling [RFC6202] that hit BOSH-based systems too 😭.

Honestly, in most situations it'd be so much better to skip tunneling XMPP over HTTP long-polled connections and just use XMPP directly. The problem is that the APIs and sandbox browsers give us don't allow that πŸ’€. The WebSocket protocol [RFC6455] exists to fix exactly this kind of problem. It's bidirectional, gives you a simple message-based framing layer, and makes communication in web apps way more robust and efficient πŸ”₯.

The WebSocket protocol gives a client and a server two-way communication, basically emulating TCP at the application layer. That means it beats a lot of the problems with existing long-polling techniques for bidirectional HTTP πŸ‘‘. This document defines a WebSocket subprotocol for XMPP.

The WebSocket binding for XMPP is built for browser-based apps (like XMPP clients written in JavaScript) 🌈. These apps usually get to see the same info and chat opportunities (like the same XMPP "roster" of contacts) as clients that connect to an XMPP server over the TCP binding defined in [RFC6120]. The only real difference is the underlying transport binding, but there are some related implications (like framing methods and discovery processes) that this spec calls out πŸŽ€.

2. Terminology πŸ¦‹

In WebSocket, the basic unit of framing is called a "message". In XMPP, the basic unit is the stanza, which is a subset of the first-level children of each document in an XMPP stream (see Section 9 of [RFC6120]). XMPP also has messages, which are stanzas with a top-level element of <message/>. In this document, the word "message" means a WebSocket message, not an XMPP message stanza (unless noted otherwise) 🧠.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] πŸ“–.

3. XMPP Subprotocol πŸ’–

3.1. Handshake 🀝

The XMPP subprotocol is what carries XMPP over a WebSocket connection. The client and server agree to use this protocol during the WebSocket handshake (see Section 1.3 of [RFC6455]).

During the WebSocket handshake, the client MUST include the value 'xmpp' in the list of protocols for the 'Sec-WebSocket-Protocol' header. The server's reply MUST also contain 'xmpp' in its own 'Sec-WebSocket-Protocol' header, or an XMPP subprotocol connection won't get established πŸ™…β€β™€οΈ.

If a client gets a handshake response that doesn't include 'xmpp' in the 'Sec-WebSocket-Protocol' header, then an XMPP subprotocol WebSocket connection wasn't established, and the client MUST close the WebSocket connection πŸšͺ.

Once the handshake has successfully completed, WebSocket messages sent or received MUST conform to the protocol defined in the rest of this document βœ….

Here's an example of a WebSocket handshake, followed by opening an XMPP stream 🧚:

C:  GET /xmpp-websocket HTTP/1.1
    Host: example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Origin: http://example.com
    ...
    Sec-WebSocket-Protocol: xmpp
    Sec-WebSocket-Version: 13

S:  HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    ...
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    Sec-WebSocket-Protocol: xmpp

[WebSocket connection established]

C:  <open xmlns="urn:ietf:params:xml:ns:xmpp-framing"
          to="example.com"
          version="1.0" />

S:  <open xmlns="urn:ietf:params:xml:ns:xmpp-framing"
          from="example.com"
          id="++TR84Sm6A3hnt3Q065SnAbbk3Y="
          xml:lang="en"
          version="1.0" />

3.2. WebSocket Messages πŸ’Œ

Data frame messages in the XMPP subprotocol MUST be of the text type and contain UTF-8 encoded data πŸ”€.

3.3. XMPP Framing πŸŽ€

The framing method for the XMPP-to-WebSocket binding is different from the framing method for the TCP binding defined in [RFC6120]. The big difference is that the WebSocket binding uses the message framing WebSocket already provides to mark off the stream open and close headers, stanzas, and other top-level stream elements πŸ“¦.

3.3.1. Framed XML Stream 🌸

A framed XML stream starts with an opening "stream header". That's an <open/> element with the right attributes and namespace declarations (see Section 3.3.2). The attributes of the <open/> element are the same as those of the <stream/> element defined for the 'http://etherx.jabber.org/streams' namespace [RFC6120], with the same semantics and restrictions 🧁.

A framed XML stream ends with the closing "stream header", which is a <close/> element with its attributes and namespace declarations (see Section 3.3.2) πŸ”š.

The <open/> and <close/> elements exist because of the parsable XML document framing restriction in Section 3.3.3. As a result, a framed XML stream doesn't have a wrapping <stream:stream/> [RFC6120] element around the whole XML stream, so don't look for one πŸ‘€.

3.3.2. Framed Stream Namespace πŸ§šβ€β™€οΈ

The XML stream headers (the <open/> and <close/> elements) MUST be qualified by the namespace 'urn:ietf:params:xml:ns:xmpp-framing' (the "framed stream namespace"). If this rule is broken, the entity that gets the offending stream header MUST close the stream with an error, and that error MUST be <invalid-namespace> (see Section 4.9.3.10 of [RFC6120]) 🚫.

3.3.3. Stream Frames πŸ¦‹

Each frame of a framed XML stream has a one-to-one correspondence with a WebSocket message, and each frame MUST be parsable as a standalone XML document, complete with all the relevant namespace and language declarations 🧩. Including XML declarations is NOT RECOMMENDED, though, because WebSocket messages are already required to be UTF-8 encoded. Adding declarations to every message would only add framing overhead to each one πŸ™…β€β™€οΈ.

The first character of each frame MUST be a '<' character ✨.

Every XMPP stanza or other XML element (including the stream open and close headers) sent directly over the XML stream MUST be sent in its own frame πŸ“¬.

Here's an example of a WebSocket message that holds an independently parsable XML document:

<message xmlns="jabber:client" xml:lang="en">
  <body>Every WebSocket message is parsable by itself.</body>
</message>

For stream features and errors, there's no parent context element giving the "stream" namespace prefix like there is in [RFC6120], so the stream prefix MUST be declared or an unprefixed form MUST be used instead πŸŽ€:

<stream:features xmlns:stream="http://etherx.jabber.org/streams">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
</stream:features>

-- OR --

<error xmlns="http://etherx.jabber.org/streams">
  <host-unknown xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
</error>

3.4. Stream Initiation ✨

okay bestie, the very first message you send after the WebSocket opening handshake MUST come from the initiating entity 🫢 and it MUST be an <open/> element qualified by the urn:ietf:params:xml:ns:xmpp-framing namespace. It also has to carry the same attributes that the <stream> opening tag needs, as described in Section 4.7 of [RFC6120] πŸŽ€

The receiving entity MUST respond with either an <open/> element (whose attributes match what Section 4.7 of [RFC6120] describes) or a <close/> element (see Section 3.6.1). those are the only two options, periodt πŸ’…

Here's a successful stream initiation, lowkey iconic πŸ¦‹

C:  <open xmlns="urn:ietf:params:xml:ns:xmpp-framing"
          to="example.com"
          version="1.0" />

S:  <open xmlns="urn:ietf:params:xml:ns:xmpp-framing"
          from="example.com"
          id="++TR84Sm6A3hnt3Q065SnAbbk3Y="
          xml:lang="en"
          version="1.0" />

Clients MUST NOT multiplex XMPP streams over the same WebSocket. no stacking multiple streams on one socket, that's a hard no πŸ™…β€β™€οΈ

3.5. Stream Errors πŸ’€

Stream-level errors in XMPP are fatal, so yeah, they're serious business 😭 If one shows up, the server MUST send the stream error as a complete element in a message to the client.

If the error happens while the stream is still opening, the server MUST send the initial open element response, followed by the stream-level error in a second WebSocket message frame. Then the server MUST close the connection as specified in Section 3.6.

3.6. Closing the Connection πŸ‘‹

The closing process for the XMPP subprotocol basically mirrors the XMPP TCP binding in Section 4.4 of [RFC6120], except a <close/> element is used instead of the ending </stream:stream> tag. it's giving familiar 🌸

Either the server or the client can close the connection at any time. Before closing, the closing party is expected to first close the XMPP stream (if one was opened) by sending a message with the <close/> element, qualified by the "urn:ietf:params:xml:ns:xmpp-framing" namespace. The stream counts as closed once a matching <close/> element comes back from the other party, and then the XMPP session is ended.

To close the WebSocket connection afterwards, the closing party MUST initiate the WebSocket closing handshake (see Section 7.1.2 of [RFC6455]).

Here's an example of ending an XMPP-over-WebSocket session by closing the XMPP stream layer first and then the WebSocket connection layer 🧚

Client                         (XMPP WSS)                      Server
|  |                                                             |  |
|  | <close xmlns="urn:ietf:params:xml:ns:xmpp-framing" />       |  |
|  |------------------------------------------------------------>|  |
|  |       <close xmlns="urn:ietf:params:xml:ns:xmpp-framing" /> |  |
|  |<------------------------------------------------------------|  |
|  |                                                             |  |
|  |                      (XMPP Stream Closed)                   |  |
|  +-------------------------------------------------------------+  |
|                                                                   |
| WS CLOSE FRAME                                                    |
|------------------------------------------------------------------>|
|                                                    WS CLOSE FRAME |
|<------------------------------------------------------------------|
|                                                                   |
|                         (Connection Closed)                       |
+-------------------------------------------------------------------+

If the WebSocket connection gets closed or breaks before the XMPP stream was closed first, the XMPP stream is treated as implicitly closed and the XMPP session ends πŸ’” BUT, if stream management resumption was negotiated (see [XEP-0198]), the server SHOULD consider the XMPP session still alive for a period of time based on server policy, as specified in [XEP-0198]. second chances are everything 🫢

3.6.1. see-other-uri πŸ›Έ

At any point, if the server wants to tell the client to move to a different WebSocket endpoint (e.g., for load-balancing purposes), it sends a <close/> element with the 'see-other-uri' attribute set to the URI of the new connection endpoint. That new endpoint MAY be for a different transport method, such as BOSH (see [XEP-0124] and [XEP-0206]).

Clients MUST NOT accept suggested endpoints with a lower security context (e.g., moving from a 'wss://' endpoint to a 'ws://' or 'http://' endpoint). no downgrading your security, ever πŸ”

Here's the server closing a stream and pointing the client at a different WebSocket endpoint:

S: <close xmlns="urn:ietf:params:xml:ns:xmpp-framing"
          see-other-uri="wss://otherendpoint.example/xmpp-bind" />

3.7. Stream Restarts πŸ”„

Whenever a stream restart is mandated (see Section 4.3.3 of [RFC6120]), both the server and client streams are implicitly closed, and new streams MUST be opened using the same process as in Section 3.4.

The client MUST send a new stream <open/> element and MUST NOT send a closing <close/> element. so it's a fresh open, not a close πŸ’–

Here's what restarting the stream looks like after a successful Simple Authentication and Security Layer (SASL) negotiation ✨

S: <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />

[Streams implicitly closed]

C: <open xmlns="urn:ietf:params:xml:ns:xmpp-framing"
         to="example.com"
         version="1.0" />

3.8. Pings and Keepalives πŸ“

Traditionally, XMPP servers and clients often send "whitespace keepalives" (see Section 4.6.1 of [RFC6120]) between stanzas to keep an XML stream alive. BUT for the XMPP subprotocol, each message has to start with a '<' character, so whitespace keepalives MUST NOT be used. no sneaky whitespace, bestie πŸ™ˆ

Good news though! the XMPP Ping extension [XEP-0199] and the XMPP Stream Management extension [XEP-0198] both give you pinging mechanisms instead πŸ’œ Either of these extensions (or both) MAY be used to figure out the state of the connection.

Clients and servers MAY also use WebSocket ping control frames for this purpose. just note that some environments, like browsers, don't give you access to generate or monitor ping control frames, so keep that in mind πŸ‘€

3.9. Use of TLS πŸ”

Transport Layer Security (TLS) can't be used at the XMPP subprotocol layer, because the subprotocol doesn't allow raw binary data to be sent. Instead, when TLS is used, it MUST be enabled at the WebSocket layer using secure WebSocket connections via the 'wss' URI scheme. (See Section 10.6 of [RFC6455].)

Since TLS is provided outside of the XMPP subprotocol layer, a server MUST NOT advertise TLS as a stream feature (see Section 4.6 of [RFC6120]) when using the XMPP subprotocol. Likewise, a client MUST ignore any advertised TLS stream feature when using the XMPP subprotocol. πŸ›‘οΈ

3.10. Stream Management πŸ“Š

To soften the blow of temporary disconnections, the client MAY use the XMPP Stream Management extension [XEP-0198] to confirm when stanzas have been received by the server.

Specifically, the client MAY use session resumption as described in [XEP-0198] to recreate the same stream session state after a temporary network drop, or after navigating to a new URL in a browser. main character recovery arc πŸ‘‘

4. Discovering the WebSocket Connection Method πŸ”

Section 3 of [RFC6120] explains how to connect to an XMPP server, including how to find the TCP/IP address and port using Domain Name System service (DNS SRV) records [RFC2782]. When you're using the WebSocket binding (instead of the TCP binding in [RFC6120]), a client needs a different way to find out how the server's connections work, since web browsers and other WebSocket-capable apps usually can't get that info from DNS. it's a whole different vibe 🌈

The alternative lookup uses Web-host Metadata [RFC6415] and Web Linking [RFC5988], where the link relation type is "urn:xmpp:alt-connections:websocket" as described in "Discovering Alternative XMPP Connection Methods" [XEP-0156]. Conceptually, the host-meta lookup for the WebSocket binding is kind of the same idea as the DNS SRV lookup for the TCP binding 🧠 Here's how it goes:

  1. Send a request over secure HTTP to the path "/.well-known/host-meta" at an HTTP origin [RFC6454] that matches the XMPP service domain (e.g., a URL of "https://im.example.org/.well-known/host-meta" if the XMPP service domain is "im.example.org").
  2. Retrieve a host-meta document specifying a link relation type of "urn:xmpp:alt-connections:websocket", such as:
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
  <Link rel="urn:xmpp:alt-connections:websocket"
        href="wss://im.example.org:443/ws" />
</XRD>

Servers MAY expose discovery information using host-meta documents, and clients MAY use that information to figure out the WebSocket endpoint for a server. πŸŽ€

Now, if the XMPP service domain doesn't match the discovered web origin of the WebSocket endpoint, the Web-host Metadata SHOULD be used to establish trust between the XMPP server domain and the WebSocket endpoint, as long as the host-meta request and response happened over secure HTTP. this matters SO much in multi-tenant situations, where one WebSocket endpoint is serving multiple XMPP domains (e.g., the XMPP service domains for both "example.com" and "im.example.org" might be served by the same WebSocket endpoint at "hosting.example.net"). See Section 6 for related discussion πŸ’…

5. IANA Considerations πŸ“

5.1. WebSocket Subprotocol Name 🏷️

IANA has registered the WebSocket XMPP subprotocol in the "WebSocket Subprotocol Name Registry", with the following data:

Subprotocol Identifier:  xmpp

Subprotocol Common Name:  WebSocket Transport for the Extensible
   Messaging and Presence Protocol (XMPP)

Subprotocol Definition:  this document

5.2. URN Sub-namespace 🌸

A URN sub-namespace for framing of Extensible Messaging and Presence Protocol (XMPP) streams is defined as follows:

URI:  urn:ietf:params:xml:ns:xmpp-framing

Specification:  this document
Description:  This is the XML namespace name for framing of
   Extensible Messaging and Presence Protocol (XMPP) streams as
   defined by RFC 7395.

Registrant Contact:  IESG <iesg@ietf.org>

6. Security Considerations πŸ”’

okay bestie, this part is SERIOUS but also kind of iconic πŸ’…. The WebSocket binding for XMPP is different from the TCP binding in [RFC6120] in a few key ways, so let's go through them:

  1. Finding a connection endpoint doesn't use DNS SRV records like the TCP binding does. Instead, it uses Web-host Metadata files fetched over HTTPS from a URL on the XMPP service domain (see Section 4 of this document). Security-wise, this is basically the same as DNS SRV resolution 🀝, and it still depends on DNS to resolve the XMPP source domain.
  2. Authenticating the connection endpoint uses TLS, usually with PKIX certificates, just like the TCP binding πŸ”. The difference is WHO gets authenticated: it's the connection endpoint address, not the XMPP service domain. Delegation from the service domain to that endpoint address (if there is one) happens through the discovery method in Section 4. So the endpoint still gets authenticated, and the delegation stays secure as long as the Web-host Metadata file is retrieved via HTTPS. Heads up though: in practice, this option might not be used when user agents are configured or deployed for a particular delegated domain.
  3. The framing method in Section 3.3 follows the WebSocket pattern, so each top-level XML element goes in its own WebSocket message, instead of streaming XML like the TCP binding does πŸ“¦. But the framing has no effect on the session's security properties. For example, end-to-end encryption of XML stanzas works just as well with WebSocket framing as it does with streaming XML πŸ™Œ.
  4. Everything else is the same as the TCP binding πŸ’–, like user authentication via SASL, which characters are allowed in XMPP addresses, and the reuse of Base 64, SASL mechanisms, UTF-8, and XML. So the WebSocket binding doesn't change the security properties of the protocol. All of those security considerations from [RFC6120] apply directly to the WebSocket binding.

To make sure WebSocket communications are just as secure as TCP ones, an operator needs to:

  1. serve the Web-host Metadata file for the XMPP service domain over secure HTTP (https URIs) only,
  2. configure the WebSocket connection endpoint to use TLS (wss URIs) only, and
  3. deploy certificates that properly identify the XMPP service domain and the WebSocket connection endpoint for usages (1) and (2), respectively.
🚨 Hot take: since application-level TLS can't be used (see Section 3.9), applications need to protect the privacy of XMPP traffic at the WebSocket layer or another appropriate layer. Don't skip this, bestie!

Browser-based apps can't inspect and verify, at the application layer, the certificate used for the WebSocket connection πŸ‘€. That means they can't check that it matches the domain in the 'to' address of the XMPP stream. There are two cases:

  1. If the XMPP service domain matches the origin for the WebSocket connection, the browser already does the check βœ…. For example, the XMPP service domain might be "foo.example", and the WebSocket endpoint discovered for the link relation type of "urn:xmpp:alt-connections:websocket" might be "wss://foo.example/websocket". As long as the certificate provided over WebSocket or HTTPS is verified according to the rules for secure HTTP [RFC2818], the browser will report that a secure connection was established. (But here's the tea β˜•: the app still can't inspect and verify the certificate on its own, so it has to trust the browser. This is a limit of existing browser tech, and WebSocket apps can't work around it.)
  2. If the user agent has to deal with delegation, and the XMPP server's domain doesn't match the web origin of the WebSocket endpoint (like in multi-tenant hosting situations 🏘️), the host-meta process from Section 4 SHOULD be used to delegate trust from the XMPP server domain to the WebSocket origin. This only works as long as the host-meta request and response happened over secure HTTP, with proper certificate verification as defined in [RFC2818].

When a new WebSocket endpoint shows up via the 'see-other-uri' attribute of a <close/> element, clients MUST NOT accept the suggestion if the security context of the new endpoint is lower than the current one. This prevents downgrade attacks from a 'wss://' endpoint to 'ws://' πŸš«β¬‡οΈ. Absolutely not, no notes.

The security considerations for both WebSocket (see Section 10 of [RFC6455]) and XMPP (see Section 13 of [RFC6120]) apply to the WebSocket XMPP subprotocol. So go read those too, bestie πŸ“šπŸ«Ά.


7. References πŸ“š

7.1. Normative References

These are the must-reads, the ones the spec leans on hard:

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997,
           <http://www.rfc-editor.org/info/rfc2119>.

[RFC2818]  Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000,
           <http://www.rfc-editor.org/info/rfc2818>.

[RFC5988]  Nottingham, M., "Web Linking", RFC 5988, October 2010,
           <http://www.rfc-editor.org/info/rfc5988>.

[RFC6120]  Saint-Andre, P., "Extensible Messaging and Presence
           Protocol (XMPP): Core", RFC 6120, March 2011,
           <http://www.rfc-editor.org/info/rfc6120>.

[RFC6415]  Hammer-Lahav, E. and B. Cook, "Web Host Metadata", RFC
           6415, October 2011,
           <http://www.rfc-editor.org/info/rfc6415>.

[RFC6455]  Fette, I. and A. Melnikov, "The WebSocket Protocol", RFC
           6455, December 2011,
           <http://www.rfc-editor.org/info/rfc6455>.

7.2. Informative References

These are the extra-credit reads, helpful for context but not required:

[RFC2782]  Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
           specifying the location of services (DNS SRV)", RFC 2782,
           February 2000, <http://www.rfc-editor.org/info/rfc2782>.

[RFC6121]  Saint-Andre, P., "Extensible Messaging and Presence
           Protocol (XMPP): Instant Messaging and Presence", RFC
           6121, March 2011,
           <http://www.rfc-editor.org/info/rfc6121>.

[RFC6202]  Loreto, S., Saint-Andre, P., Salsano, S., and G. Wilkins,
           "Known Issues and Best Practices for the Use of Long
           Polling and Streaming in Bidirectional HTTP", RFC 6202,
           April 2011, <http://www.rfc-editor.org/info/rfc6202>.

[RFC6454]  Barth, A., "The Web Origin Concept", RFC 6454,
           December 2011, <http://www.rfc-editor.org/info/rfc6454>.

[XEP-0124] Paterson, I., Smith, D., Saint-Andre, P., Moffitt, J.,
           Stout, L., and W. Tilanus, "Bidirectional-streams Over
           Synchronous HTTP (BOSH)", XSF XEP 0124, April 2014.

[XEP-0156] Hildebrand, J., Saint-Andre, P., and L. Stout,
           "Discovering Alternative XMPP Connection Methods",
           XSF XEP 0156, January 2014.

[XEP-0198] Karneges, J., Saint-Andre, P., Hildebrand, J., Forno, F.,
           Cridland, D., and M. Wild, "Stream Management",
           XSF XEP 0198, June 2011.

[XEP-0199] Saint-Andre, P., "XMPP Ping", XSF XEP 0199, June 2009.

[XEP-0206] Paterson, I., Saint-Andre, P., Stout, L., and W. Tilanus,
"XMPP Over BOSH", XSF XEP 0206, April 2014.

[XML-SCHEMA]
           Thompson, H., Beech, D., Maloney, M., and N. Mendelsohn,
           "XML Schema Part 1: Structures Second Edition", World Wide
           Web Consortium Recommendation REC-xmlschema-1-20041028,
           October 2004,
           <http://www.w3.org/TR/2004/REC-xmlschema-1-20041028>.

Appendix A. XML Schema 🧩

This schema formally defines the 'urn:ietf:params:xml:ns:xmpp-framing' namespace used in this document, following W3C XML Schema [XML-SCHEMA]. Validating XML streams and stanzas is optional, so this schema is NOT normative, and it's only here for descriptive purposes. (Not a normative requirement, just a helpful map πŸ—ΊοΈ.)

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='urn:ietf:params:xml:ns:xmpp-framing'
    xmlns='urn:ietf:params:xml:ns:xmpp-framing'
    elementFormDefault='unqualified'>

  <xs:element name='open'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='from' type='xs:string'
                        use='optional'/>
          <xs:attribute name='id' type='xs:string'
                        use='optional'/>
          <xs:attribute name='to' type='xs:string'
                        use='optional'/>
          <xs:attribute name='version' type='xs:decimal'
                        use='optional'/>
          <xs:attribute ref='xml:lang'
                        use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:element name='close'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='from' type='xs:string'
                        use='optional'/>
          <xs:attribute name='id' type='xs:string'
                        use='optional'/>
          <xs:attribute name='see-other-uri' type='xs:anyURI'
                        use='optional'/>
          <xs:attribute name='to' type='xs:string'
                        use='optional'/>
          <xs:attribute name='version' type='xs:decimal'
                        use='optional'/>
          <xs:attribute ref='xml:lang'
                        use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

Acknowledgements πŸ’œ

The authors would like to thank these lovely people for their feedback: Andreas Guth, Bjoern Hoerhmann, Dave Cridland, Florian Zeitz, Kurt Zeilenga, Matt Miller, Matthew Wild, Paul Aurich, Sergey Dobrov, and Waqas Hussain 🫢.

Dan Romascanu reviewed the document on behalf of the General Area Review Team 🌸.

During IESG review, Barry Leiba, Benoit Claise, Dan Romascanu, Jari Arkko, Juergen Schoenwaelder, Spencer Dawkins, Stephen Farrell, Ted Lemon, Kathleen Moriarty, and Pete Resnick caught several issues that needed to be addressed. Iconic squad of reviewers πŸ‘‘.

The authors also gratefully acknowledge the help of Peter Saint-Andre as document shepherd, Ben Campbell and Joe Hildebrand as the working group chairs, and Richard Barnes as the sponsoring Area Director πŸ¦‹.


Authors' Addresses βœ‰οΈ

Lance Stout (editor)
&yet

EMail: lance@andyet.net


Jack Moffitt
Mozilla

EMail: jack@metajack.im


Eric Cestari
cstar industries

EMail: eric@cstar.io
πŸ“¦ where this page comes from