Hi,

On Thu, Aug 11, 2011 at 10:46 AM, Waqas Hussain <[email protected]> wrote:
> On Thu, Aug 11, 2011 at 2:28 AM, XMPP Extensions Editor <[email protected]> 
> wrote:
>> The XMPP Extensions Editor has received a proposal for a new XEP.
>>
>> Title: XMPP Quickstart
>>
>> Abstract: This document defines methods for speeding the process of 
>> connecting or reconnecting to an XMPP.
>>
>> URL: http://www.xmpp.org/extensions/inbox/quickstart.html
>>

I find this XEP very interesting. I would typically use this in
"simple" web implementations where I cannot keep a live client
connection, hence do often short connections.

>> The XMPP Council will decide at its next meeting whether to accept this 
>> proposal as an official XEP.
>>
>>
>
> Example 1 doesn't take things to their logical extreme.
>
> STEP 1 can be merged with the TLS ClientHello message.
> STEP 4 can be merged with the server's TLS Finished message.
> STEP 5 can be merged with the client's TLS Finished message.
> STEP 9 can be merged with STEP 7.
> If the server handles it just right, STEP 8 and 10 could be merged
> into one TCP packet (in response to 7+9).
>
> If you are not negotiating TLS in the middle, you can start a stream,
> do PLAIN or ANONYMOUS login, request roster, set presence, join a
> chatroom, and send messages, all in the first TCP packet. This makes
> legacy SSL somewhat attractive. The same can be done with BOSH, if you
> skip the stream restart on SASL (which virtually all existing clients
> do?).
>
> Moving on...
>
> Does the client even need to pay attention to the pipelining stream
> feature? When connecting to any server, it can first attempt to use
> full pipelining. If that fails, it can simply reconnect without
> pipelining. It can cache the failures. It would need to do this even
> if the server indicates it can support pipelining, as the server may
> be lying/buggy and e.g., might not support merging TLS negotiation and
> XMPP data in the same TCP packet.
>
> Looking at Example 1 closely, the client pipelined <starttls/> before
> looking at the stream feature, so what's the stream feature for? Is
> the client expected to not pipeline unless it has seen the feature in
> a previous connection to the host? Why? Given that the failure case is
> harmless, and that pipelining might work on many existing servers, why
> wouldn't it want to use it on first connect? Would using it violate
> any specification?

Actually I think it can be very interesting to have done a "normal"
connection first (where you saw that pipelining feature), in order to
further optimize any further connections. Hence the client could
already know what are the features of the server, what will be the one
it will want to negotiate, and in which order.
In particular, you know there is TLS, which SASL mechanism you will
want to use, if there is compression, and if so, which compression
scheme to use, and so on. What we "earn" here is that, first of all,
the server would never have to send its list of features and the
client would thus never have to process it (even if it skips it when
it sees it while pipelining, that's still useless processing in the
"quickstart" use case).
For instance, in the example 1, because you have done once the whole
normal negotiation and you saw that the server supports pipelining,
you cache that next time you will "quickstart" with TLS+SASL
SCRAM-SHA1+bind. So the example could be like this:

STEP 1: *same*
C: <stream:stream
     from='[email protected]'
     to='im.example.com'
     version='1.0'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'>
   <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

STEP 2: *no need to send features. That's a lot "thinner" packet!*
S: <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

STEP 3: *same*
[client and server complete TLS negotiation over the existing TCP connection]

STEP 4: *your example was somewhat "bad"! The initiating identity has
to restart the stream, not the receiving one (cf. RFC 6120), though we
could imagine in quickstart, it does not matter much.*
C: <stream:stream
     from='[email protected]'
     to='im.example.com'
     version='1.0'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'>
   <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl"
         mechanism="SCRAM-SHA-1">
biwsbj1qdWxpZXQscj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQQ==
   </auth>

STEP 5: *server restarts as well and directly responds the SASL auth,
no features!*
S: <stream:stream
     from='im.example.com'
     id='vgKi/bkYME8OAj4rlXMkpucAqe4='
     to='[email protected]'
     version='1.0'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'>
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
     cj1vTXNUQUF3QUFBQU1BQUFBTlAwVEFBQUFBQUJQVTBBQWUxMjQ2OTViLTY5Y
     TktNGRlNi05YzMwLWI1MWIzODA4YzU5ZSxzPU5qaGtZVE0wTURndE5HWTBaaT
     AwTmpkbUxUa3hNbVV0TkRsbU5UTm1ORE5rTURNeixpPTQwOTY=
   </challenge>

STEP 6:
C: <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
     Yz1iaXdzLHI9b01zVEFBd0FBQUFNQUFBQU5QMFRBQUFBQUFCUFUwQUFlMTI0N
     jk1Yi02OWE5LTRkZTYtOWMzMC1iNTFiMzgwOGM1OWUscD1VQTU3dE0vU3ZwQV
     RCa0gyRlhzMFdEWHZKWXc9
   </response>

STEP 7: *ok here the server could restart the stream because it knows
first the success of the negotiation (but it does not change much. It
could restart its side at step 9). Still no features sent!*
S: <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289
   </success>
   <stream:stream
     from='im.example.com'
     id='gPybzaOzBmaADgxKXu9UClbprp0='
     to='[email protected]'
     version='1.0'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'>

STEP 8:
C: <stream:stream
     from='[email protected]'
     to='im.example.com'
     version='1.0'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'>
   <iq id='yhc13a95' type='set'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <resource>balcony</resource>
     </bind>
   </iq>

STEP 9:
S: <iq id='yhc13a95' type='result'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <jid>
         [email protected]/balcony
       </jid>
     </bind>
   </iq>

So here we have 1 step less and in particular, the server never sends
any features, which spare some useless data processing on both side.

NOTE: actually if the client is *sure* the authentication will work,
it can merge steps 6 and 8. As a consequence, the server can merge 7
and 9, saving, in all, 2 additional round trips! The whole process
would be only 7 roundtrips. Of course the downside of this is that a
failed authentication cannot be saved (as you already sent "wrongly"
the restarted stream headers, which would hence make a stream error,
and a stream must re-negotiated from the start). I would say that
could be 2 cases:
1/ if the client is user-driven, then you might want to do the 9-steps
process. Indeed in case of auth-error, you might want to pop-up the
user and ask him to type again its password to retry authentication
without having to redo the whole negotiation.
2/ if the client is a bot, you can just imagine that a failed
negotiation has no solution right now. So you do the 7-steps process
by assuming it will go all right.

So I guess you provided the stream features here because RFC-6120
writes that the receiving entity MUST send a <features/>. But as we
are in a special case of quickstart stream, we could imagine new
characteristics, couldn't we?

Actually I think the more logical would be to have a dedicated stream
attribute prefixed by the pipelining namespace. Then if the client
wants to pipeline, it adds this attribute to its initial stream
header:
<stream:stream
     from='[email protected]'
     to='im.example.com'
     version='1.0'
     pipe:pipeline='true'
     xml:lang='en'
     xmlns='jabber:client'
     xmlns:stream='http://etherx.jabber.org/streams'
     xmlns:pipe='urn:xmpp:pipelining:0'>

Then the server knows for sure it is in "pipeline" mode and does not
need to send any features, hence saving many roundtrips (up to 9 steps
in our example!) and much processing of features. In any other case,
the server can "guess" the client is trying to pipeline (by checking
how many "commands" are in the single first TCP packet), but that
implies first to check at the lower (TCP) level (which I don't find
nice here), and second it implies that 2 commands in a single TCP
packet are necessarily an attempt to pipeline while nothing forbids an
entity to have several commands in a single packet, or at the opposite
"break" into several packets (that's how TCP works after all). So as
this is in fact not necessarily true, that makes pipelining either
limited or unreliable. With an additional stream attribute here, we
make this reliable, hence we allow additional optimizations (like
removing all the <features/>).

What do you think? This way, I think this would make such a feature
extremely more interesting.

Jehan

Reply via email to