Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raucao/221e96d00ef3b704c847282fed0baf73 to your computer and use it in GitHub Desktop.
Save raucao/221e96d00ef3b704c847282fed0baf73 to your computer and use it in GitHub Desktop.

A/V calls in Conversations

Here are some short notes for server admins and developers of other XMPP clients.

Notes for server admins

Most calls will require server side assistence. Depending on the network it might be enough to have a STUN server for Conversations to learn your external IP and punch a hole in the NAT. On some, more restrictive, networks however this isn’t enough and Conversations will need a TURN server. TURN servers are used to proxy the entire (encrypted) traffic through the server. (In my initial testing this was often the case when mobile networks were involved.)

To ensure best possible user experience in all situations server admins should set up both.

Conversations will use XEP-0215: External Service Discovery to learn about server-provided STUN/TURN servers, and, in case of TURN, also get short term, temporary credentials to access the TURN server.

Instructions for ejabberd

Ejabberd 20.04 has support for XEP-0215 and has also a STUN and TURN server build in. Take a look a the new sample config (Particularly the module: ejabberd_stun section in the listen section and mod_stun_disco.)

Instructions for Prosody

A combination of running coturn and mod_turncredentials should get you going. Wiktor-k has written some instructions and provided some config files.

UDP vs TCP vs TLS

STUN and TURN can operate over three different protocols. UDP, TCP and TCP/TLS. The latter is indicated by the stuns and turns URI scheme. Using TLS does not increase security as calls are always end-to-end encrypted with DTLS-SRTP. On the down side using TCP or TLS instead of UDP might negatively impact latency and performance. The only benefit of using TURN over TLS on port 443 is that you have a higher chance of passing through restrictive firewalls. However this should only be a fallback and not the default connection mechanism.

As a general recommendation we advise you to announce the following services over XEP-0215:

  • STUN over UDP
  • TURN over UDP
  • TURNS over TLS on port 443 (requires extra IP on the server)

Ideally those three variants should exist both on IPv4 and IPv6 for a total of 6 variants.

Testing

The compliance tester will check if that discovery mechanism is working; however that doesn’t necessarily mean that TURN and STUN themselves are setup correctly. To test this you should get two Android phones and put them into different networks; connect one of them to your computer via USB and use adb logcat. Here are the lines two look out for:

Firstly if you grep for ICE with adb -d logcat -v time -s conversations | grep ICE you should see log entries like this:

04-18 12:57:59.373 D/conversations(13867): alice@example.com: discovered ICE Server: [stun:89.238.78.51:443?transport=udp] [:] [TLS_CERT_POLICY_SECURE] [] [null] [null]
04-18 12:57:59.373 D/conversations(13867): alice@example.com:: discovered ICE Server: [turn:89.238.78.51:443?transport=udp] [1587211080:a781616cb9061724:F17BHTfLXyxzOyWSEutjpmzlCrs=] [TLS_CERT_POLICY_SECURE] [] [null] [null]
04-18 12:57:59.374 D/conversations(13867): alice@example.com:: discovered ICE Server: [stun:89.238.78.51:443?transport=tcp] [:] [TLS_CERT_POLICY_SECURE] [] [null] [null]
04-18 12:57:59.374 D/conversations(13867): alice@example.com:: discovered ICE Server: [turn:89.238.78.51:443?transport=tcp] [1587211080:a781616cb9061724:F17BHTfLXyxzOyWSEutjpmzlCrs=] [TLS_CERT_POLICY_SECURE] [] [null] [null]

This means Conversations has been able to discover the servers (you should see at least one line with stun and one line with turn.

Secondly when the call connects and you grep for candidate with adb -d logcat -v time -s conversations | grep candidate you should see lines like this:

04-18 12:57:59.584 D/conversations(13867): received candidate: audio:0:candidate:2431496480 1 udp 41754623 89.238.78.51 63631 typ relay raddr 94.134.91.66 rport 22965 generation 0 ufrag JRB3::UNKNOWN
04-18 12:57:59.592 D/conversations(13867): received candidate: audio:0:candidate:3731770832 1 udp 24977151 89.238.78.51 61571 typ relay raddr 94.134.91.66 rport 22966 generation 0 ufrag JRB3::UNKNOWN
04-18 12:57:59.592 D/conversations(13867): sending candidate: audio:0:candidate:2765706476 1 udp 2122194687 10.255.12.234 42571 typ host generation 0 ufrag xJI/ network-id 3 network-cost 900::UNKNOWN
04-18 12:57:59.641 D/conversations(13867): sending candidate: audio:0:candidate:842163049 1 udp 1685987071 2.247.248.234 31910 typ srflx raddr 10.255.12.234 rport 42571 generation 0 ufrag xJI/ network-id 3 network-cost 900:stun:89.238.78.51:443:UNKNOWN
04-18 12:57:59.691 D/conversations(13867): sending candidate: audio:0:candidate:826779982 1 tcp 1518283007 2a02:303e:5014:d2d0:3188:ad11:a0db:35b6 9 typ host tcptype active generation 0 ufrag xJI/ network-id 4 network-cost 900::UNKNOWN
04-18 12:57:59.700 D/conversations(13867): sending candidate: audio:0:candidate:2431496480 1 udp 41820159 89.238.78.51 62645 typ relay raddr 2.247.248.234 rport 31910 generation 0 ufrag xJI/ network-id 3 network-cost 900:turn:89.238.78.51:443?transport=udp:UNKNOWN
04-18 12:57:59.742 D/conversations(13867): sending candidate: audio:0:candidate:3731770832 1 udp 25042687 89.238.78.51 62032 typ relay raddr 2.247.248.234 rport 6483 generation 0 ufrag xJI/ network-id 3 network-cost 900:turn:89.238.78.51:443?transport=tcp:UNKNOWN

typ srflx means STUN. typ relay means TURN. If you see entries with relay coming up that is already an OK sign. However the only true tell is if you get lines like:

04-18 12:57:59.846 D/conversations(13867): remote candidate selected: :-1:candidate:842163049 1 udp 1685921535 94.134.91.66 22965 typ srflx raddr 192.168.178.39 rport 50732 generation 0 ufrag JRB3 network-cost 10::UNKNOWN
04-18 12:57:59.846 D/conversations(13867): local candidate selected: :-1:candidate:2431496480 1 udp 41820159 89.238.78.51 62645 typ relay raddr 2.247.248.234 rport 31910 generation 0 ufrag xJI/ network-id 3 network-cost 900::CELLULAR

were at least one of them is a typ relay with your TURN server. If the call connects but you only see host or srflx it just means that you lucked out on the network and your network didn’t need turn. (And that case you should try changing networks for a better testing enviroment.

If the call doesn’t connect at all it also means that your setup might not be correct.

Testing without Conversations

If you must test without Conversations the Trickle ICE test in the WebRTC samples might give you some indication. You will probably have to manually XEP-0215 services-query your XMPP server to get temporary TURN credentials. For optimal testing (though not perfect) you should run the Trickle ICE test in Chromium since Conversations and Chromium use the same WebRTC library and there might be subtle differences between Firefox and Google’s libwebrtc.

Side note for Prosody admins

If you don’t get any notifications for incoming calls make sure that your CSI module is letting XEP-353 messages through.

Notes for developers

Conversations will display the call button if one of the contact’s connected clients supports all of the following namespaces:

  • rn:xmpp:jingle:1
  • urn:xmpp:jingle:transports:ice-udp:1
  • urn:xmpp:jingle:apps:rtp:1
  • urn:xmpp:jingle:apps:dtls:0
  • urn:xmpp:jingle:apps:rtp:audio and optionally also urn:xmpp:jingle:apps:rtp:video

To establish a call Conversations will use XEP-0353: Jingle Message Initiation send to the bare jid of the contact. However it will also support the other party attempting to directly session-initiate with it. If you use Jingle Message Initiation make sure that you include the exact same descriptions that your following session-initiate will include as well. So for example putting only media="audio"in the propose but audio and video in the session-initiate the call will be rejected.

You will also need DTLS otherwise your call will be rejected.

Usually Conversations tries to put human readable text in the termination reasons. So if your call fails make sure to check those out. As far as the UI is concerned Conversations will display 'Unable to connect call' on network errors and 'application error' when something else goes wrong or the session got terminated. Usually this means the implementation are incompatible (again; check those <text>…</text> in the reason element. (Also the reason itself might be a hint; like getting security-error when DTLS is not sent.)

Obviously if you are the developer of another client and want to ensure inter-op feel free to contact me; You will most like already have my XMPP address. If not feel free to step by the Conversations channel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment