This Google Summer of Code was about adding peer-to-peer file transfers to Dino. Dino is an XMPP client, XMPP is decentralized instant messaging standard.

The work was mostly done in two larger pull requests. The first one, dino#577, added a Jingle framework (XEP-0166), the in-band-bytestream transport (XEP-0047, XEP-0261) and the Jingle file transfer protocol (XEP-0234).

Jingle is a protocol for (mostly out-of-band) peer-to-peer connections between XMPP clients. It is designed to support multiple transport types, e.g. in-band bytestreams, connections via SOCKS5 proxies or direct IP connections. It provides support to send different kinds of data between clients, the two major users are file transfers (described below) and audio/video calls. All this is reflected in the code, the Jingle interface was designed to be extensible for more transport methods and different data types.

In-band bytestreams are a simple method of exchanging binary data between XMPP clients by sending base64-encoded data in the XMPP stream via the server. It is a good fallback method in case no other transport works, but adds 33% overhead to the data sent.

Apart from the HTTP file upload specification, the Jingle file transfer protocol is another standard way of exchanging files between XMPP clients. For Dino (and also in Conversations), this method is used transparently (using the same UI) for files larger than the upload limit of the HTTP upload server. This allows the user to benefit from both methods.

The work on this pull request was concluded by some interoperability testing with Conversations and Gajim, two other major XMPP clients.

The second pull request, dino#592 (not merged yet, currently on commit 6028fd1) added the SOCKS5 transport method for Jingle (XEP-0065, XEP-0260).

The SOCKS5 transport method allows XMPP clients to exchange data via a direct connection or via a XMPP-server provided SOCKS5 proxy. The direct transfer only works if one client can see the other client's IP address and is not firewalled, which is mostly the case if both the clients are on the same private network. It is currently not implemented and is waiting for some libnice support for enumerating the local interfaces (see below). Instead, the data can be exchanged via a proxy reachable by both clients, determined by some candidate exchange.

Interoperability testing for the second pull request uncovered some old and new bugs in both existing clients and my implementation. Thanks to the Conversations developer for taking my bug reports seriously and responding very fast.

There were also a couple of other smaller pull requests which I'll mention here:

  • dino#569. Tiny fix for logging to a file.
  • dino#570. Tiny typo fix, sorry for even mentioning. :o
  • dino#579. Improvement around the error generation in response to certain XMPP messages.

In the course of the interoperability testing, I also opened a couple of issues on other XMPP clients: Conversations#3478, Conversations#3500, Conversations#3514, Conversations#3515, Gajim#9784.

As the next steps, after Google Summer of Code, I'll implement the WebRTC transport method to get interoperability with XMPP browser clients that cannot open direct TCP connections to SOCKS5 servers. Additionally, one could implement audio/video calls on top of the current Jingle code.

At this point I'd like to thank my two mentors fiaxh and mar-v-in without whom this wouldn't have been possible. They were quick to answer any questions that arose, about architectural design of the code, the XMPP standards or even just questions about Vala, the language Dino is written in.

Thanks to my mentoring organization, the XSF (XMPP standards foundation), as well, for the weekly meetings and generally the advice given therein.