asterisk拨号计划中Hangup() App执行规则

       在asterisk执行拨号计划的业务过程中,我们经常会调用Hangup()这个App来结束呼叫,然而在asterisk中有多处逻辑位置可以调用Hangup(),而且调用此App后,呼叫通道还要继续执行后续的业务逻辑(比如:是否写CDR,是否调用发送短信接口等)。下面我们就来"踩"一下拨号计划中调用Hangup()后的一些"坑"。

在asterisk拨号计划中,主要可以在以下几处位置调用拨号计划的Hangup() App:
1)普通的context段,包含Goto语句跳转的嵌入context段。
2)Macro()宏调用context里面。
3)Gosub()子程序的context里面。
下面来实际测试每种情况,并根据拨号计划的走向得出具体的结论。

1. 普通的context段的情况:
1.1 Hangup()调用和h分机同在一个context中的情况。
1.1.1 拨号计划脚本如下:
[from-internal]
exten => _.,1,NoOp(cid=${CALLERID(num)})
exten => _.,n,Hangup()
exten => h,1,NoCDR()
exten => h,n,Verbose(-----1----)
exten => h,n,Hangup()
1.1.2 用软电话测试执行结果如下:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-00000025", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Hangup("SIP/8001-00000025", "") in new stack
  == Spawn extension (from-internal, 8888, 2) exited non-zero on 'SIP/8001-00000025'
    -- Executing [h@from-internal:1] NoCDR("SIP/8001-00000025", "") in new stack
    -- Executing [h@from-internal:2] Verbose("SIP/8001-00000025", "-----1----") in new stack
-----1----
    -- Executing [h@from-internal:3] Hangup("SIP/8001-00000025", "") in new stack
  == Spawn extension (from-internal, h, 3) exited non-zero on 'SIP/8001-00000025'
dotasterisk*CLI> 
1.1.3  说明:
执行流程很简单,在当前context(8888@from-internal)上执行Hangup()后,直接调到当前context的h分机(h@from-internal),整个过程很自然,无需过多解释。

 

1.2 用Goto语句跳到下一级,并在下一级中执行Hangup()的情况:
1.2.1 拨号计划脚本如下:
[from-internal]
exten => _.,1,NoOp(cid=${CALLERID(num)})
exten => _.,n,Goto(next-context,${EXTEN},1)
exten => h,1,NoCDR()
exten => h,n,Verbose(-----1----)
exten => h,n,Hangup()

[next-context]
exten => _8.,1,NoOp(come here)
exten => _8.,n,Hangup()
exten => h,1,Verbose(-----2----) ;注:此处是h分机执行代码的开始
exten => h,n,Hangup()

1.2.2 用软电话测试执行结果如下:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-0000002a", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Goto("SIP/8001-0000002a", "next-context,8888,1") in new stack
    -- Goto (next-context,8888,1)
    -- Executing [8888@next-context:1] NoOp("SIP/8001-0000002a", "come here") in new stack
    -- Executing [8888@next-context:2] Hangup("SIP/8001-0000002a", "") in new stack
  == Spawn extension (next-context, 8888, 2) exited non-zero on 'SIP/8001-0000002a'
    -- Executing [h@next-context:1] Verbose("SIP/8001-0000002a", "-----2----") in new stack //注:仅仅执行了当前context的h分机
-----2----
    -- Executing [h@next-context:2] Hangup("SIP/8001-0000002a", "") in new stack
  == Spawn extension (next-context, h, 2) exited non-zero on 'SIP/8001-0000002a'
dotasterisk*CLI> 
1.3.3 说明:
从执行结果看,发现只输出了[h@next-context]里面的Verbose(-----2----),而没有输出上一级[from-internal]里面Hangup()之后的拨号计划。

结论:对于普通context段里面的Hangup() App,不管里面Goto到了多少层级别,只要在某一个context执行的Hangup(),那么就在当前这个context里面寻找h分机,如果有h分机匹配,就执行h分机里面的流程。注意,h分机的拨号计划只在此处context执行,绝不会跳出此处的context,即使是当前context中没有匹配到h分机,也仍然不会跳出此context而去寻找上一级调用Goto()语句的context里面的h分机来执行。举个例子,拨号计划是:
[from-internal]
exten => _.,1,NoOp(cid=${CALLERID(num)})
exten => _.,n,Goto(next-context,${EXTEN},1)
exten => h,1,NoCDR()
exten => h,n,Verbose(-----1----)
exten => h,n,Hangup()

[next-context] ;此段没有匹配h分机
exten => _8.,1,NoOp(come here)
exten => _8.,n,Hangup()
执行结果如下:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-00000029", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Goto("SIP/8001-00000029", "next-context,8888,1") in new stack
    -- Goto (next-context,8888,1)
    -- Executing [8888@next-context:1] NoOp("SIP/8001-00000029", "come here") in new stack
    -- Executing [8888@next-context:2] Hangup("SIP/8001-00000029", "") in new stack  //注:仅仅在这里就停止了,没有跳到上一层context
  == Spawn extension (next-context, 8888, 2) exited non-zero on 'SIP/8001-00000029'
dotasterisk*CLI> 

 

2. Macro()宏里面执行Hangup():
2.1 拨号计划如下:
[from-internal]
exten => _.,1,NoOp(cid=${CALLERID(num)})
exten => _.,n,Macro(m1)
exten => h,1,NoCDR()
exten => h,n,Verbose(-----1----)
exten => h,n,Hangup()

[macro-m1]
exten => s,1,NoOp(come here)
exten => s,n,Hangup()
exten => s,n,MacroExit()
exten => h,1,Verbose(-----2----) ;//此处的h分机永远不会被执行
exten => h,n,Hangup()
2.2 执行结果如下:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-0000002b", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Macro("SIP/8001-0000002b", "m1") in new stack
    -- Executing [s@macro-m1:1] NoOp("SIP/8001-0000002b", "come here") in new stack
    -- Executing [s@macro-m1:2] Hangup("SIP/8001-0000002b", "") in new stack
  == Spawn extension (macro-m1, s, 2) exited non-zero on 'SIP/8001-0000002b' in macro 'm1'
  == Spawn extension (from-internal, 8888, 2) exited non-zero on 'SIP/8001-0000002b'
    -- Executing [h@from-internal:1] NoCDR("SIP/8001-0000002b", "") in new stack //注:没有执行宏里面的h分机
    -- Executing [h@from-internal:2] Verbose("SIP/8001-0000002b", "-----1----") in new stack
-----1----
    -- Executing [h@from-internal:3] Hangup("SIP/8001-0000002b", "") in new stack
  == Spawn extension (from-internal, h, 3) exited non-zero on 'SIP/8001-0000002b'
dotasterisk*CLI> 
2.3 说明:从执行结果看,发现里面执行Hangup()后没有执行宏里面h分机,而是跳到调用宏的普通的context里面的h分机(h@from-internal)中去执行了。
2.4 结论:在宏Macro中一般只执行s分机,定义的h分机永远也不会执行,只会跳到调用处的Macro()代码里面的context去执行,也就是说宏中定义h分机本来就是没意义的

 

3. Gosub()子程序里面执行Hangup():
3.1 情况1:sub子程序明确指定了h分机
3.1.1 拨号脚本如下:
[from-internal]
exten => _.,1,NoOp(cid=${CALLERID(num)})
exten => _.,n,Gosub(s1,${EXTEN},1)
exten => h,1,NoCDR()
exten => h,n,Verbose(-----1----)
exten => h,n,Hangup()

[s1]
exten => _.,1,NoOp(come here)
exten => _.,n,Hangup()
exten => _.,n,Return()
exten => h,1,Verbose(-----2----)
exten => h,n,Hangup()

3.1.2 执行结果如下:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-0000002c", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Gosub("SIP/8001-0000002c", "s1,8888,1") in new stack
    -- Executing [8888@s1:1] NoOp("SIP/8001-0000002c", "come here") in new stack
    -- Executing [8888@s1:2] Hangup("SIP/8001-0000002c", "") in new stack
  == Spawn extension (s1, 8888, 2) exited non-zero on 'SIP/8001-0000002c'
    -- Executing [h@s1:1] Verbose("SIP/8001-0000002c", "-----2----") in new stack //注:只执行当前context的h分机,没有调到上一层
-----2----
    -- Executing [h@s1:2] Hangup("SIP/8001-0000002c", "") in new stack
  == Spawn extension (s1, h, 2) exited non-zero on 'SIP/8001-0000002c'
dotasterisk*CLI> 

3.2 情况2:sub子程序里面没有h分机
3.2.1 拨号脚本如下:
[s1]
exten => _8.,1,NoOp(come here)
exten => _8.,n,Hangup()
exten => _8.,n,Return()
3.2.2 执行结果如下:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-0000002f", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Gosub("SIP/8001-0000002f", "s1,8888,1") in new stack
    -- Executing [8888@s1:1] NoOp("SIP/8001-0000002f", "come here") in new stack //注:发现直接在这里挂机停止了,end了
    -- Executing [8888@s1:2] Hangup("SIP/8001-0000002f", "") in new stack
  == Spawn extension (s1, 8888, 2) exited non-zero on 'SIP/8001-0000002f'
dotasterisk*CLI> 

3.3 结论
goSub的context普通的context执行Hangup() App后后续的拨号计划执行流程规则是一样的。可以这样理解:普通的context和子程序context是一样的,除了子程序context里面可以有Return()语句跳回到上一处拨号计划,其余方面的特性是一模一样的。据测试,通道变量也没有什么变量作用域的概念,在子程序里面一样可以直接用外面的变量,子程序里面设置的变量一样可以带到外面去,不同于其他编程语言里面有什么函数里面有局部变量的概念。同子程序一样,也没有局部变量的概念。关于变量测试代码如下:
[from-internal]
exten => _.,1,NoOp(cid=${CALLERID(num)})
exten => _.,n,Set(varOUT=AA)
exten => _.,n,Gosub(s1,${EXTEN},1)
exten => _.,n,NoOp(--varIN=${varIN}--) ;//可以直接用子程序里面定义的变量,不存在变量作用域的概念
exten => _.,n,WaitExten(100)
exten => h,1,NoCDR()
exten => h,n,Verbose(-----1----)
exten => h,n,Hangup()

[s1]
exten => _8.,1,NoOp(--varOUT=${varOUT}--) ;//可以打印外部变量
exten => _8.,n,Set(varIN=BB) ;//定义的变量,可以带到外部去
exten => _8.,n,Return()
输出结果:
dotasterisk*CLI> 
  == Using SIP RTP TOS bits 184
  == Using SIP RTP CoS mark 5
    -- Executing [8888@from-internal:1] NoOp("SIP/8001-00000031", "cid=8001") in new stack
    -- Executing [8888@from-internal:2] Set("SIP/8001-00000031", "varOUT=AA") in new stack
    -- Executing [8888@from-internal:3] Gosub("SIP/8001-00000031", "s1,8888,1") in new stack
    -- Executing [8888@s1:1] NoOp("SIP/8001-00000031", "--varOUT=AA--") in new stack
    -- Executing [8888@s1:2] Set("SIP/8001-00000031", "varIN=BB") in new stack
    -- Executing [8888@s1:3] Return("SIP/8001-00000031", "") in new stack
    -- Executing [8888@from-internal:4] NoOp("SIP/8001-00000031", "--varIN=BB--") in new stack
    -- Executing [8888@from-internal:5] WaitExten("SIP/8001-00000031", "100") in new stack
    
    

转载于:https://my.oschina.net/enjoycti/blog/754063

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值