一、模块

2.1    模块框架

模块框架的主要作用是在应用程序组件之间分发SIP消息,PJSIP的所有的组件,包括dialog和transaction都是以模块方式实现的,没有模块,核心协议栈将不知道如何处理SIP消息。

模块架构思基于简单但是非常强大的接口抽象,对于到达的消息,Endpoint 按照优先级向所有的模块分发消息,直到其中一个模块告知已经处理这个消息。对于出去的消息,endpoint分发消息到所有模块,在消息未到达网络之前,允许任何模块对消息做最后的修改。

2.1.1        模块声明

模块接口再<pjsip/sip_module.h>中声明,如下:

/**

* The declaration for SIP module. This structure would be passed to

* #pjsip_endpt_register_module() to register the module to PJSIP.

*/

struct pjsip_module

{

/** To allow chaining of modules in the endpoint. */

PJ_DECL_LIST_MEMBER(struct pjsip_module);

/**

* Module name to identify the module.

*

* This field MUST be initialized before registering the module.

*/

pj_str_t name;

/**

* Module ID. Application must initialize this field with -1 before

* registering the module to PJSIP. After the module is registered,

* this field will contain a unique ID to identify the module.

*/

int id;

/**

* Integer number to identify module initialization and start order with

* regard to other modules. Higher number will make the module gets

* initialized later.

*

* This field MUST be initialized before registering the module.

*/

int priority;

/**

* Optional function to be called to initialize the module. This function

* will be called by endpoint during module registration. If the value

* is NULL, then it's equal to returning PJ_SUCCESS.

*

* @param endpt   The endpoint instance.

* @return       Module should return PJ_SUCCESS to indicate success.

*/

pj_status_t (*load)(pjsip_endpoint *endpt);

/**

* Optional function to be called to start the module. This function

* will be called by endpoint during module registration. If the value

* is NULL, then it's equal to returning PJ_SUCCESS.

*

* @return       Module should return zero to indicate success.

*/

pj_status_t (*start)(void);

/**

* Optional function to be called to deinitialize the module before

* it is unloaded. This function will be called by endpoint during

* module unregistration. If the value is NULL, then it's equal to

* returning PJ_SUCCESS.

*

* @return       Module should return PJ_SUCCESS to indicate success.

*/

pj_status_t (*stop)(void);

/**

* Optional function to be called to deinitialize the module before

* it is unloaded. This function will be called by endpoint during

* module unregistration. If the value is NULL, then it's equal to

* returning PJ_SUCCESS.

*

* @param mod The module.

*

* @return       Module should return PJ_SUCCESS to indicate success.

*/

pj_status_t (*unload)(void);

/**

* Optional function to be called to process incoming request message.

*

* @param rdata   The incoming message.

*

* @return       Module should return PJ_TRUE if it handles the request,

*           or otherwise it should return PJ_FALSE to allow other

*           modules to handle the request.

*/

pj_bool_t (*on_rx_request)(pjsip_rx_data *rdata);

/**

* Optional function to be called to process incoming response message.

*

* @param rdata   The incoming message.

*

* @return       Module should return PJ_TRUE if it handles the

*           response, or otherwise it should return PJ_FALSE to

*           allow other modules to handle the response.

*/

pj_bool_t (*on_rx_response)(pjsip_rx_data *rdata);

/**

* Optional function to be called when transport layer is about to

* transmit outgoing request message.

*

* @param tdata   The outgoing request message.

*

* @return       Module should return PJ_SUCCESS in all cases.

*           If non-zero (or PJ_FALSE) is returned, the message

*           will not be sent.

*/

pj_status_t (*on_tx_request)(pjsip_tx_data *tdata);

/**

* Optional function to be called when transport layer is about to

* transmit outgoing response message.

*

* @param tdata   The outgoing response message.

*

* @return       Module should return PJ_SUCCESS in all cases.

*           If non-zero (or PJ_FALSE) is returned, the message

*           will not be sent.

*/

pj_status_t (*on_tx_response)(pjsip_tx_data *tdata);

/**

* Optional function to be called when this module is acting as

* transaction user for the specified transaction, when the

* transaction's state has changed.

*

* @param tsx The transaction.

* @param event   The event which has caused the transaction state

*           to change.

*/

void (*on_tsx_state)(pjsip_transaction *tsx, pjsip_event *event);

};

所有回调函数的指针都是可选的,如果没有被指定,被默认为返回成功。

Load, start, stop, unload这四个函数指针被enpoint调用,控制模块的状态,下面的图展示了模块状态的生命周期:

其中on­_rx_request( ) 和 on_rx_response( ) 主要作用是从sip_endpoint或其他的模块接收SIP消息。Callback函数的返回值非常重要,如果返回非0(相当于true),意味这个模块已经处理消息,这时,endpoint将停止分发消息到其他的模块。2.1.3 节呼入消息的处理将会详细描述。

On_tx_request( ) 和 on_tx_response( )在消息被广播前通过transport manager调用,这给了一些类型模块(比如:sigcomp 、 message signing)最后修改消息的机会。所有的模块必须都要返回PJ_SUCCESS(ie zero)。否则分发将会被取消,外出的消息,将会在2.1.4的将会详细描述。

On_tsx_state() 函数用来接收事务状态改变的通知,比如:接收消息、发送消息、定时器事件、传输错误事件都可能引起通知,在2.1.5节将会详细的介绍

2.1.2        模块的优先级

通过优先级指定回调调用的顺序,高优先级模块将首先调用on_rx_request 和 on_rx_response。最后调用on_tx_request 和 on_tx_response

下面是模块优先级的标准

/**

* Module priority guidelines.

*/

enum pjsip_module_priority

{

/**

* This is the priority used by transport layer.

*/

PJSIP_MOD_PRIORITY_TRANSPORT_LAYER = 8,

/**

* This is the priority used by transaction layer.

*/

PJSIP_MOD_PRIORITY_TSX_LAYER   = 16,

/**

* This is the priority used by the user agent and proxy layer.

*/

PJSIP_MOD_PRIORITY_UA_PROXY_LAYER  = 32,

/**

* This is the priority used by the dialog usages.

*/

PJSIP_MOD_PRIORITY_DIALOG_USAGE = 48,

/**

* This is the recommended priority to be used by applications.

*/

PJSIP_MOD_PRIORITY_APPLICATION = 64

};

注意: 数字越小优先级越高

PJSIP_MOD_PRIORITY_TRANSPORT_LAYER 被用于传输管理模块,优先级当前只是被用来控制消息的传送。低优先级的模块将在传输层调用on_tx_request/on_tx_response回调函数之前调用。高优先级的模块,将在传输层处理之后调用这两个函数。2.1 4 将详细介绍outgoing的细节。

PJSIP_MOD_PRIORITY_TSX_LAYER 是Transaction layer拥有的优先级,事务层接收所有属于事务层输入的消息。

PJSIP_MOD_PRIORITY_UA_PROXY_LAYER 是UA layer(dialog framework )或 proxy layer 拥有的权限,UA layer 接收所有输入dialog的消息

PJSIP_MOD_PRIORITY_DIALOG_USAGE 是dialog的拥有的优先级,目前,PJSIP实现两个类型dilalog usage: invite session 和   event subscription(包括refer)。Dialog usage 接收同一个对话的属于特定session的所有消息。

PJSIP_MOD_PRIORITY_APPLICATION 是应用模块和合适的值,当他采用transaction、dialogs 和 dislog usage时。

2.1.3        处理呼入消息的模块

当Incoming Message到达时,提供接收消息的缓存区(结构体:pjsip_rx_data,参考第5章的 “Recive Data Buffer”)传输管理模块解析消息,并且把解析的数据结构存放在缓冲区中,把消息传递到endpoint.

Endpoint 分发接收的消息到每一个注册模块,调用on_rx_request和on_rx_response的回调。从高优先级的模块开始,直到有一个模块返回非0。当模块返回非0时, endpoint 不再发送消息到剩余的模块,因为它假定这个模块关心该消息的处理。

处理消息的模块可能分发消息到其他模块,举例:事务模块接收到匹配的消息,处理该消息然后再分发到其他到事务用户(本身也是一个模块)。Transction传递消息,通过回调 on_rx_request 和 on_rx_response 传递消息到transction user,在设置transction接收缓冲区以便transction user模块能其区分transction内部消息和外部消息。

下图显示模块的如何重叠调用其他的模块

2.1.4        模块处理呼出消息

出去的请求和响应消息由transmit data buffer(pjsip_tx_data)处理,包含了消息结构体本身、内存池、连续的buffer 和 transport info。

Pjsip_transport_send( ) 被调用发送一个消息,transport manager 调用on­_tx_request 或 on_tx_response 为所有的模块,处理顺序是优先级的低先接收消息。当回调被调用时,消息可能已经或还没有被transport layer处理。Transport layer 主要负责管理transimit buffer。

l  Transport info

l  打印结构和连续 buffer的结构体

低于PJSIP_MOD_PRIORITY_TRANSPORT_LAYER优先级的模块,将会接收消息,在这些信息被获取到之前,这就意味着目标地址没有被计算出来并且消息还没有被输出到连续buffer。

如果模块准备改变消息结构体在打印buffer之前,他一定设置他的优先级高于transport layer的优先级,如果模块先看真实的packet bytes,再它被传送到网络之前,它应该设置优先级低于transport layer。

在所有的情况下,模块一定要返回PJ_SUCCESS. 如果模块返回错误码,transmission 将被取消,并且错误码将会返回到调用者pjsip_transport_send.

2.1.5        事务用户及状态回调

回调函数on_tsx_state被用来接收特定事务的通知,当事务状态发生改变时,回调是唯一的通知路径。但是transcation的事务改变也可能会因为非消息的事件引起的。比如:超时或者传输错误

当模块注册为事务用户,才拥有这个回调,在一个事务中,只允许有一个事务用户,transaction user 能够被设置为事务再每一个transction基础上。

在dialog创建的事务,transaction user 被设置为 UA layer 模块,当应用程序手工创建事务时,他们作为事务用户设置。

On_tsx_state回调收到retransmissions的request 和 response消息时,回调将不会再被调用。注意:发送和接收临时的响应将不会被认为重传。临时消息的接收和重传将会导致回调被调用。

PJSIP开发指南-第二章的更多相关文章

  1. Knockout应用开发指南 第二章:监控属性(Observables)

    原文:Knockout应用开发指南 第二章:监控属性(Observables) 关于Knockout的3个重要概念(Observables,DependentObservables,Observabl ...

  2. 二、FreeMarker 模版开发指南 第二章 数值和类型

    章节内容如下:   基本内容 类型 一.基本内容 简介 什么是数值? 什么是类型? 数据模型是哈希表 a.简介 理解数值和类型的概念是理解数据模型的关键所在.然而,数值和类型的概念并不局限于数据模型, ...

  3. Knockout应用开发指南 第九章:高级应用举例

    原文:Knockout应用开发指南 第九章:高级应用举例 1   Contacts editor 这个例子和微软为演示jQuery Data Linking Proposal例子提供的例子一样的提供的 ...

  4. [翻译]现代java开发指南 第二部分

    现代java开发指南 第二部分 第二部分:部署.监控 & 管理,性能分析和基准测试 第一部分,第二部分 =================== 欢迎来到现代 Java 开发指南第二部分.在第一 ...

  5. Android艺术开发探索——第二章:IPC机制(下)

    Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvi ...

  6. Javascript权威指南——第二章词法结构,第三章类型、值和变量,第四章表达式和运算符,第五章语句

    第二章 词法结构 一.HTML并不区分大小写(尽管XHTML区分大小写),而javascript区分大小写:在HTML中,这些标签和属性名可以使用大写也可以使用小写,而在javascript中必须小写 ...

  7. AS开发实战第二章学习笔记——其他

    第二章学习笔记(1.19-1.22)像素Android支持的像素单位主要有px(像素).in(英寸).mm(毫米).pt(磅,1/72英寸).dp(与设备无关的显示单位).dip(就是dp).sp(用 ...

  8. Spring学习指南-第二章-Spring框架基础(完)

    第二章 Spring框架基础 面向接口编程的设计方法 ​ 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...

  9. Python开发【第二章】:Python模块和运算符

    一.模块初识: Python有大量的模块,从而使得开发Python程序非常简洁.类库有包括三中: Python内部提供的模块 业内开源的模块 程序员自己开发的模块 1.Python内部提供一个 sys ...

随机推荐

  1. luogu P4516 [JSOI2018]潜入行动

    LINK:潜入行动 初看题感觉很不可做 但是树形dp的状态过于明显. 容易设\(f_{x,j,l,r}\)表示x为根子树内放了j个设备且子树内都被覆盖l表示x是否被覆盖r表示x是否放设备的方案数. 初 ...

  2. SpringBoot+Shiro+JWT前后端分离实现用户权限和接口权限控制

    1. 引入需要的依赖 我使用的是原生jwt的依赖包,在maven仓库中有好多衍生的jwt依赖包,可自己在maven仓库中选择,实现大同小异. <dependency> <groupI ...

  3. Prometheus的伴侣:Grafana在centos下的搭建

    Grafana 是一款采用 go 语言编写的开源应用,主要用于监控指标数据的可视化展现,是当前最流行的时序数据展示工具,目前已经支持绝大部分常用的时序数据库.Grafana常常搭配用作Promethe ...

  4. 题解 [SHOI2002]滑雪

    记忆化搜索$||dp||$剪枝 先讲方法,代码待会上 方法一:记忆化搜索 这个方法不怎么解释,就是每搜索完一个高度的最长路径记录一下,以后搜索其他的点时如果走到了这条路就直接用记录的值计算就是了 方法 ...

  5. ThreadLocal面试六连问

    转自:码农沉思录 中高级阶段开发者出去面试,应该躲不开ThreadLocal相关问题,本文就常见问题做出一些解答,欢迎留言探讨. ThreadLocal为Java并发提供了一个新的思路, 它用来存储T ...

  6. asp.net 远程模型验证

    有这样一些场景,我们需要模型验证,某些字段不允许重复,但是又不希望在数据访问层增加一堆额外逻辑判断.我们需要数据访问层简洁,这种模型验证在进去Action之前,验证不通过直接告诉前端. 一个特性,继承 ...

  7. 013_go语言中的函数多返回值

    代码演示 package main import "fmt" func vals() (int, int) { return 3, 7 } func main() { a, b : ...

  8. 基于深度学习的人脸识别系统Win10 环境安装与配置(python+opencv+tensorflow)

    一.需要下载的软件.环境及文件 (由于之前见识短浅,对Anaconda这个工具不了解,所以需要对安装过程做出改变:就是Python3.7.2的下载安装是可选的,因为Anaconda已经为我们解决Pyt ...

  9. 网络协议: TCP/IP 和UDP/IP

    网络协议: TCP/IP 和UDP/IP TCP/IP TCP/IP(Transmission Control Protocol/Internet Protocol)是一种可靠的网络数据传输控制协议. ...

  10. 使用webgl(three.js)创建科技版3D机房,3D机房微模块详细介绍(升级版三)—— 1

    上节课已经详细描述了微模块机房的实现过程,文章地址(https://www.cnblogs.com/yeyunfei/p/10484241.html) 紧接着上节课的内容 我们这节可来详细讲解科技版机 ...