Building a Channel Driver – Part 3


If you’ve been following this blog post series, then you should have a channel driver that’s ready to be integrated with ARI. If not, then check out Part 1 and Part 2 first. The purpose of this final chapter in the series will be to get your channel driver working with ARI, which is not as hard as it sounds. With that, let’s go ahead and jump straight into the code!

Initial Setup

Getting the basics set up is actually very simple. Knowing where to look is the hard part. There’s a file that you will need to add a single line of code to in order to get things working. Look at rest-api/api-docs/channels.json. There’s a lot of stuff in here, but we only care about one section. Scroll down to the section that looks like this:

	"path": "/channels/externalMedia",
	"description": "Create a channel to an External Media source/sink.",
	"operations": [

This is the section we will be using to link your channel driver up to ARI. There is a section within this called encapsulation that currently has two values: rtp and audiosocket. All you need to do here is add your channel driver name (for this example, groovy). After you’ve made your changes, you’ll need to run the following command from your terminal at the root Asterisk directory where you run your configure and make commands:

make ari-stubs

This will build some boiler plate code and add things to files so that you don’t have to. We’re going to focus on the things that you will need to add once this command has been run rather than what goes on behind the scenes.

Integrating With External Media

Next up, we’ll be taking a look at res/ari/resource_channels.c to get the channel driver working based on what encapsulation is passed in. First, let’s take a look at an existing function: ast_ari_channels_external_media. There’s not much that needs to be added here, as you can probably see from the function. There is one conditional that we need to modify:

if (strcasecmp(args->encapsulation, "rtp") == 0 && strcasecmp(args->transport, "udp") == 0) {
	external_media_rtp_udp(args, variables, response);
} else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
	external_media_audiosocket_tcp(args, variables, response);
} else {
		response, 501, "Not Implemented",
		"The encapsulation and/or transport is not supported");

The options should look familiar. Just add your channel driver here, with the correct transport type (unless you allow for multiple transport types). Note that based on what transport is passed in, the function called might need to change (or a conditional will need to be added to your function), so be sure to take this in to account in the next step. You will need to create another function that corresponds to your channel driver. Above this function there are two existing functions that correspond to chan_rtp and chan_audiosocket: external_media_rtp_udp and external_media_audiosocket_tcp. For your channel driver (here we will assume UDP), you might create a function like external_media_groovy_udp. Create a function following the structure of the other 2 functions that will be called within the above conditional.

static void external_media_groovy_udp(struct ast_ari_channels_external_media_args *args,
	struct ast_variable *variables,
	struct ast_ari_response *response)

There’s a lot going on in these functions, so just copy and paste all of the contents in to your function (some of this code might need to be refactored so it can be used by all of these functions). The main thing you will need to modify is the channel name. You can see that this is the only place that both of these existing functions differ as well. In the case of chan_audiosocket, there is an extra field appended to the end of the channel string. You can put any information here that you want passed in when the channel is created. This may or may not be necessary for your channel driver. chan_audiosocket requires a UUID, so we set that up here.


Believe it or not, that’s all there is to it! But how do you know if it works? Luckily, this can all be tested using the Swagger web GUI[1]. There is some initial setup[2] with ARI that you will need to complete first, unless you have already done so. Assuming you have everything set up correctly and have recompiled Asterisk, you should be able to create a channel with a POST via external media. Enter in your channel string starting with “Groovy/” and the correct transport and encapsulation, and viola! You’ve got your channel driver working with ARI!

Closing Remarks

This article is much shorter compared to the first two, showing just how easy it is to link your channel driver to ARI. This is also the last blog post in the series, so I hope you’ve learned some new things along the way. For some people, it is much easier to see the end-product, so take a look at the AudioSocket review[3] if you would like to reference the full code review.





Leave a Reply

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

The reCAPTCHA verification period has expired. Please reload the page.

About the Author

What can we help you find?