Search the Asterisk Blog

How to Contribute to Asterisk: Part One

By Matt Jordan

Have you ever run into a bug in Asterisk? If so, don’t despair. Asterisk is software, and despite anyone’s claims to the contrary, all software contains bugs. While you can – and should! – simply file a bug in the Asterisk issue tracker, you may decide that you’d like to try your hand at fixing the bug yourself. That’s the great thing about Open Source software: anyone, at any time, can make any change they’d like.

That being said, fixing a bug in any Open Source project for the first time can be a bit daunting. Where do you start? How do you share your contribution? Luckily, the Asterisk project has a lot of great documentation on this process:

Unfortunately, the project has err’d on the side of providing comprehensive documentation for this process, which can make it a bit challenging at times to find what you’re looking for – particularly if you’re new at the process. As we’ll see, there’s also a lot to do to fix a bug properly: verifying the bug, testing your patch, writing good commit messages, etc. As such, we’re going to start at ground zero, and demonstrate how to fix a bug in Asterisk and submit the patch for review.

Note: Unfortunately, while we’re going to try to be comprehensive, this series of blog posts can’t show everything. If you are unfamiliar with C, Python, or Asterisk, there’s bound to be some content in here that is confusing and/or challenging. Luckily, the project has dedicated places to discuss all things related to the Asterisk source code – the asterisk-dev mailing list as well as the #asterisk-dev IRC channel on freenode. Feel free to drop in and ask any questions you may have!

The fly in the ointment

The bug we’re going to fix in this blog post is ASTERISK-25179: “ CDR(billsec,f)  and CDR(duration,f)  report incorrect values”. Per the bug report, when the CDR function returns the  billsec  or  duration  values for a Call Detail Record, it is returning the value not as a floating point value (as it is documented to do), but instead as some weird super-fraction of a second. That is, if the  billsec  is 37 seconds, the function is returning 0.037000, as opposed to 37.000. Luckily for us, Gianluca Merlo has done a great job with this bug report, even highlighting where the problem might be in the code (yay). Unfortunately, this is one of those bug reports that can sometimes languish in an Open Source project, even though the feature is clearly broken:

  1. It only affects users who who use the f flag in the CDR function.
  2. It doesn’t affect every version of Asterisk – this feature was broken in Asterisk 12+.
  3. Because it isn’t a crash, deadlock, or some other horrible situation affecting lots of users, the normal project maintainers may not get around to the bug for some time.

As such, this is a great bug to fix for a first time contributor: there’s a clear problem, a clear way to verify that it is fixed, and it’s super helpful to the core maintainers of the project.

Let’s get to it!

Step 1: Get Asterisk

Before we can fix any bugs, we first have to get the source code for Asterisk. The project uses Git for source control, with Gerrit acting as the canonical source for the project, and mirrors on both git.asterisk.org as well as Github. While we could get the source from the mirrored locations, since we’re going to eventually contribute a patch back up to the project, we’re going to want to get the source from Gerrit.

Note: Information about all the Git services the project uses and makes available can be found on the Git Usage page on the Asterisk wiki.

While we could just clone the Asterisk repository out of Gerrit anonymously, as we want to post a patch back to the project for inclusion, we’re going to eventually need an account in Gerrit. Since there’s no time like the present, let’s start with getting an account set up.

Creating an Asterisk Project Account

All of the infrastructure used by the Asterisk project uses a single sign-on/account provided by Atlassian Crowd. To create an account, we can go to https://signup.asterisk.org:

signup-asterisk-org

Once we’ve filled all those fields in and selected Sign Up, we should see the following:

signup-asterisk-org-success

Yay! We have an account. But we aren’t done yet.

Asterisk, like some other open source projects, has a Contributor License Agreement (CLA). Before we can submit a patch to Gerrit, we’ll need to sign that as well. Signing said CLA is actually done in the Asterisk issue tracker, so we can go ahead and click the Issue Tracker link on the Sign Up success page shown above.

Signing a Contributor License Agreement

Once we’re at the Asterisk issue tracker, we should go ahead and login. For the purposes of this example, I’ll be signing in using my Username of mjordan, but you should obviously use whatever Username you specified when you created your account.

issues-asterisk-org-loginOnce we’re logged in, we’ll be shown a bunch of dashboards and other interesting information about the project. For now, however, we’re only interested in signing a CLA, which we can do by clicking the big Sign a License Agreement button at the top of the page:

issues-asterisk-org-sign-license

Once we’ve clicked that, we’ll be taken to a page with a legal description of the CLA, as well as the fields we need to fill in.

Note: Do talk to your company before signing any CLA. You should know what you’re signing up for, and what it means. If you aren’t sure, or you want to understand the project’s CLA some more, Digium has posted a few helpful blog posts explaining what the CLA means for contributors.

license-agreement

Once all the fields are filled in, you’ll hit the Next button. That will send your CLA application off to our lovely attorney, Michelle, who makes sure that all the i’s are dotted and t’s crossed. When it’s been approved, you’ll receive an e-mail, and your account will automatically be marked as a “licensed” contributor. That will then allow you to log into Gerrit.

Creating an Account in Gerrit

Once we’re licensed, we need to create an account in Gerrit so that we can upload patches and participate in code reviews. To do that, we can head over to https://gerrit.asterisk.org and click the Sign In link:

gerrit-sign-in

That will redirect us to a new login screen using Atlassian Crowd OpenID. There, we should enter in our standard Asterisk project Username and Password, and click Log In.

crowd-login

That will redirect us back to Gerrit, which should now show us as signed in:

gerrit-signed-in

From there, we need to do two more steps to set up our account: provide Gerrit our user name (which it strangely can’t infer from the OpenID login) and our SSH key for Git. To do that, click the small down arrow next to your name, and select Settings:

gerrit-name-settings

On the Settings page, you need to first provide a Username. We highly suggest that you use the same Username as your Atlassian/Asterisk project account, as that makes things a lot easier. In my case, that’s ‘mjordan’:

gerrit-username

Finally, you’ll need to add an SSH key. Click SSH Public Keys, and then Add Key. That should provide you a textbox to paste your SSH public key into. Click Add when the public key has been pasted into the textbox. If you got it all correct, you should see something like the following:

gerrit-ssh-key

And with that, all of our accounts are set up!

Cloning Asterisk

With all of our accounts properly set up, we can now clone Asterisk out of Gerrit as a contributor. Pick a nice working directory somewhere on your system, and clone Asterisk from Gerrit:

Note: this will take awhile. The Asterisk project has a loooooooooooooooong history.

Once it’s done, we’re ready to get Asterisk built and installed!

Step 2: Build, compile, and install

First, let’s get some dependencies that Asterisk needs installed. Since our bug is in Asterisk 12+, we need to get the dependencies installed for the currently supported versions of Asterisk. As of the time this blog post was written, that’s Asterisk 11 and Asterisk 13, so we need to at least make sure that Asterisk 13 has all of its dependencies.

While there’s some scripts that do that for us that come with Asterisk, they have a tendency to install the kitchen sink. Since I don’t really need every database driver that Asterisk supports, I’m going to go ahead and install just what I need to have Asterisk build for most common situations.

Note: I’m running Linux Mint, so the packages that will be installed will assume that you’re using a Debian based system. If you’re not, feel free to install your distro’s equivalents.

Asterisk 13 will also need libjansson , which provides JSON support. Some distros have this packaged; others do not. I’ll assume we may need to build that from source, which we can do as shown below:

libjansson  installs by default into /usr/local/lib , so you may need to tell ldconfig  how to go find it:

Lastly, we’ll install pjproject . We don’t really need a SIP channel driver to fix this CDR bug, but it’s almost a certainty that we’ll want one eventually, and I’m personally a much bigger fan of the new PJSIP stack than I am of the legacy chan_sip  channel driver. So let’s get that installed as well:

Note that we’ve given PJSIP a few directives here:

  1. We’ve told it to disable its assertions. PJSIP is a bit liberal in its assertions, and sometimes we’d rather just have Asterisk handle those conditions. This will also help with some of Asterisk’s other build options, which treat assertions as a rather fatal event.
  2. We’ve told PJSIP to enable IPv6.
  3. We’ve told PJSIP to bump the default SIP maximum packet length. That will let us handle more modern SIP requests.
  4. We’ve told PJSIP to build shared objects. Asterisk doesn’t link statically to PJSIP; it only links dynamically.

Once installed, it’s time to configure Asterisk. Before we do that, however, we should checkout a branch for the bug fix we’re going to work on, and base it on the appropriate upstream branch. In the Asterisk project, bugs are usually fixed in the oldest supported version that has that bug, which in our case, is Asterisk 13. That means we need to make a branch off of origin/13 :

Once we’re in our branch, we can configure Asterisk:

Note that we’re passing two special parameters to configure as well: one that specifies that we want Asterisk to be configured in development mode, another that says not to build unless we find PJSIP. The first is pretty important. When configured in development mode, a number of new compilation options that enable unit and functional testing will be enabled, and compiler warnings will be treated as errors. The Continuous Integration systems always build Asterisk at least one time in development mode, and will fail patches that don’t compile. When contributing, always build Asterisk in development mode!

Once Asterisk has finished configuring, we’ll be greeted with the following:

We can now pick our more advanced build options. To do that, we’ll use menuselect:

This will run the menuselect tool:

menuselect-one

Select Compiler Flags – Development. In the Compiler Flags – Development list of compilation options, select the following:

  • DONT_OPTIMIZE  – this will turn off optimizations, which makes it possible to get useful backtraces in the event of a crash.
  • BETTER_BACKTRACES  – if available, select this. This will make our crash backtraces even more useful.
  • DO_CRASH  – treat assertions as a fatal crash. If we assert, we want a backtrace so we can fix it. (Note: this is why we disable PJSIP assertions. An assertion in PJSIP is often an expected and manageable error in Asterisk. Assertions at the Asterisk level are more serious.)
  • TEST_FRAMEWORK  – enables the unit tests and functional test drivers.

Hit Esc, then select Test Modules. In the Test Modules list of options, select all unit tests that can be enabled. Some unit tests may require dependencies you don’t have installed – that’s okay. At a minimum, we definitely need the CDR unit tests provided by test_cdr , as we’ll be fixing a CDR related bug.

Hit Esc to go back to the main  menu, then hit Esc again. We’ll be prompted to save our changes:

menuselect-two

Hit S to save the changes and exit menuselect.

Now we can build Asterisk:

Install Asterisk:

And install the sample configuration files:

If everything worked appropriately, we should now be able to start Asterisk:

Note: Did I just run Asterisk as an elevated user? Yes. Yes I did. That’s a big security no-no. I’m assuming you’re doing this all on a local, safe, secured development machine; don’t do this on a production system. Similarly, for the sake of convenience, I’ll be running other items with ‘sudo’. If you want to go ahead and set up a user/group for Asterisk, please do so – in which case, ignore the ‘sudo’ that shows up here and there in this and later blog posts.

Step 3: Run unit tests

First, it’s a good idea to make sure that all the unit tests pass on your system. The last thing you want to do is to make a change in the code, break some existing test, and have your patch get rejected late in the review process. To start, however, we’re going to need to tweak a few of Asterisk’s configuration files. A few tests require Asterisk’s HTTP server and Manager Interface (AMI) to be enabled. We can enable both of these subsystems in http.conf  and manager.conf , respectively.

Note: It would be far better if the tests that used AMI or the HTTP server bothered to detect if those subsystems were enabled before running. That’d be a nice patch for someone to write …

Exit Asterisk ( core stop gracefully ) and edit the configuration files, as shown below:

Finally, one test that covers out of call message handling tries to test what happens if there isn’t a dialplan location to send the message into. Unfortunately, Asterisk tries to dump that message into extension s  of context default , which the default extensions.conf  provides for us. Hilarity ensues when we try to play a sound file back over the Message channel driver. In order to work around that, we’ll provide a blank extensions.conf  – which is better than having an extensions.conf  full of stuff we don’t want.

Note: A make target that provided all of the Asterisk configuration files needed to run the unit tests would also be a good idea. I’ll admit that it’s kind of sad that I don’t realize these things until I’m writing blog posts.

Once that’s done, we can start Asterisk back up again:

asterisk $ sudo asterisk -cvvvg

Once we’re back in Asterisk, we can look at all of the registered unit tests from the Asterisk CLI:

To run all of the tests, execute the test execute all CLI command:

Note that when running tests, you’ll often see plenty of ERROR or WARNING messages fly by. That’s okay. Unit tests tend to test off nominal conditions and – sometimes – play a little fast and loose with what constitutes an Asterisk channel. When all of the tests are done executing we should get presented with how many passed/failed, which is what we really want to see. You may have a different number of unit tests registered than what is shown below, but all of them should pass:

With all the unit tests running, we can now proceed to fixing this noxious little bug, right? Right?

Not quite.

First, we can inspect the unit tests that cover CDRs by running test show registered category /main/cdr/, which should show something close to the following:

Remember that our bug was actually occurring in the CDR  dialplan function – specifically, in an option it provides for interpreting the  duration  and  billsec  attributes. For the most part, our CDR unit tests only cover the CDR core. Now, we might get lucky and our bug might be in the core, but it’s far more likely to be in the dialplan function itself. Currently, we don’t have any unit tests that cover the CDR  dialplan function. That leaves us with two options:

  1. Write a new unit test module that covers the CDR  dialplan function.
  2. Look at the Asterisk Test Suite to see if it has any CDR  dialplan function tests.

As fun as writing unit tests in C is, it’s often much more efficient to test dialplan functionality using a higher level language, like Python. As such, I’ll bet you know where I’m headed with this… next time: to the Asterisk Test Suite!

There's One Comment

Add to the Discussion

Your email address will not be published. Required fields are marked *

About the Author

Matt Jordan

Matt is CTO at Digium and the project lead for Asterisk. Matt joined the team in 2011, and since then has been involved in the development of both Asterisk and the Asterisk Test Suite. His background in software development can best be described as “eclectic”, having worked in a variety of industries. Uniting the various experiences, however, is a firm belief in good software development practices and methodologies and the effect they have on producing quality software (and keeping software developers from going insane).

See All of Matt's Articles

More From
The Digium Blog

  • No items