The XMPP Component framework is coming on nicely. It can connect and send/receive messages:
Using C# again is a joy. I absolutely love the dynamic capabilities.
For example, in this factory method, Ping is dynamically added – it is not a property:
Which produces the following XML:
<iq id='e59823e0-96ad-4659-8802-ad9b00edb0f9' type='get' to='aquinas'> <ping xmlns='urn:xmpp:ping'/> </iq>
Eventually Ping will be its own subpacket, but for now this will suffice to keep the connection alive.
The RPC dispatch mechanism is working, here is a sample controller:
From within Pidgin’s XMPP Console, I can send a message to the component and get a response:
Thanks to the excellent reflection support in C# it is easy to infer argument types for a method before dispatching a request. But as a hint to the client, the return type is explicitly declared.
There is an optional attribute that allows the decoupling of the method name from the action name, and to override the inferred return type:
The request now uses action = “greet” and the response contains type = “greeting”:
It’s been a busy few weeks, 145 classes in 5 projects:
Pretty much all the architecture is in place, from dependency injection to XMPP composability and RPC dispatching. Lots more work to do to comply with XMPP standards.
The objective is to completely abstract all messaging from the application space, so the developer just needs to focus on implementing the various controllers, repositories, services, entities etc. for his own application. For example, the EchoController we saw earlier. Velocity is the sample project that uses the XMPP framework provided by the BeyondVelocity libraries.
Regarding dependency injection, it’s working fine. I like Java’s Spring Context, so I implemented a very lightweight version for this project. It’s possible to resolve a specific instance of a “bean” by asking for it by name, or naming an argument accordingly.
In this example, there’s nothing out of the ordinary:
But this works too, resolving separately named (and initialised) instances of a repository:
For RPC a custom extension is used:
That affords the flexibility to do your own thing, and if required to add standards support later.
Most of the complexity was in building the XMPP Parser which is a stack-based, re-settable streaming parser. It essentially functions as a state machine that processes data received from a socket and emits XMPP packets:
The basic building block is the BvElement which represents an XML element. From this class are inherited all the various XMPP packets. The goal was a compartmentalised framework for:
- Low Coupling
- High Cohesion
- Simple Evolution
This architecture allows the construction of the framework in a flexible way, end to end, with minimal functionality up and running quickly; and the simple evolution and refactoring of functionality via isolated composable units – plug and play if you will:
Umbrello is handy tool, but some things are a little difficult to show such as a Packet can contain zero or more other Packets, similarly with BvElements.
To help with performance I implemented a RingBuffer which avoids locking:
Having reached the milestone version 0.01 I can take the foot off the accelerator. It’s actually fully functional for my needs at the moment, but something I hope to evolve over time. When it reaches a bit more maturity I’ll push it to Github.
If I can find a client side Flutter library I’ll start using it immediately. Stone looks promising.
Why not gRPC? gRPC has many advantages, particularly in performance.
XMPP is fast enough in most cases – even for WhatsApp. There are many excellent XMPP servers available such as EJabberd and Openfire. Not only can these servers act as a gateway, provide security, and can be federated, they are simple to extend with components which can be easily scaled. XMPP is the universal messaging standard.
It’s been fun. I’m really enjoying coding in JetBrain’s Rider, using .NET 5 on KDE Neon.
Still hoping Xamarin officially comes to Linux 🙂