dect
/
asterisk
Archived
13
0
Fork 0

Update existing Local channel documentation.

A complete re-write of the Local channel documentation has been performed, with
the existing information from localchannel.txt and localchannel.tex merged in.

(closes issue #16637)
Reported by: kobaz
Patches: 
      localchannel.tex uploaded by lmadsen (license 10)
      localchannel.txt uploaded by lmadsen (license 10)
Tested by: lmadsen, jsmith, mmichelson

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@250609 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
lmadsen 2010-03-03 21:22:55 +00:00
parent 869624a523
commit bc7135b833
1 changed files with 473 additions and 69 deletions

View File

@ -1,84 +1,488 @@
\subsection{Introduction}
chan\_local is a pseudo-channel. Use of this channel simply loops calls back
into the dialplan in a different context. Useful for recursive routing.
In Asterisk, Local channels are a method used to treat an extension in the
dialplan as if it were an external device. In essense, Asterisk will send the
call back into the dialplan as the destination of the call, versus sending the
call to a device.
\subsection{Syntax}
\begin{verbatim}
Local/extension@context[/{n|j}]
\end{verbatim}
Adding "/n" at the end of the string will make the Local channel not do a
native transfer (the "n" stands for "n"o release) upon the remote end answering
the line. This is an esoteric, but important feature if you expect the Local
channel to handle calls exactly like a normal channel. If you do not have the
"no release" feature set, then as soon as the destination (inside of the Local
channel) answers the line and one audio frame passes, the variables and dial plan
will revert back to that of the original call, and the Local channel will become a
zombie and be removed from the active channels list. This is desirable in some
circumstances, but can result in unexpected dialplan behavior if you are doing
fancy things with variables in your call handling.
There is another option that can be used with local channels, which is the "j"
option. The "j" option must be used with the "n" option to make sure that the
local channel does not get optimized out of the call. This option will enable
a jitterbuffer on the local channel. The jitterbuffer will be used to de-jitter
audio that it receives from the channel that called the local channel. This is
especially in the case of putting chan\_local in between an incoming SIP call
and Asterisk applications, so that the incoming audio will be de-jittered.
Using the "m" option will cause chan\_local to forward music on hold start and stop
requests. Normally chan\_local acts on them and it is started or stopped on the
Local channel itself.
\subsection{Purpose}
The Local channel construct can be used to establish dialing into any part of
the dialplan.
Imagine you have a TE410P in your box. You want to do something for which you
must use a Dial statement (for instance when dropping files in
\path{/var/spool/outgoing}) but you do want to be able to use your dialplans
least-cost-routes or other intelligent stuff. What you could do before we had
chan\_local was create a cross-link between two ports of the TE410P and then
Dial out one port and in the other. This way you could control where the call
was going.
Of course, this was a nasty hack, and to make it more sensible, chan\_local was
built.
The "Local" channel driver allows you to convert an arbitrary extension into a
channel. It is used in a variety of places, including agents, etc.
This also allows us to hop to contexts like a GoSub routine; See examples below.
Two of the most common areas where Local channels are used include members
configured for queues, and in use with callfiles. There are also other uses
where you want to ring two destinations, but with different information, such as
different callerID for each outgoing request.
\subsection{Examples}
Local channels are best demonstrated through the use of an example. Our first
example isn't terribly useful, but will demonstrate how Local channels can
execute dialplan logic by dialing from the Dial() application.
\subsection{Trivial Local channel example}
In our dialplan (extensions.conf), we can Dial() another part of the dialplan
through the use Local channels. To do this, we can use the following dialplan:
\begin{astlisting}
\begin{verbatim}
[inbound] ; here falls all incoming calls
exten => s,1,Answer
exten => s,2,Dial(local/200@internal,30,r)
exten => s,3,Playback(sorrynoanswer)
exten => s,4,Hangup
[devices]
exten => 201,1,Verbose(2,Dial another part of the dialplan via the Local chan)
exten => 201,n,Verbose(2,Outside channel: ${CHANNEL})
exten => 201,n,Dial(Local/201@extensions)
exten => 201,n,Hangup()
[internal] ; here where our phones falls for default
exten => 200,1,Dial(sip/blah)
exten => 200,102,VoiceMail(${EXTEN}@default)
exten => 201,1,Dial(DAHDI/1)
exten => 201,102,VoiceMail(${EXTEN}@default)
exten => _0.,1,Dial(DAHDI/g1/${EXTEN:1}) ; outgoing calls with 0+number
[extensions]
exten => 201,1,Verbose(2,Made it to the Local channel)
exten => 201,n,Verbose(2,Inside channel: ${CHANNEL})
exten => 201,n,Dial(SIP/some-named-extension,30)
exten => 201,n,Hangup()
\end{verbatim}
\end{astlisting}
\subsection{Caveats}
The output of the dialplan would look something like the following. The output
has been broken up with some commentary to explain what we're looking at.
If you use chan\_local from a call-file and you want to pass channel variables
into your context, make sure you append the '/n', because otherwise
chan\_local will 'optimize' itself out of the call-path, and the variables will
get lost. i.e.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:1] Verbose("SIP/my_desk_phone-00000014", "2,Dial another part of the dialplan via the
Local chan") in new stack
== Dial another part of the dialplan via the Local chan
\end{verbatim}
\end{astlisting}
We dial extension 201 from SIP/my\_desk\_phone which has entered the [devices]
context. The first line simply outputs some information via the Verbose()
application.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:2] Verbose("SIP/my_desk_phone-00000014",
"2,Outside channel: SIP/my_desk_phone-00000014") in new stack
== Outside channel: SIP/my_desk_phone-00000014
\end{verbatim}
\end{astlisting}
The next line is another Verbose() application statement that tells us our
current channel name. We can see that the channel executing the current dialplan
is a desk phone (aptly named 'my\_desk\_phone').
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:3] Dial("SIP/my_desk_phone-00000014", "Local/201@extensions") in new stack
-- Called 201@extensions
\end{verbatim}
\end{astlisting}
Now the third step in our dialplan executes the Dial() application which calls
extension 201 in the [extensions] context of our dialplan. There is no
requirement that we use the same extension number -- we could have just as
easily used a named extension, or some other number. Remember that we're dialing
another channel, but instead of dialing a device, we're "dialing" another part
of the dialplan.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@extensions:1] Verbose("Local/201@extensions-7cf4;2", "2,Made it to the Local
channel") in new stack
== Made it to the Local channel
\end{verbatim}
\end{astlisting}
Now we've verified we've dialed another part of the dialplan. We can see the
channel executing the dialplan has changed to Local/201@extensions-7cf4;2. The
part '-7cf4;2' is just the unique identifier, and will be different for you.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@extensions:2] Verbose("Local/201@extensions-7cf4;2", "2,Inside channel:
Local/201@extensions-7cf4;2") in new stack
== Inside channel: Local/201@extensions-7cf4;2
\end{verbatim}
\end{astlisting}
Here we use the Verbose() application to see what our current channel name is.
As you can see the current channel is a Local channel which we created from our
SIP channel.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@extensions:3] Dial("Local/201@extensions-7cf4;2", "SIP/some-named-extension,30") in new stack
\end{verbatim}
\end{astlisting}
And from here, we're using another Dial() application to call a SIP device
configured in sip.conf as [some-named-extension].
Now that we understand a simple example of calling the Local channel, let's
expand upon this example by using Local channels to call two devices at the same
time, but delay calling one of the devices.
\subsection{Delay dialing devices}
Lets say when someone calls extension 201, we want to ring both the desk phone
and their cellphone at the same time, but we want to wait about 6 seconds to
start dialing the cellphone. This is useful in a situation when someone might be
sitting at their desk, but don't want both devices ringing at the same time, but
also doesn't want to wait for the full ring cycle to execute on their desk phone
before rolling over to their cellphone.
The dialplan for this would look something like the following:
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,Verbose(2,Call desk phone and cellphone but with delay)
exten => 201,n,Dial(Local/deskphone-201@extensions&Local/cellphone-201@extensions,30)
exten => 201,n,Voicemail(201@default,${IF($[${DIALSTATUS} = BUSY]?b:u)})
exten => 201,n,Hangup()
[extensions]
; Dial the desk phone
exten => deskphone-201,1,Verbose(2,Dialing desk phone of extension 201)
exten => deskphone-201,n,Dial(SIP/0004f2040001) ; SIP device with MAC address
; of 0004f2040001
; Dial the cellphone
exten => cellphone-201,1,Verbose(2,Dialing cellphone of extension 201)
exten => cellphone-201,n,Verbose(2,-- Waiting 6 seconds before dialing)
exten => cellphone-201,n,Wait(6)
exten => cellphone-201,n,Dial(DAHDI/g0/14165551212)
\end{verbatim}
\end{astlisting}
When someone dials extension 201 in the [devices] context, it will execute the
Dial() application, and call two Local channels at the same time:
\begin{itemize}
\item Local/deskphone-201@extensions
\item Local/cellphone-201@extensions
\end{itemize}
It will then ring both of those extensions for 30 seconds before rolling over to
the Voicemail() application and playing the appropriate voicemail recording
depending on whether the \$\{DIALSTATUS\} variable returned BUSY or not.
When reaching the deskphone-201 extension, we execute the Dial() application
which calls the SIP device configured as '0004f204001' (the MAC address of the
device). When reaching the cellphone-201 extension, we dial the cellphone via
the DAHDI channel using group zero (g0) and dialing phone number 1-416-555-1212.
\subsection{Dialing destinations with different information}
With Asterisk, we can place a call to multiple destinations by separating the
technology/destination pair with an ampersand (\&). For example, the following
Dial() line would ring two separate destinations for 30 seconds:
\begin{astlisting}
\begin{verbatim}
exten => 201,1,Dial(SIP/0004f2040001&DAHDI/g0/14165551212,30)
\end{verbatim}
\end{astlisting}
That line would dial both the SIP/0004f2040001 device (likely a SIP device on
the network) and dial the phone number 1-416-555-1212 via a DAHDI interface. In
our example though, we would be sending the same callerID information to both
end points, but perhaps we want to send a different callerID to one of the
destinations?
We can send different callerIDs to each of the destinations if we want by using
the Local channel. The following example shows how this is possible because we
would Dial() two different Local channels from our top level Dial(), and that
would then execute some dialplan before sending the call off to the final
destinations.
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,NoOp()
exten => 201,n,Dial(Local/201@internal&Local/201@external,30)
exten => 201,n,Voicemail(201@default,${IF($[${DIALSTATUS} = BUSY]?b:u)})
exten => 201,n,Hangup()
[internal]
exten => 201,1,Verbose(2,Placing internal call for extension 201)
exten => 201,n,Set(CALLERID(name)=From Sales)
exten => 201,n,Dial(SIP/0004f2040001,30)
[external]
exten => 201,1,Verbose(2,Placing external call for extension 201)
exten => 201,n,Set(CALLERID(name)=Acme Cleaning)
exten => 201,n,Dial(DAHDI/g0/14165551212)
\end{verbatim}
\end{astlisting}
With the dialplan above, we've sent two different callerIDs to the destinations:
\begin{itemize}
\item "From Sales" was sent to the local device SIP/0004f2040001
\item "Acme Cleaning" was sent to the remote number 1-416-555-1212 via DAHDI
\end{itemize}
Because each of the channels is independent from the other, you could perform
any other call manipulation you need. Perhaps the 1-416-555-1212 number is a
cell phone and you know you can only ring that device for 18 seconds before the
voicemail would pick up. You could then limit the length of time the external
number is dialed, but still allow the internal device to be dialed for a longer
period of time.
\subsection{Using callfiles and Local channels}
Another example is to use callfiles and Local channels so that you can execute
some dialplan prior to performing a Dial(). We'll construct a callfile which
will then utilize a Local channel to lookup a bit of information in the AstDB
and then place a call via the channel configured in the AstDB.
First, lets construct our callfile that will use the Local channel to do some
lookups prior to placing our call. More information on constructing callfiles is
located in the doc/callfiles.txt file of your Asterisk source.
Our callfile will simply look like the following:
\begin{verbatim}
Local/00531234567@pbx becomes Local/00531234567@pbx/n
Channel: Local/201@devices
Application: Playback
Data: silence/1&tt-weasels
\end{verbatim}
Add the callfile information to a file such as 'callfile.new' or some other
appropriately named file.
Our dialplan will perform a lookup in the AstDB to determine which device to
call, and will then call the device, and upon answer, Playback() the silence/1
(1 second of silence) and the tt-weasels sound files.
Before looking at our dialplan, lets put some data into AstDB that we can then
lookup from the dialplan. From the Asterisk CLI, run the following command:
\begin{verbatim}
*CLI> database put phones 201/device SIP/0004f2040001
\end{verbatim}
We've now put the device destination (SIP/0004f2040001) into the 201/device key
within the phones family. This will allow us to lookup the device location for
extension 201 from the database.
We can then verify our entry in the database using the 'database show' CLI
command:
\begin{verbatim}
*CLI> database show
/phones/201/device : SIP/0004f2040001
\end{verbatim}
Now lets create the dialplan that will allow us to call SIP/0004f2040001 when we
request extension 201 from the [extensions] context via our Local channel.
\begin{astlisting}
\begin{verbatim}
[devices]
exten => 201,1,NoOp()
exten => 201,n,Set(DEVICE=${DB(phones/${EXTEN}/device)})
exten => 201,n,GotoIf($[${ISNULL(${DEVICE})}]?hangup) ; if nothing returned,
; then hangup
exten => 201,n,Dial(${DEVICE},30)
exten => 201,n(hangup(),Hangup()
\end{verbatim}
\end{astlisting}
Then, we can perform a call to our device using the callfile by moving it into
the /var/spool/asterisk/outgoing/ directory.
\begin{verbatim}
# mv callfile.new /var/spool/asterisks/outgoing
\end{verbatim}
Then after a moment, you should see output on your console similar to the
following, and your device ringing. Information about what is going on during
the output has also been added throughout.
\begin{astlisting}
\begin{verbatim}
-- Attempting call on Local/201@devices for application Playback(silence/1&tt-weasels) (Retry 1)
\end{verbatim}
\end{astlisting}
You'll see the line above as soon as Asterisk gets the request from the
callfile.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:1] NoOp("Local/201@devices-ecf0;2", "") in new stack
-- Executing [201@devices:2] Set("Local/201@devices-ecf0;2", "DEVICE=SIP/0004f2040001") in new stack
\end{verbatim}
\end{astlisting}
This is where we performed our lookup in the AstDB. The value of
SIP/0004f2040001 was then returned and saved to the DEVICE channel variable.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:3] GotoIf("Local/201@devices-ecf0;2", "0?hangup") in new stack
\end{verbatim}
\end{astlisting}
We perform a check to make sure \$\{DEVICE\} isn't NULL. If it is, we'll just
hangup here.
\begin{astlisting}
\begin{verbatim}
-- Executing [201@devices:4] Dial("Local/201@devices-ecf0;2", "SIP/0004f2040001,30") in new stack
-- Called 000f2040001
-- SIP/0004f2040001-00000022 is ringing
\end{verbatim}
\end{astlisting}
Now we call our device SIP/0004f2040001 from the Local channel.
\begin{verbatim}
-- SIP/0004f2040001-00000022 answered Local/201@devices-ecf0;2
\end{verbatim}
We answer the call.
\begin{astlisting}
\begin{verbatim}
> Channel Local/201@devices-ecf0;1 was answered.
> Launching Playback(silence/1&tt-weasels) on Local/201@devices-ecf0;1
\end{verbatim}
\end{astlisting}
We then start playing back the files.
\begin{astlisting}
\begin{verbatim}
-- <Local/201@devices-ecf0;1> Playing 'silence/1.slin' (language 'en')
== Spawn extension (devices, 201, 4) exited non-zero on 'Local/201@devices-ecf0;2'
\end{verbatim}
\end{astlisting}
At this point we now see the Local channel has been optimized out of the call
path. This is important as we'll see in examples later. By default, the Local
channel will try to optimize itself out of the call path as soon as it can. Now
that the call has been established and audio is flowing, it gets out of the way.
\begin{astlisting}
\begin{verbatim}
-- <SIP/0004f2040001-00000022> Playing 'tt-weasels.ulaw' (language 'en')
[Mar 1 13:35:23] NOTICE[16814]: pbx_spool.c:349 attempt_thread: Call completed to Local/201@devices
\end{verbatim}
\end{astlisting}
We can now see the tt-weasels file is played directly to the destination
(instead of through the Local channel which was optimized out of the call path)
and then a NOTICE stating the call was completed.
\subsection{Understanding When To Use /n}
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.
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 definition, we can keep the
Local channel in the call path, along with any channel variables, or other
channel specific information.
For example, if we were calling a Local channel from the Dial() application, we
could change:
\begin{verbatim}
Dial(Local/201@devices)
\end{verbatim}
...into the following line:
\begin{verbatim}
Dial(Local/201@devices/n)
\end{verbatim}
By adding /n to the end, our Local channel will now stay in the call path and
not go away.
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 then performs another
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.
Here is an overview of our call flow, and the information associated with the
channels:
\begin{enumerate}
\item SIP device PHONE\_A calls Asterisk via a SIP INVITE
\item Asterisk accepts the INVITE and then starts processing dialplan logic
\item Our dialplan calls Dial(Local/2@services) -- notice no /n
\item The Local channel then executes dialplan at extension 2 within the services context
\item Extension 2 within [services] then performs another Dial() to a SIP channel with the line: Dial(SIP/PHONE\_B,,L(60000:450000:15000))
\item The call is then placed to SIP/PHONE\_B which then answers the call.
\item The Local channel 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.
\item SIP/PHONE\_A and SIP/PHONE\_B then continue talking indefinitely.
\end{enumerate}
Now, if we were to modify 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:
\begin{enumerate}
\item Use 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.
\item Place the L() option outside of the Local channel so that when it is
optimized out of the call path, the information required to make L() work is
associated with the outside channel. For example:
\begin{verbatim}
Dial(Local/2@services,,L(60000:45000:15000))
\end{verbatim}
\end{enumerate}
\subsection{Local channel modifiers}
There are additional modifiers for the Local channel as well. They include:
\begin{itemize}
\item 'n' -- Adding "/n" at the end of the string will make the Local channel not
do a native transfer (the "n" stands for "n"o release) upon the remote
end answering the line. This is an esoteric, but important feature if
you expect the Local channel to handle calls exactly like a normal
channel. If you do not have the "no release" feature set, then as soon
as the destination (inside of the Local channel) answers the line and
one audio frame passes, the variables and dial plan will revert back
to that of the original call, and the Local channel will become a
zombie and be removed from the active channels list. This is desirable
in some circumstances, but can result in unexpected dialplan behavior
if you are doing fancy things with variables in your call handling.
\item 'j' -- Adding "/j" at the end of the string allows you to use the generic
jitterbuffer on incoming calls going to Asterisk applications. For
example, this would allow you to use a jitterbuffer for an incoming
SIP call to Voicemail by putting a Local channel in the middle. The
'j' option must be used in conjunction with the 'n' option to make
sure that the Local channel does not get optimized out of the call.
This option is available starting in the Asterisk 1.6.0 branch.
\item 'm' -- Using the "/m" option will cause the Local channel to forward music on
hold (MoH) start and stop requests. Normally the Local channel acts on
them and it is started or stopped on the Local channel itself. This
options allows those requests to be forwarded through the Local
channel.
This option is available starting in the Asterisk 1.4 branch.
\item 'b' -- The "/b" option causes the Local channel to return the actual channel
that is behind it when queried. This is useful for transfer scenarios
as the actual channel will be transferred, not the Local channel.
This option is available starting in the Asterisk 1.6.0 branch.
\end{itemize}