Asterisk drop call when one of the parties left the call

Hello, The case am pursuing is as follow:

When receiving a call from the caller(A-party). I want to dial to called(B-party) and initiate a sub-routine, for simplicity let’s say we only want for the B-party to listen to a tone.

I am using the below configuration:

[default]
exten => _X.,1,Dial(SIP/${EXTEN},20,U(test))
same => n,Hangup()

[test]
exten => s,1,Playback(tt-monkeys)
same => n,Return()

The problem I am facing is that while playing the tone, if A-party hangs up the call, B-party still hears the remaining of the tone (the call is not dropped from the B-party side directly).
What I want is if one of the parties left the call, the call must be dropped from both parties immediately and all created channels must be closed.

PS: I can’t use option A in dial since Playback is not the only application I want to use.

Playback() app keep the session open, and it won’t drop until it finish being executed, one way is get the channel name of the (B-party) and using h extension tell Asterisk to hangup that channel

Thank you very much for the quick reply.
How can I get the channel name of the B-party? and how can I perform a hangup to a specific channel in the dialplan? which application should I use?

  • ${CHANNEL} * - Current channel name

channel request hangup

let us say the configuration is the below:

[default]
exten => _X.,1,Dial(SIP/${EXTEN},20,U(test))
same => n,Hangup()

exten => h,1,Set(ch1={CHANNEL})

[test]
exten => s,1,Playback(tt-monkeys)
same => n,Return()

in this way, the ch1 will be equal to the channel name of the A-party… how can I get the channel name of B-party?

Regarding the hangup of the channel( channel request hangup), should I use System application to hang up a certain channel same as below?
same => n,System(asterisk -rx ‘channel request hangup ${ch1}’)

The only way you are going to be able to do this just from dialplan is by using G on dial, so that there is an active thread controlling both channels. You will need to do this instead of U. There are likely to be race conditions.

The h extension definitely won’t run until the subroutine returns. Whilst I haven’t looked into the details of hangup handlers, I’d be surprised if they started a new thread on a channel that was already marked as in the PBX, i.e. having a controlling dialplan thread.

Another way of handling this would be to have an AMI process that monitored the call, detected the A side hangup and issued hangup for B. There may be some subtleties here, in that the channel wouldn’t be fully hung up, until the subroutine returned, and I’m not sure if AMI would get events to say that the channel technology driver had detected a hangup. (There are two parallel data structures for a channel, there is the technology independent structure, but there is also a private, technology dependant structure. I think the main channel structure would only get marked with a soft hangup state, which might not generate AMI events.)

The basic issue here is that a thread has to own a channel before it can be properly hungup and before technology specific hangups can be fully detected. Whilst that thread is running a subroutine, it is executing dialplan as though the B side channel were the primary channel and doesn’t know about the A side. There is some code, auto-service, that monitors the A side, but that is mainly to throw away any media received, and it cannot process a hangup through to completion.

The easiest way for the A side to get the B side channel, before it is bridged, is for the B side to set a shared variable. At some point Dial sets some variables, but I’m conscious of the ability to dial multiple addresses in parallel, and I can’t remember when any channel variable reflecting the answering B side is set. You might want to check for suitable standard variables.

There wasn’t a third party hangup dialplan application at the time I was actively developing, although that might have changed, but you can definitely do channel redirects from the dialpla, which could redirect to dialplan that calls Hangup().

This won’t be run until the subroutine returns and Dial regains control.

Thank you @david551 what you mentioned is clear enough. Let me show you what I did using G option in Dial:

[default]
exten => _X.,1,Answer()
same => n,Set(__ch1=${CHANNEL})
same => n,Dial(SIP/222,60,G(test^555^1))

[test]
exten => 555,1,Goto(calling,1,1)
same => n,Goto(called,1,1)

[calling]
exten => 1,1,NoOp(calling ${CALLERID(num)} → ${CALLERID(dnid)})
same => n,BridgeWait(“test”,participant,e(n))
same => n,NoOp(called channel-name ${DIALEDPEERNAME})

exten => h,1,NoOp(hangup called channel)
same => n,System(asterisk -rx ‘channel request hangup ${DIALEDPEERNAME}’)

[called]
exten => 1,1,NoOp(called ${CALLERID(num)} → ${CALLERID(dnid)})
same => n,Answer()
same => n,Playback(tt-monkeys)
same => n,Bridge(${ch1})

exten => h,1,NoOp(hangup caller channel)
same => n,System(asterisk -rx ‘channel request hangup ${ch1}’)

Here, there are 2 channels, the first channel is the main channel and related to the calling party, and the other channel is inherited from the first one and related to the called party.
I’ve used BridgeWait in calling-leg for waiting for the called party to join the call, and Bridge for merging the 2 legs.

I’ve tried it and it worked fine. But I have many concerns especially about the part how I’m hanging up the legs through the System application (same => n,System (asterisk -rx ‘channel request hangup ${DIALEDPEERNAME}’)).

What do you think? Is it a good solution? What about the hangup of the legs? Would this lead to a performance issue? Frankly, I have never used the System application before, thus I need your advice to move forward.

Your help is greatly appreciated. Thank you.

I’d prefer channel redirect, as it keeps it in the dialplan, but I can’t see any real problem, other than the cost of launching a shell and Asterisk console process in doing with asterisk -x

Thank you, @david551 , it worked fine now. But there is an issue occurring frequently when I’m trying to redirect the channel, and it’s already closed. Below is the error:

WARNING[383521][C-000000ff] channel.c: Can’t move channel. One or both is dead (Surrogate/SIP/192.1
68.13.13-000001f3 ← SIP/192.168.13.13-000001f3)
[Aug 24 00:26:03] WARNING[383521][C-000000ff] pbx.c: Unable to gain control of channel SIP/192.168.13.13-000001f3

I want to check first if the channel is closed or not before performing the redirection. Is there any application that I can use in order to check that?

If it is just a warning, I would live with it. I suspect any test would also produce a warning, and you couldn’t do the test atomically with the use, so there would still be race conditions.

If it is returning non-zero, you could use tryexec to isolate it.

yes, I have tried tryexec and it worked fine. Thank you dear!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.