This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.
Asterisk: Moving on from chan_sip
Making major changes to core functionality in an existing software project can be daunting. Making those changes in a project that has been in existence since 1999, has approximately 1.4 million lines of code, a massive installed base, and whose users are in an industry with a well-known aversion to change can seem outright impossible.
But that is just what the Asterisk developer community has done over the past year by introducing a new SIP stack based on Teluu's PJSIP in Asterisk 12. How and why the Asterisk project decided to make this change is important, as it was a decision not taken lightly, and not without reason.
The legacy SIP channel driver in Asterisk--chan_sip--was created more than 10 years ago, in 2002. RFC 3261, which defined SIP as we know it today, was released in June of the same year. Asterisk was only three years old at the time, but it already had a number of other VoIP channel drivers in it. As such, Mark Spencer based the design of chan_sip on what existed already.
It is doubtful that anyone could have predicted the growth of both SIP and Asterisk over the next decade. As both grew, the size of chan_sip grew as well, quickly outpacing what the original design foresaw. Even still, chan_sip has held up well over the years, helping to make Asterisk the world's most widely adopted open source communications platform. However, as time progressed and both Asterisk and SIP capabilities grew, the design of chan_sip began to limit the SIP functionality that could be added to Asterisk.
The largest limitation in chan_sip's design is its monolithic structure. All of the SIP functionality in Asterisk resides primarily in a single file, chan_sip.c. This includes code that handles SIP dialogs, registration, event subscription, messaging, interactions with the Asterisk core, configuration, and more. The lack of separation of concerns in chan_sip means it is difficult to improve or enhance the functionality, because changes often result in unintended consequences.
However, merely having difficulty extending the channel driver is not sufficient cause to abandon it. For some time, we in the community had the suspicion that a large amount of effort was spent on simply maintaining chan_sip. That effort--if it could be reduced--could be spent adding other features and capabilities to the platform.
To quantify that, we looked at the percentage of total bugs reported in the Asterisk issue tracker that were against chan_sip. To no one's surprise, not only was chan_sip the recipient of the most bugs, but the number of bugs in chan_sip as a percentage of the total reported bugs has, for the most part, grown over the years! To some extent, that growth can be accounted for due to the growth of SIP as a VoIP protocol and its use in Asterisk. Ideally, however, the percentage of bugs against chan_sip would be holding steady, not growing. This seemed a clear indication that the design of chan_sip was working against us.
This data, and the experiences of the many developers who maintained the channel driver, convinced the overall developer community that Asterisk 12 was the version in which to finally craft a solution to the problem. The first major decision we faced was whether we should attempt to re-factor chan_sip into something else, or build something new from scratch. Re-factoring chan_sip had the advantage of letting us work with a known code base and use the years of features and support that had been put into it; building something new had the advantage of starting with a clean architecture. After much discussion, the consensus was to build a new channel driver. Primarily, this was decided upon for two reasons:
(1) The monolithic structure of chan_sip resists change. Even small, incremental improvements are difficult, and once a large sweeping change is made, it can be tantamount to a rewrite. In fact, the spike in chan_sip issues in 2011 can partially be attributed to major changes made in the Asterisk channel core that rippled out into chan_sip. That knowledge tended to give the community pause when advocating a re-factoring of the existing channel driver.
(2) A new SIP channel driver can exist in parallel to the legacy chan_sip channel driver. This approach would give the Asterisk community more time to test and adopt the new channel driver, while maintaining the existing functionality in chan_sip. As a result, writing a new channel driver entailed less risk than re-factoring the existing channel driver.
Armed with that decision, the Asterisk developer community embarked on creating the new SIP stack in Asterisk 12 to avoid the pitfalls in chan_sip. First, we decided to focus on Asterisk providing SIP functionality as an engine of communications, and not on it being a SIP stack itself. That meant using a third-party SIP stack. After much deliberation, the community decided on PJSIP by Teluu. PJSIP is a well-known and widely-deployed SIP stack, which meant Asterisk could take advantage of its proven robustness, and developers could focus on providing communications features that make use of that functionality.
One of the most important decisions made in the development of the new functionality was to design both a channel driver as well as a suite of dynamically loadable modules that comprise a full SIP stack. The channel driver would be a relatively slim module, while each module in the suite would provide a specific piece of functionality. The design structure of this stack is such that functionality can be added, modified, or removed with minimal impact on other modules.
For example, the module providing SIP registration services is completely separate from the module that provides SIP subscription services. Improvements or modifications to one of these modules does not affect the others. This makes the entire suite of SIP functionality much easier to modify and extend safely. From a maintainability perspective, it is also much easier to maintain such a module--for example, chan_pjsip, which is the actual channel driver, is only around 2,000 lines of code, while chan_sip tops out at nearly 35,000!
It is also important to note that the development of Asterisk 12 was a community effort. Design decisions, implementation of many features, code reviews, advice and suggestions, testing, and a whole host of activities were shared by the community. In addition, several community members shouldered a substantial amount of the maintenance burden for the other supported branches of Asterisk, so that some of the developers at Digium could focus on the new development work. Without these valuable contributions, it would have been very difficult for us to focus on the work in Asterisk 12 while adequately maintaining the existing branches. This highlights one of the benefits we at Digium have with Asterisk being an open source project--we never approach a major problem alone!
As we move away from chan_sip, it is important to thank the architects and developers of chan_sip for its years of service. While it is easy to criticize its monolithic architecture today, one cannot discount the fact that untold numbers of VoIP calls have been made and serviced thanks to its code. Countless smart, talented, dedicated engineers have built the functionality that has serviced those calls, and we have been lucky to use it for so many years. As Isaac Newton is said to have remarked, "If I have seen further, it is by standing on the shoulders of giants"--and that is certainly true of Asterisk 12 and its new SIP functionality. I look forward to what we'll see in the next 10 years!