How XMPP works step by step

 

 

                                                       HAPPY NEW YEAR!

 

Last year, 2010,  i used BOSH as an agent to negotiate with ejabberd server from my mbed. In that way, XMPP streams are wrapped into HTTP format on mbed and send to server over TCP link. And the BOSH extracts the XMPP payload and hands to XMPP server. There is another way to do it on mbed. It was found that, XMPP streams can be directly handled by ejabberd server. This is more simple than that of using BOSH, cause it is straightforward and bypass potential HTTP errors.

Then, i spend time to read through the XMPP core protocol. @http://xmpp.org/rfcs/rfc3920.html.

 

Things need to know about XMPP.

1. Client and server communicate through port 5222 via a TCP connection. 2. XMPP informations are contained on XML streams. A XMPP session is opened by <stream> tag and ended by </stream> tag.  All other parts are located between them. 3. For security purpose, the open stream is followed by moderate Transpor Layer Security (TLS)  negotiation and compulsory Simple Authentication and Security Layer (SASL) negotiation. 4. A new stream will be opened immediately after the SASL negotiation, and it will be more securit and safe.  

 

How XMPP works step by step

Step 1: Open stream

Client: Clients send a open stream packet to server to request a new session. <stream:stream       to='example.com'       xmlns='jabber:client'       xmlns:stream='http://etherx.jabber.org/streams'       version='1.0'> where “example.com” is domain name of XMPP server connected to.

Server: Server sends back a XML stream starts with <stream:freatures>, includes requirements of either TLS  or SASL negotiation, or both.

<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>    <mechanism>PLAIN</mechanism>   <mechanism>EXTERNAL</mechanism>  </mechanisms> </stream:features>

Step 2: Encryption and Authorization.

2.1 If server needs TLS negotiation.

Client: Clients send a STARTTLS to server. <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> Server: Server sends back a message shows the TLS is allowed: <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> or failed: <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> </stream:stream> In case of failure, the server closed the TCP connect.

Client: If TLS is processed, then clients request a new session: <stream:stream    xmlns='jabber:client'    xmlns:stream='http://etherx.jabber.org/streams'    to='example.com'    version='1.0'>

Server: Server responses a XML stream indicating the needs of SASL negotiation. <stream:stream    xmlns='jabber:client'    xmlns:stream='http://etherx.jabber.org/streams'    from='example.com'    id='c2s_234'    version='1.0'> <stream:features>  <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>    <mechanism>DIGEST-MD5</mechanism>    <mechanism>PLAIN</mechanism>    <mechanism>EXTERNAL</mechanism>  </mechanisms> </stream:features>

2.2 SASL negotiation

Client needs to choose an authentication method available from server to carry out SASL negotiation. In case above, “DIGEST-MD5“, “PLAIN” and “EXTERNAL” are options.

The “PLAIN” authorization method is the simplest among them. It works as following.

Client: Client send a stream with selected authorization method with base64 encoded user name and password. The user name and password are allocated in format of “\0UserName\0Password”.

For example, i would like to log on as “mbed@ceit.org”, whose password is “mirror”. And, the string to be send to encoder is “\0mbed\0mirror”, and the encoded string is “AG1iZWQAbWlycm9y”.

Then, the client sends the following stream to server. <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AG1iZWQAbWlycm9y</auth>

Server: If the server accept the authorization, it sends back a stream with “success” tag. <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/> or: Server: If the password does not match the user name, or there is an error on encoding, the server will sends a failure stream. <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Details of “DIGEST-MD5” authorization can be found at http://www.ietf.org/rfc/rfc2831.txt.

Round 3 Resource binding (Optional)

Client: Client asks server to bind a resource: <iq type='set' id='bind_1'> <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/> </iq>

or: Client: Client binds a resource: <iq type='set' id='bind_2'>

<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

   <resource>someresource</resource>

</bind>

</iq>

Server: Server sends back another <iq> stanza, if the “type” tag is “result”, that means the binding is successful, otherwise, it is failed. <iq type='result' id='bind_2'>

<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>

   <jid>somenode@example.com/someresource</jid>

</bind>

</iq>

Step 4: Request a new session

Immediately after SASL negotiation or optional resource binding, clients must establish a session to start instant messaging.

Client: Client request session with server: <iq to='example.com'     type='set'     id='sess_1'>   <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/> </iq>

Server: Server sends back a iq stanza showing whether session has been created successful or not.

The successful message will be like: <iq from='example.com'     type='result'     id='sess_1'/>

If the server failed to create a session, it will reply a message like below or other type of error messages. <iq from='example.com' type='error' id='sess_1'>    <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>    <error type='auth'>      <forbidden          xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>    </error>  </iq>

Step 5: client and server exchange XMPP stanzas

If all steps above are successful, then client can send XMPP stanzas to server and receive XML streams. Client can send <iq> stanzas to request roster or other information from server, and use <presence> stanzas to change its presence status. Instance message and other payload can be send via <message> stanzas.

Step 6: close stream

Finally, if clients want to finish the talk and close the XMPP session, it needs to send a close stream to server. <presence type='unavailable'/> </stream:stream>

Then, server will change client's presence to “Offline” and close TCP connections with clients.

Comments

what the new way to connect to ejabberd server?

Hi~ What you mean by ' It was found that, XMPP streams can be directly handled by ejabberd server'? Which mechanism u r using? And which ejabberd server u r referring to?

RE:

What happened was that i tried to talk to ejabberd server from mbed using BOSH, as seen from my previous posts. BOSH wrapped XMPP stanzas and streams into HTTP format, and send HTTP pages to server via TCP connection. It is a way to get XMPP working. But i later found that XMPP stanzas and streams can be sended to server without BOSH, and server had responses, so i give up using BOSH, and do straight XMPP streams exchanges.

Im using ejabberd-2.1.5

Is this clear enough?

RE:

I think I missed something in your previous blogs, actually, the ejabber server is running at localhost which is your Mac, is it? And does this XML streams exchange works on other remote servers? let say we are going to connect to talkr.im(which is a remote xmpp server, www.talkr.im), do you think the talkr.im server can understand XML stream rather than using BOSH?

Thank you.

RE

1. Yes, the ejabberd server is running on my mac, which is connected to a router as well as the mbed. The architecture is Mac<---XMPP---> router <---XMPP--->mbed.

2. I havent test it on other remote server, but i will certainly do it later.

3.The XMPP is in format of XML streams, so XMPPs are XML streams, and XML streams mentioned here are for XMPP. Thus, the talkr.im will understand right formated XMPP(XML) streams.