 So, who has looked at reciprocates already? Yeah? Only a few people. Who is a C++ programmer? Yeah? Okay. Who knows Python? A lot more. Who is a system administrator? Okay. So a little bit about how we work in the reciprocate community. It's a C++ project. We've recently added some Python integration, and that's going to expand. It's cross-platform. So we aim to make it work on Linux, Solaris, Android, Windows, Mac. So just about everything. Embedded platforms. It's a BSD-style license. So people can integrate this in products where they don't want to release all of the other source code they develop. There are packages for many leading Linux distributions. So if you're a system administrator or if you just want something that you can install and you don't want to hack on it, then the packages might be for you. I've personally been involved in packaging for Debbie and Fedora, Red Hat, Obuntu, and other platforms. We use Git, and at the moment we're using GitHub. We also use Travis CI to run continuous integration tests. And we have lots of unit tests. That's a big part of our methodology is unit testing. So when we change something, we often add new unit tests, both to test what we've done and also to make sure that feature doesn't break in the future if someone changes it again. So some reasons to use reciprocate. Even if you're not a developer and you're just looking at something that you want to install on your router at home as a voice-over IP service. These are some of the things to think about. IPv6. It's been there all along. In a lot of software, you'll find it's hard-coded for IPv4. And more and more networks are moving to IPv6 or offering dual-stack environments. Some end users won't be able to connect to services that don't support IPv6. So a lot of developers are finding they have to hack their existing code to support it. And when you start hacking existing code to add IPv6, you can introduce new bugs. You might not have complete coverage because you don't know what you have to change. But with reciprocate, it's been there since day one. It's always been part of the development strategy. So we don't have to go back and add it. We don't have to worry if we've missed anything because it's always been part of reciprocate. TLS. This is another big thing as people become more and more concerned about privacy and security. The people want to run their SIP network over the public internet, even if it's just because a single user is working from an office at home. TLS is becoming really important. TLS is also important for helping you get through NAT. In many environments, UDP is not allowed through corporate firewalls. But a TLS connection going to port 443 is indistinguishable from web traffic. So this provides a great way to increase the reliability of SIP using TLS. It's got extensive coverage of the full SIP spec. Many of the developers have been involved in drafting the RFCs, adding different features to SIP. Things like SIP outbound are very well supported. Outbound is very helpful for getting through firewalls as well. We've got different APIs. We've got low-level APIs which allow you to interact with individual messages. We've got high-level APIs which allow you to just create a phone with one or two objects. And we've also got the Python API which is expanding at the moment. So you can approach development from any of those directions. The architecture is also very highly generalized. So the transport code is easily expanded to add new transports. When we added the WebSocket support for WebRTC, we only had to add a few more classes. We didn't have to completely rewrite our transport code. The existing architecture was generic enough that we could drop that in and it would work very quickly without breaking other things as well. So looking at the low-level API interacting with individual SIP messages, in this example we're going to see a handler script is taking copies of the messages that have been picked up by Homer. It's sending them through a message bus to another process which is there to examine them and to test them. The consumer pulls each message off that message bus and then it examines it. Now an interesting feature of the stack is that it has a lazy parser. So when the messages go through the SIP proxy, it doesn't parse every header. So if one of the headers is corrupt or is deliberately designed to cause a problem, it may not get noticed if that header is not parsed. But in this example, the intention is to parse every header. So we disable the lazy parsing and that forces the stack to parse all the headers. Can people read this at the back? So the first, most of the code is just a string containing a sample SIP message. The line that's in bold, the second last line, parses the message. That's it. That creates a SIP message object from that text. The final line prints the request method, which is invite. So it shows how to extract the request line and how to extract the method from the request line. So the API is in those last two lines of code. The rest of what you see there is just the string containing the sample message. So if we wanted to force it to parse all of the headers, then we have to enable an option in the stack. The default behavior is that it doesn't actually examine anything in the string until we ask for that particular header and value. So let's look at the high-level API. The test UA is one of those test programs that's distributed in the repository. It shows us how to build a conferencing server with a single class. It has a basic command line interface to exercise features of the recon API, which is a high-level API. The same API can be used to build soft phones, voicemail servers, a B2B UA or session border controller. So let's have a look at using that class. Once again, it's very simple. We have a callback method that we have to implement on incoming participant. This method will be called when a call comes in, and we can answer it or we can make some decision about rooting it. We can display a pop-up dialogue to ask the user if they want to answer or reject. We can put whatever logic we like in these methods when we override them. So this is the high-level API, and you can basically implement most of the functionality of a phone or any other type of interactive telephony service by sub-classing these methods. So some things that we built that are already there for you to use Repro is a SIP proxy that supports all those things I spoke about before, TLS, IPv6, WebRTC, all of those things that they're part of Repro and they just work. Return server is a turn server. This is to relay media for users behind NAT. So this improves the reliability, eliminates problems with one-way audio. Recon server is an example of a B2B UA. Once again, you get all the features of the stack, so the IPv6, the TLS in a B2B UA. You can use this between Asterisk and the real Internet just to eliminate some of the things that might come in that you don't want to send to a full PBX. We've got the MOH Park server, which is a music on hold server. So some SIP phones will work with that and that can generate music on hold. You can run it on a separate server with separate network infrastructure just to distribute that workload. The registration agent, this is a much smaller example. What this does is it lets you send registrations to your service provider with a contact header containing any value that you want. So the contact header can force all your incoming calls to go to your SIP proxy. If you use Asterisk or FreeSwitch to register for you, then it will construct the contact header so that the calls come back to that same process. With this registration agent, you can direct the calls to go to any process you want to use to receive those incoming calls. So if you actually want to have just a SIP proxy without having Asterisk or FreeSwitch or any other PBX, you can use the registration agent to register and receive your incoming calls. Here's an example of the web interface in the repro SIP proxy. So this is where we add a route. Can you see that at the back? Yep. So we can use regular expressions when we write the URI. It will then examine the incoming SIP messages, compare the request URI to the regular expressions, and then it will route to the destination, which is in that second-last box based on the URI. You can also take patterns from the request URI and put them into the destination using the placeholders. Here's an example of deploying the repro SIP proxy with Asterisk for WebRTC. So I've used this in a number of cases where the Asterisk server was an older version of Asterisk and it didn't have the latest connectivity for WebRTC that we felt that repro offered better WebSocket support, but we had functionality in Asterisk that we wanted to use. So the incoming connection from the browser, it goes to the web server first, it downloads the JavaScript, so JS SIP or whatever it displays the page, the user starts the call. It makes a WebSocket connection to the SIP proxy, which is repro from reciprocate. And repro can accept that over TLS, for example. So on the left-hand side, that connection is a TLS. I don't know if my laser is working there. So the connection coming into the SIP proxy will be TLS, and then the connection going over to Asterisk might be regular TCP or UDP, and that's fine because that's within your network. So that's just one example of using the repro SIP proxy. Here's another example. This is the Python API. So if you look at Camillo, for example, it has a customer or a bespoke scripting language. Asterisk has various dial plan macros that you can use. In repro, we decided to simply use Python. So we can use all the features of the Python API. In this example, there are two methods. The first method on load is called when the SIP proxy starts. The second method, provide root, is called for each time a call is routed. So instead of using that regular expression matching we just saw, we can use Python to take the destination and change it to any other destination. In fact, we use a list so we can provide multiple destinations. It can ring two different extensions. So if you have some logic to root calls in a call center based on the languages that people speak and you know the language of the caller and you know the language of each agent, then you could use the Python script to build a list of people who can take that call and to return that to the proxy. We can also add custom headers. How do you get it? Well, because it's packaged, you can install it on Debian or Red Hat, so Fedora, REL, whichever you prefer, or CentOS, just using apt or yum. After you install it, you edit the repro.config and you restart the service and you're ready to go. It also works quite easily with Let's Encrypt for TLS certificates. There's a lot more in the project. We have the iChat gateway, which is an XMPP gateway that we developed a long time ago and we've just been updating that for the latest XMPP support. The telepathy reciprocate module, this allows you to integrate with the Linux desktop, which has the telepathy API. There are a number of soft phones that support that. SIP dial, it's just a click-to-dial client which works with a number of phones. This is an example of the telepathy integration and the GNOME empathy as the soft phone using reciprocate as a back-end. What next? You can mix and match. You can do things like combining reciprocate with Camillo or with Asterisk or with FreeSwitch or any other product. You can integrate it with Homer. There are lots of options to integrate with existing systems. See the real-time communication quick start guide. That's rtcquickstart.org. You can find step-by-step instructions there. If you want to learn about the APIs and start developing with reciprocate, take a look at our unit tests. They provide a lot of great examples and you're also very welcome to help us improve them or contribute tests for things you rely on. Does anyone have any questions about or comments about reciprocate? I'll do this very quickly. The messaging integration. I've been integrating Apache Cupid Proton into the SIP proxy. It sends an announcement to the message broker when someone registers or when the registration expires. If you want to know more about messaging and also look at integrating with other message brokers, then that's the code to look at. For Android, there's an example project in GitHub. It's called Android demo message, I believe. That would be... We haven't really got time. I was going to open it up, but look for the Android demo in GitHub under reciprocate. Another question? Last question. Anyone? Hi. Do you expose symbols in any other languages except Python? As part of developing the Android demo, we started to integrate with Java. Because it's C++ code, you have to compile it with JNI, and then you have a Java class running on Android that interacts with it, so you have to expose some of the methods and objects to Java. But we only did maybe a few methods, not the whole API, but it shows that we can take it further if we want to. There are also some tools for automatically generating bindings for other languages. I haven't experimented with any of them. Incidentally, one of them is actually called SIP. Typically, C++ is easier to export the symbols with this, like, when switched. Yeah. Okay, thank you, Dan. Yeah, thank you. Thank you.