Hello again! Last time, we looked at Asterisk 12. Since then, a lot has happened – namely, AstriCon! You may have read just a little bit about AstriCon on this blog, but what you may not have read about were the major events that occurred in conjunction with AstriCon.
The first was the annual AstriDevCon meeting, in which numerous developers and power users in the Asterisk community met and discussed Asterisk 12 and the roadmap for the next major version of Asterisk. The response to the new SIP stack and the APIs was overwhelmingly positive, and a lot of features and ideas that were built on the new SIP stack, architecture, and APIs were mapped out during that meeting.
The second event that occurred in conjunction with AstriCon was the first beta release of Asterisk 12. This release signified an advancement in the readiness of Asterisk 12 for more general use. As we mentioned in previous blog posts, due to the numerous architectural improvements, Asterisk 12 contains more changes than previous Asterisk releases and is thus undergoing two test release cycles. People looking to test out Asterisk 12 should, of course, read up on all of the changes before deploying it.
With all of that said, today we’ll be looking at the new SIP stack in Asterisk 12, based on Teluu’s PJSIP stack, with a focus on the design and architecture of the new stack and what it means for the future of Asterisk.
The legacy SIP channel driver in Asterisk was created roughly ten years ago, in 2002. At the time, SIP was a relatively new standard with RFC 3261 having only been released in June of that year. At the time, no one could have fully predicted the dominance that SIP would eventually play in the VoIP market or the rapid expansion of RFCs and standards that would follow. The SIP channel driver implementation in Asterisk was done in a single channel driver module called chan_sip. Because the full scope of what would encompass “SIP” was not known at the time, by 2012 the design of chan_sip had reached a point where its structure was no longer able to keep pace with the expansion in technology. At AstriDevCon 2012, the developer community felt that an alternative was needed.
So, motivated by chan_sip’s limitations, we set out to design a new set of modules that would not only provide the SIP functionality Asterisk needs today, but would be flexible and tolerant to changing requirements in the future. The result is the PJSIP stack in Asterisk, which is still a channel driver, but also a lot more.
One of the first decisions that influenced the design philosophy for the new SIP functionality in Asterisk was to implement that functionality as a stack provided by a suite of loadable modules instead of a single channel driver module. This means that while there is a PJSIP channel driver in Asterisk 12 – aptly named chan_pjsip – its purpose is to bridge between the PJSIP stack and the actual PJSIP channel executing dialplan in Asterisk. The PJSIP stack itself consists of a host of other modules, each of which provides a different piece of functionality that the channel driver and other modules can use. This approach has several benefits:
- Implementation of functionality within the PJSIP stack is isolated, making it easier to enhance, maintain, and even replace! For example, the code that handles media negotiation and setting up calls is in a separate dynamically loadable module from the code that handles MWI subscriptions and notifications. Separating this logic, which follows well known software design best practices, also has the added benefit of letting a user customize their installation by only loading the modules that provide the functionality that they need.
- Developing new functionality for the PJSIP stack is substantially easier than it was for the chan_sip channel driver. The PJSIP stack in Asterisk today has modules that provide frameworks that subsequent modules can consume to provide end-user features. As an example, a single module, res_pjsip_pubsub, provides a publish/subscribe framework that other modules use to provide event notification features. This includes features such as MWI, provided by res_pjsip_mwi, and device state, provided by res_pjsip_exten_state. The fact that the implementation of such features can be done in separate modules means that developers who want to enhance Asterisk with new functionality, such as adding new event packages, can do so in a manner that not only minimizes the portion of the stack that they interface with but also minimizes the impact to existing systems.
A high level view of the modular architecture of the PJSIP stack in Asterisk 12 is shown below. Note that this does not show all of the modules currently available in the PJSIP stack; rather, it shows the functionality provided by a small selection of the most commonly used modules.
Configuration for the new PJSIP stack uses a very different schema than the historical SIP channel driver. Rather than lump all configuration for a device into a peer/user/friend (which does not have a strong relationship to SIP concepts), the new stack takes the approach of breaking up configuration into logical sections so that there are different sections for different purposes. For example, there are sections for configuring how a SIP endpoint authenticates and how it identifies itself, as well as the media and other behavioral properties that are allowed on the endpoint.
As an example, in sip.conf a SIP peer might have looked something like this:
[my_phone] type = peer context = local_office disallow = all allow = ulaw host = dynamic secret = super_secret qualify = yes dtmfmode = rfc2833
This peer definition mixes basic properties of the device, such as the codecs that are allowed, along with authentication and registration behavior. While this has some benefits in that a single peer can be quickly defined, this approach encounters drawbacks when attempting to define disparate shared attributes among multiple devices. It has also historically forced a rather large schema for real time database integrations, which is not always ideal.
The PJSIP configuration for this endpoint would look like the following:
[my_phone_auth] type = auth auth_type = userpass username = my_phone password = super_secret [my_phone_aors] type = aor max_contacts = 10 qualify_frequency = 300 [my_phone_endpoint] type = endpoint auth = my_phone_auth aors = my_phone_aors disallow = all allow = ulaw context = local_office dtmfmode = rfc4733
While the definition of all of these options is beyond the scope of this blog post (and is available on the Asterisk wiki and via the CLI command ‘config show help’), you can see that there are different sections that make up the full definition of the SIP endpoint. Not only does this allow a user to make greater use of templates in the configuration of endpoints, it also more cleanly maps back to a real time database that stores this data.
More information on how to configure PJSIP can be found on the Asterisk wiki:
State of PJSIP in Asterisk 12
The first goal for PJSIP in Asterisk 12 was to strive for feature parity with the existing SIP channel driver. While we did not quite reach full feature parity, the PJSIP stack is feature rich and suitable for many deployment scenarios. Some of the features available in Asterisk 12 are:
- Calls/media sessions
- Media streams (audio/video), including media format attribute negotiation and support for all Asterisk formats/codecs
- Caller ID/Connected Line/Redirecting/Forwarding information
- DTMF (inband, RTP, and INFO request)
- Session Timers
- Reason header
- Multiple transports (UDP, TCP, TLS, and WS)
- Secure media (SDES-SRTP and DTLS-SRTP)
- Digest authentication
- INVITE with Replaces
- Refer handling with NOTIFY request support
- INFO requests
- Video refresh/fast picture update
- One touch recording
- Messaging – out of call/in call text MESSAGE request integration
- Integration with Asterisk’s SIP Security Framework
- Registration/Registrar, including allowing multiple device registrations to a single endpoint
- Qualify support using OPTIONS requests
- CLI/AMI initiated NOTIFY requests with configurable event packages
- SIP header manipulation – SIP_HEADER function (add, update, and remove SIP headers)
- Trace logging
- Publish/subscribe handling
- MWI event package
- Extension/device state (PIDF, XPIDF, and CPIM-PIDF)
There are some features that chan_sip provides that did not make the first cut. However, due to the release policy enacted for Asterisk 12, we fully expect that many of these features will be introduced in Asterisk 12 as time goes on. In addition, many AMI and CLI commands are currently being implemented by members of the Asterisk developer community, and new functionality is being added on a continuing basis. Expect the PJSIP feature list to grow considerably in the months to come!
The Future of SIP in Asterisk
We in the Asterisk developer community have spent a significant amount of time and effort testing PJSIP for the Asterisk 12 beta. However, that does not mean that the work is finished. We will need all members of the Asterisk community to test the new PJSIP channel driver and all of the various modules that provide SIP functionality. As you test and start to deploy PJSIP, feedback is welcomed on the asterisk-dev mailing list.
We are fully confident that the new PJSIP stack is the best path forward for SIP in Asterisk. Working together, the Asterisk community can help make PJSIP a successful reality as the provider of SIP functionality for the future of Asterisk.