概述

在之前的文章中,我们介绍了如何使用fs的event事件机制来获取呼叫的各种信息。

这些event事件一般都是底层模块定义好的,其中的各种信息已经很完备了,日常的开发需求都可以满足。

但是,总有一些场景是无法完全满足的,例如,在fs的注册事件中,就没有X-自定义头域的信息。

在定制化的sip交互过程中,freeswitch是支持自定义头域的,头域格式要满足“X-***”的模式。而当我们订阅了"sofia::register"事件,在事件中是无法获得自定义头域的信息的。

本文从fs的核心模块mod_sofia的代码出发,分析如何增加对自定义头域的信息的获取和事件上报。

环境

centos:CentOS  release 7.0 (Final)或以上版本

freeswitch:v1.8.7

GCC:4.8.5

mod_sofia模块

mod_sofia模块是fs在sofia-sip库的基础上实现的SIP终端模块,fs中所有的sip消息处理和上报都要通过mod_sofia模块来对接。

我们可以在 src\mod\endpoints\mod_sofia\sofia_reg.c 文件中,找到注册消息的处理函数“sofia_reg_handle_register_token”,并在函数中找到“MY_EVENT_REGISTER "sofia::register"”事件的创建和上报流程。

if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) {

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-hosts", profile->presence_hosts ? profile->presence_hosts : "n/a");

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);

switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);

if (update_registration) {

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "update-reg", "true");

}

if (v_event && *v_event) {

switch_event_merge(s_event, *v_event);

}

//add by zr 20220121

for (sip_unknown_t *un = sip->sip_unknown; un; un = un->un_next) {

switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, un->un_name, un->un_value);

}

switch_event_fire(&s_event);

}

从上面的代码中,我们可以看到“sofia::register”事件中包含的所有头域内容。

sofia sip协议栈会解析所有的头域,并把非标准的头域都放到“sip->sip_unknown”中。

在红色新增的代码中,我们把所有unknown的头域都放到register上报事件中。

编译

cd freeswitch-1.8.7/src/mod/endpoints/mod_sofia

make

make install

测试

启动freeswitch,使用sip终端注册1002账户。

使用api命令“/event plain ALL”打开fs的事件打印,可以在屏显中看到如下信息:

RECV EVENT

Event-Subclass: sofia::register

Event-Name: CUSTOM

Core-UUID: b95d5721-38f1-406d-b6f1-8c056394d63e

FreeSWITCH-Hostname: localhost.localdomain

FreeSWITCH-Switchname: localhost.localdomain

FreeSWITCH-IPv4: 192.168.0.152

FreeSWITCH-IPv6: ::1

Event-Date-Local: 2022-01-21 17:15:14

Event-Date-GMT: Fri, 21 Jan 2022 09:15:14 GMT

Event-Date-Timestamp: 1642756514420767

Event-Calling-File: sofia_reg.c

Event-Calling-Function: sofia_reg_handle_register_token

Event-Calling-Line-Number: 2011

Event-Sequence: 902

profile-name: internal

from-user: 1002

from-host: 192.168.0.152

presence-hosts: 192.168.0.152,192.168.0.152

contact: "1002" <sip:1002@10.9.136.138:1666;fs_nat=yes;fs_path=sip:1002@10.9.136.138:1666>

call-id: 1378235421@10.9.136.138

rpid: unknown

status: Registered(UDP-NAT)

expires: 3600

to-user: 1002

to-host: 192.168.0.152

network-ip: 10.9.136.138

network-port: 1666

username: 1002

realm: 192.168.0.152

user-agent: FaramAndroid/1.5.9

sip_number_alias: 1002

sip_auth_username: 1002

sip_auth_realm: 192.168.0.152

number_alias: 1002

user_name: 1002

domain_name: 192.168.0.152

record_stereo: true

default_gateway: example.com

default_areacode: 918

transfer_fallback_extension: operator

toll_allow: domestic,international,local

accountcode: 1002

user_context: default

effective_caller_id_name: Extension 1002

effective_caller_id_number: 1002

outbound_caller_id_name: FreeSWITCH

outbound_caller_id_number: 0000000000

callgroup: techsupport

X-Packet: com.sipp

X-Brand: huawei

X-Osver: 29

X-Token: IQAAAACy0eGUAAAWdHyqUVfb0b

X-Jgtoken: 190e35f7e0

X-Olduser: 12345678

我们可以在事件信息的最后看到“X-”开头的自定义头域信息打印。

总结

本文从fs的sip协议栈出发,修改了mod_sofia模块代码,增加自定义消息头域的事件上报,对sip消息的定制有一定参考意义。

但是,在日常的VOIP中,我们应该尽量避免自定义头域的使用,以避免兼容性的问题。


空空如常

求真得真

freeswitch修改mod_sofia模块并上报自定义头域的更多相关文章

  1. Joomla - 自定义(自定义模块、修改原有模块样式、添加全局JS)

    一.自定义模块 自定义模块 参考 Joomla - 模块系统(新建模块.模块类别.自定义模块)第三点 自定义模块部分 自定义模块布局 参考 Joomla - T3模板(非常好用的4屏响应式模板) 的第 ...

  2. APM飞控修改数传模块方法

    APM飞控修改数传模块方法 硬件 ARDUCOPTER第二代 数传模块(USB接口) 数传模块(telem接口) usb-ttl模块 修改方法 注意:APM固件版本和数传模块估计版本是分开的,但有一定 ...

  3. 21、手把手教你Extjs5(二十一)模块Form的自定义的设计

    前面几节完成了模块Grid的自定义,模块Form自定义的过程和Grid的过程类似,但是要更复杂一些.先来设计一下要完成的总体目标. 1、可以有多个Form方案,对应于显示.新增.修改.审核.审批等功能 ...

  4. Django实现自定义template页面并在admin site的app模块中加入自定义跳转链接

    在文章 Django实现自定义template页面并在admin site的app模块中加入自定义跳转链接(一) 中我们成功的为/feedback/feedback_stats/路径自定义了使用tem ...

  5. laravel修改用户模块的密码验证

    做项目的时候,用户认证几乎是必不可少的,如果我们的项目由于一些原因不得不使用 users 之外的用户表进行认证,那么就需要多做一点工作来完成这个功能. 现在假设我们只需要修改登录用户的表,表名和表结构 ...

  6. freeswitch的话单模块

    概述 最近因为业务需要,在看freeswitch中话单相关的一些模块. 在voip的使用过程中,话单是重要的基础模块,涉及到计费和问题查找. 呼叫话单最重要的一点是稳定,不能有错误或遗漏. 本章对fs ...

  7. C#综合揭秘——通过修改注册表建立Windows自定义协议

    引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...

  8. 【转】C#综合揭秘——通过修改注册表建立Windows自定义协议

    引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...

  9. 修改VCL源码实现自定义输入对话框

    来自:https://yq.aliyun.com/wenji/88428 通过修改VCL源码实现自定义输入对话框 在BCB中有两个函数可以实现输入对话框:InputBox和InputQuery,其实I ...

  10. Swift自定义头视图和尾视图

    var data: [[String]]! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup a ...

随机推荐

  1. 怎么在Android项目中导入ffmpeg库?

    1.前言 在这里我以导入静态库(.a)为例进行分析,动态库(.so)是类似的.在导入前,各位要先编译好ffmpeg库,需要注意的是在编译的时候要开启交叉编译,目标平台为Android,其他平台的库(w ...

  2. NoSQL数据库与关系数据库的比较

    1.在原理方面 2.在数据规模方面 3.在数据库模式方面 4.查询效率方面: 5.在事务一致性方面: 6.在数据完整性方面: 7.在可扩展性方面: 8.在可用性方面 9.在标准化方面: 10.在技术支 ...

  3. Redis 学习笔记2:持久化

    目录 1 什么是持久化 1.1 aof 1.2 rdb 2 RDB持久化 2.1 RDB 是什么 2.2 手动触发 3 AOF持久化 3.1 aof 是什么 3.2 appendfile 文件说明: ...

  4. Oracle表空间和数据文件

    表空间:tablespace 表空间就是:存放数据库表.索引.等等对象的逻辑空间. oracle数据在安装并创建实例后,默认会自动创建多个表空间. ORACL默认表空间 SYSTEM表空间 存放ora ...

  5. 在Linux服务器上装jenkins(方式一:war包)

    官网下载jenkins https://www.jenkins.io/zh/download/ 官网下载太慢,可以去清华镜像下载(百度搜索:清华镜像) 下载的文件是jenkins.war 把安装文件放 ...

  6. 用c++写 爱心图案

    绘制爱心曲线 现代数学的一个有趣的证明是 Georg Cantor 证明了有理数是可枚举的.在这篇博客中,我们将通过编程绘制一个简单而美丽的数学图形:爱心曲线. 爱心曲线代码 //爱心曲线 (x^2 ...

  7. flutter屏幕适配方案

    使用MediaQuery和比例因子 优点:使用简单,可以处理大多数情况下的屏幕适配需求. 缺点:需要手动计算比例因子,并且随着UI元素变得更加复杂和层次化(例如多层次列表或动画效果),使用此方法可能会 ...

  8. 18、Scaffold 布局组件

    Scaffold 是一个非常重要的布局组件,它提供了一个常见的应用程序结构布局,包含了许多基础的 UI 元素和交互方式. Scaffold 组件主要由以下几个部分组成: AppBar:用于显示在页面顶 ...

  9. 云图说|ModelArts开发环境,让AI开发、探索、教学更简单

    摘要:ModelArts开发环境,以云原生的资源使用和开发工具链的集成,目标为不同类型AI开发.探索.教学用户. 本文分享自华为云社区<[云图说]| 第280期 ModelArts开发环境,让A ...

  10. 你应该知道的数仓安全——默认权限实现共享schema

    摘要: 一种典型客户场景是一些用户是数据的生产方,需要在schema中创建表并写入数据:而另一些用户是数据的消费方,读取schema中的数据做分析.使用Alter default privilege语 ...