0

We use Asterisk AMI Originate for outbound calls (our software), so after successfully connecting to the first leg (external), we can use dialplan to Dial the second leg (internal) and handle the hangup.

Now we are using AMI in our software to pick up Hangup Event on the first leg/channel (if we have not established a connection - busy, noanswer, etc). Is it possible to set the hangup_handler for the first channel in AMI Originate (similar to Asterisk Application Originate, which has option b, where you can set the hangup_handler)?

-- Edited

I was able to do it through Local channels, but I think it's a bit complicated, maybe there is another way?

channel originate Local/0123456789@to_caller extension ivm_100@process_ivm

dialplan:

[to_caller]
exten => _X.,1,Log(VERBOSE,OUTGOING CALL)
same => n,NoCDR()
; remember about variable inheritance https://asteriskfaqs.org/2021/02/23/asterisk-users/channel-variable-inheritance.html
; can set here same variables
same => n,Set(CALLERID(num)=0123456789) 
same => n,Set(CALLERID(name)=${CALLERID(num)})
same => n,Set(__clrCID=${CALLERID(num)})
;end test
same => n,Dial(SIP/${EXTEN},30,b(set_hangup_handler,s,1)U(remove_hangup_handler,s,1)))

[set_hangup_handler]
exten => s,1,Set(CHANNEL(hangup_handler_push)=to_caller_hangup_handler,s,1)
;test variables in new channel
same => n,NoOp(clrCID: ${clrCID})
; need to set CALLERID for new channel
same => n,Set(CALLERID(num)=${clrCID})
same => n,Set(CALLERID(name)=${CALLERID(num)})
;end test
same => n,Return()

[remove_hangup_handler]
exten => s,1,NoOp(Remove hangup_handler)
same => n,Set(CHANNEL(hangup_handler_pop)=)
same => n,Set(MASTER_CHANNEL(clrFCH)=${CHANNEL(name)})
same => n,Return()

[to_caller_hangup_handler]
exten => s,1,NoOp(TO_CALLER_HANGUP_HANDLER First Call Leg)
same => n,NoOp(Data: CHANNEL: ${CHANNEL}, SIP Cause - ${HANGUPCAUSE}, Technology Cause Code "${HANGUPCAUSE(${CHANNEL},tech)}", Asterisk Cause Code "${HANGUPCAUSE(${CHANNEL},ast)}")
same => n,Return()

[process_ivm]
exten => _ivm.,1,NoOp(Process dialplan IVM)
same => n,NoCDR()
same => n,ChannelRedirect(${clrFCH},ivms,${EXTEN},1) ; redirect from Local to real channel
same => n,Hangup() ; hangup Local channel

exten => h,1,NoOp(Hangup Local channel)

[ivms]
; here is main logic when DIALSTATUS will be ANSWER

2 Answers2

0

One more asterisk software made without asterisk expert in team...

First, to make a hangup event you don't need AMI or handler, much simpler is to use CEL or beanstalk integration.

Second, AMI is not designed to really control anything in dialplan. It is more about events/commands.

Third, if you still want you do handler for dialout leg, you should use Local/ channel dialling, not SIP. Check source code of any modern opensource solution. For example, vicidial.org

After that in dialplan, you can setup any handler and see how it affect your reability and perfomance.

arheops
  • 15,544
  • 1
  • 21
  • 27
  • I am very grateful for the answer. The solution with the Local channel is already in development/testing (I was planning to make a description of the solution here next week for future searchers), I just thought that I don't know something and it is possible to do it somehow without reworking the existing mechanism – Artem Vyshniakov May 21 '23 at 08:04
0

Found another way (without ChannelRedirect), maybe someone knows a simpler (more convenient) way? My goal is to use the AMI Originate mechanism to make a call to the outside (the first leg of the call), to be able to process Hangup through the dialplan logic(if the call attempt is unsuccessful, some process, save statuses to DB etc), and if the attempt (first leg) is successful, to switch to the main dialplan (where the main logic will be already there - either playing IVM records or searching for and connecting to inside operators)

command:

channel originate SIP/0123456789@127.0.0.1 application Wait 0

sip.conf

[local]
type=peer
context=to_caller2
host=127.0.0.1
deny=0.0.0.0
permit=127.0.0.1

dialplan:

[set_hangup_handler]
exten => s,1,Set(CHANNEL(hangup_handler_push)=to_caller_hangup_handler,s,1)
; need to set CALLERID for new channel
same => n,Set(CALLERID(num)=${clrCID})
same => n,Set(__clrMID=992)
same => n,Return()

[to_caller_hangup_handler]
exten => s,1,NoOp(TO_CALLER_HANGUP_HANDLER First Call Leg)
same => n,NoOp(Data: CHANNEL: ${CHANNEL}, SIP Cause - ${HANGUPCAUSE}, Technology Cause Code "${HANGUPCAUSE(${CHANNEL},tech)}", Asterisk Cause Code "${HANGUPCAUSE(${CHANNEL},ast)}")
; some logic, save to DB etc
same => n,Return()

[to_caller2]
exten => _X.,1,Log(VERBOSE,OUTGOING CALL)
same => n,NoCDR() ; we not need in CDR record for local channel
same => n,Set(CALLERID(name)=${CALLERID(num)})
same => n,Set(__clrCID=${CALLERID(num)})
; cannot use U and G at the same time
; G - If the call is answered, transfer the CALLER party to the specified priority and the CALLED party to the specified priority plus one.
same => n,Dial(SIP/${EXTEN},30,b(set_hangup_handler^s^1)G(ivms^ivm_${clrMID}^1)))

exten => _[hit],1,NoOp(!!!End local channel!!!!)

[ivms]
exten => _ivm.,1,Hangup(); close local channel
exten => _ivm.,2,NoOp(Start main logic)
same => n,NoOp(Remove hangup_handler)
same => n,Set(CHANNEL(hangup_handler_pop)=)
;same => n,Set(CALLERID(num)=${clrCID}) ; CALLERID for real channel
... (logic)
same => n,Hangup(16)

exten => h,1,GotoIf($[${REGEX("local" ${CHANNEL(name)})}]?end) 
same => n,... (hangup logic for real channel)
same => n(end),NoOp()
  • Bad idea. It may result in weird issues with rtp and firewall. – arheops May 23 '23 at 23:11
  • Thank you for the answer. The main problem with the second option is the inability to initialise the variables in the Originate->[Variable] block that are needed in the dialplan, so we returned to the first option (Channel Local, channel originate Local/0123456789@to_caller extension ivm_1@process_call) – Artem Vyshniakov May 24 '23 at 10:07