asterisk拨号计划中Hangup() App执行规则
2019独角兽企业重金招聘Python工程师标准>>>
在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
asterisk拨号计划中Hangup() App执行规则相关推荐
- Asterisk拨号方案中变量的应用
在拨号方案中使用变量可以减少打字.增加清晰度,也有助于在拨号方案中加入逻辑. 这里的变量有全局变量,通道变量和环境变量. 1.全局变量 全局变量应该在extensions.conf文件的开始利用[gl ...
- oracle 计划中的view,执行计划里的view
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 FYI Views ===== When a view cannot be merged into the main query you will oft ...
- Asterisk拨号方案一
9|.是去掉号码前面的9, 0755|.是去掉号码前面的0755 X代表一个0-9中的任意一个数字 Z代表一个1-9中的任意一个数字 N代表一个2-9中的任意一个数字 |号代表去掉号码前面的指定数字 ...
- Asterisk权威指南/第六章 拨号计划基础
拨号计划是你的Asterisk系统的心脏.它定义了呼叫是如何流进和流出系统的.拨号计划用一种脚本语言写成的,Asterisk依照其中的指令响应外部触发.和传统电话系统相比,Asterisk的拨号计划是 ...
- 《实施Cisco统一通信管理器(CIPT2)》一1.6 拨号计划方面面临的挑战
本节书摘来异步社区<实施Cisco统一通信管理器(CIPT2)>一书中的第1章,第1.6节,作者: [美]Chris Olsen 译者: 刘丹宁, CCIE#19920 , 卢铭 , 陈国 ...
- Microsoft Teams Voice语音落地系列-3 实战:拨号计划的配置
上一节我们讨论了所有用于Teams语音落地的前置条件准备,一齐来回顾一下: 1) 权限与管理员准备:O365管理员/Teams管理员:SBC管理员:本地Skype管理员:网络管理员:DNS/CA管理员 ...
- oracle cost cardinality,ORACLE 执行计划中cost cardinality bytes cpu_cost io_cost解释
从网上找到的资料,加上我在文档中查到的内容: ■ Cost The cost assigned to each step of the query plan by the CBO. The CBO w ...
- oracle 计划中的view,为何执行计划中会出现个VIEW: VM_NWVW_1 ?
为何执行计划中会出现个VIEW: VM_NWVW_1 ? 数据库中根本没有这个OBJECT. 也不象系统自己产生的! SELECT R.CREATED_OFFICE STOCK_CODE, R.CU ...
- 执行计划中的参数解释
执行计划中的各个参数解释: 一.Recursive calls (递归调用) 1.参考:Oracle Database Reference, 10g Release 2 (10.2).pdf第916页 ...
最新文章
- Python 之 matplotlib (五)Annotation注解
- WindowManager如何被Android深度解析(3)
- Java 多线程使用
- 微信订阅号开发笔记(三)
- Three.js中自定义控制几何体的点和面的属性
- Gym - 101889I Imperial roads(最小生成树+树链剖分+线段树)
- 数据库查询求小于_SQL学习笔记(二)简单查询
- 论文致谢走红后,中科院博士回信了!
- 4027-计数排序(C++,附解析)
- csredis封装_在.NET Core中使用CSRedis
- 让你在职场游刃有余的10句话
- VS 2005部署应用程序提示“应用程序无法正常启动( 0x0150002)” 解决方案
- docker中 system limit for_springboot中redis的缓存穿透问题
- MSBuild 命令参数
- 数据分析中会常犯哪些错误,如何解决? 三
- vrchat模型保存_VRChat简易教程3-往世界里导入模型和VRC接口初探
- react实现关于文本框的双向绑定
- 360免费wifi的linux驱动下载,360随身wifi驱动
- 华为云计算机访问手机软件,手机也能当电脑使用?华为黑科技:手机云电脑
- SSM项目使用Mybatis通用mapper插件tk.mybatis的用法