Asterisk channel

From 탱이의 잡동사니
Jump to: navigation, search


Asterisk channel concept 내용 정리


Asterisk 에서 channel 을 빼고는 거의 이야기할 만한 것이 없다. A channel is an entity inside Asterisk that acts as a channel of communication between Asterisk and another device. That is, a phone, a PBX, another Asterisk system, or even Asterisk itself(in the case of a local channel)l

Call 을 이야기할 때, 많은 부분에서 channel 을 이야기하게 된다. Call 이란, 하나 혹은 그 이상의 channel 들로 이루어진 communication path, activity though the Asterisk system 이라고 할 수 있다.

간단하게 채널은 다음의 역할을 수행한다(실제로는 더 많다)

Channel Drivers provide channels in Asterisk.
Channels can interface with each other through bridges.
Applications and functions can affect the state or attributes of a channel or its media stream.
Channels are commonly passing audio between communication endpoints, but can pass other data, such as video or text messages.
Channels execute instructions with dialplan, but can be controlled by other APIs (AGI, AMI, ARI) or interfaces(CLI).

Common Asterisk channels

One of the many benefits of Asterisk is the capability to interface with as many different technologies as you have channel drivers! However, most administrators will only make use of a few types at a time.

Here are a few commonly used channel types:

A SIP channel driver such as chan_sip or chan_pjsip.
DAHDI channels provided by chan_dahdi.
Local channels provided by chan_local(This was moved into the core in Asterisk 12).

SIP channels are used to interface with SIP capable VOIP devices, such as phones, channel banks, other PBXs or Internet Telephony Service Providers.

DAHDI channels are used to interface with DAHDI drivers and PRI libraries. In this case chan_dahdi allows you to any DAHDI capable devices, such as Digium's line of T1/E1/J1 interface cards.

Local channels are used for dialing inward to the system itself, allowing any Asterisk component that can dial to call directly into dialplan. This provides sort of "fake" call that still executes real instructions.

Local Channel

Local Channel Optimization

Default Channel Optimization

By default, the Local channel will try to optimize itself out of the call path. This means that once the Local channel has established the call between the destination and Asterisk, the Local channel will get out of the way and let Asterisk and the end point talk directly, instead of flowing through the Local channel.

This can have some adverse effects when you're expecting information to be available during the call that gets associated with the Local channel. When the Local channel is optimized out of the call path, any Dial() flags, or channel variables associated with the Local channel are also destroyed and are no longer available to Asterisk.

Asterisk LocalChannels Optimization.png

Figure 1

This is a call in an unanswered (ringing) state - from SIP to SIP using Local Channels in between.

Figure 2

By default, after the callee answers this is what the call would look like with the Local Channels optimizing out.

Figure 3

This is what the call would look like when established if you called the Local Channel with "/n". You can see the Local Channels get pushed into bridges with channels they were connected with through app_dial previously.

Disabling Local Channel Optimization

You may have read about /n modifier in here[1]. We can force the Local channel to remain in the call path by utilizing the /n directive. By adding /n to the end of the channel dial-string, we can keep the Local channel in the call path, along with any channel variables, or other channel specific information.

When to disable optimization

Lets take a look at an example that demonstrates when the use of the /n directive is necessary. If we spawn a Local channel which does a Dial() to a SIP channel, but we use the L() option(which is used to limit the amount of time a call can be active, along with warning tones when the time is nearly up), it will be associated with the local channel, which is then optimized out of the call path, and thus won't perform as expected.

This following dialplan will not perform as expected.

exten => 2,1,Dial(SIP/PHONE_B,,L(60000:45000:15000))
exten => 4,1,Dial(Local/2@services)

In order to make this behave as we expect(limiting the call), we would change

exten => 4,1,Dial(Local/2@services)

.. into the following:

exten => 4,1,Dial(Local/2@services/n)

By adding /n to the end of the dial-string, our Local channel will now stay in the call path and not go away.

Why does adding the /n option all of a sudden make the 'L' option work? First we need to show an overview of the call flow that doesn't work properly, and discuss the information associated with the channel:

- SIP device PHONE_A calls Asterisk via a SIP INVITE.
- Asterisk accepts the INVITE and then starts processing dialplan logic in the [internal] context.
- Our dialplan call Dial(Local/2@services) : noticed the lack of the "/n".
- The Local channel then executes dialplan at extension 2 within the [services] context.
- Extension 2 within [services] then performs Dial() to PHONE_B with the line: Dial(SIP/PHONE_B,,L(60000:45000:15000))
- SIP/PHONE_B then answers the call.
- Even though the L option was given when dialing the SIP device, the L information is stored in the channel that is doing the Dial() which is the Local channel, and not the endpoint SIP channel.
- The Local channel in the middle, containing the information for tracking the time allowance of the call, is then optimized out of the call path, losing all information about when to terminate the call.
- SIP/PHONE_A and SIP/PHONE_B then continue talking indefinitely.

Now, if we were to add /n to our dialplan at step three(3) then we would force the Local channel to stay in the call path, and the L() option associated with the Dial() from the Local channel would remain, and our warning sounds and timing would work as expected.

There are two workarounds for the above described scenario.

Use what we just described, Dial(Local/2@services/n) to cause the Local channel to remain in the call path so that the L() option used inside the Local channel is not discarded when optimization is performed.
Place the L() option at the outermost part of the path so that when the middle is optimized out of the call path, the information required to make L() work is associated with the outside channel. The L information will then be stored on the calling channel, which is PONE_A.
exten => 2,1,Dial(SIP/PHONE_B)
exten => 4,1,Dial(Local/2@services,,L(60000:45000:15000));

Optimization and Zombie call

As per default, the Asterisk will try to optimize the channels. to end up with the a bridge as short as possible. This behavior can be omitted by using the "/n" option in the Dial() command.

- SIP/201 makes a call to 202.
- The call enters the dialplan in the context [Incoming].
- [Incoming] makes a Dial() to [SomeOtherContext], that makes a Dial() to [DoTheDial], that then dials SIP/202.

Without the "/n" option, the Asterisk will optimize the channels to get as few as possible in the path. So, to start with, channels

- SIP/201 -> [Incoming]
- [Incoming] -> [SomeOtherContext]
- [SomeOtherContext] -> [DoTheDial]
- [DoTheDial] -> SIP/202

This is a lot of channels and in most cases is not necessary to keep them all. So the Asterisk does some optimization.

SIP/201 is bridged with [SomeOtherContext]. So the "[Incoming] -> [SomeOtherContext]" is no longer needed, that will create some channels that are not longer attached to another channel. So they are "zombies" (not doing anything, they just exists with no purposes).

Now the channels look like this

- SIP/201 -> [SomeOtherContext]
- [SomeOtherContext] -> [DoTheDial]
- [DoTheDial] -> SIP/202

But there's more to optimize. So the Asterisk keeps optimizing. Now it bridges [SomeOtherContext] directly to SIP/202, which leaves behind the [DoTheDial] channel as a zombie.

- SIP/201 -> [SomeOtherContext]
- [SomeOtherContext] -> SIP/202

And finally the last channels are bridged, so the final result is

- SIP/201 -> SIP/202

So now only two channels exists; the one from SIP/201 to asterisk and one from asterisk to SIP/202, and they are directly bridged together.

See also