Google Summer of Code 2020 - Websocket support for Ignite Realtime’s Smack
- Student: Aditya Borikar
- Mentors: Florian Schmaus, Paul Schaub
- Umbrella-Organisation: XMPP Standards Foundation
- Sub-Organisation: Ignite Realtime
Welcome to my GSoC 2020 project page.
XMPP protocols are the base protocols for instant messaging and presence. It stands for eXtensible Messaging and Presence Protocol. Applications using XMPP make use of either of the three transports: TCP, Bidirectional-streams Over Synchronous HTTP (BOSH) and websocket transport. Ignite Realtime’s Smack already has support for TCP and BOSH based connections. And my job was to add websocket support to Smack.
XMPP on web through BOSH faces issues like long polling. The WebSocket protocol enables two-way communication between a client and a server, using TCP at the application layer. So in a way, the websocket transport uses the goodness of TCP and overcomes the issues which are seen in BOSH. However, the information shared between resources is still the same, the only difference will be in the underlying transport. Use of websockets support browser based clients.
XEP-0156: Discovering Alternative XMPP Connection Methods
The XEP mentions two lookup processes, out of which we use the HTTP Web-host Metadata lookup for fetching websocket endpoints. Conceptually, the host-meta lookup process used for the Websocket binding is analogous to the DNS SRV lookup process used for the TCP binding.
The process can be divided into two steps:
1) Send a request over secure HTTP to the path “/.well-known/host-meta” at an HTTP origin that matches the XMPP service domain (e.g., a URL of “https://im.example.org/.well-known/host-meta” if the XMPP service domain is “im.example.org”).
2) Retrieve a host-meta document specifying a link relation type of “urn:xmpp:alt-connections:websocket”, such as:
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'> <Link rel="urn:xmpp:alt-connections:websocket" href="wss://im.example.org:443/ws" /> </XRD>
To obtain a websocket endpoint we look for the hyperlink reference corresponding to the link relation “urn:xmpp:alt-connections:websocket”. The implementation for http lookup can be found here.
There is a significant difference in the stream opening and closing elements between TCP connections and websocket based connections.
A typical tcp stream open element is like,
<stream:stream email@example.com' to='im.example.com' version='1.0' xml:lang='en' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
whereas a websocket stream open element is,
<open xmlns="urn:ietf:params:xml:ns:xmpp-framing" to="example.com" version="1.0" />
This means that these stream elements are supposed to be transport specific and that Smack should take care of that. To solve this problem, Smack now uses StreamOpenAndCloseFactory. This change along with a few relevant changes can be found here, here and here!
Current Finite State Machine of Smack’s Modular Architecture
As it is apparent from the diagram above, we have successfully plugged in EstablishingWebsocketConnection phase inside Smack’s modular architecture. This implementation resides inside the smack-websocket module and the commit can be found here.
The use case for establishing a websocket connection can be found inside smack-repl.
To test Smack’s transport against modular architecture, there is now a very simple integration test in place which can be used to transfer a message stanza from user to another. The integration test can be found here.
Apart from these, I am especially happy about my first ever contribution to an XEP! Here, I improved the abstract of XEP-0156. Previously it suggested that the XEP defines only one format for use in discovering alternative methods to connect to an XMPP server although there clearly are two ways for the same. Now the abstract properly sums up the content of the XEP.
What more can be expected ahead
The websocket implementation is yet to be incorporated into Spark. This also means that Spark is unaware of Smack’s modular architecture. Since the modular architecture itself is quite new, while working on Spark we might discover cases which are yet to be considered. Along with that, smack-websocket is prone to improvements as and when realised.
Over the period of past three months, I was exposed to innumerable difficult situations like imperfect timing, choosing unpropitious approach, and various technical frameworks. I however enjoyed tackling these scenarios. I was encouraged by my mentors to consume more information and think in the right direction. I loved the dynamic of the Ignite Realtime community, the exacting and collective environment helped me function at my best.
Thanks to Florian Schmaus and Paul Schaub for pushing me forward when I got stuck and appreciating me when did things the right way. Special thanks to Guus der Kinderen for going out out his way to guide me while formulating my proposal and sticking with Paul and me during Ignite Realtime’s weekly meet to make me feel welcome.
subscribe via RSS