by Kegan Dougal | Mar 2, 2015 | Tech, Tutorials |
This post has now been edited into a guide – you can find the source in github, and the formatted guide on the matrix.org website!
Hi everyone. I’m Kegan, one of the core developers on Matrix. I’d like to explain a bit more about one of the upcoming features in Matrix: Application Services. This is an entirely new component in the Matrix architecture which gives great power (along with great responsibility!) to the wielder.
Application services are distinct modules which which sit alongside a home server providing arbitrary extensible functionality decoupled from the home server implementation. Just like the rest of Matrix, they communicate via HTTP using JSON. Application services function in a very similar way to traditional clients, but they are given much more power than a normal client. They can reserve entire namespaces of room aliases and user IDs for their own purposes. They can silently monitor events in rooms, or any events directed at any user ID. This power allows application services to have extremely useful abilities which overall enhance the end user experience.
One of the main use cases for application services is for protocol bridges. As you may know, we have an IRC bridge bot on matrix.org which resides as a user on #matrix, #matrix-dev, #openwebrtc and #vuc which bridges into freenode. There is nothing special about this bot; it is just treated as a client. However, this limits the things the bot can do. For example, the bot cannot reserve the virtual user IDs it creates, and cannot lazily bridge arbitrary IRC rooms on-the-fly. By using application services, the IRC bot can do both of these things. This would allow any Matrix user to join a room alias which doesn’t exist: say #irc.freenode.python:matrix.org, which would then tell the application service to create a new Matrix room, make the alias for it, join #python on freenode and bridge into it. Any IRC user on #python would then be provisioned as a virtual user e.g. @irc.freenode.alice:matrix.org. This also allows PMs to be sent directly to @irc.freenode.alice:matrix.org, no matter what channel Alice is on.
Application services have enormous potential for creating new and exciting ways to transform and enhance the core Matrix protocol. For example, you could aggregate information from multiple rooms into a summary room, or create throwaway virtual user accounts to proxy messages for a fixed user ID on-the-fly. As you may expect, all of this power assumes a high degree of trust between application services and home servers. Only home server admins can allow an application service to link up with their home server, and the application service is in no way federated to other home servers. You can think of application services as additional logic on the home server itself, without messing around with the book-keeping that home servers have to do. This makes adding useful functionality very easy.
Example
The application service (AS) API itself uses webhooks to communicate from the home server to the AS:
– Room Alias Query API : The home server hits a URL on your application server to see if a room alias exists.
– User Query API : The home server hits a URL on your application server to see if a user ID exists.
– Push API : The home server hits a URL on your application server to notify you of new events for your users and rooms.
A very basic application service may want to log all messages in rooms which have an alias starting with “#logged_” (side note: logging won’t work if these rooms are using end-to-end encryption).
Here’s an example of a very basic application service using Python (with Flask and Requests) which logs room activity:
# app_service.py:
import json, requests # we will use this later
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route("/transactions/<transaction>", methods=["PUT"])
def on_receive_events(transaction):
events = request.get_json()["events"]
for event in events:
print "User: %s Room: %s" % (event["user_id"], event["room_id"])
print "Event Type: %s" % event["type"]
print "Content: %s" % event["content"]
return jsonify({})
if __name__ == "__main__":
app.run()
Set your new application service running on port 5000 with:
python app_service.py
The home server needs to know that the application service exists before it will send requests to it. This is done via a registration YAML file which is specified in Synapse’s main config file e.g. homeserver.yaml. The server admin needs to add the application service registration configuration file as an entry to this file.
# homeserver.yaml
app_service_config_files:
- "/path/to/appservice/registration.yaml"
NB: Note the “-” at the start; this indicates a list element. The registration file registration.yaml should look like:
# registration.yaml
# this is the base URL of the application service
url: "http://localhost:5000"
# This is the token that the AS should use as its access_token when using the Client-Server API
# This can be anything you want.
as_token: wfghWEGh3wgWHEf3478sHFWE
# This is the token that the HS will use when sending requests to the AS.
# This can be anything you want.
hs_token: ugw8243igya57aaABGFfgeyu
# this is the local part of the desired user ID for this AS (in this case @logging:localhost)
sender_localpart: logging
namespaces:
users: []
rooms: []
aliases:
- exclusive: false
regex: "#logged_.*"
You will need to restart the home server after editing the config file before it will take effect.
To test everything is working correctly, go ahead and explicitly create a room with the alias “#logged_test:localhost” and send a message into the room: the HS will relay the message to the AS by PUTing to /transactions/<tid> and you should see your AS print the event on the terminal. This will monitor any room which has an alias prefix of “#logged_”, but it won’t lazily create room aliases if they don’t already exist. This means it will only log messages in the room you created before: #logged_test:localhost. Try joining the room “#logged_test2:localhost” without creating it, and it will fail. Let’s fix that and add in lazy room creation:
@app.route("/rooms/<alias>")
def query_alias(alias):
alias_localpart = alias.split(":")[0][1:]
requests.post(
# NB: "TOKEN" is the as_token referred to in registration.yaml
"http://localhost:8008/_matrix/client/api/v1/createRoom?access_token=TOKEN",
json.dumps({
"room_alias_name": alias_localpart
}),
headers={"Content-Type":"application/json"}
)
return jsonify({})
This makes the application service lazily create a room with the requested alias whenever the HS queries the AS for the existence of that alias (when users try to join that room), allowing any room with the alias prefix #logged_ to be sent to the AS. Now try joining the room “#logged_test2:localhost” and it will work as you’d expect. You can see that if this were a real bridge, the AS would have checked for the existence of #logged_test2 in the remote network, and then lazily-created it in Matrix as required.
Application services are powerful components which extend the functionality of home servers, but they are limited. They can only ever function in a “passive” way. For example, you cannot implement an application service which censors swear words in rooms, because there is no way to prevent the event from being sent. Aside from the fact that censoring will not work when using end-to-end encryption, all federated home servers would also need to reject the event in order to stop developing an inconsistent event graph. To “actively” monitor events, another component called a “Policy Server” is required, which is beyond the scope of this post. Also, Application Services can result in a performance bottleneck, as all events on the homeserver must be ordered and sent to the registered application services. If you are bridging huge amounts of traffic, you may be better off having your bridge directly talk the Server-Server federation API rather than the simpler Application Service API.
I hope this post demonstrates how easy it is to create an application service, along with a few ideas of the kinds of things you can do with them. Obvious uses include build protocol bridges, search engines, invisible bots, etc. For more information on the AS HTTP API, check out the new Application Service API section in the spec, or the raw drafts and spec in https://github.com/matrix-org/matrix-doc/. The AS API is not yet frozen, so feedback is very welcome!
by Matthew Hodgson | Feb 12, 2015 | General, Tech |
We just pushed out a major new release of Synapse 0.7.0, the python reference server for Matrix, and a minor maintenance update for matrix-angular-sdk 0.6.2, the reference web client implementation.
The emphasis here has been on federation performance and stability – with all the recent interest from FOSDEM and LWN and HackerNews we’ve been getting a lot of traffic on matrix.org and new servers federating up, so we’ve been busy profiling and fixing performance on some of the hot paths by adding in-memory caches and similar.
This release is *highly* recommended if you are running a federated server, as it fixes many denial-of-service failure modes in the federation implementation, as well as many performance improvements
Behind the scenes, there’s also lots of work going on for v2 of the Client-Server API (which lets you filter the events your client subscribes to in a room, and combines the ‘initial sync’ and ‘eventstream’ APIs into a single simplified ‘/sync’ API) – the alpha of this has landed in 0.7.0, but we don’t recommend trying to use it yet. Meanwhile the Application Service API is effectively finished, but hasn’t landed on the master branch yet. Synapse also finally has initial support for push notifications for the iOS client now via the sygnal APNS gateway, although we need to actually document how to set this up to be usable in general.
Finally, we have switched to recommending that synapse is installed in a virtualenv rather than into ~/.local, due to various problems with how setup.py’s dependency management works. Instructions on setting up a virtualenv can be found in the README.
On the clientside: we’ve improved performance, enabled identicons for unknown users, and now fully support OpenWebRTC for VoIP calling from Safari, Bowser, and other OpenWebRTC-capable browsers!
Thanks to everyone running servers – please upgrade, tell your friends, and help us grow Matrix!
Changes in synapse v0.7.0 (2015-02-12)
======================================
* Add initial implementation of the query auth federation API, allowing
servers to agree on whether an event should be allowed or rejected.
* Persist events we have rejected from federation, fixing the bug where
servers would keep requesting the same events.
* Various federation performance improvements, including:
- Add in memory caches on queries such as:
* Computing the state of a room at a point in time, used for
authorization on federation requests.
* Fetching events from the database.
* User's room membership, used for authorizing presence updates.
- Upgraded JSON library to improve parsing and serialisation speeds.
* Add default avatars to new user accounts using pydenticon library.
* Correctly time out federation requests.
* Retry federation requests against different servers.
* Add support for push notifications and push rules.
* Add alpha versions of proposed new CSv2 APIs, including ``/sync`` API.
Changes in Matrix Angular SDK 0.6.2 (2015-02-12)
================================================
Bug fixes:
- Fixed a bug which caused OpenWebRTC to occasionally fail.
- Fixed a bug which caused multiple room initial syncs to occur in rapid
succession.
Features:
- Display a "Joining Room" dialog when joining rooms.
- Display identicons for users with no avatar.
- Display m.notice events with full formatting.
- Add push notification rules to settings.
Improvements:
- Modified the red/blue notification colours to be more noticeable on a wider
range of displays.
- Highlight room invitations in blue.
- Calculate room names for rooms of 3+ members.
- Improved page load performance.
by Emmanuel Rohee | Feb 5, 2015 | General, Tech |
A new release of the iOS SDK and the iOS Matrix Console app is available on GitHub: https://github.com/matrix-org/matrix-ios-sdk.
If you use CocoaPods to manage your application dependencies, note that the Matrix SDK pod has been updated too.
The changes since the last release are:
SDK
- Improvements:
-
- MXFileStore stores data on a separated thread to avoid blocking the UI thread.
- MXRestClient: Callback blocks in all MXRestClient methods are now optional.
- MXEvent: Cleaned up exposed properties and added a description for each of them.
- Features:
-
- Added API for registering for push notifications.
- Added generic API methods to make any kind of registration or login flow.
- Added Identity server API: lookup3pid, requestEmailValidation, validateEmail and bind3PID.
- Management of event redaction: there is a new method in the SDK to redact an event and the SDK updates its data on redaction event.
- Bug fixes:
-
- SYIOS-5 – Expose registration API
- SYIOS-44 – Credentials persist across logout
- SYIOS-54 – Matrix Console app slightly freezes when receiving a message
- SYIOS-59 – Infinite loop in case of back pagination on new created room
- MXRoom: Fixed [MXRoom sendTextMessage]
Matrix Console
- Improvements:
-
- When long pressing on a message, the app shows the JSON string of the Matrix event.
- On this screen, the user can redact the event – if he has enough power level.
- Use home server media repository facilities to use lower image size for thumbnails and avatars
- Settings screen: show build version with the app version.
- Settings screen: added an option to hide information related to redacted event.
- Settings screen: added an option to enable reading of local phonebook. The country is required to internationalise phone numbers.
- Features:
-
- Push notifications.
- Added a contacts screen that displays Matrix users the user had interactions with and contacts from the device phonebook.
- Contacts from the device phonebook who have an email linked to a Matrix user id are automatically recognised.
- Bug fixes:
-
- SYIOS-53 – multilines text input that expands as you type mutiplines would be nice
- SYIOS-45 – Need to check the thumbnail params requested by iOS
- SYIOS-55 – High resolution avatars create memory pressure
- SYIOS-57 – Back pagination does not work well for self chat
- SYIOS-56 – add cache size handling in settings
- SYIOS-60 – In a self chat, Console takes ages to paginate back even if messages are in cache
- SYIOS-61 – Chat room : cannot scroll to bottom when keyboard is opened whereas the growing textview contains multi-lines text.
- SYIOS-63 – calculate room names for 3+ memebers if no room name/alias
- SYIOS-44 – Credentials persist across logout
- SYIOS-64 – Chat room : unexpected blank lines are added into history when user types in growing textview
- SYIOS-65 – IOS8 : in case of search in recents, keyboard is not dismisssed when user selects a room.
- SYIOS-16 Add option in Console to join room thanks to its alias
by Matthew Hodgson | Jan 7, 2015 | General, Tech |
Happy 2015 from everyone at Matrix.org!
We’re excited to kick off the new year with a major performance upgrade for Synapse: having had a chance to do some profiling over the Christmas break, Synapse 0.6.1 improves performance by up to an order of magnitude thanks to optimising the way events are constructed and manipulated, DB optimisations, etc. Suddenly things are feeling *much* more snappy and less of a PoC and more of a real system, which hopefully bodes well for 2015! Please upgrade if you’re running a homeserver, or install one if you’re not – grab the code from http://github.com/matrix-org/synapse.
The iOS SDK and demo app has also been improving lots in the last few weeks – grab the latest code from http://github.com/matrix-org/matrix-ios-sdk. We have zoomable image support; full support for the new media repository in Synapse 0.6.0; file transfer status UI; offline support; snappy message synchronisation and more…
We also released a new simple Python SDK client library for Python called matrix-client, which is now being used by NEB (our general-purpose Matrix helper bot).
Meanwhile, our (constantly evolving) plan for the beginning of 2015 is:
- Finish v2 of the client-server API based on all the lessons learnt since launch: draft in progress here
- Finish the Application Services API to allow proper gateways and services in and out of Matrix at last:draft in progress here
- Re-release the spec based on the above
- Build robust gateways (IRC, XMPP, SIP and more) on top of the AS API
- Polish and release the iOS, Android demo clients – including push notification and VoIP support!
- Overhaul the identity server architecture and add end-to-end crypto
Given the rate at which Matrix is maturing, the next few months should be really exciting – please come join us on #matrix:matrix.org and get involved!
Changes in synapse 0.6.1 (2015-01-07)
=====================================
* Major optimizations to improve performance of initial sync and event sending
in large rooms (by up to 10x)
* Media repository now includes a Content-Length header on media downloads.
* Improve quality of thumbnails by changing resizing algorithm.
by Matthew Hodgson | Dec 24, 2014 | Events, General, Tech |
Last week we had a great time attending WebRTC Conference Expo Paris 2014 – chatting to lots of new folks about Matrix; speaking in the “To Build or Not To Build” panel discussion; giving a general presentation on Matrix, and participating in the Demo shoot-out.
And we’re very proud to say that we won the Best Innovation Award for a slightly frantic demo, showing an iPad mounted on our pet Trossen Robotics PhantomX Hexapod being used for robot telepresence by streaming video and audio to an Oculus Rift VR headset. This was using our proprietary in-house WebRTC stack, but once Matrix has fully taken off we hope to share our WebRTC stack with the world too :) This was a very last minute demo – we wanted to show something different to normal browser-to-browser IM/Video calling via Matrix and had the idea to use the Rift at the last minute – and in fact it still wasn’t working when we went on stage (turns out that iOS 8.1 introduces some quirks in the video capture API which were producing corrupt video). By switching from an iPhone 5S running iOS 8.1 to an iPad running iOS 6 we were able to turn the demo around in the nick of time and get it working live on stage (modulo a RGB<->BGR colourspace bug) just in time to win the award. Huge thanks to the jury for voting for us against the odds :D For those interested in displaying raw video straight onto the Oculus Rift (without using any head-mounted tracking), there’s an OpenGL code snippet up at https://gist.github.com/ara4n/875b5e8b66be3617efb7.

(Image credit to Victor Pascual Avila at Quobis)
Also, huge congratulations to Vladimir Beloborodov who won the Best Data Channel Award for hacking his Romotive telepresence robot to rendezvous via Matrix with his iPad, stream video via Google’s WebRTC stack and control the robot’s motion via the WebRTC Data Channel:

We’re really excited to see other folks’ Matrix projects out there winning prizes!
by Matthew Hodgson | Dec 19, 2014 | General, Tech |
We’re proud to announce the new 0.6.0 major release of Synapse: the Python reference implementation of Matrix – as well as 0.6.0 of the AngularJS example Matrix client, as a special early Christmas present from the Matrix team :)
The main priority here has been hunting down stability bugs whilst also adding in a few more features. The most exciting new feature is the new Media/Content API: this allows every homeserver to replicate, cache and thumbnail any files associated with Matrix rooms, rather than relying on retrieving them from the origin homeserver as was previously the case. This is really cool, as it effectively makes Matrix a distributed content distribution network and gives the same replication semantics to file attachments as to the rest of JSON in rooms.
We’ve also landed a major new branch which changes the way events are represented internally in order to make them immutable, and fixes a whole range of minor stability issues. In other news, performance issues are still a work in progress…
To get involved, head over to https://github.com/matrix-org/synapse and install and upgrade today!
Changes in synapse 0.6.0 (2014-12-19)
=====================================
* Add new API for media upload and download that supports thumbnailing.
* Replicate media uploads over multiple homeservers so media is always served
to clients from their local homeserver. This obsoletes the
--content-addr parameter and confusion over accessing content directly
from remote homeservers.
* Implement exponential backoff when retrying federation requests when
sending to remote homeservers which are offline.
* Implement typing notifications.
* Fix bugs where we sent events with invalid signatures due to bugs where
we incorrectly persisted events.
* Improve performance of database queries involving retrieving events.
Changes in Matrix Angular SDK 0.6.0 (2014-12-19)
================================================
Breaking changes:
- Uploading files in the web client will now hit the new content repository URL
introduced in Synapse 0.6, and be incompatible with previous Matrix clients.
Bug fixes:
- Fixed a bug which caused the event stream to become wedged when the computer is asleep.
- Fixed a bug which caused the recents to update but not the message window.
Features:
- Typing notifications will now be sent.
- Typing notifications will now be displayed for other users.
- Use the new content repository introduced in Synapse 0.6 when uploading files.
Improvements:
- Display more error dialogs rather than silently failing.
- Display loading spinners on signup.
- Display feedback when joining a room.
- CTRL + clicking on a recents entry will now open that room in a new tab.
- Clicking on links in messages will now open them in a new tab.
- Provide a progress dialog when uploading files.
- Display a red bar when the event stream connection is lost for an extended period of time.
Recent Comments