MatriX vNext developer tutorial

About

MatriX vNext

Our first XMPP library for .NEt/c# was released back in 2002 with .NET 1.0. Our XMPP libraries and the .NET technologies had many major evolutions over the years.

With the switch to .Net Core we also took the opportunity for a major rewrite and redesign of the codebases. The API for clients, servers and components is not backwards compatible, but all XMPP protocol classes remain the same. Updating existing code bases to MatriX vNext should be pretty straightforward.

Some highlights

  • new software design and more modern API
  • target .Net Core and netStandard
  • high performance sockets using Azure DotNetty
  • Completly Task based using the TAP pattern (async/await)
  • more Linq extensions
  • Rx (Reactive Extensions)
  • Open Source and available under a dual license (Open Source and commercial)

Install from NuGet

NuGet packages are available for all platforms we offer MatriX for. You can find all packages also here.

PM> Install-Package Matrix.vNext

This document

  • This document is a tutorial for XMPP development with MatriX vNext.
  • You should already be familiar with the XMPP basics before you start working with MatriX vNext and this document.
  • If you are not familiar with the XMPP basics then we suggest to read a book first

Logging

TODO

Client connection

Client connections are handled in the XmppClient class in MatriX.

XMPP is a domain based protocol like email. So never use IP adresses for your XMPP domain (server name). Or do you write emails to addresses like user@166.166.166.166?

Open

Connecting to a XMPP server is very simple. All you have to do is set the Username, Password and XMPP server. After that call the ConnectAsync method to establish the connection.

var xmppClient = new XmppClient()
{
    Username = "alex",
    Password = "secret",
    XmppDomain = "ag-software.net"    
};

await xmppClient.ConnectAsync();

SRV-Records

XMPP is using SRV records to find the hostname and port of the XMPP service automatically. SRV records are required by the XMPP RFCs for XMPP services. Usually you want to use the **SrvNameResolver** located in the **Matrix.vNext.Srv* NuGet package.

Install the NuGet package:

PM> Install-Package Matrix.vNext.Srv

Set the Hostname resolver in your code:

xmppClient.HostnameResolver = new SrvNameResolver();

If you don’t want to use SRV records you can specify the hostname and port manual and disable the SRV lookups. This is often necessary during development the develoment when you are not testing against live servers. You can specify the hostname and port of your server manual using the StaticNameResolver

xmppClient.HostnameResolver = new StaticNameResolver(IPAddress.Parse("192.168.1.1"), 5222);

Encryption

XMPP is using TLS to encrypt the XML stream. With the Tls property of the XMPP client you can control the encryption settings. By default its set to true and automatically enabled when supported by the target server.

When you open a new connection and Tls is true MatriX will automatically initialize TLS on this session and encrypt ithe socket stream using TLS when supported by the target server.

SSL/TLS Certificate

TLS is based on certificates. When the stream gets updated to TLS then the server presents a certificate to the client. The .NET Framework and MatriX automatically validates the certificate. When there are any validation errors MatriX will not proceed during TLS negotiation and terminate the stream.

However in some deployments, testing or staging environments you may have an “invalid”, self signed or untrusted TLS certificate and still want to secure the connection using TLS. In this case you can set a custom CertificateValidator handler and validate the TLS certifcate and tell MatriX whether you trust this certificate or not.

Here is an example where an AlwaysAcceptCertificateValidator get set to accept all certificates which is useful for development purposes.

xmppClient.CertificateValidator = new AlwaysAcceptCertificateValidator();

Roster

In XMPP the contact list aka buddy list™ is called roster. After your connection succeeded you can request the roster from the server with the following code:

var roster = await xmppClient.RequestRosterAsync();

Messaging

After successful login a message can be sent to any entity at any time. The follwing example sends a simple text message of type chat.

var msg = new Matrix.Xmpp.Client.Message
                {
                    Type = MessageType.chat,
                    To = "user1@server.com",
                    Body = "Hello World!"
                };
await xmppClient.SendAsync(msg);

Formatted messages

Formatted messages (rich text) in XMPP is using the XEP-0071 XHTML-IM extension.
When formatted messages get sent you should always also include a plain text version of the content for clients which don’t understand the XHTML-IM extension.

var msg = new Matrix.Xmpp.Client.Message
            {
                Type = MessageType.chat,
                To = "user1@server.com",
                Body = "Hello World formatted!",
                XHtml = new Matrix.Xmpp.XHtmlIM.Html
                {
                    Body = new Matrix.Xmpp.XHtmlIM.Body
                        {
                            InnerXHtml = "<p><i>Hello</i> <strong>World</strong> formatted!</p>"
                        }
                }
            };
await xmppClient.SendAsync(msg);

Chat states

XMPP supports chat state notifications of conversations partners. Those notifications are events like “the user starts typing”, or “the user closed this chat windows and is not partcipating any,ore at this conversation”. For chat state notificatons XEP-0085: Chat State Notifications gets used.

Here is an example how to send the “user is typing” notification.

var msg = new Matrix.Xmpp.Client.Message
            {
                Type = MessageType.chat,
                To = "user1@server.com/MatriX",
                Chatstate = Matrix.Xmpp.Chatstates.Chatstate.composing
            };	
await xmppClient.SendAsync(msg);

Offline messages

Offline messages are a core feature of XMPP. When a message gets sent to a user which is offline at the momen then the server must store it. As soon as the receipient comes online again the server delivers the stored offline messages for this user.

When a server stores a message offline then it adds a timestamp to the message. This timestamp in included when the offline message gets delivered.

In the following example we check if a message has a timestamp and store it in the ts variable.

if (e.Message.XDelay != null)
{
    // message has a timestamp
    var ts = e.Message.XDelay.Stamp;
}

Incoming messages

You can oberserve all incoming messages by subscribing to the XmppXElementStreamObserver instance.

xmppClient
    .XmppXElementStreamObserver
    .Where(el => el is Message)
    .Subscribe(el =>
    {
        Debug.WriteLine(el.ToString());
    });

Glossary

C2S

Client to server connection. XMPP client initiate C2S connections to a XMPP server.

Jid

The Jabber Identifier (Jid) is the address of an entity in the XMPP network. Here are some examples of Jids:

  • user@domain.com
  • user@domain.com/Phone
  • domain.com

The Jid consists of 3 parts

  • node
  • domain
  • resource
alice @ example.com / Home
node   domain   resource

Bare Jid

Jid without resource identifier, eg. user@domain.com.

Full Jid

Jid including the resource, eg. user@domain.com/Home.

Roster

The contact list (buddy list ™) is called roster in XMPP.

Presence

A stanza which contains the presence information (online/offline status) of a XMPP idendity. The XMPP server automatically distributes this information to all subscribed contacts.

Directed Presence

A directed presence is a presence which is sent manual from idendity to another idendity, and not automatically distributed by the server.  In MUC for example we need directed presence when we join or leave a room.

Priority

The priority is a number that specifies the priority level of the resource. The value must be an integer between -128 and +127. The priority is important when messages gets sent to a bare Jid. The highest priority will receive the message in this case. A resource with a negative priority will never receive messages sent to a bare Jid.

S2S

Server to server connection. XMPP server communicate to each other over S2S connections.

XEP

XEP stands for XMPP Extension Protocols. The XMPP core protocols were designed to be extenible. The XMPP Standards Foundation (XSF) maintains all the XMPP Extension Protocols.

XSF

XSF stands for XMPP Standards Foundation, the standards organization that defines the XEPs and promotes the XMPP protocol.