Tuesday, February 9, 2021

Cancel calls in Asterisk dialsting

 Sometimes life gives strange tasks.

Imagine, you have dialstring in Asterisk like


But you need to stop the call at the moment when one of destinations hangup. It's against Asterisk logic, but may be useful sometimes, if all destinations (devices) belongs to same person.

So, solution is to use a combination of pre-dial handlers and hangup handlers

Code actually - extensions.conf



exten => _X.,1,NoOp(Call from UAS received)
    same => n,Dial(PJSIP/${EXTEN}@sipp_uas1&PJSIP/${EXTEN}@sipp_uas2,,b(arm_simultaneous_dial^s^1))


exten => s,1,NoOp(I am on channel:${CHANNEL})
    same => n,Set(CHANNEL(hangup_handler_push)=simultaneous_dial_hangup_channel,s,1)
    same => n,Set(CHILD_COUNT=1)
    same => n,While($[("x${MASTER_CHANNEL(CHILD_${CHILD_COUNT})}" != "x" && $[${CHILD_COUNT} <= ${MAX_CHILD}])])
    same => n,Set(CHILD_COUNT=$[${CHILD_COUNT} + 1])
    same => n,EndWhile()
    same => n,Return


exten => s,1,NoOp(Hangup on channel:${CHANNEL})

; you may put here analyze of hangup code, so not to hangup on failed destination, etc.
    same => n,Set(CHILD_COUNT=1)
    same => n,While($[("x${MASTER_CHANNEL(CHILD_${CHILD_COUNT})}" != "x" && $[${CHILD_COUNT} <= ${MAX_CHILD}])])
    same => n,GoToIf($[ "x${CHANNEL}" = "x${MASTER_CHANNEL(CHILD_${CHILD_COUNT})}"]?skip_myself)
    same => n,SoftHangup(${MASTER_CHANNEL(CHILD_${CHILD_COUNT})})
    same => n(skip_myself),Set(CHILD_COUNT=$[${CHILD_COUNT} + 1])
    same => n,EndWhile()
    same => n,Return

Idea is to save child channels id's in sequential CHILD_X variables of the master channel and on hangup one of child's - softhangup other child's.

Full proof of concept is available as docker-compose containing Asterisk and SIPP's on my GitHub.

No comments:

Post a Comment