您的位置:首页 > 移动开发

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

2016-10-01 00:00 260 查看
在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息