Subject: [xmpp] pipelining during stream setup

From: Peter Saint-Andre <[email-masked]>
Date: Wed, 09 Sep 2009 15:50:44 -0600

This is a forward from an older discussion on the [email-masked]
list. I will probably look into this for the -02 version of 3920bis and
might post about it again soon.

/psa

- -------- Original Message --------
Subject: Re: [Standards] mobile optimizations (was: Re:  Google Androïd
SDK not XMPP compliant ?)
Date: Mon, 18 Feb 2008 13:33:13 +0000
From: Tony Finch <[email-masked]>
Reply-To: XMPP Extension Discussion List <[email-masked]>
To: XMPP Extension Discussion List <[email-masked]>
References:
<[email-masked]>
<[email-masked]>
<[email-masked]>

How important is session startup latency for mobile XMPP? The motivation
for SMTP quickstart was to make sending email faster. Sending email is
quite an interactive action (though good client software can hide the
latency). The equivalent in XMPP is sending a message on a connection
that's already open. Session startup, on the other hand, is tied in with
things like associating with an access point or starting a GPRS
connection, doing DNS lookups, and all sorts of slow things before XMPP
can get going.

With that in mind, if it is worth optimising XMPP startup, then it's
probably worth taking the simplest possible approach which does not
require any stunt buffer handling. From the specification writer's point
of view, it amounts to adding some text to 3920bis which explains where
XMPP is asynchronous / pipelinable and where it is not. If you allow
pipelining of startup utterances other than transitions between XML and
TLS, and SASL exchanges, you can get something like the following. By
startup utterances, I mean that client and server can say <stream> in
either order, and the client can cache the server's <features/> and
proceed with <starttls/> and <auth/> on the assumption that the
<features/> have not changed.

C: TCP SYN
S: TCP SYN/ACK
C: TCP ACK

client does not need to wait for server's <stream> header, since its
stream header is the same regardless. in principle it should wait for the
server's <features/> before issuing <starttls/> but (a) it can cache the
<features/>, (b) unexpected lack of TLS support is something worth warning
the user about, (c) the protocol allows it to recover gracefully from the
error.

C: XMPP1 <stream>
          <starttls/>

server has to wait for client syn

S: XMPP1 <stream>
          <features/>
          <proceed/>

layering switch here, so there must be a round trip delay. there are two
kinds of TLS negotiation, without and with a session cache hit.

without

C: TLS hello
S: TLS stuff
C: TLS again
S: TLS finish

with

C: TLS hello
S: TLS stuff
C: TLS finish

to properly benefit from session cache optimisation, you need to let
either the server or the client start the stream first. that is, the
following two utterances can be in either order. the server and the client
send these as soon as the TLS layer returns from the handshake, and with a
good TLS implementation one of these will piggy-back on the last TLS
finish packet.

with a TLS session cache hit the packets come in this order:

C: XMPP2 <stream>
          <auth/>

S: XMPP2 <stream>
          <features/>

the client now has to wait for the server's reply, which in this case
should come immediately. (without a TLS session cache there's another
round trip delay.) the server can re-start its stream immediately, since
it is always the last to speak in SASL. when the client gets the SASL
response it can re-start its stream (and XML parser).

S: XMPP2  <success/>
   XMPP3 <stream>
          <features/>

C: XMPP3 <stream>
          <iq><bind/></iq>

client must wait for <iq> reply before it can do anything useful

S: XMPP3 <iq><bind><jid/></bind></iq>

Without a TLS session cache hit, we get 6RTT before useful data can be
transferred:

C: TCP SYN
S: TCP SYN/ACK
C: TCP ACK
   TCP XMPP1 <stream><starttls/>
S: TCP XMPP1 <stream><features/><proceed/>
C: TCP XMPP1 TLS hello
S: TCP XMPP1 TLS stuff
C: TCP XMPP1 TLS again
S: TCP XMPP1 TLS finish
   TCP XMPP1 TLS XMPP2 <stream><features/>
C: TCP XMPP1 TLS XMPP2 <stream><auth/>
S: TCP XMPP1 TLS XMPP2 <success/>
   TCP XMPP1 TLS XMPP2 XMPP3 <stream><features/>
C: TCP XMPP1 TLS XMPP2 XMPP3 <stream><iq><bind/></iq>
S: TCP XMPP1 TLS XMPP2 XMPP3 <iq><bind><jid/></bind></iq>

With a TLS session cache hit, we get 5RTT:

C: TCP SYN
S: TCP SYN/ACK
C: TCP ACK
   TCP XMPP1 <stream><starttls/>
S: TCP XMPP1 <stream><features/><proceed/>
C: TCP XMPP1 TLS hello
S: TCP XMPP1 TLS stuff
C: TCP XMPP1 TLS finish
   TCP XMPP1 TLS XMPP2 <stream><auth/>
S: TCP XMPP1 TLS XMPP2 <stream><features/><success/>
   TCP XMPP1 TLS XMPP2 XMPP3 <stream><features/>
C: TCP XMPP1 TLS XMPP2 XMPP3 <stream><iq><bind/></iq>
S: TCP XMPP1 TLS XMPP2 XMPP3 <iq><bind><jid/></bind></iq>

Note that all the layers come in contiguous lumps. Stunt buffering is
required if they get interleaved in the packet trace, e.g.

C: TCP ACK
   TCP XMPP1 <stream><starttls/>
   TCP XMPP1 TLS hello
S: TCP XMPP1 <stream><features/><proceed/>
   TCP XMPP1 TLS stuff
C: TCP XMPP1 TLS finish
   TCP XMPP1 TLS XMPP2 <stream><auth/>
   TCP XMPP1 TLS XMPP2 XMPP3 <stream><iq><bind/></iq>
S: TCP XMPP1 TLS XMPP2 <stream><features/><success/>
   TCP XMPP1 TLS XMPP2 XMPP3 <stream><features/><iq><bind><jid/></bind></iq>

I have not treated SASL in detail above. In particular I haven't examined
challenge/response mechanisms. In the last trace above, the XMPP2 layer
startup and the SASL negotiation get interleaved. I think this is be OK
since SASL is framed by XMPP2, not layered on top like TLS.

Tony.
- --
f.a.n.finch  <[email-masked]>  http://dotat.at/
VIKING NORTH UTSIRE: NORTHWEST 5 OR 6, DECREASING 4. MODERATE OR ROUGH.
OCCASIONAL RAIN. MODERATE OR GOOD, OCCASIONALLY POOR.

---

From: Dirk Meyer <[email-masked]>
Date: Thu, 10 Sep 2009 11:05:46 +0200

Tony Finch wrote:
> require any stunt buffer handling. 

Well, maybe we want to merge TLS and client authentication into one step
without a stream restart. We had some discussion about it some time ago,
but maybe we want to consider it for a fast restart.

C: <stream>

S:  <stream>
      <features>
        <starttls/>
        <tlssrp/>
      </features>
     </stream>

C: <tlsstrp/>

S: <proceed/>

Now we use TLS-SRP with server certificates and the client using user
name and password for authentication:

C: TLS hello, request SRP, JID
S: Accept SRP, send certificate
C: Proof identity, TLS finish
S: TLS finish

After that the server continues with sending a new set of features:

S: <features/>

This get's rid of the two stream restarts for TLS and SASL and SASL
itself.

Dischi

-- 
Never put off until tomorrow what you can do the day after.