Federation

Posted by wave_admin
Printer-friendly versionPrinter-friendly version

Email has been successful as a communications medium for a couple of reasons:

  • It's easy to use. Basically all the concepts of normal mail have been translated across. We address our electronic mail to people send it off and hope it's delivered to the users mailbox.
  • There is a common language. Each Mail Server and Mail Client speaks the same languange. Thanks to Open Standards and Open Protocols, anyone who wants to build their own email infrastructure can.

While there is some debate as to how easy Wave is to use, Google has opened up the "common language" that will allow different Wave servers hosted by different organisations to talk to one another.

This is called the Federation Protocol.

The protocol itself is based upon the XMPP core protocols originally developed for the Jabber IM suite and since extended to meet a number of different communication needs.

A Federated Wave

Before we go into detail on how the Federation protocol works let's have a look at the structure of a federated Wave.

It looks pretty simple in the pretty picture doesn't it. However as always, there is a lot more happening under the hood.

Anatomy of a Federated Wave - Looking at the guts

The best way to see how Federation works is to step through a federated conversation and see what's happening on the insides. Working from the figure above we have two participants on two different servers, Fred who works for abc123.com and George who is his opposite number over at partner company xyz789.com.

Fred wants to talk to George about the designs for the new widget that xyz789.com is going to be building for abc123.com, so he launches a new wave on his server and adds George to the wave. George sees the new wave pop up in his client and away they go. Sounds simple enough.

Looking underneath however there is a lot happening.

When Fred opens his new wave, he is telling the abc123.com wave server that it is the Authorative Server for this wave. This means that this server hosts and maintains the master history of the wave which can be queried by other participating servers.

Once he has his wave open, he adds George to the wave. This triggers a discovery process between his server (the Authorative Server) and the server that hosts the newly added participant. In this case, abc123.com will send a packet like the one below to xyz789.com:

<iq type="get" id="3602-0" to="xyz789.com" from="abc123.com">
  <query xmlns="http://jabber.org/protocol/disco#items"/>
</iq>

This is a stock standard XMPP query between servers. The aim is for the remote server to return a list of the services that it supports. In our case we might something like this from xyz789.com:

<iq type="result" id="3602-0" from="xyz789.com" to="abc123.com">
  <query xmlns="http://jabber.org/protocol/disco#items">
    <item jid="wave.xyz789.com" name="Google Prototype Wave Server - FedOne"/>
    <item jid="pubsub.xyz789.com" name="Publish-Subscribe service"/>
    <item jid="conference.xyz789.com" name="Public Chatrooms"/>
  </query>
</iq>

What the abc123.com server is looking for is the "wave.xyz789.com" entry. Once it determines that the remote server supports wave, the discovery process is finished and the validation process begins.

Each server validates the packets it sends by signing them against a key. When two servers initiate a new conversation, they must exchange their public keys so that they can ensure that the packets that appear to be coming from the remote server are actually doing so. This is called the validation process. Each server exchanges their certificates via the following packets:

<iq type="set" id="7261-1" from="wave.abc123.com" to="wave.xyz789.com">
  <pubsub xmlns="http://jabber.org/protocol/pubsub">
    <publish node="signer">
      <item>
        <signature xmlns="http://waveprotocol.org/protocol/0.2/waveserver" domain="wave.abc123.com" algorithm="SHA256">
          <certificate><![CDATA[Certificate Data Goes Here]]></certificate>
        </signature>  
      </item>
    </publish>
  </pubsub>
</iq>

Note a slight change here. Whereas the first few packets where abc123.com to xyz789.com, after the verification process has occured all future packets are addressed specifically to the wave service on the remote server.

So we now have a wave that's hosted on the abc123.com wave server. It has communicated with the xyz789.com wave server to verify its capabilities and to determine the proper address for the direct federation. Now we can move onto setting up the conversation.

At this moment in time, there is not a standard client/server communication protocol, so we're not going to attempt to cover that here, however we shall cover the conversation as it occurs between the servers.

The first step in the conversation phase is adding the George user to the wave. To do this the abc123.com wave server sends a packet similar to that below:

<message type="normal" from="wave.abc123.com" id="323-5" to="wave.xyz789.com">
  <request xmlns="urn:xmpp:receipts"/>
  <event xmlns="http://jabber.org/protocol/pubsub#event">
    <items>
      <item>
        <wavelet-update xmlns="http://waveprotocol.org/protocol/0.2/waveserver" wavelet-name="abc123.com/w+xupQe5xgR01P/conv+root">
          <applied-delta><![CDATA[]]></applied-delta>
        </wavelet-update>
      </item>
    </items>
  </event>
</message>

This message packet contains some very important information:

  • The name of the wavelet that George is being added to - abc123.com.au/w+xupQe5xgR01P/conv+root
  • The current state of the wave (also known as the applied-delta. Note this is encrypted using the sending servers certificate.

A message packet can have multiple items, however in this case because it's the start of the wave, it only has the one.

When the xyz789.com server recieves the above packet it checks to see if George is a user, and if he is creates a new wave and notifies Georges wave client. Also note that in the packet above a request has been made for the xyz789.com server to respond with a reciept when it gets the packet. The xyv789.com server will then send a request for a full history of the wave:

<iq type="get" id="8545-1376" from="wave.xyv789.com" to="wave.abc123.com">
  <pubsub xmlns="http://jabber.org/protocol/pubsub">
    <items node="wavelet">
      <delta-history xmlns="http://waveprotocol.org/protocol/0.2/waveserver" start-version="0" start-version-hash="">
    </items>
  </pubsub>
</iq>

This packet is a "delta history" request. Because this is a new wave, the request starts from version 0 of the wave. The Authorative server will then return the history of the wave up until now.

<iq type="result" id="8545-1376" from="wave.abc123.com" to="wave.xyz789.com">
  <pubsub xmlns="http://jabber.org/protocol/pubsub">
    <items>
      <item>
        <applied-delta xmlns="http://waveprotocol.org/protocol/0.2/waveserver"><![CDATA[]></applied-delta>
      </item>
      <item>
        <commit-notice xmlns="http://waveprotocol.org/protocol/0.2/waveserver" version="1"/>
      </item>
      <item>
        <history-truncated xmlns="http://waveprotocol.org/protocol/0.2/waveserver" version="1"/>
      </item>
    </items>
  </pubsub>
</iq>

There are three "items" in this packet. The first one is the encrypted difference between version 0 and version 1 of the Wave. The server at xyz789.com then takes that delta and applies to it's own version of the wave bringing it into sync. Now that all versions of the Wave are in sync, we can move on to process the conversation.

Fred opens the conversation with a pleasantry:

"Hi George."

Freds client then communicates this change to the wave to the server at abc123.com, which processes it and builds the following packet:

<message type="normal" from="wave.abc123.com" id="2732-11" to="wave.xyz789.com">
  <request xmlns="urn:xmpp:receipts"/>
  <event xmlns="http://jabber.org/protocol/pubsub#event">
    <items>
      <item>
        <wavelet-update xmlns="http://waveprotocol.org/protocol/0.2/waveserver" wavelet-name="abc123.com/w+xupQe5xgR01P/conv+root">
          <applied-delta><![CDATA[]]></applied-delta>
        </wavelet-update>
      </item>
    </items>
  </event>
</message>

This packet sends processed difference between the pre-change wave and the post-change wave to the other participating wave server (in this case xyz789.com). This is called the applied-delta. Upon recieving this packet, xyz789.com then processes the change against it's own internal copy of the wave and presetns this to Georges client. It also sends back a reciept packet.

<message id="2732-11" from="wave.xyz789.com" to="wave.abc123.au">
  <received xmlns="urn:xmpp:receipts"/>
</message>

Upon seeing Freds initial post, George replies:

"Hi, did you send the documents?"

Which then triggers the server at xyz789.com to send the following packet containing the operation to be processed:

<iq type="set" id="2932-1703" from="wave.xyz789.com" to="wave.abc123.com">
  <pubsub xmlns="http://jabber.org/protocol/pubsub">
    <publish node="wavelet">
      <item>
        <submit-request xmlns="http://waveprotocol.org/protocol/0.2/waveserver">
          <delta wavelet-name="abc123.com/w+xupQe5xgR01P/conv+root"><![CDATA[]]></delta>
        </submit-request>
      </item>
    </publish>
  </pubsub>
</iq>

This packet contains the operation to be applied and the wave that it is meant to be applied to. This information is contained within the delta element. Once the authorative server (abc123.com) finishes processing the operation, it then sends out a message packet to the other participating servers similar to the following:

<message type="normal" from="wave.abc123.com" id="1092-9" to="wave.xyz789.com">
  <request xmlns="urn:xmpp:receipts"/>
  <event xmlns="http://jabber.org/protocol/pubsub#event">
    <items>
      <item>
        <wavelet-update xmlns="http://waveprotocol.org/protocol/0.2/waveserver" wavelet-name="abc123.com/w+xupQe5xgR01P/conv+root">
          <applied-delta><![CDATA[]></applied-delta>
        </wavelet-update>
      </item>
    </items>
  </event>
</message>

And so the conversation continues, with the authorative server applying the changes and then broadcasting them to all other participating servers.