Why is Hangup extension in Dialplan called twice

Hello,

This simple callfile and dialplan makes the hangup extension be called twice. Can someone tell me why, and how can I make it a single invocation? I think it is because two channels are hung up, Local and PJSIP, so may be it cannot be avoided. If so, is there a way to tell which channel is currently meant? The variable ${CHANNEL} does not give me the right value.

Dialplan:

[fax_caller]
exten => faxout,1,NoOp(** Fax caller **)
same => n,Dial(PJSIP/mysipprovider/sip:${ReceiverPhoneNr}@mysipprovider.com)
exten => faxsend,1,NoOp(** Sending fax **)
exten => h,1,NoOp(** Channel ${CHANNEL} hung up with Fax status ${FAXSTATUS} with cause ${HANGUPCAUSE} **)

Callfile:

Channel:Local/faxout@fax_caller
MaxRetries:0
WaitTime:45
Context:fax_caller
Extension:faxsend
Priority:1
Setvar:ReceiverPhoneNr=+430000000000

This is the log:

    -- Attempting call on Local/faxout@fax_caller for faxsend@fax_caller:1 (Retry 1)
    -- Called faxout@fax_caller
    -- Executing [faxout@fax_caller:1] NoOp("Local/faxout@fax_caller-00000005;2", "** Fax caller **") in new stack
    -- Executing [faxout@fax_caller:2] Dial("Local/faxout@fax_caller-00000005;2", "PJSIP/mysipprovider/sip:RECEIVERPHONENR@mysipprovider.com:5084,,b(fax_outgoing_init^faxout^1(SENDERPHONENR,mysipprovider.com:5084))") in new stack
    -- PJSIP/mysipprovider-00000004 Internal Gosub(fax_outgoing_init,faxout,1(SENDERPHONENR,mysipprovider.com:5084)) start
    -- Executing [faxout@fax_outgoing_init:1] NoOp("PJSIP/mysipprovider-00000004", "** Pre dial settings **") in new stack
    -- Executing [faxout@fax_outgoing_init:2] Set("PJSIP/mysipprovider-00000004", "PJSIP_HEADER(add,P-Preferred-Identity)="<sip:SENDERPHONENR@mysipprovider.com:5084>"") in new stack
    -- Executing [faxout@fax_outgoing_init:3] Return("PJSIP/mysipprovider-00000004", "") in new stack
  == Spawn extension (from-external, faxout, 1) exited non-zero on 'PJSIP/mysipprovider-00000004'
    -- PJSIP/mysipprovider-00000004 Internal Gosub(fax_outgoing_init,faxout,1(SENDERPHONENR,mysipprovider.com:5084)) complete GOSUB_RETVAL=
    -- Called PJSIP/mysipprovider/sip:RECEIVERPHONENR@mysipprovider.com:5084
    -- PJSIP/mysipprovider-00000004 is ringing
    -- Local/faxout@fax_caller-00000005;1 is ringing
    -- PJSIP/mysipprovider-00000004 is ringing
       > 0x7f37f8017ca0 -- Strict RTP learning after remote address set to: 193.84.65.208:12214
    -- PJSIP/mysipprovider-00000004 answered Local/faxout@fax_caller-00000005;2
    -- Local/faxout@fax_caller-00000005;1 answered
    -- Executing [faxsend@fax_caller:1] NoOp("Local/faxout@fax_caller-00000005;1", "** Sending fax **") in new stack
    -- Auto fallthrough, channel 'Local/faxout@fax_caller-00000005;1' status is 'UNKNOWN'
    -- Executing [h@fax_caller:1] NoOp("Local/faxout@fax_caller-00000005;1", "** Channel Local/faxout@fax_caller-00000005;1 hung up with Fax status  with cause 0 **") in new stack
[Sep 26 17:38:34] NOTICE[12922][C-0000000c]: pbx_spool.c:463 attempt_thread: Call completed to Local/faxout@fax_caller
    -- Channel PJSIP/mysipprovider-00000004 joined 'simple_bridge' basic-bridge <e0397daf-0c9f-49d9-b977-0a4225581829>
    -- Channel Local/faxout@fax_caller-00000005;2 joined 'simple_bridge' basic-bridge <e0397daf-0c9f-49d9-b977-0a4225581829>
    -- Channel Local/faxout@fax_caller-00000005;2 left 'simple_bridge' basic-bridge <e0397daf-0c9f-49d9-b977-0a4225581829>
    -- Channel PJSIP/mysipprovider-00000004 left 'simple_bridge' basic-bridge <e0397daf-0c9f-49d9-b977-0a4225581829>
  == Spawn extension (fax_caller, faxout, 2) exited non-zero on 'Local/faxout@fax_caller-00000005;2'
    -- Executing [h@fax_caller:1] NoOp("Local/faxout@fax_caller-00000005;2", "** Channel Local/faxout@fax_caller-00000005;2 hung up with Fax status  with cause 16 **") in new stack

Your pasted dialplan is incomplete, as you are sending it to a “faxsend” extension but haven’t provided it.

The answer though is that a Local channel actually creates 2 channels. In your call file both channels end up in dialplan in the “fax_caller” context. As a result both would execute the “h” extension.

2 Likes

@jcolp Sorry, obviously I remove a line too much when pasting into here. I corrected my post. Still behaviour remains the same. I also appended the log.

With the dialplan as provided that behavior is expected, the reason why is in my previous post.

Ok, so, is it possible to determine in the h extension which of the two channels it was triggered by - for example, some variable? Or is there a way tell the Dial application that its hangup should go elsewhere?

It would just be easiest to use hangup handlers[1] and not use the h extension.

[1] https://wiki.asterisk.org/wiki/display/AST/Hangup+Handlers

Not yet tested… Where should I put these lines? I do not understand how this should behave differently. If I add

same => n,Set(CHANNEL(hangup_handler_push)=...)

before or after the Dial command, how does this line determine if the handler is attached to the Local or the PJSIP channel?

It would have to be before. And it is attached to the channel that it is executed on. If it executes on the Local channel then that is what executes it.

After testing… Before the Dial command, the Local channel is meant; after the Dial command, it is ignored.

But the PJSIP channel dials the receiver number and sends the fax, so the delivery information I need is within the PJSIP channel. The variable FAXSTATUS is not accessible from the Local channel.

The wiki page I linked has a mention of using pre-dial handlers[1] to attach a hangup handler on a dialed channel.

[1] https://wiki.asterisk.org/wiki/display/AST/Pre-Dial+Handlers

In my production dial plan, there is already a pre-dial hook to set a SIP header. Sure, I will give it a try tomorrow.

@jcolp Your suggestion did not yet do the trick entirely… But thanks so far, as this looks much better now.

[fax_caller}
[-- cut -- ]
same => n,Dial(${ChannelPrefix}:${ReceiverPhoneNr}@${ChannelPostfix},,b(fax_outgoing_init^faxout^1(${SenderPhoneNr},${ChannelPostfix})))
[-- cut --]

[fax_outgoing_init]
exten => faxout,1,NoOp(** Fax, pre-dial hook **)
same => n,Set(PJSIP_HEADER(add,P-Preferred-Identity)="<sip:${ARG1}@${ARG2}>")
same => n,Set(CHANNEL(hangup_handler_push)=fax_caller,hup,1)
same => n,Return()

And renamed the standard h extension to hup.

But I do not have the result of SendFAX - that is the variable FAXSTATUS - in the hup extension.

1 Like

Ok, I restructured my dialplan completely. Reading the delivery notification is now done in an own extension called by Gosub, either after SendFax or in the failed extension. I got rid of any hangup event handler entirely, now. This looks clean to me now.

1 Like