一、模块

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. 初学编程丨从零开始学习编程的基本路线,BAT程序员亲手总结!

    编程并不是说代码怎么写,框架怎么用,业务怎么转换为代码逻辑,这些都不是编程的要素(但却是工作的刚需......).我认为按照下面这个路线来学习编程,会使自己在学习的路途上少去很多问题(比如为啥会有多线 ...

  2. 6.18 省选模拟赛 树 倍增 LCT

    LINK:树 考虑暴力 保存每个版本的父亲 然后暴力向上跳.得分20. 考虑离线 可以离线那么就可以先把树给搞出来 然后考虑求k级祖先 可以倍增求. 如何判断合法 其实要求路径上的边的时间戳<= ...

  3. 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用

    一.什么是 RestTemplate? RestTemplate是执行HTTP请求的同步阻塞式的客户端,它在HTTP客户端库(例如JDK HttpURLConnection,Apache HttpCo ...

  4. 《分享》Koa2源码分析

    曾经在公司内部做的一起关于koa源码的分享,希望对你有帮助: koa2 源码分析整理 koa2(2.4.1版本)源码主要包含四个js,包括application.js, context.js, req ...

  5. 29-main()的使用说明

    * 1. main()方法作为程序的入口 * 2. main()方法也是一个普通的静态方法 * 3. main()方法可以作为我们与控制台交互的方式.(使用Scanner) 如何将控制台获取的数据传给 ...

  6. cocos2d-x_下载游戏引擎并创建第一个项目

    我是一名小白. 下载并创建游戏项目 第一步:去官网下载cocos2d-x http://www.cocos.com/download 第二步:将安装包里边的 setup.py 拖进命令行点击回车键 , ...

  7. 关于Springboot配置文件的理解

    一.Springboot Springboot是用来简化Spring框架搭建和开发一款框架,可以理解为是一种Spring框架的简化版. 二.如何在IDEA里面初始化Springboot 主要可以分为两 ...

  8. FTP服务器搭建及自动备份设置

    本次随笔内容主要是FTP服务器搭建. 其实去年十月服务器就搭建完了.当时写了个PPT保存了一下,准备以后写博客,结果时隔快一年我自己都快要看不懂我自己写的PPT了  ( = o = ) 不过还是尽量尝 ...

  9. 37 Reasons why your Neural Network is not working

    37 Reasons why your Neural Network is not working Neural Network Check List 如何使用这个指南 数据问题 检查输入数据 试一下 ...

  10. SpringBoot进阶教程(六十三)Jasypt配置文件加密

    数据库密码直接明文写在配置中,对安全来说,是一个很大的挑战.一旦密码泄漏,将会带来很大的安全隐患.尤其在一些企业对安全性要求很高,因此我们就考虑如何对密码进行加密.本文着重介绍Jasypt对Sprin ...