1、关于PJSIP介绍
PJSIP是开源的SIP协议栈,在最近的Asterisk版本中,官方已经开始使用PJSIP协议栈作为Asterisk引擎的SIP协议栈。关于为什么Asterisk选择PJSIP作为Asterisk新一代SIP协议栈的讨论读者可以查阅此链接:
SIP Stack Research
https://wiki.asterisk.org/wiki/display/AST/SIP+Stack+Research
PJSIP的核心是SIP endpoint,通过pjsip_endpoint来表示。

pjsip_endpoint负责几个方面的工作:
- 它具有一个pool factory, 为SIP模块分配自己的pool。
- 它支持对每个SIP模块实现定时器管理。
- 它支持一个传输管理模块,传输管理模块支持对SIP传输和控制消息解析打印。
- 它支持PJLIB的 ioqueue支持网络事件的调度处理。
- 它提供thread安全保护,对每个应用的thread进行安全管理。
- 它可以管理PJSIP的相关模块,拓展,解析处理等功能。
- 它负责从管理模块接收到的SIP 进入的消息,分发SIP消息到其他模块。
因为篇幅的关系,笔者在这里不再做太多关于PJSIP的介绍,网络有很多关于PJSIP协议栈,PJSIPUA的使用方式,读者可以安装练习。这里,我们主要介绍pjsip_endpoint的作用,因为它直接影响着我们后续章节中所讨论的Asterisk呼叫流程。
2、PJSIP在Asterisk的结构
在Asterisk环境中,PJSIP通过各自的模块对终端,业务订阅,认证和传输都进行管理。PJSIP模块的几个核心模块如下:

Asterisk中PJSIP相关的几个主要包括:
- res_pjsip 模块,这是一个基础模块,提供对上层其他业务的支持。
- res_pjsip_session模块,提供呼叫,媒体和会话管理,包括媒体流处理协商,DTMF,会话定时器设置,PRACK/100rel,SIP 原因头处理,传输设置和媒体加密。
- res_pjsip_regiestrar, 提供SIP注册模块的管理。
- res_pjsip_pubsub, 提供对SIP消息的订阅发布。
- res_pjsip_messaging, 提供MWI事件包处理,分机/设备的状态拓展支持(例如,PIDF,XPIDF,和CPIM-PIDF)。
3、PSJIP相关的几个实体对象说明
我们现在讨论的PJSIP和以前的chan_sip配置文件有所不同。在PJSIP中,Asterisk借用了几个实体概念来部署相关配置。如果用户不了解其具体作用的话,可能引起很多的误解。在前面的介绍中,我们已经说明,Endpoint是PJSIP的核心。通过Endpoint关联了很多相关的配置属性关系。以下是一个ER关系图实例,读者可以基本了解其配置关系:

当一个新的SIP请求进入到PJSIP时,PJSIP的res_pjsip模块首先需要确认Endpoint在res_pjsip中的注册类型。注册类型不同则关联不同的配置参数设置。当然,Endpoint的确认也有不同的优先级。用户可以通过CLI命令来检查这些Endpoint类型:
- *CLI> pjsip show identifiers
- Identifier Names:
- name not specified
- ip
- username
- anonymous
- header
- auth_username
大部分情况下,PJSIP会通过“From”头中的username来查询Endpoint中的username。如果匹配到了相应的username,则继续匹配其他的配置参数。
在res_pjsip中提供了对Endpoint的类型定义,不同的类型又和不同的配置进行了绑定,这些具体的配置包括:
- Transport支持,提供对传输协议配置(TCP/UDP),加密配置(TLS/SSL),WS配置。
- AUTH支持,认证部分提供对用户的Inbound和Outbound的Authentication处理,包括用户注册信息处理以及认证方式。
- AOR(Address of Record)支持,此配置通知Asterisk在那里可以连接endpoint终端。如果没有AOR记录的话,不能连接endpoint终端。当Asterisk收到一个注册请求时,它首先需要查询可用的AOR记录。
- REGISTRATION注册,提供对外SIP服务器的注册支持,对接ITSP trunk配置。
- IDENTIFY支持,此配置控制res_pjsip_endpoint_identifier_ip模块来决定进入到系统的数据是哪种endpoint终端类型。如果Asterisk收到一个来自于某个IP地址的数据,则匹配这个地址的相应的终端。
- Contact配置选项工作方式类似于SIP URL的别名,保存进入到注册消息。它可以关联单个独立的SIP 用户代理。
以上ER图例说明了它们之间的关联关系。如果用户对某些概念理解有问题的话,可以查阅笔者的历史文档,这里不再对基本概念做过多讨论,相关文章包括:
- B2BUA/SBC/Proxy的SIP消息重构和RFC7092详解
- 一封信读懂SIP注册消息关键词
- 深入理解SIP服务器的注册和定位服务流程中关于AOR和COntact的说明。
4、Asterisk中PJSIP的处理流程
根据前面章节的介绍,一个呼叫通过SIP呼叫到Asterisk系统中,需要经过几个模块的处理。读者需要更多关注Res_pjproject.c文件(启动PJSIP,分配模块资源,设置log等)和Res_pjsip.c 文件。Res_pjsip.c开始加载其其他的上层模块的逻辑处理,包括创建thread,监听IP和端口,确认Endpoint类型和优先级判断,确认endpoint相关配置,DTMF,管理SDP,Callerd等。以下图例是关于Asterisk服务器中PJSIP协议如何处理一个呼叫请求的处理流程。

Asterisk中PJSIP的呼叫处理流程如下:
- 首先启动PJSIP协议栈。
- 把新的request存放到threadpool中,等待处理。
- 确认Endpoint以及其配置类型。
- 如果有NAT支持,则修改NAT配置。如果没有,则继续执行下一步流程。
- 如果有re-INVITE则执行,修改媒体状态;如果没有,则继续进行下一步操作。
- 创建Dialog。
- 对请求进行认证处理。
- 创建一个新的会话。
- 处理SDP Offer。
- 提取Caller ID,保存提取的值。
- 创建一个ast_channel object 对象。
- 检查是否有T38传真支持处理。如果没有则继续执行下一步流程。
- 正式启动IPPBX,进入拨号规则。
5、Asterisk拨号规则中的PJSIP分机呼叫流程分析
在Asterisk呼叫中,首先需要根据呼叫的需求编写一个拨号规则(dialplan)。 这个拨号规则定义了呼叫的具体流程。IPPBX的呼叫流程可以非常复杂,也可以非常简单。为了配合以上内容,我们编写一个简单的拨号规则来说明PJSIP分机之间呼叫需要处理的流程。具体拨号规则的语法如下:

这里需要提前说明,此示例中,分机已经创建,拨号规则和SIP分机可以注册退出注册。所以,读者如果需要测试的话,需要提前安装Asterisk,如果需要real-time的分机管理的话,需要安装Asterisk数据库和创建相关的表(例如,asterisk.ps_endpoints,asterisk.ps_aors等)来存储PJSIP的AOR,Contacts,Endpoints等数据。另外,读者需要了解关于PJSIP的CLI命令,方便查看AOR,Contacts,和Auth等数据状态)。以下示例说明了Asterisk环境中PJSIP分机呼叫的主要处理流程:

在以上的出来流程中,Asterisk大概需要几个步骤来实现分机之间的呼叫:
- 注册的分机拨打200发起一个请求。
- Asterisk检查此分机是否属于特别设置的context,我们这里是hiastar。如果是,则可以进行第三步的流程。这里,读者可以通过Asterisk CLI 命令检查AOR 的状态。
- 在Asterisk PBX中,首先检查需要匹配的拨打的号码,这里用户拨打了200,当然,用户也可以拨打其他号码设置。
- 如果在拨号规则中匹配检测通过,则执行app 命令Dial,然后拨打PJSIP协议通道的分机。
- Asterisk再次检查分机的状态,比如相关分机200的AOR和绑定的Contacts。这里,一些新用户可能比较迷惑,笔者重点说明一下。如果创建了分机以后,系统可以马上创建AOR记录,但是没有Contacts记录。如果用户使用SIP终端注册登录以后,Contact 记录才能显示,并且绑定了具体的IP地址对象。一个AOR可以绑定多个Contacts地址,也就是说,一个AOR记录可以支持多台SIP终端注册登录。在笔者的实验中,一个AOR 200,绑定了两个SIP 终端,这两台终端都已经登录注册,所以可以显示两个不同的IP地址。分机注册前后的的状态


Asterisk检查到200分机已经注册,并且获悉了其IP地址以后,对此SIP分机发送INVITE请求,对其发起呼叫。
通过以上六个步骤,PJSIP分机之间的呼叫创建完成。
6、总结
此文章主要介绍了关于Asterisk环境中使用PJSIP分机拨号的基本处理流程和其相关的技术架构。首先,笔者简单说明了PJSIP的介绍了PJSIP的使用原因和官方说明,然后介绍了PJSIP的核心模块,然后介绍了PJSIP在Asterisk的架构和其相关的应用服务模块。因为,PJSIP涉及了SIP协议几个主要的概念,笔者又分别说明了几个概念之间的绑定关系。为了让读者能够充分了解Asterisk中PJSIP的处理流程,笔者通过图例的方式,按照总共13个步骤说明了PJSIP是如何一步步进行呼叫流程的处理的。最后,笔者通过一个PJSIP分机呼叫的示例,配合简单的拨号规则说明了拨号规则的处理流程。
参考资料:
www.asterisk.org
www.freepbx.org.cn
www.pjsip.org


关注微信公众号:asterisk-cn,获得有价值的Asterisk行业分享
Asterisk freepbx,FreeSBC技术文档: www.freepbx.org.cn
融合通信商业解决方案,协同解决方案首选产品:www.hiastar.com
Asterisk/FreePBX中国合作伙伴,官方qq技术分享群(3000人):589995817