Last week’s article explained how Jami establishes peer-to-peer connections with ICE and uses TURN as a fallback if it doesn’t work (if you didn’t read it yet, you should do it before reading this one unless you already are an expert in this stuff). Those protocols are implemented in the PJSIP library, which Jami heavily relies on to negotiate direct links between peers. While PJSIP is recognized as the reference for Voice over IP communication applications, it is not designed to work in a distributed network. For this reason, our team had to make significant contributions to the PJSIP project. In order to grasp the nature of those improvements, it is necessary to understand the difference between UDP and TCP. They are both data transfer protocols allowing machines to communicate, but they work differently.
TCP keeps track of every packet of data sent and ensures that they are reliably transferred by requiring the receiver to confirm reception of every single one of them and the sender to resend those that were lost. UDP on the other hand, doesn’t handle packet loss. While it is less reliable, it is preferable in applications such as media streaming because the data is time sensitive. In those cases, a lost packet will simply cause a small video or audio glitch and waiting for it to be resent would make it worse than simply moving on to the following bits. In the case of data transfer however, a single lost packet can corrupt a whole file and reliability is therefore more important than timeliness, which is why TCP is more suited for this application.
PJSIP had support for TCP, but not over ICE or TURN, which is why we had to implement it ourselves in order to support it for peer-to-peer communications. We started by implementing support for the RFC 6062 standard in PJSIP, allowing TCP data transfers through TURN only. This was completed in 2017 and it allowed us to add the file sharing feature to Jami. We recently completed the support for the RFC 6544 standard in PJSIP, finally allowing truly peer-to-peer file transfers in Jami by using ICE over TCP without requiring a TURN server.
The improvement we made also has another important benefit. During a SIP call, there is always a control communication channel opened between the peers in addition to the audio and video channels.The control channel has many purposes, it is used to initiate, terminate, pause and unpause calls, send text messages, send the vcard including the avatar and display name, negotiate codecs and change the video orientation. Because we had to rely on UDP for this channel, packet loss could occasionally cause issues and unexpected behavior. In the near future, we will use TCP for this channel, eliminating those issues and making Jami much more reliable.
Our implementation of RFC 6062has since been merged upstream by the PJSIP team and our RFC 6544 implementation will be as well when it is ready, making them available to use by all other applications that also rely on this library. This is the perfect example of how open source projects such as Jami and PJSIP are built on top of each other and can work together to improve one another. The next time you send a file using Jami, you will have a better understanding of what is going on under the hood and all the work that was necessary to make that possible. For more technical details about file transfer in Jami, please view our documentation.
By Sébastien Blin and François Naggar-Tremblay