Google Wave’s Federation Protocol Under the Hood, Part 4

Posted Feb 16, 2010 by Anthony in Architecture, Blogs, Google Wave


Purpose [Updated 4/3/2010]

This is the fourth post in the series dedicated to exploring the internals of the FedOne architecture.  This post is more a reference that will quickly guide you to the location in code that corresponds to the receipt and execution of an XMPP packet (e.g. History Request IQ Get Packet or a Wavelet Update Message Event).  The messages processed are those supported by the FedOne codebase and is not based off of the documentation (not saying anything against the documentation, which I referenced many times. For instance to see examples of successful Packet transmissions).  

FedOne was recently updated to introduce more robust error handling mechanisms.  You will now find a set of files in the package org.waveprotocol.wave.federation that are dedicated to federation errors.  The error codes supported can be found in org.waveprotocol.wave.federation.federation_error.protodevel (note this is the specification, if you want to see the actual .java file, go to proto_src/org.waveprotocol.wave.federation.FederationErrorProto). Per the documentation, the error codes map to XMPP error stanzas as specified in RFC 3920 (9.3.3).  There is also a wrapper FederationErrors.java to make it easy to create the FederationError objects.  You will see these used throughout the communication code as a parameter to org.waveprotcol.wave.federation.xmpp.PacketCallaback responses (also used to communicate success).  For an example of its use see wave.federation.xmpp.processHistoryRequest().

Communication Interfaces

XMPP communication within the federation protocol occurs in the org.waveprotocol.wave.federation.xmpp package.  All elements related specifically to XMPP (e.g. IQ packets) are read in here and stripped out into neutral formats (well, let’s count ProtoBuf as neutral).  The resulting data is then passed to the wave server for processing.  For each operation, I will list the file/method of the XMPP filter along with the file/method within the wave server that processes the data.  Please recall that I am focusing on Server to Server communication, however, I will try to list the mirrored methods of the wave server that would be used by the client (e.g. - instead of just listing the server’s response to an incoming submitRequest, I will attempt to show where a local client would initiate its own submitRequest).

As a preliminary note, all incoming packets are received by receivePacket() in org.waveprotocol.wave.federation.xmpp.XmppManager

HistoryRequest - received from Federation remote to request wavelet operations from the hosting wave providers.
Packet Type IQ Get Packet
XMPP Filter wave.federation.xmpp.XmppFederationHost processHistoryRequest() - collect history request data from XMPP IQ packet and pass to Wavelet provider for processing.
WaveServer Handler fedone.waveserver.WaveServerImpl.requestHistory() - retrieves info for a signer of an applied delta and returns IQ result to foreign remote via fedone.federation.xmpp.XmppFederationHost. HistoryResponsePacketListener.onSuccess(). Note: onFailure currently just logs an error, but does not actually send error back to foreign remote.
WaveServer Mirror fedone.waveserver.WaveServerImpl.requestHistory() - gets the transformed history for a wavelet and returns to caller. Note this call is overloaded, so it is not the same method as above.


SignerRequest - received from Federation remote to request certificates for wavelets where the signer is unknown.  Request sent to host wave providers.
Packet Type IQ Get Packet
XMPP Filter wave.federation.xmpp.XmppFederationHost. processGetSignerRequest() - collect signer request data from XMPP IQ packet and pass to Wavelet provider for processing.
WaveServer Handler fedone.waveserver.WaveServerImpl.getDeltaSignerInfo() - retrieves delta history for a given wavelet and returns info to listener via wave.federation.xmpp.XmppFederationHost. DeltaSignerInfoPacketListener.onSuccess() or .onFailure().


DiscoveryInfoRequest (Disco) - received from foreign source to get info on what we support.  Will send back message saying we are Wave Component.
Packet Type IQ Get Packet
XMPP Filter wave.federation.xmpp.XmppDisco.processDiscoInfoGet() - handles discovery info get. Will send back message identifying server as a Wave Server.
WaveServer Handler N/A


DiscoveryItemRequest (Disco) - received from foreign source to get disco items.  No defined use within Wave.
Packet Type IQ Get Packet
XMPP Filter wave.federation.xmpp.XmppDisco. processDiscoItemsGet() - handles discovery item get. Will send back copy of message in response.
WaveServer Handler N/A


errorCallback - when the WaveServer sends a packet, it has the option of specifying an error callback in the case the host or remote responds with an error.
Packet Type IQ Error Packet
XMPP Filter  wave.federatoin.xmpp.XmppManager.response() - on an error packet, checks to see if there is a callback defined.
WaveServer Handler N/A


MessageReceived - received from Federation remote to acknowledge an update.
Packet Type Message Received Packet
XMPP Filter wave.federatoin.xmpp.XmppManager.response() - handles Wavelet Update Response by sending packet to callback handler.
WaveServer Handler N/A


MessageEvent (update) - received from Federation Host to Federation Remote to update a wavelet.
Packet Type Message Event Packet
XMPP Filter wave.federation.xmpp.XmppFederationRemote.update() - Parses update message. Creates a latched callback that is invoked when all deltas of all wavelet updates are applied. Also parses final commit notice if one is given.
WaveServer Handler fedone.waveserver.WaveServerImpl.listenerForDomain(). waveletDeltaUpdate() - get and check state of wavelet.  Place deltas in ProtoBuf and get/create remoteWavelet to update. 

fedone.waveserver.WaveServerImpl.listenerForDomain(). waveletCommitUpdate()  - notify client listener that update has been persisted and they can release any resources held for update (of course since there is no persistence we’re just telling lies)

fedone.waveserver.RemoteWaveletContainerImpl.update() - pre-fetch all the signers and run the internalUpdate.


Message Ping - provide evidence of available service.
Packet Type Message Ping Packet
XMPP Filter wave.federation.xmpp.XmppManager.processMessage() - adds receipt to response and sends back to requestor.
WaveServer Handler N/A


DiscoveryInfoResult (Disco- handles disco info result for remote JID and triggers callback.
Packet Type IQ Result Packet
XMPP Filter wave.federation.xmpp.XmppManager.response() - forwards to callback hander defined in

PacketCallback.run() of wave.federation.xmpp.RemoteDisco. requestDiscoInfo() - receives response from a disco info request to a specific target JID (supports wave) and processes in 

wave.federation.xmpp.RemoteDisco.finish() - if we find the remote JID, execute the callback functions that were set in wave.federation.xmpp.RemoteDisco.discoverRmoteJID().
WaveServer Handler N/A


DiscoveryItemResult (Disco- handles disco item response from remote JID and triggers callback.
Packet Type IQ Result Packet
XMPP Filter wave.federation.xmpp.XmppManager.response() - forwards to callback hander defined in
PacketCallback.run() of wave.federation.xmpp.RemoteDisco.startDisco() that calls

wave.federation.xmpp.RemoteDisco.processDiscoItemsResult() - process disco item results executing requestDiscoInfo() to see if any are wave servers.
WaveServer Handler N/A


HistoryResult - foreign Federation Host sending history response.
Packet Type IQ Result Packet
XMPP Filter  wave.federation.xmpp.XmppFederationRemote .processHistoryRequest() - receives history request response packet, decodes it and calls wave server. [this is defined as the PacketCallback in wave.federation.xmpp.XmppFederationRemote. requestHistory()]
WaveServer Handler fedone.waveserver.RemoteWaveletContainerImpl.internalUpdate() [onSuccess() method defined in federationProvider.requestHistory() call] - converts deltas into ProtoBuf format and calls
fedone.waveserver.RemoteWaveletContainerImpl.update() - pre-fetches signer info and calls
fedone.waveserver.RemoteWaveletContainerImpl.internalUpdate() [note, first reference to this function above was not actually direct call.  What was called was the onSuccess() method that was defined as a parameter in the requestHistory() method, so there is no recursion here] - applies deltas received from foreign Federation Host.


SubmitResponse - handles response from a submit request
Packet Type IQ Result Packet
XMPP Filter  wave.federation.xmpp.XmppFederationRemote. processSubmitResponse() receives submit response response packet, decodes it and calls wave server callback. [defined in PacketCallback.run() of wave.federation.xmpp.XmppFederationRemote.submitRequest()]
WaveServer Handler not really implemented in FedOne or by the WaveServer.  The responsibility of handling a submit response does not necessarily fall to the Federation Remote since it does not host the wave.  We should store the applied deltas, but the client will ultimately handle this response.  This is done at a very basic level in the FedOne at fedone.waveclient.common.ClientBackend. sendAndAwaitWaveletDelta().


PostSignerResponse - ACK from foreign Host server in response to certificate chain sent to authenticate wave delta.  This must be done first time before sending any wave delta.
Packet Type IQ Get Packet
XMPP Filter wave.federation.xmpp.XmppFederationHost. WaveletFederationProvider. DeltaSignerInfoResponseListenter() - receives post signer response packet, decodes it and calls wave server callback.
WaveServer Handler fedone.waveserver.WaveServerImpl.submitDelta() [callback defined as parameter in postAllSignerInfo() method] - logs success and then uses Federation Remote to submit request.


SubmitRequest - handles a submit request from a foreign Remote server
Packet Type IQ Set Packet
XMPP Filter  wave.federation.xmpp.XmppFederationHost. processSubmitRequest() - receives submit request packet, decodes it and calls wave server callback.
WaveServer Handler fedone.waveserver.WaveServerImpl.submitRequest() - ensures delta is properly signed and meets preconditions to be applied, then submits delta calling:
fedone.waveserver.WaveServerImpl.submitDelta() - submits delta to local or remote wavelets (remote first sends signatures then delta) , broadcast updates to Federation Hosts and Client.  Returns result via listener.
WaveServer Mirror fedone.waveserver.WaveServerImpl.submitRequest() - signs the delta and calls:
fedone.waveserver.WaveServerImpl.submitDelta() - submits delta to local or remote wavelets and returns result to listener


PostSignerRequest - Signer info from foreign Remote to be stored prior to receiving and applying deltas.
Packet Type IQ Set Packet
XMPP Filter wave.federation.xmpp.XmppFederationHost. processPostSignerRequest() - receives post signer request packet, decodes it and calls wave server.
WaveServer Handler fedone.waveserver.WaveServerImpl.postSignerInfo() - stores signer info with CertificateManager.


Next In Series

The next post will be focused on Persistence.  I will highlight where the local in-memory store occurs and hopefully point out the correct areas to implement persistence if you so choose.

Related posts:

  1. Google Wave’s Federation Protocol Under the Hood, Part 5 Purpose [Updated 4/3/2010] This is the fifth and final post...
  2. MongoWave: Persistence on Google FedOne Wave Server with mongoDB Purpose My company, SESI, has been working on applying...
  3. Google Wave’s Federation Protocol Under the Hood, Part 3 Purpose [Updated 4/3/2010] This is the third post in...
  4. Google Wave’s Federation Protocol Under the Hood, Part 2 Purpose [Updated 4/3/2010] This post is the second in a...
  5. Google Wave’s Federation Protocol Under the Hood, Part 1 Purpose [Updated 4/3/2010] This post is the first in...

Related posts brought to you by Yet Another Related Posts Plugin.

Tags: , , , ,

3 Responses to “Google Wave’s Federation Protocol Under the Hood, Part 4”

  1. [...] Google Wave’s Federation Protocol Under the Hood, Part 4 Posted Feb 16, 2010 [...]

    Reply to this comment
  2. maximos

    20. Sep, 2010

    Hello I have tried to locate the above mentioned code but there isn’t such a directory under my wave-protocol/src directory.
    Is it located somewhere else?
    I have used this command->hg clone https://wave-protocol.googlecode.com/hg/ wave-protocol
    to check the code, but under the directory you specify I have only a file called federation.protodevel and no .java files.
    regards maxsap

    Reply to this comment
  3. maxsap

    20. Sep, 2010

    Turns out that if you follow the link mentioned above you won’t find the source file, instead check this link :
    hg clone https://libraries.wave-protocol.googlecode.com/hg/ wave-protocol-libraries
    regards maxsap

    Reply to this comment

Leave a Reply

Subscribe without commenting