1
votes

We are programming on an iOS Chat Application based on the XMPP Robbie Hanson framework at the moment. Server side we deploy openfire running on 3 servers with hazelcast plugin. Now we encountered following problem: the client connection and authentication takes about 2 sec. without TLS/SSL. With TLS/SSL it takes about 4 sec. We tried everything to shorten this time as it looks strange if the user gets a push notification that he received a message, opens the app and it takes that long to actually get the message. We do not use SRV records so it can’t be the DNS lookup that takes that long. We tried to modify the xmpp handshake so that the user sends all data (startls,auth method...) right from the start without waiting for server response but the server does not accept this. We also tried to use faster servers with very high network bandwith, but this didn't helped. Finally we even tried to use ejabberd but we have exactly the same times so we stayed with openfire.

The reason we thought it MUST be possible to shorten connection times is other messenger like WhatsApp or Threema which need less than 1 sec. So do you have any advice, what else we could try?Is it possible to reach that time only by optimizing the client and without modifying the openfire code?

Thank you so much!

This is my Handshake Log:

C2S - RECV (1083417823): <?xml version='1.0'?>
C2S - RECV (1083417823): <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' to='chat.example.com'>
C2S - SENT (1083417823): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="chat.example.com" id="5a051bc8" xml:lang="en" version="1.0">
C2S - SENT (1083417823): <stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>
C2S - RECV (1083417823): <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Starting Hazelcast Clustering Plugin
C2S - RECV (1083417823): <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' to='chat.example.com'>
C2S - SENT (1083417823): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="chat.example.com" id="5a051bc8" xml:lang="en" version="1.0"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>DIGEST-MD5</mechanism></mechanisms><auth xmlns="http://jabber.org/features/iq-auth"/></stream:features>
C2S - RECV (1083417823): <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="DIGEST-MD5"/>
C2S - SENT (1083417823): <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09Im5vZGVzLmZsaXhtaW5kZXIuY29tIixub25jer0iQ1hOS3MxWG9WY0xMTmsvedRUWlFIYmpGS1Vta2s4SG5WQ01TWUJnWiIscW9wPSJhdXRoIixjaGFyc2V0PXV0Zi04LGFsZ29yaXRobT1tZDUtc2Vzcw==</challenge>
C2S - RECV (1083417823): <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dXNlcm5hbWU9IjAwNDkyMjIiLHJlYWxtPSJub2Rlcy5mbGl4bWluZGVyLmNvbSIsbm9uY2UtrkNYTktzMVhvVmNMTE5rL3dEVFpRSGJqRktVbWtrOEhuVkNNU1lCZ1oiLGNub25jZT0iMkU2RURCRTctNUI2NC00QjQwLTg0OUMtQkUzQ0YwMTRCNTk0IixuYz0wMDAwMDAwMSxxb3A9YXV0aCxkaWdlc3QtdXJpPSJ4bXBwL25vZGVzLmZsaXhtaW5kZXIuY29tIixyZXNwb25zZT1mMDRhYzM4MjBlY2MwMGE1Mjk1ZTkxMjc5YTc1Zmz4MCxjaGFyc2V0PXV0Zi04</response>
C2S - SENT (1083417823): <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD05NDk2NTA2NWRlNDQ2MzRhNWRlMWNzuTc0NjI3MGNhZg==</success>
C2S - RECV (1083417823): <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' to='chat.example.com'>
C2S - SENT (1083417823): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="chat.example.com" id="5a051bc8" xml:lang="en" version="1.0"><stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>
C2S - RECV (1083417823): <iq type="set" id="F3CFA293-6D45-4E03-9065-3FD10D617C02"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></iq>
C2S - SENT (1083417823): <iq type="result" id="F3CFA293-6D45-4E03-9065-3FD10D617C02" to="chat.example.com/5a051bc8"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>[email protected]/5a051bc8</jid></bind></iq>
C2S - RECV (1083417823): <iq type="set" id="D351FF85-535B-4B08-B5C2-3C11D92C1EA9"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>
C2S - SENT (1083417823): <iq type="result" id="D351FF85-535B-4B08-B5C2-3C11D92C1EA9" to="[email protected]/5a051bc8"/>
C2S - RECV (1083417823): <presence/>
C2S - SENT (1083417823): <presence from="[email protected]/5a051bc8" to="[email protected]/5a051bc8"/>
C2S - SENT (1083417823): <presence from="[email protected]/5a051bc8" to="[email protected]/5a051bc8"/>
CLOSED (1446853640) 
3
Have you found any other optimization tricks for xmpp connection? Do you observe any time increase when the load on the server increases?small_ticket

3 Answers

8
votes

I'd recommend trying to get some logs to find out exactly what is taking the most amount of time. Figuring out exactly how many roundtrips you are using will help you determine what to optimize.

There's a XEP for XMPP Quickstart, XEP-0305. This has some general recommendation, but also a pipelining protocol which should do the bundling of data for you, if your server and client support it.

Some tips:

  • Make sure you cache DNS results for the specified TTL.
  • Save the user's roster locally and use roster versioning to only get any changes that might've happend to the user's roster.
  • At the TLS level, you could try to get session resumption or false start working. Also make sure the server sends no extra certificates (like a root you know the client will trust). Use faster algorithms (ECDHE instead of DHE, RSA-2048 instead of RSA-4096), but keep security in mind (please no RC4).
  • If you do stuff like setting/retrieving vCards, service discovery, etc., make sure that happens later and doesn't block anything else.
  • If you are using SCRAM-SHA-1 and the server is using hashed password storage (i.e., sending the same salt every time) you can cache the SaltedPassword value, which should save a large amount of time.
  • If your server is new enough (so implements RFC 6121 correctly), you can skip a roundtrip by skipping the urn:ietf:params:xml:ns:xmpp-session IQ. See https://datatracker.ietf.org/doc/draft-cridland-xmpp-session/?include_text=1.
  • Cache the entity caps of your contacts and your server to skip retrieving them. You can even embed caps that are used often inside your app.
  • If at any step you want to send multiple stanzas at the same time, make sure they are sent in a single TLS packet. Every packet has both an overhead in size (somewhere in between 25-85 extra bytes: header, IV, padding, MAC) and in processing time (parsing, verifying MAC).
2
votes

It appears that you don't now where the 4 seconds are spend, it's hard to give you a specific answer. I snuggest you try to profile that time-frame and determine what mechanisms/phases/methods are invoked and how much time they take to complete.

There is XEP-305: XMPP Quickstart. Which may provides additional information for you. Besides that I doubt that you can improve the time it takes to establish an XMPP session without modifying the server code.

0
votes

As a data-point, I work with an ejabberd deployment at scale with mobile clients based on the SleekXMPP client and there's no problems with connection delays. I've often used OpenFire for small-scale office communications and it's not that slow, either.

Mobile networking is tricky. Try connecting to your server from a desktop XMPP client, preferably on the same network as the server. This will help you eliminate (or implicate) the network and the mobile client as the problem.

If the problem appears isolated to the server, the only real possibility is that you're overloaded. If you're only connecting a single client, then either your server is very anemic or you're talking to some external DB for authentication and that DB is overloaded.

If the problem is not the server, try connecting the mobile client to WiFi rather than a cell network. Then run a packet-sniffer adjacent to the client and another one on the server. That should tell you whether you have some client bug or a network problem.