Struggling to make sense of sending DTMF and why DIAL is trying to make multiple calls?


#1

Hi there; I’m trying to dial into a Zoom conference, send some digits,
wait, send a name, and be “in the room”, as it were.

I thought this would work:

same => n,Dial(PJSIP/02036950088@voipfone-205,12,r(callWaiting)D(WWW12345W#WW::))

But it didn’t, so I tried all of these:

same => n,Dial(PJSIP/02036950088@voipfone-205,12,r(callWaiting)D(:WWW12345W#WW:))
same => n,Dial(PJSIP/02036950088@voipfone-205,12,r(callWaiting)D(::WWW12345W#WW))
same => n,Dial(PJSIP/02036950088@voipfone-205,12,r(callWaiting)D(WWW12345W#WW:WWW12345W#WW:WWW12345W#WW))

Still nothing. So I thought send_DTMF might work.

Of course, this is too simple, and doesn’t work:

[dial-zoom-bcab]
exten => s,1,Verbose(1,Dialling BCAB Zoom)
    same => n,Dial(PJSIP/02036950088@voipfone-205,,U(dial-zoom-bcab^called_channel^1)))
    same => n,Wait(3)
    same => n,SendDTMF(1234#WWW#WW)
    same => n,Playback(technical-support)
    same => n,SendDTMF(#)
    ;same => n,Wait(15)
    same => n,Hangup()

So I found an example of how to dial, and then send DTMF at
https://wiki.asterisk.org/wiki/display/AST/Asterisk+15+Application_Dial

[dial-zoom-bcab]
exten => s,1,Verbose(1,Dialling BCAB Zoom)
    same => n,Dial(PJSIP/02036950088@voipfone-205,,U(dial-zoom-bcab^called_channel^1)))
    same => n,Playback(abandon-all-hope)
    same => n,Hangup()

exten => called_channel,1,Answer()
    same => n,Wait(3)
    same => n,SendDTMF(1234#WWW#WWW)
    same => n,Playback(technical-support)
    same => n,SendDTMF(#)
    ;same => n,Wait(8)
    same => n,Return()

Not only did that not work, but I rapidly got an email alerting me to
having run out of ITSP credit (fortunately I only keep £2 or so and
the calls are only 1.2p each).

What I hadn’t noticed on the log was that asterisk was making multiple
simultaneous calls, and even after I had hung up!

Here’s my ITSP log for the latest batch. The only way to stop the
calls was to restart Asterisk. I’m confused (and concerned) as hell as
to how this happened with that example code above?

Time, ext, number, duration.
12:25 205 02036950088 0:14 0.0120 0
12:25 205 02036950088 0:16 0.0120 0
12:25 205 02036950088 0:18 0.0120 0
12:25 205 02036950088 0:20 0.0120 0
12:25 205 02036950088 0:21 0.0120 0
12:25 205 02036950088 0:23 0.0120 0
12:25 205 02036950088 0:25 0.0120 0
12:25 205 02036950088 0:27 0.0120 0
12:25 205 02036950088 0:29 0.0120 0
12:25 205 02036950088 0:31 0.0120 0
12:25 205 02036950088 0:33 0.0120 0
12:25 205 02036950088 0:35 0.0120 0
12:24 205 02036950088 0:37 0.0120 0
12:24 205 02036950088 0:39 0.0120 0
12:24 205 02036950088 0:40 0.0120 0
12:24 205 02036950088 0:42 0.0120 0
12:24 205 02036950088 0:44 0.0120 0
12:24 205 02036950088 0:46 0.0120 0
12:24 205 02036950088 0:48 0.0120 0

Is order of channels shown by Function_CHANNELS consistently newest first?
#2

There is nothing there that would cause Asterisk to make more outgoing calls than incoming ones.

You need to provide Asterisk verbose logs (at least verbosity 5), and details of your PJSIP configuration, particularly the option relating to DTMF handling, and codecs.


#3

Hi @david551

Revisiting this with Asterisk 16 a few months later - I spend a whole night on this, trying to figure this out.

Still doing it - it seems to make as many calls as outbound channels allow, at the same time.

I. Simply. Don’t. Understand.

I just want it to dial, send some tones. But from looking through the logs, it just looks like the gosubroutine is returning to the dial string of the extension s,1. But then, it doesn’t look like called_channel is actually doing anything.

This is what it looks like on my ITSP control panel - 6 parallel calls; all I hear is silence when I answer the first one (the others are handled by voicemail which cuts off after 6 mins).

Time Ext Dialled Duration cost ?
13:16 201 01XXXXXXXXX 0:08 0.0120 0
13:16 201 01XXXXXXXXX 5:58 0.0716 0
13:16 201 01XXXXXXXXX 5:59 0.0718 0
13:16 201 01XXXXXXXXX 5:59 0.0718 0
13:16 201 01XXXXXXXXX 5:59 0.0718 0
13:16 201 01XXXXXXXXX 0:13 0.0120 0

Reminder of dialplan from the example at https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Dial

[dial-zoom-bcab]
exten => s,1,Verbose(1,Dialling BCAB Zoom)

   ; line below causes as many outgoing parallel calls as my ITSP can handle (gets expensive!)
    same => n,Dial(PJSIP/01XXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1)))
    same => n,Playback(technical-support)
    same => n,SendDTMF(#)
    same => n,Wait(5) 
    same => n,Hangup()  
 
exten => called_channel,1,NoOp()
    same => n,Wait(1)
    same => n,SendDTMF(WW12345#WWWWW#WWWWW)
    same => n,Playback(technical-support)
    same => n,SendDTMF(#)
    same => n,Return()  


#4

The log:

 -- Executing [s@dial-zoom-bcab:1] Verbose("PJSIP/voipfone-201-0000001e", "1,Dialling BCAB Zoom") in new stack
 Dialling BCAB Zoom
    -- Executing [s@dial-zoom-bcab:2] Dial("PJSIP/voipfone-201-0000001e", "PJSIP/01XXXXXXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1))") in new stack
    -- Called PJSIP/01XXXXXXXXX@voipfone-201
       > 0x7f4a740efd30 -- Strict RTP learning after remote address set to: 46.31.231.XXX:22522
    -- PJSIP/voipfone-201-0000001f is making progress passing it to PJSIP/voipfone-201-0000001e
    -- PJSIP/voipfone-201-0000001f is making progress passing it to PJSIP/voipfone-201-0000001e
       > 0x7f4a740efd30 -- Strict RTP switching to RTP target address 46.31.231.XXX:22522 as source
    -- PJSIP/voipfone-201-0000001f answered PJSIP/voipfone-201-0000001e
    -- PJSIP/voipfone-201-0000001f Internal Gosub(dial-zoom-bcab,s,1(called_channel,1)) start
    -- Executing [s@dial-zoom-bcab:1] Verbose("PJSIP/voipfone-201-0000001f", "1,Dialling BCAB Zoom") in new stack
 Dialling BCAB Zoom
    -- Executing [s@dial-zoom-bcab:2] Dial("PJSIP/voipfone-201-0000001f", "PJSIP/01XXXXXXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1))") in new stack
    -- Called PJSIP/01XXXXXXXXX@voipfone-201
       > 0x7f4a74078ec0 -- Strict RTP learning after remote address set to: 46.31.231.XXX:47332
    -- PJSIP/voipfone-201-00000020 is making progress passing it to PJSIP/voipfone-201-0000001f
    -- PJSIP/voipfone-201-00000020 is making progress passing it to PJSIP/voipfone-201-0000001f
       > 0x7f4a74078ec0 -- Strict RTP switching to RTP target address 46.31.231.XXX:47332 as source
    -- PJSIP/voipfone-201-00000020 answered PJSIP/voipfone-201-0000001f
    -- PJSIP/voipfone-201-00000020 Internal Gosub(dial-zoom-bcab,s,1(called_channel,1)) start
    -- Executing [s@dial-zoom-bcab:1] Verbose("PJSIP/voipfone-201-00000020", "1,Dialling BCAB Zoom") in new stack
 Dialling BCAB Zoom
    -- Executing [s@dial-zoom-bcab:2] Dial("PJSIP/voipfone-201-00000020", "PJSIP/01XXXXXXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1))") in new stack
    -- Called PJSIP/01XXXXXXXXX@voipfone-201
       > 0x7f4a74055860 -- Strict RTP learning complete - Locking on source address 46.31.231.XXX:48418
       > 0x7f4a74089950 -- Strict RTP learning after remote address set to: 46.31.231.XXX:48518
    -- PJSIP/voipfone-201-00000021 is making progress passing it to PJSIP/voipfone-201-00000020
    -- PJSIP/voipfone-201-00000021 is making progress passing it to PJSIP/voipfone-201-00000020
       > 0x7f4a74089950 -- Strict RTP switching to RTP target address 46.31.231.XXX:48518 as source
    -- PJSIP/voipfone-201-00000021 answered PJSIP/voipfone-201-00000020
    -- PJSIP/voipfone-201-00000021 Internal Gosub(dial-zoom-bcab,s,1(called_channel,1)) start
    -- Executing [s@dial-zoom-bcab:1] Verbose("PJSIP/voipfone-201-00000021", "1,Dialling BCAB Zoom") in new stack
 Dialling BCAB Zoom
    -- Executing [s@dial-zoom-bcab:2] Dial("PJSIP/voipfone-201-00000021", "PJSIP/01XXXXXXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1))") in new stack
    -- Called PJSIP/01XXXXXXXXX@voipfone-201
       > 0x7f4a740efd30 -- Strict RTP learning complete - Locking on source address 46.31.231.XXX:22522
       > 0x7f4a74146ee0 -- Strict RTP learning after remote address set to: 46.31.231.XXX:41114
    -- PJSIP/voipfone-201-00000022 is making progress passing it to PJSIP/voipfone-201-00000021
    -- PJSIP/voipfone-201-00000022 is making progress passing it to PJSIP/voipfone-201-00000021
       > 0x7f4a74146ee0 -- Strict RTP switching to RTP target address 46.31.231.XXX:41114 as source
    -- PJSIP/voipfone-201-00000022 answered PJSIP/voipfone-201-00000021
    -- PJSIP/voipfone-201-00000022 Internal Gosub(dial-zoom-bcab,s,1(called_channel,1)) start
    -- Executing [s@dial-zoom-bcab:1] Verbose("PJSIP/voipfone-201-00000022", "1,Dialling BCAB Zoom") in new stack
 Dialling BCAB Zoom
    -- Executing [s@dial-zoom-bcab:2] Dial("PJSIP/voipfone-201-00000022", "PJSIP/01XXXXXXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1))") in new stack
    -- Called PJSIP/01XXXXXXXXX@voipfone-201
       > 0x7f4a74078ec0 -- Strict RTP learning complete - Locking on source address 46.31.231.XXX:47332
  == Everyone is busy/congested at this time (1:1/0/0)
    -- Executing [s@dial-zoom-bcab:3] Playback("PJSIP/voipfone-201-00000022", "technical-support") in new stack
    -- <PJSIP/voipfone-201-00000022> Playing 'technical-support.alaw' (language 'en_GB')
       > 0x7f4a74089950 -- Strict RTP learning complete - Locking on source address 46.31.231.XXX:48518
    -- Executing [s@dial-zoom-bcab:4] SendDTMF("PJSIP/voipfone-201-00000022", "#") in new stack
    -- Executing [s@dial-zoom-bcab:5] Wait("PJSIP/voipfone-201-00000022", "5") in new stack
       > 0x7f4a74146ee0 -- Strict RTP learning complete - Locking on source address 46.31.231.XXX:41114
    -- Executing [s@dial-zoom-bcab:6] Hangup("PJSIP/voipfone-201-00000022", "") in new stack
  == Spawn extension (dial-zoom-bcab, s, 6) exited non-zero on 'PJSIP/voipfone-201-00000022'
[Oct 18 13:16:25] NOTICE[4712][C-0000000e]: app_stack.c:1080 gosub_run: PJSIP/voipfone-201-00000022 Abnormal 'Gosub(dial-zoom-bcab,s,1(called_channel,1))' exit.  Popping routine return locations.
    -- Channel PJSIP/voipfone-201-00000022 joined 'simple_bridge' basic-bridge <c00a5718-2fb5-460d-861a-7a1ae27c49ca>
    -- Channel PJSIP/voipfone-201-00000021 joined 'simple_bridge' basic-bridge <c00a5718-2fb5-460d-861a-7a1ae27c49ca>
       > Bridge c00a5718-2fb5-460d-861a-7a1ae27c49ca: switching from simple_bridge technology to native_rtp
       > Remotely bridged 'PJSIP/voipfone-201-00000021' and 'PJSIP/voipfone-201-00000022' - media will flow directly between them
    -- Channel PJSIP/voipfone-201-00000022 left 'native_rtp' basic-bridge <c00a5718-2fb5-460d-861a-7a1ae27c49ca>
    -- Channel PJSIP/voipfone-201-00000021 left 'native_rtp' basic-bridge <c00a5718-2fb5-460d-861a-7a1ae27c49ca>
  == Spawn extension (dial-zoom-bcab, s, 2) exited non-zero on 'PJSIP/voipfone-201-00000021'
[Oct 18 13:16:25] NOTICE[4712][C-0000000e]: app_stack.c:1080 gosub_run: PJSIP/voipfone-201-00000021 Abnormal 'Gosub(dial-zoom-bcab,s,1(called_channel,1))' exit.  Popping routine return locations.
    -- Channel PJSIP/voipfone-201-00000021 joined 'simple_bridge' basic-bridge <b398cbf6-85c1-4ab1-9ee9-f95bf8a1843d>
    -- Channel PJSIP/voipfone-201-00000020 joined 'simple_bridge' basic-bridge <b398cbf6-85c1-4ab1-9ee9-f95bf8a1843d>
       > Bridge b398cbf6-85c1-4ab1-9ee9-f95bf8a1843d: switching from simple_bridge technology to native_rtp
> Remotely bridged 'PJSIP/voipfone-201-00000020' and 'PJSIP/voipfone-201-00000021' - media will flow directly between them

shows multiple incoming calls (note the suffix to the incoming channel name is different for each one, and I think, if you had take this from the log file, there would have been different thread IDs for each one).

Have you possibly got a broken SIP proxy between the device and Asterisk, which is turning re-invites into new calls? You need to provide the actual SIP logs for all the INVITE transactions.


#5
[dial-zoom-bcab]
exten => s,1,Verbose(1,Dialling BCAB Zoom)
    same => n,Dial(PJSIP/02036950088@voipfone-205,,U(dial-zoom-bcab^called_channel^1)))

I see the problem. It is your use of Dial’s ‘U’ option. You are passing incorrect parameters to it. The ‘U’ option predates the more complete format expected by the ‘B’ and ‘b’ options. The ‘U’ option expects parameters the way macros did. See the extracted online Dial ‘U’ option documentation below. The x argument value is the context name and that is all you can specify on where the subroutine exists in dialplan. Everything else are parameters to the subroutine.

    U(x[^arg[^...]]): 
        x - Name of the subroutine to execute via 'Gosub'

        arg - Arguments for the 'Gosub' routine
Execute via 'Gosub' the routine <x> for the *called* channel before connecting
to the calling channel. Arguments can be specified to the 'Gosub' using '^' as
a delimiter. The 'Gosub' routine can set the variable ${GOSUB_RESULT} to
specify the following actions after the 'Gosub' returns.
        ${GOSUB_RESULT}: 
            ABORT: Hangup both legs of the call.
            CONGESTION: Behave as if line congestion was encountered.
            BUSY: Behave as if a busy signal was encountered.
            CONTINUE: Hangup the called party and allow the calling party to
            continue dialplan execution at the next priority.
            GOTO:[[<context>^]<exten>^]<priority>: Transfer the call to the
            specified destination.
    NOTE: You cannot use any additional action post answer options in
    conjunction with this option. Also, pbx services are run on the peer
    (called) channel, so you will not be able to set timeouts via the
    'TIMEOUT()' function in this routine.

What is happening in your dialplan is this:

  1. You start executing your dial routine
  2. When the call is answered, Dial executes the ‘U’ subroutine at context dial-zoom-bcab, exten s, priority 1. Since this is the same location as your dialing routine it dials again in a loop.

#6

Hi @rmudgett - I really appreciate your speedy response, but I feel I’m being terribly thick here.

I’m looking at the latest official documentation for the version of Asterisk I am using, at https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Dial

Here is the example given

[default]
 
exten => called_channel,1,NoOp()
 same => n,Playback(hello)
 same => n,Return()
 
exten => _X.,1,NoOp()
 same => n,Dial(PJSIP/alice,,U(default^called_channel^1))
 same => n,Hangup()

and here’s what I’ve got (with extraneous stuff removed). I don’t see where my “incorrect” parameters differ from the official docs example?

[dial-zoom-bcab]

exten => called_channel,1,NoOp()
    same => n,SendDTMF(WW12345#WWWWW#WWWWW)
    same => n,Playback(technical-support)
    same => n,Return()  

exten => s,1,Verbose(1,Dialling BCAB Zoom)
    same => n,Dial(PJSIP/01XXXXX@voipfone-201,,U(dial-zoom-bcab^called_channel^1)))
    same => n,Hangup()  

I’ve had a cup of tea, rubbed my eyes, had a walk round, had another looked, banged my head against the table a few times , emailed it to someone for a second look, then had another look myself.
All we spotted was that I put an extra closing bracket, but removing it changed nothing.

But what I notice was that you talked about the “extracted online Dial ‘U’ option documentation below”.

But that line doesn’t exist anywhere in the docs, not using the inbuilt search, nor using Google to search the site. So now I’m even more confused than when I started struggling with this on Aug 3rd.

I know it’s going to be one of those “duh” moments, I’m missing something so obvious, but I (and my second pair of eyes) just don’t see where. Thanks


#7

Ah. That example in the documentation is incorrect. The documentation of the ‘U’ option itself describes the actual syntax expected. This is what the example should be to be clear about the described syntax with the ‘U’ option:

[my_gosub_routine]
exten = s,1,NoOp(ARG1=${ARG1} ARG2=${ARG2})
same = n,Playback(hello)
same = n,Return

[default]
exten = _X.,1,NoOp()
same = n,Dial(PJSIP/alice,,U(my_gosub_routine^my_gosub_arg1^my_gosub_arg2))
same = n,Hangup()

The online documentation I extracted was from the CLI ‘core show application dial’. The information is also available on the wiki (https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Dial) as both locations get the contents from the XML documentation comment in the source file. The main difference being the one from the CLI is always going to be specific to the Asterisk version you are using. The wiki version may not match with your Asterisk version because of differing features.


#8

Oh no, so you mean all this time since August, I’ve been correctly following incorrect docs?
OK, there’s a few nights and grey hairs that can be put down to “these things happen”, and I’ve added a warning to the foot of the page in comments.

I appreciate your clarification. I’m still confused about one thing though - you say that

The online documentation I extracted was from the CLI ‘core show application dial’. The information is also available on the wiki (https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Dial) as both locations get the contents from the XML documentation comment in the source file.

But that is exactly where I was getting that information from, but it appears to differ on that page greatly.

So when you say

The wiki version may not match with your Asterisk version because of differing features.

are you saying that I should not rely on

https://wiki.asterisk.org/wiki/display/AST/Asterisk+15+Application_Something
https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Something

to be correct documentation for Application_Something for versions 15 and 16 respectively?
In which case, should the pages not come with a big H1 size warning at the top to say “this documentation may not be current or correct, use the CLI instead”?


#9

I was looking at the part of the documentation describing the ‘U’ option itself. The expected syntax for the option is indicated there. You were apparently only looking at the dialplan example. The CLI documentation and the wiki get their content from the same place but format the same information differently.

That is not what I was saying.

The wiki documentation is supposed to track the latest documentation in the source code at the tip of the corresponding branch (when the auto-update bots are working :slight_smile: ). This is why at the bottom of those automatically generated pages you see: This documentation was imported from Asterisk Version GIT-16-b8bf57dc38

The command line documentation is the documentation extracted from the source code when the Asterisk version was released. The command line documentation is fixed to your specific version of Asterisk as it is stored on your machine.

The wiki and command line documentation can differ because of when the content is extracted from the source code. The reason for differences are many such as new features were added, errors corrected, improved or expanded wording, etc.


#10

I wonder if you’re seeing a different version of that page at https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Dial as an admin?

As a public user, I see this:

U( x^arg ) - Execute via Gosub the routine x for the called channel before connecting to the calling channel. Arguments can be specified to the Gosub using ^ as a delimiter. The Gosub routine can set the variable GOSUB_RESULT to specify the following actions after the Gosub returns.
GOSUB_RESULT
ABORT - Hangup both legs of the call.
CONGESTION - Behave as if line congestion was encountered.
BUSY - Behave as if a busy signal was encountered.
CONTINUE - Hangup the called party and allow the calling party to continue dialplan execution at the next priority.
GOTO:[[<CONTEXT>^]<EXTEN>^]<PRIORITY> - Transfer the call to the specified destination.
x - Name of the subroutine to execute via Gosub
arg[^arg...] - Arguments for the Gosub routine

but you are quoting this (which I also see on the CLI)

 U(x[^arg[^...]]): 
        x - Name of the subroutine to execute via 'Gosub'

        arg - Arguments for the 'Gosub' routine
Execute via 'Gosub' the routine <x> for the *called* channel before connecting
to the calling channel. Arguments can be specified to the 'Gosub' using '^' as
a delimiter. The 'Gosub' routine can set the variable ${GOSUB_RESULT} to
specify the following actions after the 'Gosub' returns.
        ${GOSUB_RESULT}: 
            ABORT: Hangup both legs of the call.
            CONGESTION: Behave as if line congestion was encountered.
            BUSY: Behave as if a busy signal was encountered.
            CONTINUE: Hangup the called party and allow the calling party to
            continue dialplan execution at the next priority.
            GOTO:[[<context>^]<exten>^]<priority>: Transfer the call to the
            specified destination.
    NOTE: You cannot use any additional action post answer options in
    conjunction with this option. Also, pbx services are run on the peer
    (called) channel, so you will not be able to set timeouts via the
    'TIMEOUT()' function in this routine.

Try signing out or going incognito and you’ll see what I mean.


#11

I am seeing the same thing as you. The same information is there except for a NOTE that appears only in the CLI output for some reason. You can also note that this forum has butchered the wiki formatting in your quote.

So I don’t see what you are trying to point out other than the fact that the information is presented differently.