diff --git a/xep-0124.xml b/xep-0124.xml index b2fb85fb..87c68975 100644 --- a/xep-0124.xml +++ b/xep-0124.xml @@ -152,9 +152,10 @@

The following design requirements reflect the need to offer performance as close as possible to a standard TCP connection.

  1. Compatible with constrained runtime environments** (e.g., mobile and browser-based clients).
  2. -
  3. Enable browser-based clients to make cross-domain connections.*
  4. +
  5. Enable browser-based clients to make bi-directional cross-domain connections.*
  6. Compatible with proxies that buffer partial HTTP responses.*
  7. -
  8. Compatible with HTTP/1.0.
  9. +
  10. Efficient through proxies that limit the duration of HTTP responses.*
  11. +
  12. Fully-compatible with HTTP/1.0.*
  13. Compatible with restricted network connections (e.g., firewalls, proxies, and gateways).
  14. Fault tolerant (e.g., session recovers after an underlying TCP connection breaks at any stage during an HTTP request).
  15. Extensible.
  16. @@ -193,8 +194,8 @@ Connection Manager

    Since HTTP is a synchronous request/response protocol, the traditional solution to emulating a bidirectional-stream over HTTP involved the client intermittently polling the connection manager to discover if it has any data queued for delivery to the client. This naive approach wastes a lot of network bandwidth by polling when no data is available. It also reduces the responsiveness of the application since the data spends time queued waiting until the connection manager receives the next poll (HTTP request) from the client. This results in an inevitable trade-off between responsiveness and bandwidth, since increasing the polling frequency will decrease latency but simultaneously increase bandwidth consumption (or vice versa if polling frequency is decreased).

    The technique employed by this protocol achieves both low latency and low bandwidth consumption by encouraging the connection manager not to respond to a request until it actually has data to send to the client. As soon as the client receives a response from the connection manager it sends another request, thereby ensuring that the connection manager is (almost) always holding a request that it can use to "push" data to the client.

    -

    If the client needs to send some data to the connection manager then it simply sends a second request containing the data. Unfortunately most constrained clients do not support HTTP Pipelining (concurrent requests over a single connection), so the client typically needs to send the data over a second HTTP connection. The connection manager always responds to the request it has been holding on the first connection as soon as it receives a new request from the client - even if it has no data to send the client. It does that to make sure the client can send more data immediately if necessary. (The client cannot open more than two HTTP connections at the same time, In order to reduce network congestion, RFC 2616 recommends that clients SHOULD NOT keep more than two HTTP connections to the same HTTP server open at the same time. Clients running in constrained enviroments typically have no choice but to abide by that recommendation. so it would otherwise have to wait until the connection manager responds to one of the requests.)

    -

    BOSH works reliably even if network conditions force every HTTP request to be made over a different TCP connection. However, if as is usually the case, the client is able to use HTTP/1.1, then (assuming reliable network conditions) all requests during a session will pass over the same two persistent connections. Almost all of the time (see below) the client is able to push data on one of the connections, while the connection manager is able to "push" data on the other (so latency is as low as a standard TCP connection). It's interesting to note that the roles of the two connections typically switch whenever the client sends data to the connection manager.

    +

    If the client needs to send some data to the connection manager then it simply sends a second request containing the data. Unfortunately most constrained clients do not support HTTP Pipelining (concurrent requests over a single connection), so the client typically needs to send the data over a second HTTP connection. The connection manager always responds to the request it has been holding on the first connection as soon as it receives a new request from the client - even if it has no data to send the client. It does that to make sure the client can send more data immediately if necessary. (The client SHOULD NOT open more than two HTTP connections to the connection manager at the same time, In order to reduce network congestion, RFC 2616 recommends that clients SHOULD NOT keep more than two HTTP connections to the same HTTP server open at the same time. Clients running in constrained enviroments typically have no choice but to abide by that recommendation. so it would otherwise have to wait until the connection manager responds to one of the requests.)

    +

    BOSH works reliably even if network conditions force every HTTP request to be made over a different TCP connection. However, if as is usually the case, the client is able to use HTTP/1.1, then (assuming reliable network conditions) all requests during a session will pass over the same two persistent TCP connections. Almost all of the time (see below) the client is able to push data on one of the connections, while the connection manager is able to "push" data on the other (so latency is as low as a standard TCP connection). It's interesting to note that the roles of the two connections typically switch whenever the client sends data to the connection manager.

    If there is no traffic in either direction for an agreed amount of time (typically a couple of minutes), then the connection manager responds to the client with no data, and that response immediately triggers a fresh client request. The connection manager does that to ensure that if a network connection is broken then both parties will realise within a reasonable amount of time. This exchange is similar to the "keep-alive" or "ping" that is common practice over most persistent TCP connections. Since the BOSH technique involves no polling, bandwidth consumption is not significantly greater than a standard TCP connection. If there is no traffic other than the "pings" then bandwidth consumption will be double that of a TCP connection (although double nothing is still nothing). If data is sent in large packets then bandwidth consumption will be almost identical.

    Most of the time data can be pushed immediately. However, if one of the endpoints has just pushed some data then it will usually have to wait for a network round trip until it is able to push again. If HTTP Pipelining is available to the client then multiple concurrent requests are possible. So the client can always push data immediately. It can also ensure the connection manager is always holding enough requests such that even during bursts of activity it will never have to wait before pushing data. Furthermore, if the pool of requests being held by the connection manager is large enough, then the client will not be under pressure to send a new empty request immediately after receiving data from the connection manager. It can instead wait until it needs to send data. So, if over time the traffic to and from the client is balanced, bandwidth consumption will be about the same as if a standard TCP connection was being used.

    Each block of data pushed by the connection manager is a complete HTTP response. So, unlike the Comet technique, the BOSH technique works through intermediate proxies that buffer partial HTTP responses. It is also fully compliant with HTTP/1.0 - which does not provide for chunked transfer encoding. Also unlike Comet, Web clients can use BOSH to make cross-domain connections.

    @@ -204,7 +205,7 @@ Connection Manager

    Clients SHOULD send all HTTP requests over a single persistent HTTP/1.1 connection using HTTP Pipelining. However, a client MAY deliver its POST requests in any way permited by RFC 1945 or RFC 2616. For examples, constrained clients can be expected to open more than one persistent connection instead of using Pipelining, or in some cases to open a new HTTP/1.0 connection to send each request. However, clients and connection managers SHOULD NOT use Chunked Transfer Coding, since intermediaries may buffer each partial HTTP request or response and only forward the full request or reponse once it is available.

    Clients MAY include an HTTP Accept-Encoding header in any request. If the connection manager receives a request with an Accept-Encoding header, it MAY include an HTTP Content-Encoding header in the response (indicating one of the encodings specified in the request) and compress the response body accordingly.

    Requests and responses MAY include HTTP headers not specified herein. The receiver SHOULD ignore any such headers.

    -

    Each BOSH session MAY share the HTTP connection(s) it uses with other HTTP traffic, including other BOSH sessions and HTTP requests and responses completely unrelated to this protocol (e.g., web page downloads).

    +

    Each BOSH session MAY share the HTTP connection(s) it uses with other HTTP traffic, including other BOSH sessions and HTTP requests and responses completely unrelated to this protocol (e.g., web page downloads). However, the responses to requests that are not part of the session sent over the same connection using HTTP pipelining (or queued to be sent over the same connection) may be delayed if they were sent while a request that is part of the session is being held (since the connection manager MUST send its responses in the same order that the requests were received, and the connection manager typically delays its responses).

    The HTTP Content-Type header of all client requests SHOULD be "text/xml; charset=utf-8". However, clients MAY specify another value if they are constrained to do so (e.g., "application/x-www-form-urlencoded" or "text/plain"). The client and connection manager SHOULD ignore all HTTP Content-Type headers they receive.

    @@ -220,7 +221,7 @@ Connection Manager

    The <body/> wrapper MUST NOT contain any XML character data, although its child elements MAY contain character data. The <body/> wrapper MUST contain zero or more complete XML immediate child elements (called "stanzas" in this document, e.g., XMPP stanzas, or elements containing XML character data that represents objects using the JSON data interchange format - see &rfc4627;). Each <body/> wrapper MAY contain stanzas qualified under a wide variety of different namespaces.

    The <body/> element of every client request MUST possess a sequential request ID encapsulated via the 'rid' attribute; For details, refer to the Request IDs section of this document.

    - +

    The first request from the client to the connection manager requests a new session.

    The <body/> element of the first request SHOULD possess the following attributes (they SHOULD NOT be included in any other requests except as specified in Adding Streams To A Session):

    @@ -231,13 +232,13 @@ Connection Manager
  17. 'wait' -- This attribute specifies the longest time (in seconds) that the connection manager is allowed to wait before responding to any request during the session. This enables the client to limit the delay before it discovers any network failure, and to prevent its HTTP/TCP connection from expiring due to inactivity.
  18. 'hold' -- This attribute specifies the maximum number of requests the connection manager is allowed to keep waiting at any one time during the session. If the client is not able to use HTTP Pipelining then this SHOULD be set to "1".
  19. -

    Note: Clients that only support Polling Sessions MAY prevent the connection manager from waiting by setting 'wait' or 'hold' to "0". However, polling is NOT RECOMMENDED since the associated increase in bandwidth consumption and the decrease in responsiveness are typically one or two orders of magnitude!

    +

    Note: Clients that only support Polling Sessions MAY prevent the connection manager from waiting by setting 'wait' or 'hold' to "0". However, polling is NOT RECOMMENDED since the associated increase in bandwidth consumption and the decrease in responsiveness are both typically one or two orders of magnitude!

    A connection manager MAY be configured to enable sessions with more than one &server; in different domains. When requesting a session with such a 'proxy' connection manager, a client SHOULD include a 'route' attribute that specifies the protocol, hostname, and port of the &server; with which it wants to communicate, formatted as "proto:host:port" (e.g., "xmpp:jabber.org:9999"). Although the syntax of the 'route' attribute bears a superficial resemblance to a URI or IRI, it is not a URI/IRI and MUST NOT be processed in accordance with the rules specified in RFC 3986, RFC 3987, or draft-saintandre-xmpp-iri. A connection manager that is configured to work only with a single &server; (or only with a defined list of domains and the associated list of hostnames and ports that are serving those domains) MAY ignore the 'route' attribute. (Note that the 'to' attribute specifies the domain being served, not the hostame of the machine that is serving the domain.)

    A client MAY include a 'from' attribute to enable the connection manager to forward its identity to the &server;.

    A client MAY include an 'ack' attribute (set to "1") to indicate that it will be using acknowledgements throughout the session and that the absence of an 'ack' attribute in any request is meaningful (see Acknowledgements).

    A client MAY include a 'secure' attribute to specify that communications between the connection manager and the &server; must be "secure". (Note: The 'secure' attribute is of type xs:boolean (see &w3xmlschema2;) and the default value is "false". &BOOLEANNOTE;) If a connection manager receives a session request with the 'secure' attribute set to "true" or "1", then it MUST respond to the client with a remote-connection-failed error as soon as it determines that it cannot communicate in a secure way with the &server;. A connection manager SHOULD consider communications with the &server; to be "secure" if they are encrypted using SSL or TLS with verified certificates, or if it is running on the same physical machine as the &server;. A connection manager MAY consider communications over a "private" network to be secure, even without SSL or TLS; however, a network SHOULD be considered "private" only if the administrator of the connection manager is sure that unknown individuals or processes do not have access to the network (i.e., individuals or processes who do not have access to either the connection manager or the &server;). The connection manager SHOULD try to establish a secure connection with the &server; even if the client does not specifically require it.

    Some clients are constrained to only accept HTTP responses with specific Content-Types (e.g., "text/html"). The <body/> element of the first request MAY possess a 'content' attribute. This specifies the value of the HTTP Content-Type header that MUST appear in all the connection manager's responses during the session. If the client request does not possess a 'content' attribute, then the HTTP Content-Type header of responses MUST be "text/xml; charset=utf-8".

    - + A connection manager MAY include an 'ack' attribute (set to the value of the 'rid' attribute of the session creation request) to indicate that it will be using acknowledgements throughout the session and that the absence of an 'ack' attribute in any response is meaningful (see Acknowledgements).

    If the connection manager supports session pausing (see Inactivity) then it SHOULD advertise that to the client by including a 'maxpause' attribute in the session creation response element. The value of the attribute indicates the maximum length of a temporary session pause (in seconds) that a client MAY request.

    For both requests and responses, the <body/> element and its content SHOULD be UTF-8 encoded. If the HTTP Content-Type header of a request/response specifies a character encoding other than UTF-8, then the connection manager MAY convert between UTF-8 and the other character encoding. However, even in this case, it is OPTIONAL for the connection manager to convert between encodings. The connection manager MAY inform the client which encodings it can convert by setting the optional 'charsets' attribute in the session creation response element to a space-separated list of encodings. Each character set name (or character encoding name -- we use the terms interchangeably) SHOULD be of type NMTOKEN, where the names are separated by the white space character #x20, resulting in a tokenized attribute type of NMTOKENS (see Section 3.3.1 of &w3xml;). Strictly speaking, the Character Sets registry maintained by the Internet Assigned Numbers Authority (see <http://www.iana.org/assignments/character-sets>) allows a character set name to contain any printable US-ASCII character, which might include characters not allowed by the NMTOKEN construction of XML 1.0; however, the only existing character set name which includes such a character is "NF_Z_62-010_(1973)".

    -

    As soon as the connection manager has established a connection to the &server; and discovered its identity, it MAY forward the identity to the client by including a 'from' attribute in a response, either in its session creation response, or (if it has not received the identity from the &server; by that time) in any subsequent response to the client. If it established a secure connection to the &server; (as defined in Initiating an HTTP Session), then in the same response the connection manager SHOULD also include the 'secure' attribute set to "true" or "1".

    +

    As soon as the connection manager has established a connection to the &server; and discovered its identity, it MAY forward the identity to the client by including a 'from' attribute in a response, either in its session creation response, or (if it has not received the identity from the &server; by that time) in any subsequent response to the client. If it established a secure connection to the &server; (as defined in Initiating a BOSH Session), then in the same response the connection manager SHOULD also include the 'secure' attribute set to "true" or "1".

    The connection manager SHOULD return an HTTP 200 OK response with an empty <body/> element. Upon receiving the response, the client MUST consider the HTTP session to have been terminated.

    - +

    The client MUST generate a large, random, positive integer for the initial 'rid' (see Security Considerations, this also prevents non-compliant proxies from caching Script Syntax responses) and then increment that value by one for each subsequent request. The client MUST take care to choose an initial 'rid' that will never be incremented above 9007199254740991 9007199254740991 is 253-1. Some weakly typed languages use IEEE Standard 754 Doubles to represent all numbers. These Doubles cannot represent integers above 253 accurately. within the session. In practice, a session would have to be extraordinarily long (or involve the exchange of an extraordinary number of packets) to exceed the defined limit.

    @@ -959,7 +960,7 @@ Content-Length: 0]]>
  20. Include extra HTTP headers to prevent request/response caching or storage by any intermediary.

Note: All whitespace between "GET " and " HTTP/1.1" in the HTTP GET header lines in the following two examples is included only to improve readability. In practice there MUST be no whitespace.

- ") ]]>