| CARVIEW |
Select Language
HTTP/2 200
accept-ranges: bytes
alt-svc: h3=":443"; ma=2592000
content-type: text/xml; charset=utf-8
etag: "dbhs9al9duok26a7"
last-modified: Mon, 21 Jul 2025 13:55:31 GMT
server: Caddy
vary: Accept-Encoding
content-length: 101455
date: Wed, 31 Dec 2025 19:12:49 GMT
Blog - Dino. Communicating happiness.
https://dino.im/blog/
Hugo -- gohugo.io
en
Dino Team
Fri, 11 Apr 2025 18:30:00 +0200
-
Dino 0.5 Release
https://dino.im/blog/2025/04/dino-0.5-release/
Fri, 11 Apr 2025 18:30:00 +0200
https://dino.im/blog/2025/04/dino-0.5-release/
<p><em>Dino is a secure and open-source messaging application.
It uses the XMPP (Jabber) protocol for decentralized communication.
We aim to provide an intuitive and enjoyable user interface.</em></p>
<p>The 0.5 release improves the user experience around file transfers and includes two completely reworked dialogs.</p>
<h2 id="improved-file-sharing">Improved file sharing</h2>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2025/04/dino-0.5-release/image_preview_loading.png" width="374px"/> </figure>
</div>
<p>The way file transfers are currently done in the XMPP ecosystem is limited in functionality and files can sometimes be received out-of-order. Dino now supports a new method for announcing file transfers (<a href="https://xmpp.org/extensions/xep-0447.html">XEP-0447</a>), which solves this issue. Additionally, users can now see preview images or other file details before downloading the file. Dino currently only uses the new method for unencrypted file transfers, for example in public channels. Encrypted file transfers will also support the new protocol once Dino supports full-stanza encryption. All file transfers now also display the upload or download progress.</p>
<div class="blog-figure blog-figure-outleft-plain">
<figure>
<img src="https://dino.im/blog/2025/04/dino-0.5-release/new_dialogs.png"
alt="Screenshots of three dialogs for account settings, encryption and contact details" width="470px"/> </figure>
</div>
<h2 id="reworked-dialogs">Reworked dialogs</h2>
<p>The account and preferences dialogs have been combined into a single, new dialog. This dialog lets you manage accounts and adjust encryption and other settings. It now also includes some new settings like an option for OMEMO encryption by default, which is enabled by default.</p>
<p>Additionally, the conversation details dialog has been completely redesigned. Both dialogs are now fully compatible with mobile devices.</p>
<h2 id="colors-and-more">Colors and more</h2>
<p>Dino now uses the same fallback avatar colors as other clients (<a href="https://xmpp.org/extensions/xep-0392.html">XEP-0392</a>), creating a more consistent experience across applications.</p>
<p>A new unread line has been added, indicating the point up to which you’ve already read the messages.</p>
<p>Dino has also switched from CMake to Meson, which allows for an easier development process.</p>
<h1 id="alentejo">Alentejo</h1>
<p><em>We named this Dino release “Alentejo” after a region in Portugal.</em></p>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2025/04/dino-0.5-release/monsaraz.jpg" width="374px"/> </figure>
</div>
<p>Alentejo is a region in southern Portugal that is known for its wide plains that are dotted with wineyards and cork trees.
The region has a Mediterranean climate with summers regularly reaching temperatures above 40 degrees.</p>
<p>Currently, about 3.6% of all deaths in the region are caused by heat.
Heatwaves, in particular, pose a serious health risk and are expected to become more frequent and severe due to global warming [<a href="https://www.who.int/news-room/fact-sheets/detail/climate-change-heat-and-health">1</a>].
If CO₂ emissions keep increasing, heat-related deaths could make up 15.8% of all deaths in the region by 2100.
However, if action is taken to combat climate change, this number could be limited to 6.6% [<a href="https://bmcpublichealth.biomedcentral.com/articles/10.1186/s12889-024-21058-8">2</a>].</p>
-
Dino 0.4 Release
https://dino.im/blog/2023/02/dino-0.4-release/
Tue, 07 Feb 2023 22:00:00 +0100
https://dino.im/blog/2023/02/dino-0.4-release/
<p><em>Dino is a secure and open-source messaging application.
It uses the XMPP (Jabber) protocol for decentralized communication.
We aim to provide an intuitive and enjoyable user interface.</em></p>
<p>The 0.4 release adds support for message reactions and replies. We also switched from GTK3 to GTK4 and make use of libadwaita now.</p>
<h2 id="reactions-and-replies">Reactions and Replies</h2>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2023/02/dino-0.4-release/reaction.png" width="350"/> </figure>
</div>
<p>Reactions give you a quick and light-weight way to respond to a message with an emoji.
They can be used to express agreement or disagreement 👍️👎️, for voting, to express a feeling 🥳🤯, and much more 🦕.
You can react with any emoji you want and with as many as you want!</p>
<p>The new Dino release also adds another way for you to interact with messages: Replies.
The original message is displayed alongside the reply, and you can click on it to jump up to the original message.</p>
<div class="blog-figure blog-figure-outleft-plain d-none d-xl-block">
<figure>
<img src="https://dino.im/blog/2023/02/dino-0.4-release/message_menu.png" width="80px"/> </figure>
</div>
<p>You can add a reaction or reply to a message via the message menu.
To access the message menu, hover the message or tap it on touch-screens.</p>
<div class="blog-figure blog-figure-outleft-plain">
<figure>
<img src="https://dino.im/blog/2023/02/dino-0.4-release/reply.png"
alt="Screenshot of a reply"/> </figure>
</div>
<p>Reactions and replies are always possible in direct conversations.
In group chats and channels, the admin decides whether to support the features.</p>
<h2 id="gtk4-and-libadwaita">GTK4 and libadwaita</h2>
<p>Dino now uses GTK4 instead of GTK3 to display its user interface.
To the outside there are no big UI changes.
However, we can now make use of new or improved GTK features.</p>
<p>Furthermore, we started using libadwaita, which contains specialized Widgets and provides tools to build mobile-friendly UIs.
We already adjusted Dino’s main view for usage on mobile devices.</p>
<h1 id="ilulissat">Ilulissat</h1>
<p><em>Glaciers are fascinating landscapes of flowing ice.
We named this Dino release “Ilulissat” after a glacier in Greenland to help spread information on the effects of global warming on glaciers.</em></p>
<p>Glaciers are created over a span of centuries from fallen snow that compacts and transforms into glacial ice.
When the ice reaches a certain thickness, it starts to behave like a liquid.
Thus, glaciers are in constant movement, driven downhill by gravity under their own weight.</p>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2023/02/dino-0.4-release/Jakobshavn_Glacier_2019.jpg"
alt="Satellite view of the Ilulissat glacier and icefjord"/> <figcaption>
<p>Satellite view of the Ilulissat glacier and icefjord</p>
</figcaption></figure>
</div>
<p>Very large glaciers, also known as ice sheets, exist on Antarctica and Greenland.
Greenland’s ice sheet covers about 80% of the island and has an average thickness of 1,5 km.</p>
<p>The Greenland Ice Sheet, like all glaciers, is constantly in motion.
It accumulates ice in the interior of the island and flows outwards,
eventually reaching the ocean through so-called outlet glaciers.
One such outlet glacier is the Ilulissat glacier in West Greenland,
the fastest draining outlet of the Greenland Ice Sheet with a flow speed of over 20 meters per day.</p>
<p>Unfortunately, the Greenland Ice Sheet has been shrinking for past 26 years [<a href="https://eng.geus.dk/about/news/news-archive/2022/september/greenland-ice-sheet-is-shrinking">1</a>].
Rising water and air temperatures are causing outlet glaciers to melt at an accelerating pace,
draining the ice sheet more quickly and resulting in increased sea levels [<a href="https://climate.nasa.gov/vital-signs/ice-sheets/">2</a>].
Between 1992 and 2020, meltwater from the Greenland Ice Sheet alone increased global sea levels by over 1,3 cm,
where every centimeter of sea level rise is estimated to expose 6 Million people to coastal flooding [<a href="https://climate.copernicus.eu/climate-indicators/ice-sheets">3</a>].</p>
-
Stateless File Sharing: Source Attachment and Wrap-Up
https://dino.im/blog/2022/11/stateless-file-sharing-source-attachment-and-wrap-up/
Sat, 12 Nov 2022 00:00:00 +0000
https://dino.im/blog/2022/11/stateless-file-sharing-source-attachment-and-wrap-up/
<h2 id="recap">Recap</h2>
<p>Stateless file sharing (sfs) is a generic file sharing message which, alongside metadata, sends a list of sources where the file can be retrieved from.
It is generic in the sense, that sources can be from different kinds of file transfer methods.
HTTP, Jingle and any other file transfers can be encapsulated with it.
The big idea is that functionality can be implemented for all file transfer methods at once, thanks to this wrapper.</p>
<h2 id="source-attaching">Source Attaching</h2>
<p>The idea is simple: Once somebody started sfs, anybody can contribute more sources to the list of sources.
A sfs-attachment consists of the message id of the original sfs, as well as a list of sources that should be attached.</p>
<p>You might ask: “But <em>why?</em> I have used many messengers and never heard of such a feature, why should somebody else in the chat be able to do that?”</p>
<p>I was surprised as well, but there actually are some reasonable use cases.</p>
<ol>
<li>Peer-to-Peer file sharing in groups</li>
<li>Reviving dead download links</li>
<li>Announcing file uploads before the upload is finished</li>
</ol>
<p><strong>Security Considerations</strong></p>
<p>We obviously have to prevent the possibility of other members attaching wrong files to other people’s sfs.
To prevent this, sources can only be attached to sfs, which have checksums in their metadata.</p>
<p>Clients need to dismiss source attachments,</p>
<ol>
<li>if the sfs didn’t provide a checksum</li>
<li>if the checksum algorithm is not trusted or unknown</li>
<li>if the checksum of the downloaded file doesn’t match</li>
</ol>
<h2 id="google-summer-of-code-retrospect">Google Summer of Code Retrospect</h2>
<p>This was the first time with Google Summer of Code and honestly, it’s been a nice ride.
I’ve come to enjoy my stay and take pride in finishing the different components.</p>
<p>When I started earlier this year, I had developed a bit of an <a href="https://en.wikipedia.org/wiki/Impostor_syndrome">Imposter syndrome</a>.
For one I wasn’t sure if I understood the full scope of the project, but I was also uncertain if I had the skill to work on it.</p>
<p>Confidence came over time, when I managed to get an overview of everything that needed to be done.
Everything suddenly looks much more manageable, when you understand the purpose and inner workings of each subcomponent that will be required over the way.
Of course, it’s not completely straight forward.
I often had to realize that I will need another component somewhere, but one thing at a time is manageable.
Since I had my mentor to back me up whenever I got stuck, working on the project didn’t get frustrating.</p>
<p><strong>Blog posts</strong></p>
<p>Parallel to working on the project, we were expected to publish blog posts.
Originally I was going for a weekly interval, but yea…</p>
<p>I don’t think writing the blog posts helped me in any meaningful way.
However, I do think writing blogs is a good habit and hope that</p>
<ol>
<li>I improved my blog writing skills</li>
<li>The blogs will someday help someone</li>
</ol>
<h2 id="progress">Progress</h2>
<p>The GSoC period has already finished.
See my <a href="https://github.com/dino/dino/pull/1275">pull request</a>.</p>
-
Stateless File Sharing: Async, Metadata with Thumbnails and some UI
https://dino.im/blog/2022/09/stateless-file-sharing-async-metadata-with-thumbnails-and-some-ui/
Fri, 09 Sep 2022 00:00:00 +0000
https://dino.im/blog/2022/09/stateless-file-sharing-async-metadata-with-thumbnails-and-some-ui/
<h2 id="async">Async</h2>
<p>Asynchronous programming is a neat tool, until you work with a foreign project in a foreign language using it.
As a messenger, Dino uses lots of asynchronous code, not always though.
Usually my progress wasn’t interfered by such instances, but sometimes I had to work around it.</p>
<p><strong>Async in Vala</strong></p>
<p>No surprises here.
Functions are annotated with <code>async</code>, and <code>yield</code> expressions that are asynchronous themselves.
And you can’t easily call <code>async</code> methods directly in non-<code>async</code> functions.</p>
<p><strong>Creating problems</strong></p>
<p>I had a <code>async</code> function I wanted to call in a synchronous context.
For quick prototyping, I wanted to call that function and get the result directly by blocking.
However, the furthest I got there was a variable in a function that is only initialized if you access it late enough (wouldn’t recommend).
At that point I restructured the code so that the <code>async</code> call would actually be in an <code>async</code> context with a simple <code>yield</code>.</p>
<p><a href="https://wiki.gnome.org/Projects/Vala/Tutorial#Asynchronous_Methods">Here</a> a proper introduction to Vala <code>async</code>.</p>
<h2 id="metadataprovider">MetadataProvider</h2>
<p>With the introduction of the metadata element, more metadata can be extracted from files and attached to file transfers.
You wouldn’t have guessed, but there are actually a rather big variety of file types.
So not only do different files use different metadata fields, but they can also use the fields in different ways.</p>
<p>To accommodate that relation, the FileManager module now keeps a list of FileMetadataProviders, which will be extended over time.
When a file is sent, each provider is asked if it is compatible with the file. If yes, it is called.
The first provider is a generic one which is called for every file and fills in name, last-edit-date, size, mime-type and hashes.</p>
<h2 id="thumbnail-creation">Thumbnail creation</h2>
<p>A special new field is a list of thumbnails.
They are intended for small previews of whichever file it is attached to, be it a image, video or pdf.
So far, I have implemented thumbnails for images, which introduced two design decisions.</p>
<p><strong>Size</strong>: Which dimensions should the preview have?
When it is displayed, it should be stretched to the format of the original image, so the aspect ratio <em>should</em> sort of match.
My mentor, <a href="https://dino.im/blog/author/larma/">larma</a>, suggested that we create very small thumbnails for now, about 8 or 9 pixels.
Which dimensions would that allow? 1x8, 2x4, 3x3, 4x2, 8x1.
Well, that sounds pretty diverse, no?
Those are the dimensions that we use for now, and I select the dimension with the closest aspect ratio.</p>
<p><strong>Scaling</strong>: Now that we have the size, how do we scale the image?
Luckily, Gtk (which Vala is closely integrated with), has scaling methods for images.
So far, I used bilinear scaling, which is usually the suggested method according to the docs.
However, scaling to such a small size results in a lot of gray.
While you could probably come up with a fancy custom-made algorithm, I’ll stick with the Gtk built-in methods.
Maybe nearest-neighbor could be a better choice, because it would show a ’true’ color from the original image.</p>
<h2 id="ui">UI</h2>
<p>I tried to hold off on UI work until the last weeks of the projects.
While this could’ve easily been due to procrastination (I don’t enjoy UI coding a lot), I actually have a good excuse here.
The Dino codebase is being migrated to Gtk4 from Gtk3 this year.
Due to this, a lot of UI code is being rewritten, and it would’ve been wasted work to implement new UI elements in the old codebase.
The new UI element I introduced is the <code>FilePreviewWidget</code>, which holds a thumbnail of files which are so large that they aren’t immediately downloaded (currently >5 MB).
Luckily, the user interaction and graphical components are really close to the <code>FileImageWidget</code> and <code>FileDefaultWidget</code>, so the implementation wasn’t that difficult.</p>
<h2 id="progress">Progress</h2>
<p>We are nearly finished.
The one thing left is <a href="https://xmpp.org/extensions/xep-0447.html#attach-source">source attaching</a>, which the next (and last) progress post will cover.
Like always, you can track my progress on the <a href="https://github.com/Patiga/dino/tree/stateless-file-sharing">stateless-file-sharing</a> branch.
I also created a pre-gtk4-rebase branch <a href="https://github.com/Patiga/dino/tree/stateless-file-sharing-pre-gtk4">stateless-file-sharing-pre-gtk4</a>.</p>
-
Stateless File Sharing: Sources and Compatibility
https://dino.im/blog/2022/08/stateless-file-sharing-sources-and-compatibility/
Fri, 19 Aug 2022 00:00:00 +0000
https://dino.im/blog/2022/08/stateless-file-sharing-sources-and-compatibility/
<p>This is my next progress post about my Google Summer of Code project of implementing <a href="https://xmpp.org/extensions/xep-0447.html">Stateless File Sharing</a> (sfs)</p>
<h2 id="storing-sfs-sources-in-a-database">Storing sfs sources in a database</h2>
<p>Like everything else we receive, we need to store the sfs sources in a database.
In this case, we are in a unique position:
Not only are there different kinds of sources, but even http sources on their own are not trivial.
For now, we only use the url, but later we need to store much more to receive all kinds of http files.
Whether it’s cookies, necessary headers or authentication data, it would be a hassle to store everything in their own column or extra table.</p>
<p>Instead, we decided it would be easier and better with forward compatibility if we use some kind of serialization to be able to store any such data.
For that we create a table <code>SfsSources</code> with <code>file_id</code>, source <code>type</code> and <code>data</code>.
The idea is that we store the sources we obtain in a serialized data field.
This way we can store elements we don’t use yet and have a unified table for everything.
However, this also means that data can’t be searched properly with database queries.</p>
<h2 id="vala-interfaces">Vala interfaces</h2>
<p>This paragraph will compare elements of the programming languages <a href="https://vala.dev/">Vala</a> and <a href="https://www.rust-lang.org/">Rust</a>.</p>
<p>Being kinda new to vala, I struggled to map sfs sources into a class.
The main issue is that it needs to support multiple variants.</p>
<p>In Rust, I would immediately go with a Rust <a href="https://doc.rust-lang.org/stable/book/ch06-01-defining-an-enum.html">enum</a>, which allows you to store different data in each variant.
For this, I was told that I should use a Vala <a href="https://www.vala-project.org/doc/vala/Interfaces.html">interface</a>.
This confused me, because reading the documentation, they seemed to me a lot more like Rust <a href="https://doc.rust-lang.org/book/ch10-02-traits.html">traits</a>:
They define shared behavior that other classes can implement and then be passed generically as the interface type.</p>
<p>The big difference between Rust traits and Vala interfaces, however, is that you can easily cast the generic interface type back into its original class.
Using this, they can also be used similar to Rust enums.</p>
<h2 id="all-the-compatibility">ALL the compatibility</h2>
<p>I guess we are adding a new file transfer method.
Well then, let’s maybe try to not lose compatibility with all the other clients?</p>
<p><strong>Fallback body</strong></p>
<p>When we send a sfs file transfer with a http source, we want to allow the receiver to see <a href="https://xmpp.org/extensions/xep-0066.html">Out of Band Data</a>.
Exactly to support backwards compatibility, sfs can be attached to any other message, simply as another subnode.
All we have to do here, is to create a normal message stanza with Out-of-Band-Data, and send the sfs along with it.</p>
<p><strong>Double Receive</strong></p>
<p>Well darn, now we receive that file transfer twice, because two modules registered an incoming file transfer. Who could’ve guessed.</p>
<p>Dino has about 4 entry points for message listeners</p>
<ol>
<li>A Signal that listeners can connect to. Owned by <code>MessageModule</code> (module <code>xmpp_vala</code>)</li>
<li>A Pipeline of listeners owned by <code>MessageModule</code> (module <code>xmpp_vala</code>)</li>
<li>A Signal that listeners can connect to. Owned by <code>MessageProcessor</code> (module <code>libdino</code>)</li>
<li>A Pipeline of listeners owned by <code>MessageProcessor</code> (module <code>libdino</code>)</li>
</ol>
<p>As we can see, there are two types of listeners, and each type is present in each <code>xmpp_vala</code> and <code>libdino</code>.</p>
<ul>
<li>Signal: listeners are called in an arbitrary order</li>
<li>Pipeline: listeners are called in specified order, used when listeners depend on each other. Listeners can also drop messages so that they don’t get processed further</li>
<li><code>xmpp-vala</code>: Lower level, access to raw xml elements</li>
<li><code>libdino</code>: For text messages, called after messages are stored in the database</li>
</ul>
<p>Out-of-Band-Data is retrieved via a <code>ReceivedMessageListener</code> that connects to <code>MessageModule</code>’s signal and sfs via <code>MessageProcessor</code>’s signal.
To avoid the double-receive, we create a sfs <code>MessageFlag</code>, that gets attached when we successfully received sfs from a message.
The Out-of-Band-Data listener first checks whether that flag is set, before parsing the message itself.</p>
<p><strong>Unifying http file transfers</strong></p>
<p>We of course still expect to receive Out-of-Band-Data messages.
However, it is not very nice to need to handle two variants of http file transfer differently in databases and other code.
The answer is rather simple here: When we receive Out-of-Band-Data, we convert it into an incoming sfs and handle it as such.</p>
<h2 id="next-up">Next up</h2>
<p>The next To-do I will approach is image and video specific metadata.
As always, you can track my progress on my <a href="https://github.com/Patiga/dino/tree/stateless-file-sharing">stateless-file-sharing</a> branch</p>
-
Stateless File Sharing: Base implementation
https://dino.im/blog/2022/08/stateless-file-sharing-base-implementation/
Sun, 07 Aug 2022 00:00:00 +0000
https://dino.im/blog/2022/08/stateless-file-sharing-base-implementation/
<p>The last few weeks were quite busy for me, but there was also a lot of progress.
I’m happy to say that the base of stateless file sharing is implemented and working.
Let’s explore some of the more interesting topics.</p>
<h2 id="file-hasheshttpsxmpporgextensionsxep-0300html"><a href="https://xmpp.org/extensions/xep-0300.html">File Hashes</a></h2>
<p>File hashes have some practical applications, such as file validation and duplication detection.
As such, they are part of the <a href="https://xmpp.org/extensions/xep-0446.html">metadata element</a> that stateless file sharing introduces.
The hash values are stored as the base64 encoded raw byte representation of the hashes result.
Multiple hashes can be added, and it is not specified which algorithm should be used.
Instead, <a href="https://xmpp.org/extensions/xep-0414.html#recommendations">XEP-0414</a> has a maintained list of the recommended hash algorithms.</p>
<p>The idea behind not specifying which algorithm should be used is to keep flexibility and to stay future-proof.
However, this does make implementations more complicated because you somehow have to handle multiple hashes, and perhaps from algorithms your code is unaware of.
As of now, I intend to only send the sha256 in the metadata.</p>
<h2 id="file-sources">File Sources</h2>
<p>As you might recall, the big idea behind stateless file sharing is that it is not bound to a specific method for file transfer.
Same as with the hashes, multiple sources can be provided.
For this project, the goal is just to have HTTP file transfers working (the base of which already works) in an extendable way.
This is mostly because the type of jingle (peer-to-peer) file transfer that exists in Dino is not suitable for this:
Dino currently only allows users to start a file transfer as the sending party (‘push’).
Suitable would be if a sender could signal an available file and have the receiver signal that they now want to receive it (‘pull’).</p>
<h2 id="new-file-transfer-method-in-dino">New file transfer method in Dino</h2>
<p>Turns out, you need to edit multiple components of a messenger when adding something that sends and parses certain messages.
Figuring out which parts of Dino’s code I will need to touch wasn’t exactly clear to me.
Dino is written in <a href="https://en.wikipedia.org/wiki/Vala_(programming_language)">Vala</a>, which was also a new language for me.</p>
<p>The components I had to touch are:</p>
<ul>
<li><code>xmpp-vala</code>: low level XMPP code</li>
<li><code>libdino</code>: Code that can be used to build a messenger UI</li>
<li><code>plugins</code>: Messenger components that can be disabled</li>
</ul>
<p>So, which parts of my code goes where?</p>
<ul>
<li><code>xmpp-vala</code>: Stanza definitions, serializing, parsing, methods for the stanzas</li>
<li><code>libdino</code>: File management, storing data in the correct database, attaching to the correct XMPP streams</li>
<li><code>plugins</code>: To have <code>libsoup</code> as an optional dependency, HTTP file transfer stuff is a plugin</li>
</ul>
<p>By adding the different components, I had to both edit and add new tables to the database.</p>
<ul>
<li>The <code>FileTransfer</code> table received more fields to accommodate the additional metadata</li>
<li><code>FileHashes</code> is a new table to store the triple <code>file_id</code>, <code>hash_algorithm</code>, and <code>hash_value</code></li>
<li><code>SfsHttpSources</code> stores the tuple <code>file_id</code>, <code>url</code>. New columns can be added later for more complicated HTTP requests</li>
</ul>
<h2 id="writing-vala-and-debugging">Writing Vala and Debugging</h2>
<p>Having not programmed in <a href="https://en.wikipedia.org/wiki/Vala_(programming_language)">Vala</a> before, I must say that I was very positively surprised at how little debugging I had to do.
Most smaller things simply worked out of the box.</p>
<p>There were of course also instances where debugging wasn’t trivial.
Especially database code and connecting to networking didn’t work out of the box for me.
While trial-and-error with printf-debugging sometimes did the trick, sometimes I figured that outside help would cut down the time I would need drastically.
For many things I contacted my mentor, <a href="https://dino.im/blog/author/larma/">Marvin</a> who could usually point me in the right direction very quickly, which made work on the project quite pleasant.</p>
<p>Also helpful was of course debugging with gdb.
In particular when critical warnings are already output, setting the environment variable <code>G_DEBUG=fatal-criticals</code> helps a lot.
This will simply break on every such warning, which allows you to easily inspect what went wrong.</p>
<h2 id="next-steps">Next Steps</h2>
<p>While there was a lot of progress, there are also a good amount of loose ends to tie up.
The reusage of the HTTP send and receive code is a bit hacky, and some parts of the code should be written more extendable.
Next up is cleaning up the code that was introduced.
After that, there is still obtaining the image- and video-specific metadata and some UI work.</p>
<p>As always, progress can be tracked on my <a href="https://github.com/Patiga/dino/tree/stateless-file-sharing">stateless-file-sharing branch</a></p>
-
Project Stateless File Sharing: First Steps
https://dino.im/blog/2022/06/project-stateless-file-sharing-first-steps/
Thu, 30 Jun 2022 00:00:00 +0000
https://dino.im/blog/2022/06/project-stateless-file-sharing-first-steps/
<p>Hey, this is my first development update!
As some of you might already know from my last blog post, my Google Summer of Code project is implementing Stateless File Sharing for Dino.
This is my first XMPP project and as such, I had to learn very basic things about it.
In my blog posts I’ll try to document the things I learned, with the idea that it might help someone else in the future.
I won’t refrain from explaining terms you might take for granted in the XMPP world.</p>
<h2 id="the-idea-behind-stateless-file-sharing">The idea behind Stateless File Sharing</h2>
<p>Currently there are mutiple ways to send files via XMPP.
Some of those methods initiate the file transfers in very different ways.
This makes it difficult to add shiny new features like blurred previews of images, because we would need to implement that for each file transfer individually.</p>
<p>What we want is a unified initiation for file transfers.
In that initiation, “sources” should be specified that tell the receiver how they can access that file.</p>
<h2 id="relevant-xeps">Relevant XEPs</h2>
<p>The core of the XMPP protocol is very slim, defining only general ways of communicating data.
It is build to be extensible, and XEP are exactly that: XMPP Extension Protocols.</p>
<p>Stateless File Sharing is <a href="https://xmpp.org/extensions/xep-0447.html">XEP-0447</a>.
It depends on <a href="https://xmpp.org/extensions/xep-0446.html">XEP-0446</a>, which defines the metadata that should be sent alongside a file.
XEP-0446 in turn depends on <a href="https://xmpp.org/extensions/xep-0300.html">XEP-0300</a>, where the integration of hashes is specified, and <a href="https://xmpp.org/extensions/xep-0264.html">XEP-0264</a>, which defines the usage of thumbnails.</p>
<h2 id="stanzas">Stanzas</h2>
<p>This is a term that comes up everywhere if you dive into XMPP technical information.
Since it confused be for a while, here a quick rundown.</p>
<p>Stanzas are the basic form of communication between XMPP clients and servers.
There are different types of them, but they are all encoded with XML.
As such, they inherit XML’s structure.</p>
<p>An XML element can be viewed as a tree.
See for instance the format example for the file metadata element (<a href="https://xmpp.org/extensions/xep-0446.html">XEP-0446</a>):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt"><file</span> <span class="na">xmlns=</span><span class="s">'urn:xmpp:file:metadata:0'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><media-type></span>text/plain<span class="nt"></media-type></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><name></span>test.txt<span class="nt"></name></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><date></span>2015-07-26T21:46:00+01:00<span class="nt"></date></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><size></span>6144<span class="nt"></size></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><hash</span> <span class="na">xmlns=</span><span class="s">'urn:xmpp:hashes:2'</span>
</span></span><span class="line"><span class="cl"> <span class="na">algo=</span><span class="s">'sha-1'</span><span class="nt">></span>w0mcJylzCn+AfvuGdqkty2+KP48=<span class="nt"></hash></span>
</span></span><span class="line"><span class="cl"><span class="nt"></file></span>
</span></span></code></pre></div><p>The root element is called ‘file’, and has only one attribute “xmlns”.
Each attribute has a value assigned, in this case its ‘urn:xmpp:file:metadata:0’.
The ‘file’ element also has child elements, all containing a text body.
Only the “hash” child element has an additional attribute.</p>
<h2 id="progress-as-of-29062022">Progress (as of 29/06/2022)</h2>
<p>I’m now familiar with how Dino represents Stanzas.
I’ve created the base struct for the file metadata element (<a href="https://xmpp.org/extensions/xep-0446.html">XEP-0446</a>) and serialize, send, and deserialize it.
So far I simply integrate the code into the http file transfer code, detaching from it will come later.</p>
<p>You can track my progress on my <a href="https://github.com/Patiga/dino/tree/stateless-file-sharing">stateless-file-sharing branch</a>!</p>
-
Stateless File Sharing GSoC project
https://dino.im/blog/2022/06/stateless-file-sharing-gsoc-project/
Tue, 21 Jun 2022 00:00:00 +0000
https://dino.im/blog/2022/06/stateless-file-sharing-gsoc-project/
<p>Hey!</p>
<p>I’m Patiga, a computer science student from Germany and a new contributor to Dino.
The yearly Google Summer of Code has started, and I’m glad to be part of it.
This time, you can look forward to a modernized file transfer called “Stateless File Sharing”.</p>
<p>End users can look forward to blurred previews of large images and other metadata alongside file transfers.
You might already know this from other messengers, now it’s coming to Dino/XMPP.</p>
<p>There are some more technicalities, which we will dive into deeper in upcoming blog posts.
If you want to have a peek at some technical information already, see the relevant <a href="https://xmpp.org/extensions/xep-0447.html">XEP-0447</a>.</p>
-
Dino 0.3 Release
https://dino.im/blog/2022/02/dino-0.3-release/
Sat, 12 Feb 2022 22:22:00 +0100
https://dino.im/blog/2022/02/dino-0.3-release/
<p><em>Dino is a secure and privacy-friendly messaging application. It uses the XMPP (Jabber) protocol for decentralized communication. We aim to provide an intuitive, clean and modern user interface.</em></p>
<div class="blog-figure blog-figure-plain">
<figure>
<img src="https://dino.im/blog/2022/02/dino-0.3-release/conference_call_screenshot.png"/> </figure>
</div>
<div class="blog-figure blog-figure-outleft-plain d-none d-xl-block">
<figure>
<img src="https://dino.im/blog/2022/02/dino-0.3-release/start_call.svg" width="180px"/> </figure>
</div>
<p>The 0.3 release is all about calls. Dino now supports calls between two or more people!</p>
<p>Calls are end-to-end encrypted and use a direct connection between the peers whenever possible, but fallbacks are also in place.</p>
<p>As always, we put lots of love into the user interface and hope that you will enjoy using it.
To call a friend, just open a conversation with them and select whether you want to start an audio-only or a video call.</p>
<h2 id="groupcalls">Groupcalls</h2>
<p>You also can start a call in a private group or invite additional contacts to an existing call.
Using a peer-to-peer approach for groupcalls means that no additional server support is required, besides conference rooms.</p>
<p>Peer-to-peer calls require more bandwidth than calls routed through a server and are thus not suited for a large number of participants.
In the future, we plan to also develop calls via a forwarding server to solve resource issues on the client side and to allow for calls with more participants.</p>
<h2 id="encrypted">Encrypted</h2>
<div class="blog-figure blog-figure-outright-plain d-none d-lg-block">
<figure>
<img src="https://dino.im/blog/2022/02/dino-0.3-release/encryption.svg" width="320px"/> </figure>
</div>
<p>Calls are end-to-end encrypted with the best encryption supported by both you and your contact.
The encryption keys for a call are exchanged using DTLS and the call is then encrypted with SRTP.
You can see the DTLS keys used for the current call in the UI and compare them with the ones your contact sees.</p>
<p>Additionally, the DTLS keys are authenticated using OMEMO. If you verified the OMEMO key beforehand, you can be sure that you have an end-to-end encrypted call with a device that you trust.</p>
<h2 id="interoperabilility--open-protocols">Interoperabilility & Open Protocols</h2>
<p>Calls are established and conducted using openly standardized protocols.
Call intents are sent (<a href="https://xmpp.org/extensions/xep-0353.html">XEP-0353</a>) and connection methods exchanged via XMPP (<a href="https://datatracker.ietf.org/doc/html/rfc6120">RFC 6120</a>) in a standardized way (<a href="https://xmpp.org/extensions/xep-0167.html">XEP-0167</a>), the data is encrypted (<a href="https://datatracker.ietf.org/doc/html/rfc5763">RFC 5763</a>) and transferred (<a href="https://datatracker.ietf.org/doc/html/rfc3550">RFC 3550</a>) all via standardized and documented means.</p>
<p>You can establish calls between Dino and every other application that follows these standards.
Encrypted video calls can be made between Dino and for example Conversations or Movim. With clients like Gajim that don’t support encryption, making unencrypted calls is also possible. If a client doesn’t support video, audio-only calls can still be made.</p>
<div class="blog-figure blog-figure-plain">
<figure>
<img src="https://dino.im/blog/2022/02/dino-0.3-release/call_ended.svg"/> </figure>
</div>
<h1 id="theikenmeer">Theikenmeer</h1>
<p><em>Peat bogs are unique ecosystems that mitigate the effects of climate change if they’re in a natural state, but worsen climate change when they are drained.
We named this Dino release “Theikenmeer” after a bog nature reserve in Germany to help spread the word about these important yet endangered ecosystems.</em></p>
<p>Peat bogs are wetlands that accumulate peat, a deposit of dead moss and other plant material.
Due to low oxygen levels, moss below the water surface does not decay and thus accumulates bit by bit.
By accumulating plant material, bogs store carbon.
Although they only make up 3% of the world’s land surface, bogs store twice as much carbon as all forests together! [<a href="https://www.iucn.org/resources/issues-briefs/peatlands-and-climate-change">1</a>]</p>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2022/02/dino-0.3-release/Ostercappeln_-_Venne_-_Venner_Moor_11.jpg"/> </figure>
</div>
<p>Besides capturing carbon, a bog also provides other benefits to its surroundings.
A bog acts like a sponge: It absorbs water when it’s abundant and releases it back into the surrounding when it’s dry.
Thus, it reduces the severity of floods and droughts.
Bogs also lower the temperatures in the surroundings, filter the groundwater and are home to endangered and specialized plants and animals.</p>
<p>During the last centuries, peat bogs have been increasingly drained in order to make use of the land or to extract the peat.
When a bog is dry, the accumulated plant material starts to decay, releasing the stored carbon into the atmosphere.</p>
<p>Theikenmeer is a nature reserve in the north-west of Germany containing a peat bog and a lake.
The peat bog has been drained to extract peat and due to nearby farming until the peat bog and the lake were completely dried out by 1977.
It has been calculated that the Theikenmeer peat bog would release 2250 tons of CO₂ into the atmosphere every year while it’s dry [<a href="https://www.bsh-natur.de/uploads/Biotope/026%20-%20Theikenmeer.pdf">2</a>].
Fortunately, volunteers started closing the drainage channels in the early 1980s.
Today, the bog is wet again and bog plants and wildlife started returning into the area, allowing the bog to capture CO₂ instead of releasing it.</p>
<p>Theikenmeer’s peat bog belongs to a small percentage of natural peat bogs in Germany.
However, over 90% of all peat bogs in Germany are still drained, causing almost 7% of Germany’s yearly greenhouse gas emissions [<a href="https://www.bmuv.de/download/bund-laender-zielvereinbarung-zum-moorbodenschutz">3</a>].
Drained peat bogs only make up 0.3% of the world’s land surface, yet they emmit 5% of all anthropogenic greenhouse gases [<a href="https://www.iucn.org/resources/issues-briefs/peatlands-and-climate-change">1</a>].</p>
-
Dino 0.2 Release
https://dino.im/blog/2020/11/dino-0.2-release/
Thu, 12 Nov 2020 19:00:00 +0100
https://dino.im/blog/2020/11/dino-0.2-release/
<p><em>Dino is a secure and open-source messaging application.
It uses the XMPP (Jabber) protocol for decentralized communication.
We aim to provide an intuitive, clean and modern user interface.</em></p>
<p>The 0.2 release adds message correction, improves the file upload functionality and provides more information about message encryption.
Besides other smaller changes it also fixes a number of bugs.</p>
<h1 id="message-correction">Message correction</h1>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2020/11/dino-0.2-release/message_correction.png" width="535"/> </figure>
</div>
<p>It is now possible to correct the last message you sent.
You can access the function by hovering the message that you want to correct and then click the edit button that appears.
If you’re a fan of shortcuts, you can also press the UP key.
Last message correction has been the most frequently requested feature addition so far.
We are happy about how it turned out and hope you are, too!</p>
<h1 id="file-sharing">File sharing</h1>
<div class="blog-figure blog-figure-outleft-plain">
<figure>
<img src="https://dino.im/blog/2020/11/dino-0.2-release/file_upload2.png" width="535"/> </figure>
</div>
<p>You can now send files via drag and drop!
Furthermore, you can now send Images by pasting them from your clipboard.
As before, there is also still the option to press the “Send a File”-button.</p>
<p>Especially with those new ways of sending a file it is important to know that you are sending the right file to the right person.
That’s why Dino now presents a confirmation dialog with a file preview and some file details.</p>
<h1 id="encryption">Encryption</h1>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2020/11/dino-0.2-release/encryption2.png" width="535"/> </figure>
</div>
<p>It has already been possible to accept, verify or reject OMEMO keys.
Now you can see the relevant information alongside each message:
A small lock or seal symbol above a message indicates whether the message was encrypted by an accepted or a verified device, respectively.
A red, open lock warns you in case your contact sends unencrypted messages in an encrypted conversation.</p>
<h1 id="unread-pending-and-more">Unread, pending and more…</h1>
<div class="blog-figure blog-figure-outleft-plain">
<figure>
<img src="https://dino.im/blog/2020/11/dino-0.2-release/unread_count.svg" width="415"/> </figure>
</div>
<p>Dino now displays the number of unread messages in the conversation list. The color of the circle tells you whether the new messages triggered a notification (e.g. direct messages, mentions in channels).</p>
<p>Furthermore, Dino lets you know in case your message has not been sent yet by displaying “pending…” alongside the message.</p>
<p>In moderated channels, Dino will inform you if you don’t have the permission to write messages and offer the possibility to request that permission from a moderator.</p>
<h1 id="coral-reefs">Coral Reefs</h1>
<p><em>Coral reefs are diverse and important ecosystems. Climate change and local human influences endanger coral reefs around the world.
We named this Dino release “Mexican Caribbean Coral Reefs” to help spread the word about what needs to be done to preserve these unique ecosystems.</em></p>
<p>While coral reefs only occupy 0.1% of the ocean area, they are home to 25% of all marine species.
Those reefs are made up of the calcium carbonate skeletons of corals.
Corals grow very slowly and thus reefs require thousands of years to form.
Many tropical corals live in symbiosis with tiny algae, which provide the corals with nutrients in exchange for shelter.</p>
<p>Climate change harms corals in two ways: First, it raises the ocean temperatures.
Corals lose their algae in high water temperatures, which is called “bleaching”.
Without the algae the corals starve.
Secondly, the ocean absorbs parts of the increasing carbon dioxide amounts from the atmosphere.
In water, CO₂ reacts to carbonic acid, which dissolves coral skeletons.</p>
<p>Many coral reefs are located in the shallow water near coasts and are thus highly affected by local human activities:
Sediments and nutrients are washed into the ocean and deprive the corals of light;
Overfishing can negatively affect the whole ecosystem;
Destructive fishing using poisons or explosives harms the corals.</p>
<p>For example, the coral cover in the Mexican Caribbean Coral Reefs decreased by 60% between 1980 and 2016.
This was caused by mass bleaching events due to increased water temperature, hurricane impacts, and an increased amount of sediment due to deforestation [<a href="https://www.nature.com/articles/s41598-020-65801-8#Abs1">1</a>].</p>
<p>Various programs aim to protect individual coral reefs from local dangers.
However, the ecosystem coral reef can only be preserved by also eliminating the global threat: Climate change.
According to multiple studies, coral reefs only have a chance of survival if the global temperature increase is limited to 1.5°C [<a href="https://whc.unesco.org/en/news/1878">2</a>, <a href="https://climate.nasa.gov/news/2865/a-degree-of-concern-why-global-temperatures-matter/#:~:text=Ocean%20warming%2C%20acidification%20and%20more,existent%20at%202%20degrees%20warming.">3</a>].
Your actions have an impact.</p>
-
Setting out for calls and conferences
https://dino.im/blog/2020/08/setting-out-for-calls-and-conferences/
Tue, 11 Aug 2020 14:00:00 +0100
https://dino.im/blog/2020/08/setting-out-for-calls-and-conferences/
<p>Video calls have become a widely used means of communication in personal and in business settings. Especially during the last months, people increasingly used video calls to keep in touch. Unfortunately, many turn to US-based, centralized and closed-source solutions that come with privacy and security issues.</p>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2020/08/setting-out-for-calls-and-conferences/calling-screen.png"
alt="Screen showing dinosaurs in a video conference" width="380"/> </figure>
</div>
<p>We are now starting to implement decentralized calls and conferences in Dino. As with the rest of the UI, we aim for a nice and simple user experience. The call features are planed to be implemented and published step-by-step over the next 12 months. Support for encrypted two-party calls that are compatible with Conversations should be ready by the end of this year or early next year. For conference calls, we are also looking into compatibility with the popular video-conferencing solution Jitsi Meet, that is also based on the XMPP protocol.</p>
<p>This work is made possible through contributions from the NGI0 PET Fund. The fund is managed by NLnet and dedicated to Privacy and Trust Enhancing technologies. It was established with financial support from the European Commission’s Next Generation Internet programme.</p>
<div class="blog-figure blog-figure-plain">
<figure>
<img src="https://dino.im/blog/2020/08/setting-out-for-calls-and-conferences/logos.svg"
alt="Logos of NGI0 PET, NLnet and European Commission"/> </figure>
</div>
-
Dino 0.1 Release
https://dino.im/blog/2020/01/dino-0.1-release/
Wed, 29 Jan 2020 18:00:00 +0100
https://dino.im/blog/2020/01/dino-0.1-release/
<p>We are thrilled to announce the first release of Dino: Version 0.1. This marks an important milestone of the development process that started three years ago and already combined work of 30 contributors, including 4 summer of code students and multiple development sprints.</p>
<p>Dino is a secure and open-source application for decentralized messaging. It uses the XMPP (“Jabber”) protocol and is interoperable with other XMPP clients and servers. We aim to provide an intuitive, clean and modern user interface.</p>
<div class="blog-figure blog-figure-plain">
<figure>
<img src="https://dino.im/blog/2020/01/dino-0.1-release/main_window.png"
alt="Dino's Main Window"/> </figure>
</div>
<h2 id="motivation-why-dino">Motivation: Why Dino?</h2>
<p>Chat applications like WhatsApp and Facebook Messenger are easy to use and thus were adopted by billions of people. However, they are closed-source and the companies behind them are frequently criticized for misuse of private data. Multiple messaging apps grew around the idea of providing a privacy-friendly alternative, for example Signal and Wire. While they provide encryption and release source-code, their users still have to rely on a centralized service and trust a single company.</p>
<p>XMPP is an open protocol for federated communication. There are lots of public servers that communicate with each other and anyone can host their own server. This makes it a great basis to write a privacy-friendly and decentralized messenger on. A number of clients already exist for the XMPP protocol, however Dino sets a different focus. Existing clients target tech-savvy power users. The XMPP ecosystem lacks a client that is enjoyable to use while providing the features people expect from a modern chat application. Dino fills that gap by aiming to be secure and privacy-friendly while at the same time providing a great user experience.</p>
<h2 id="features">Features</h2>
<p>At first glance, Dino’s user interface is similar to what you might be used to from other popular messengers. On the left side your opened conversations are listed, ordered such that the latest messages are always on top. You can open new conversations or join channels with the ‘+’ menu.</p>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2020/01/dino-0.1-release/file_transfer.png"
alt="Conversation with inline images and a file in Dino" width="380"/> </figure>
</div>
<h3 id="messaging-and-more">Messaging and more</h3>
<p>You can send messages to individuals as well as to private group chats and public channels. Dino can be used together with other clients simultaneously, allowing you continue the same conversation on your mobile phone as well as on your desktop. Messages you sent and received while Dino was offline are synchronized on start up.</p>
<div class="blog-figure blog-figure-outleft">
<figure>
<img src="https://dino.im/blog/2020/01/dino-0.1-release/message_search.png"
alt="Dino's message search with highlighted results" width="400"/> <figcaption>
<p>Message search</p>
</figcaption></figure>
</div>
<p>Dino supports sharing images and other files. It can transfer files via your server or directly to your contact, peer-to-peer and without size limitations.</p>
<p>An advanced message search allows you to search and filter your message history - globally or within one conversation. After looking through the results, you can jump to a message to read more of the context.</p>
<p>You can use multiple accounts in the same interface, allowing you for example to conveniently separate your work and private identities.</p>
<h3 id="security-and-privacy">Security and Privacy</h3>
<div class="blog-figure blog-figure-outright-plain">
<figure>
<img src="https://dino.im/blog/2020/01/dino-0.1-release/security_omemo.png"
alt="Dino's OMEMO Key Management Dialog" width="400"/> </figure>
</div>
<p>Security has been a focus for Dino development since the beginning. That’s why we support two end-to-end-encryption methods out of the box: The well-known encryption standard OpenPGP allows you to extend your Web-of-Trust from e-Mail to XMPP. The OMEMO double-ratchet encryption provides you with a modern encryption scheme with individual device trust that is widely used in the XMPP network.</p>
<p>We take your privacy seriously in every detail. For example you can keep Dino from informing the sender when you read a message, so they won’t see a double-tick on their messages. Dino allows you to configure all of its privacy features per contact: You can keep your best friends up-to-date while not sharing anything with strangers.</p>
<h3 id="fast-and-well-integrated">Fast and well integrated</h3>
<p>Dino does not include a full browser stack with its large resource usage and potential of security issues. Instead it is a native desktop application meaning it is small and has a light footprint. Dino integrates nicely with the rest of your desktop applications and services.</p>
<h2 id="get-started">Get Started</h2>
<p>Once you created an XMPP account, you can contact people across the globally connected XMPP network. XMPP addresses are of the form <code>user@example.com</code>. You can sign in with an existing account or create a new one!</p>
-
End of the Google Summer of Code
https://dino.im/blog/2019/08/end-of-the-google-summer-of-code/
Mon, 26 Aug 2019 00:00:00 +0000
https://dino.im/blog/2019/08/end-of-the-google-summer-of-code/
<p>This Google Summer of Code was about adding peer-to-peer file transfers to
Dino. <a href="https://dino.im/">Dino</a> is an XMPP client, <a href="https://xmpp.org/">XMPP</a> is
decentralized instant messaging standard.</p>
<p>The work was mostly done in two larger pull requests. The first one,
<strong><a href="https://github.com/dino/dino/pull/577">dino#577</a></strong>, added a Jingle framework
(<a href="https://xmpp.org/extensions/xep-0166.html">XEP-0166</a>), the in-band-bytestream
transport (<a href="https://xmpp.org/extensions/xep-0047.html">XEP-0047</a>,
<a href="https://xmpp.org/extensions/xep-0261.html">XEP-0261</a>) and the Jingle file
transfer protocol (<a href="https://xmpp.org/extensions/xep-0234.html">XEP-0234</a>).</p>
<p>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.</p>
<p>In-band bytestreams are a simple method of exchanging binary data between XMPP
clients by sending <a href="https://en.wikipedia.org/wiki/Base64">base64</a>-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.</p>
<p>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 <a href="https;//conversations.im/">Conversations</a>), 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.</p>
<p>The work on this pull request was concluded by some <a href="https://dino.im/blog/2019/06/third-week-interoperability-testing/">interoperability
testing</a> with Conversations and Gajim, two other
major XMPP clients.</p>
<p>The second pull request, <strong><a href="https://github.com/dino/dino/pull/592">dino#592</a></strong>
(not merged yet, currently on commit
<a href="https://github.com/dino/dino/commit/6028fd15a81a084b63311bc61f7b48d9f3d00746">6028fd1</a>)
added the <a href="https://en.wikipedia.org/wiki/SOCKS">SOCKS5</a> transport method for
Jingle (<a href="https://xmpp.org/extensions/xep-0065.html">XEP-0065</a>,
<a href="https://xmpp.org/extensions/xep-0260.html">XEP-0260</a>).</p>
<p>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.</p>
<p><a href="https://dino.im/blog/2019/08/ninth-and-tenth-week-interoperability-fun/">Interoperability testing</a> 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.</p>
<p>There were also a couple of other smaller pull requests which I’ll mention
here:</p>
<ul>
<li><a href="https://github.com/dino/dino/pull/569">dino#569</a>. Tiny fix for logging to a
file.</li>
<li><a href="https://github.com/dino/dino/pull/570">dino#570</a>. Tiny typo fix, sorry for
even mentioning. :o</li>
<li><a href="https://github.com/dino/dino/pull/579">dino#579</a>. Improvement around the
error generation in response to certain XMPP messages.</li>
</ul>
<p>In the course of the interoperability testing, I also opened a couple of issues
on other XMPP clients:
<a href="https://github.com/siacs/Conversations/issues/3478">Conversations#3478</a>,
<a href="https://github.com/siacs/Conversations/issues/3500">Conversations#3500</a>, <!-- raw HTML omitted --><!-- raw HTML omitted -->Conversations#3514<!-- raw HTML omitted -->,<!-- raw HTML omitted -->
<a href="https://github.com/siacs/Conversations/issues/3515">Conversations#3515</a>,
<a href="https://dev.gajim.org/gajim/gajim/issues/9784">Gajim#9784</a>.</p>
<p>As the <strong>next steps</strong>, after Google Summer of Code, I’ll implement the
<a href="https://en.wikipedia.org/wiki/WebRTC">WebRTC</a> 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.</p>
<p>At this point I’d like to thank my two mentors
<a href="https://github.com/fiaxh">fiaxh</a> and <a href="https://github.com/mar-v-in">mar-v-in</a>
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
<a href="https://en.wikipedia.org/wiki/Vala_(programming_language)">Vala</a>, the language
Dino is written in.</p>
<p>Thanks to my mentoring organization, the XSF (XMPP standards foundation), as
well, for the weekly meetings and generally the advice given therein.</p>
-
Ninth and tenth week: Interoperability fun
https://dino.im/blog/2019/08/ninth-and-tenth-week-interoperability-fun/
Tue, 06 Aug 2019 00:00:00 +0000
https://dino.im/blog/2019/08/ninth-and-tenth-week-interoperability-fun/
<p>After finishing the SOCKS5 bytestreams transport for Jingle (S5B,
<a href="https://xmpp.org/extensions/xep-0065.html">XEP-0065</a>,
<a href="https://xmpp.org/extensions/xep-0260.html">XEP-0260</a>), I was asked whether I
had already done interoperability testing with other clients for the fallback
to in-band bytestreams.</p>
<blockquote>
<p>flow: […] which other transports do you support? How far has interoperability testing between different implementations be done?</p>
<p>hrxi: only socks5 and ibb, conversations and gajim both work fine</p>
<p>flow: […] did you also test the socks5 to ibb fallback?</p>
<p>hrxi: no, that doesn’t work yet</p>
<p>flow: uh, maybe you find the time to implement that in the remaining two weeks, or are there other plans?</p>
</blockquote>
<p>I guess I should’ve seen it coming at this point. Here’s how the fallback
should work, according to the Jingle SOCKS5 XEP
(<a href="https://xmpp.org/extensions/xep-0260.html#fallback">XEP-0260#Fallback</a>),
excluding acks and simplified (dropping a lot of elements that need to be
present):</p>
<pre tabindex="0"><code>
1. <jingle action="session-initiate"> <transport xmlns="j-s5b" /> </jingle>
==>
2. <jingle action="session-accept"> <transport xmlns="j-s5b" /> </jingle>
<==
3. <jingle action="transport-info"> <transport xmlns="j-s5b"> <candidate-error /> </transport> </jingle>
<=>
4. <jingle action="transport-replace"> <transport xmlns="j-ibb" /> </jingle>
==>
5. <jingle action="transport-accept"> <transport xmlns="j-ibb" /> </jingle>
<==
6. <open xmlns="ibb" />
==>
</code></pre><p>First, the normal Jingle session initiation happens, the client offering a file
sends a <code>session-initiate</code> including SOCKS5 proxy information and waits. Then,
when the receiving user accepts the file, or if the receiving client
automatically accepts the file based on some conditions, it sends a
<code>session-accept</code> including its SOCKS5 proxy information.</p>
<p>In point 3, we start to deviate from the normal “happy path”; in order to test
the fallback, I made Dino send no local candidates and skipped checking all of
the remote candidates, leading to both clients sending a <code>transport-info</code> with
a <code>candidate-error</code>, meaning that none of the candidates offered by the peer
work.</p>
<p>Now (4), according to the XEP, the <em>initiator</em> (left side) should send a
<code>transport-replace</code> to change the transport method to in-band bytestreams.</p>
<p>In 5, the responder accepts this change.</p>
<p>After getting this response, the initiator is supposed to open the in-band
bytestream (<a href="https://xmpp.org/extensions/xep-0261.html#protocol-flow">XEP-0261#Protocol
flow</a>) to complete the
negotiation.</p>
<p>It took a few tries until I had Dino-Dino fallback working. The other clients
were also fun:</p>
<p><strong>Dino → Conversations</strong> The best case. Fails in step 2, but only because of
some minor problems, the block size negotiation doesn’t take into account what
Dino sent. Dino asks for a block size of 4096 bytes, Conversation is only
allowed to lower this value but sets the consensus to 8192 bytes. I ignored
this and the fact that Conversations did not send a <code>sid</code> and got a working
fallback.
<a href="https://github.com/siacs/Conversations/issues/3515">Conversations#3515</a>.</p>
<p><strong>Conversations → Dino</strong> <!-- raw HTML omitted -->Fails in step 4, for some reason Conversations
doesn’t send a <code>transport-replace</code> after the SOCKS5 transport failed.
<a href="https://github.com/siacs/Conversations/issues/3514">Conversations#3514</a>. <!-- raw HTML omitted -->
<strong>EDIT</strong> Seems to be my mistake, couldn’t reproduce it when trying to test it
with the Conversations developer.</p>
<p><strong>Dino → Gajim</strong> Fails in a funny way, in step 5. Gajim responds to
<code>transport-replace</code> with a <code>session-accept</code>. <code>session-accept</code> is only valid in
response to <code>session-initiate</code>, so I don’t know how that happens. Some
Conversations user already reported that issue.
<a href="https://dev.gajim.org/gajim/gajim/issues/9692">Gajim#9692</a>.</p>
<p><strong>Gajim → Dino</strong> Gets stuck in step 6, Gajim doesn’t open the in-band
bytestream even though it is the initiator.
<a href="https://dev.gajim.org/gajim/gajim/issues/9784">Gajim#9784</a>.</p>
<p>Of course I’m not sure that I diagnosed all of these issues correctly, these
might be mistakes on my part and in my code, too. Let’s see how these issue
threads develop.</p>
<p><strong>EDIT</strong> And of course there was at least one mistake by me, Conversations →
Dino seems to work.</p>
-
Eighth week: Standards
https://dino.im/blog/2019/07/eighth-week-standards/
Thu, 25 Jul 2019 00:00:00 +0000
https://dino.im/blog/2019/07/eighth-week-standards/
<p>Sometimes, XEPs are really imprecise or even lack information about some
interactions. Most of the time, it’s about error handling where it’s not really
specified what to do in error cases, as the XEP mostly deals with the “happy
path” when everything is working.</p>
<p>This week, I tried to get SOCKS5 bytestreams (S5B,
<a href="https://xmpp.org/extensions/xep-0065.html">XEP-0065</a>,
<a href="https://xmpp.org/extensions/xep-0260.html">XEP-0260</a>) working for file
transfers. Most of the stuff simply worked after implementing the S5B
transport, since the Jingle module was offering a transport-agnostic bytestream
to the outside world, or in this case Jingle file transfers
<a href="https://xmpp.org/extensions/xep-0234.html">XEP-0234</a>. However, file transfers
with Conversations got stuck at 100%. After some debugging, I found out that
Conversations doesn’t close the SOCKS5 connection after sending the file. Since
I relied on the the peer closing the connection after sending the complete
file, this led to Conversations waiting for me to acknowledge the file transfer
and me waiting for Conversations to close the connection. I opened
<a href="https://github.com/siacs/Conversations/issues/3500">Conversations#3500</a> about
this inconsistency.</p>
<p>Reading into <a href="https://xmpp.org/extensions/xep-0234.html">XEP-0234</a>, I tried to
find out how to detect the end of the file transfer. The two relevant sections
I found were</p>
<blockquote>
<p>Once a file has been successfully received, the recipient MAY send a Jingle
session-info message indicating receipt of the complete file, which consists
of a <code><received/></code> element qualified by the
<code>'urn:xmpp:jingle:apps:file-transfer:5'</code> namespace. The <code><received/></code> element
SHOULD contain <code>'creator'</code> and <code>'name'</code> attributes sufficient to identify the
content that was received.</p>
</blockquote>
<p><a href="https://xmpp.org/extensions/xep-0234.html#received">(8.1 Received)</a></p>
<p>and</p>
<blockquote>
<p>Once all file content in the session has been transfered, either party MAY
acknowledge receipt of the received files (see Received) or, if there are no
other active file transfers, terminate the Jingle session with a Jingle
session of <code><success/></code>. Preferably, sending the <code>session-terminate</code> is done
by the last entity to finish receiving a file to ensure that all offered or
requested files by either party have been completely received (up to the
advertised sizes).</p>
</blockquote>
<p><a href="https://xmpp.org/extensions/xep-0234.html#sect-idm46562772093488">(6.2 Ending the Session)</a>
(link might die in the future, has a weird anchor).</p>
<p>I wasn’t able to find the relevant information, so I looked at Conversation’s
source code to find out how it determines when the file transfer is complete.
Turns out it’s simply checking whether it has already read as many bytes as the
integer in the <code><size></code> field in the initial file offer. Adding that as a
“filetransfer complete” condition, I can now receive files from Conversations.
This however, is not a general solution, as the <code><size></code> field only SHOULD be
present when offering a file, so we can’t rely on it being available when
receiving files over Jingle.</p>
<p>If anyone knows what the correct way to detect a completed file transfer is,
please tell me.</p>
-
Seventh week: Socks 5 file transfer
https://dino.im/blog/2019/07/seventh-week-socks-5-file-transfer/
Mon, 22 Jul 2019 00:00:00 +0000
https://dino.im/blog/2019/07/seventh-week-socks-5-file-transfer/
<p>The blog posts have slipped somewhat, last blog post covering two weeks. Let’s
try to fix that.</p>
<p>The next step for file transfers was to implement more Jingle transport
methods. Currently, only <a href="https://dino.im/blog/2019/06/second-week-ibb-proof-of-concept/">in-band bytestreams are
implemented</a> as transport methods.
The inefficiencies have been discussed already, it mostly boils down to the
fact that in-band bytestreams exchange base64-encoded data over the XMPP
stream.</p>
<p>The next transport method to be implemented are
<a href="https://en.wikipedia.org/wiki/SOCKS">SOCKS5</a> bytestreams (S5B,
<a href="https://xmpp.org/extensions/xep-0065.html">XEP-0065</a>,
<a href="https://xmpp.org/extensions/xep-0260.html">XEP-0260</a>). They can work in direct
(peer-to-peer) or mediated (via a proxy server) mode, depending on whether the
clients are visible to each other or whether they want to share their IP
address.</p>
<p><a href="https://en.wikipedia.org/wiki/SOCKS">SOCKS5</a> is a relatively simple protocol,
it can basically be implemented after reading its <a href="https://en.wikipedia.org/wiki/SOCKS">Wikipedia
page</a>: After establishing a
<a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a> connection
to the proxy server, the client sends its available authentication methods, the
server chooses one, the authentication happens. After successful
authentication, the client specifies where it wants to connect to and the
server acks that. Thereafter, one can use the TCP connection as if it was
connected to the previously specified IP address, sending and receiving data as
if one were connected directly.</p>
<p>SOCKS5 bytestreams use this protocol in a somewhat peculiar way. Instead of
specifying IP addresses to connect to, the SOCKS5 proxy more or less acts like
a rendez-vous point. Both sides that want to use the proxy as mediator connect
to it, and specify a common but somewhat random fictional domain name to
connect to. After one of the clients “activates” the connection via XMPP, data
can flow between these clients.</p>
<p>In theory, this is just another Jingle transport method, so one wouldn’t have
to modify the Jingle code to add it. However, since we only have one transport
method yet, the abstractions are probably not quite right yet: For example, S5B
needs support for <code><jingle action="transport-info"></code>, which IBB didn’t.</p>
<p>Let’s see how this works out.</p>
-
Fifth and sixth week: File receiving
https://dino.im/blog/2019/07/fifth-and-sixth-week-file-receiving/
Tue, 09 Jul 2019 00:00:00 +0000
https://dino.im/blog/2019/07/fifth-and-sixth-week-file-receiving/
<p>In the last two weeks, file receiving over Jingle has been implemented. This
means that basic Jingle file transfers are available in
<a href="https://dino.im/">Dino</a> now (at least once the pull request
<a href="https://github.com/dino/dino/pull/577">#577</a> has been merged).</p>
<p>As predicted by the <a href="https://gist.github.com/legastero/fa80e2366c448fd6e141">Jingle implementation
gist</a>, this was
actually a bit more than I would have guessed – you basically have to
implement the Jingle and file transfer protocol again, but this time from the
other side. Doing so involved some refactoring of the original code in order to
fit better with Dino’s internals. I moved the code from <a href="https://wiki.gnome.org/Projects/Vala/SignalsAndCallbacks">signal-style
callbacks</a> to
<a href="https://wiki.gnome.org/Projects/Vala/AsyncSamples">async</a>
<a href="https://valadoc.org/gio-2.0/GLib.IOStream.html"><code>IOStream</code>s</a>.</p>
-
Fourth week: Some UI integration
https://dino.im/blog/2019/06/fourth-week-some-ui-integration/
Thu, 27 Jun 2019 00:00:00 +0000
https://dino.im/blog/2019/06/fourth-week-some-ui-integration/
<p>File sending over Jingle (with in-band-bytestream transport) has now been
integrated into the UI. This has fortunately been quite easy as
<a href="https://dino.im/">Dino</a> already had support for file sending, via HTTP
uploads. Thus I only needed to hook into the existing UI to also offer Jingle
file transfers. This means that now you can click on the “attach” paper clip to
send a file. Since prioritization of different transport methods and file
receiving haven’t been implemented so far, these changes aren’t in the master
branch yet.</p>
<p>Prioritization is important so that HTTP file uploads are preferred where
possible (file small enough, server supports it): Jingle file transfers only
work to a single target and only when it is online at the same time as the
sender.</p>
<p>Since the ability to receive files via Jingle can also be reasonably expected
if the client supports sending them, we basically have two blockers for
merging.</p>
<div class="blog-figure">
<figure>
<img src="https://dino.im/blog/2019/06/fourth-week-some-ui-integration/screenshot.png"
alt="Screenshot of Dino showing the paper clip button and a lot of file transfers"/> <figcaption>
<p>Screenshot of Dino showing the paper clip button and a lot of file transfers</p>
</figcaption></figure>
</div>
<p>Above you can see the chat window after some testing. ;)</p>
-
Third week: Interoperability testing
https://dino.im/blog/2019/06/third-week-interoperability-testing/
Tue, 18 Jun 2019 00:00:00 +0000
https://dino.im/blog/2019/06/third-week-interoperability-testing/
<p>I managed to get the basic in-band bytestream file transfers working. It still
doesn’t have any user interface, that’s depending on a project by my mentor.
For now, it’s simply triggered by a hardcoded target JID that gets a file
transfer when it sends a presence.</p>
<p>After finishing the proof of concept, I added some error handling and did some
code cleanup. With that done, I did some interoperability testing. With
<a href="https://gajim.org">Gajim</a>, the file transfers now worked well, so I moved on
to test with <a href="https://conversations.im/">Conversations</a>. Here, something funny
happened, my Dino code sent (abbreviated for brevity):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt"><iq</span> <span class="na">type=</span><span class="s">'set'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><jingle</span> <span class="na">action=</span><span class="s">'session-initiate'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><content></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><description</span> <span class="na">xmlns=</span><span class="s">'urn:xmpp:jingle:apps:file-transfer:5'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> …
</span></span><span class="line"><span class="cl"> <span class="nt"></description></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><transport</span> <span class="na">xmlns=</span><span class="s">'urn:xmpp:jingle:transports:ibb:1'</span> <span class="na">block-size=</span><span class="s">'4096'</span> <span class="nt">/></span>
</span></span><span class="line"><span class="cl"> <span class="nt"></content></span>
</span></span><span class="line"><span class="cl"> <span class="nt"></jingle></span>
</span></span><span class="line"><span class="cl"><span class="nt"></iq></span>
</span></span></code></pre></div><p>And Conversations responded:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt"><iq</span> <span class="na">type=</span><span class="s">'set'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><jingle</span> <span class="na">action=</span><span class="s">'session-accept'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><content></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><description</span> <span class="na">xmlns=</span><span class="s">'urn:xmpp:jingle:apps:file-transfer:5'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> …
</span></span><span class="line"><span class="cl"> <span class="nt"></description></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><transport</span> <span class="na">xmlns=</span><span class="s">'urn:xmpp:jingle:transports:s5b:1'</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><candidate</span> <span class="na">host=</span><span class="s">'146.255.57.229'</span> <span class="na">type=</span><span class="s">'proxy'</span> <span class="na">jid=</span><span class="s">'proxy.jabber.ccc.de'</span> <span class="na">port=</span><span class="s">'5224'</span> <span class="nt">/></span>
</span></span><span class="line"><span class="cl"> <span class="nt"></transport></span>
</span></span><span class="line"><span class="cl"> <span class="nt"></content></span>
</span></span><span class="line"><span class="cl"> <span class="nt"></jingle></span>
</span></span><span class="line"><span class="cl"><span class="nt"></iq></span>
</span></span></code></pre></div><p>In essence, my Dino code asked to open a Jingle session for a file transfer,
using in-band-bytestreams as the transport. Then, Conversations responded that
it accepts my offer of Socks 5-based Jingle transport for the file transfer,
accepting an offer I didn’t make. I <em>think</em> this is a violation of the Jingle
XEP (<a href="https://xmpp.org/extensions/xep-0166.html">XEP-0166</a>): If the other party
wants to negotiate a different transport, it should probably use the
<code>transport-replace</code> Jingle action. I created an issue
(<a href="https://github.com/siacs/Conversations/issues/3478">Conversations#3478</a>)
which was quickly resolved. I have yet to test the fix, I don’t have a
development setup for Conversations yet.</p>
<p>The in-band bytestream file transfers I tested were quite slow (<2KB/s),
probably some rate-limiting of the servers, I didn’t investigate furtherly.</p>
-
Second week: IBB Proof of Concept
https://dino.im/blog/2019/06/second-week-ibb-proof-of-concept/
Mon, 10 Jun 2019 00:00:00 +0000
https://dino.im/blog/2019/06/second-week-ibb-proof-of-concept/
<p>As the first task, we planned to get a working, proof-of-concept Jingle file
transfer over an “in-band bytestream”
(IBB, <a href="https://xmpp.org/extensions/xep-0047.html">XEP-0047</a>,
<a href="https://xmpp.org/extensions/xep-0261.html">XEP-0261</a>). To get to this point, I
planned to write a module for basic Jingle interactions, supporting the
necessities for file transfers, and a non-final API for transport methods on
the other side.</p>
<p>What do in-band bytestreams look like? “In-band” means that the file data will
go through the same connection as the rest of the XMPP stream that also
contains your chat messages and metadata like read receipts, etc. It has to fit
into the XML stream, an example with an 28-byte file below:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt"><iq</span> <span class="na">xmlns=</span><span class="s">"jabber:client"</span> <span class="na">to=</span><span class="s">"tish@example.com/gajim"</span> <span class="na">from=</span><span class="s">"blagovest@example.com/dino"</span> <span class="na">type=</span><span class="s">"set"</span> <span class="na">id=</span><span class="s">"e8656828-2da8-48a5-828d-804542945851"</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> <span class="nt"><data</span> <span class="na">xmlns=</span><span class="s">"https://jabber.org/protocol/ibb"</span> <span class="na">seq=</span><span class="s">"0"</span> <span class="na">sid=</span><span class="s">"514ef10b-22e7-4e58-bf46-cca01629e826"</span><span class="nt">></span>
</span></span><span class="line"><span class="cl"> SGVsbG8sIGluLWJhbmQgYnl0ZXN0cmVhbXMhCg==
</span></span><span class="line"><span class="cl"> <span class="nt"></data></span>
</span></span><span class="line"><span class="cl"><span class="nt"></iq></span>
</span></span></code></pre></div><p>As you can see, this is quite inefficient. The <code><iq></code>/<code><data></code> tags amount to
roughly 256 bytes. The actual data has to be
<a href="https://en.wikipedia.org/wiki/Base64">base64</a>-encoded because XML cannot
contain arbitrary binary data, leading to an extra 33% overhead. With the
default blocksize of 4096 bytes as specified in the IBB XEP, we get a total
overhead of 40%. Nevertheless, this transport is simple to implement as it does
not need additional network connections beyond the already existing.</p>
<hr>
<p>While trying different approaches for the Jingle transport API,
<a href="https://github.com/fiaxh/">fiaxh</a> (my mentor) helped me decide: I’m now using
abstract classes for the different transports, and signals for the users of a
Single session, a pretty Vala-esque approach. After this planning, I went ahead
and tried to realize this in actual code. This resulted in basic session
opening support (only initiating), support for in-band bytestreams and file
transfers.</p>
<p>What’s still missing for merging this? I was pretty happy that the code almost
worked after fixing syntax error and obvious oversights. It still has a pretty
serious bug: Currently, when testing the file transfer from Dino to Gajim,
Gajim drops the last chunk we send. Additionally, the code needs proper error
handling, currently it just writes a message to the standard error output.</p>
<hr>
<p>During the weekly organization chat, flow sent me an interesting
<a href="https://gist.github.com/legastero/fa80e2366c448fd6e141">document</a>
written by someone who implemented the Jingle protocol in multiple clients and
wrote about the “enlightenment” he achieved in doing so. Thanks for that, I’ll
check it out the next week.</p>