背景

最近Gemfield团队在使用其它部门的某三方库进行GB28181协议的适配,然后在Docker化的过程中遇到了问题:SIP信令在Docker网络上无法正常工作。具体来说,当服务部署在宿主机(192.168.2.102)上的时候,UAS给UAC发送invite指令是没有问题的;但是服务一旦部署在Docker容器里,网络使用Docker自身的bridge进行SIP协议的收发时,UAS发送给UAC的invite指令的目的地址就是错误的(通过wireshark抓包分析),本来应该是UAC(国标IPC,地址192.168.2.103)的IP,但不知道什么原因,这个IP变成了宿主机的IP(192.168.2.102):

为了排除其它网络问题,Gemfield在同一个容器里使用python脚本进行同一invite指令的模拟,发现指令的目的IP变成国标IPC的了(192.168.2.103),信令也能正常工作:

模拟该信令的脚本如下所示:

import socket
def main():# filename = sys.argv[1]port = 5060ip = '192.168.2.103'# ts, pkt = dpkt.pcap.Reader(open(filename, 'r'))sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)gemfield_payload = bytearray.fromhex('30333a3...<copy the payload from wireshark as hex>...0300d0a0d0a')sock.sendto(gemfield_payload, (ip, port))buf, addr = sock.recvfrom(2048, 0)print(addr)if __name__ == '__main__':main()

于是排除了网络的原因。但因为种种原因,主要因为其它部门太忙了,无法进一步debug下去,问题迟迟得不到解决。这个时候,Gemfield设置了一个独立的task,在小组内部来并行推动这个事情的解决:使用开源的SIP协议栈库来进行这个问题的模拟和复现。这个开源的SIP协议栈,Gemfield选择了ReSIProcate。

ReSIProcate库的简介

ReSIProcate来源于功能完善的开源SIP协议栈VOCAL,基于RFC3261和RFC2327标准,使用C++语言编写,性能稳定。

  1. 项目地址为:https://github.com/resiprocate/resiprocate;
  2. ReSIProcate feature列表(非常值得一看):https://www.resiprocate.org/ReSIProcate_Current_Features;
  3. Ubuntu上的ReSIProcate package:https://launchpad.net/ubuntu/+source/resiprocat;

ReSIProcate库主要分为reSIProcate stack(核心协议栈)、DUM(The Dialog Usage Manager )、recon(Conversation Manager )、repro(SIP Proxy)这四部分。

reSIProcate stack

项目的resip/stack目录为核心的SIP栈的实现,基于该项目进行开发的普通程序员不应该涉及这部分底层的东西,相反,应该使用DUM、repro、recon这些层。核心协议栈的UTcase和参考例子在ReSIProcate项目的rutil/test 和 resip/stack/test 目录下,特别注意testStack.cxx这个文件。

The Dialog Usage Manager (DUM)

这部分代码在resip/dum目录下,UT case和参考例子在resip/dum/test目录下。DUM在核心的SIP栈之上,用来SIP Dialog的创建和处理。这可以用来设置Registrations、Calls/InviteSessions、Subscriptions、Publications等。对于Invite Sessions来说,DUM会将收到的SDP bodies交给上层的应用程序处理。 大多数SIP应用程序都基于DUM这一层进行开发,因为DUM提供了极高的灵活性和可扩展性。

Conversation Manager (recon)

代码在resip/recon目录下,UT case和参考例子在resip/recon/test目录下,可以特别留神testUA.cxx文件。recon在核心SIP栈和DUM层之上,用来和media以及相关的sip信令打交道。recon使用sipXtapi media栈提供audio RTP的处理。

SIP Proxy(repro)

repro是一个独立的SIP服务程序,该部分代码在项目的repro目录下,repro在核心SIP栈之上,使用DUM来进行SIP注册的处理,使用核心SIP栈来进行SIP信令的proxy。

ReSIProcate库的消息处理架构如下所示:

ReSIProcate库中的类层次如下图所示:

编译ReSIProcate库

使用如下步骤进行基本的编译:

root@uas:/home/gemfield/github/resiprocate-master# autoreconf -fi
root@uas:/home/gemfield/github/resiprocate-master# ./configure
root@uas:/home/gemfield/github/resiprocate-master# make -j4
root@uas:/home/gemfield/github/resiprocate-master# make check
root@uas:/home/gemfield/github/resiprocate-master# make install

上述configure的时候可以指定安装的目录,比如:./configure --prefix=/home/gemfield/github/tmp_install/ 将会导致最后的安装如下所示:

root@5a941ec09bd0:/home/gemfield/github/Gemfield/resiprocate# make install
Making install in rutil
......
Libraries have been installed in:/home/gemfield/github/tmp_install/lib

生成的install目录如下所示:

root@uas:/home/gemfield/github/tmp_install# ls -l
total 12
drwxr-xr-x 4 root root 4096 Nov 25 08:04 include
drwxr-xr-x 2 root root 4096 Nov 25 08:04 lib
drwxr-xr-x 3 root root 4096 Nov 25 08:04 share

有头文件、库文件和文档。其中库文件如下所示:

root@uas:/home/gemfield/github/tmp_install# ls -l lib/
total 140876
-rwxr-xr-x 1 root root 13431224 Nov 25 08:04 libdum-1.12.so
-rw-r--r-- 1 root root 36667544 Nov 25 08:04 libdum.a
-rwxr-xr-x 1 root root     1183 Nov 25 08:04 libdum.la
lrwxrwxrwx 1 root root       14 Nov 25 08:04 libdum.so -> libdum-1.12.so
-rwxr-xr-x 1 root root 20110880 Nov 25 08:04 libresip-1.12.so
-rw-r--r-- 1 root root 54648650 Nov 25 08:04 libresip.a
-rwxr-xr-x 1 root root     1147 Nov 25 08:04 libresip.la
lrwxrwxrwx 1 root root       16 Nov 25 08:04 libresip.so -> libresip-1.12.so
-rwxr-xr-x 1 root root   181088 Nov 25 08:04 libresipares-1.12.so
-rw-r--r-- 1 root root   353168 Nov 25 08:04 libresipares.a
-rwxr-xr-x 1 root root     1061 Nov 25 08:04 libresipares.la
lrwxrwxrwx 1 root root       20 Nov 25 08:04 libresipares.so -> libresipares-1.12.so
-rwxr-xr-x 1 root root  5323416 Nov 25 08:04 librutil-1.12.so
-rw-r--r-- 1 root root 13493638 Nov 25 08:04 librutil.a
-rwxr-xr-x 1 root root     1097 Nov 25 08:04 librutil.la
lrwxrwxrwx 1 root root       16 Nov 25 08:04 librutil.so -> librutil-1.12.so

这些库和文件都来自:

#动态库
./resip/stack/.libs/libresip.so
./resip/stack/.libs/libresip-1.12.so
./resip/dum/.libs/libdum-1.12.so
./resip/dum/.libs/libdum.so
./rutil/dns/ares/.libs/libresipares-1.12.so
./rutil/dns/ares/.libs/libresipares.so
./rutil/.libs/librutil.so
./rutil/.libs/librutil-1.12.so
#静态库
./contrib/popt/win32/lib/libpopt.dll.a
./contrib/popt/win32/lib/libpopt.a
./resip/stack/.libs/libresip.a
./resip/dum/.libs/libdum.a
./rutil/dns/ares/.libs/libresipares.a
./rutil/.libs/librutil.a
#可执行文件
./resip/certs/makeCA
./resip/certs/makeCert
......

如果要使用这些库,则需要在编译的时候设置LD_RUN_PATH,而在运行的时候设置LD_LIBRARY_PATH;如果需要一个更多功能的编译,则在configure的时候加上更多的参数:

root@uas:/home/gemfield/github/resiprocate-master# ./configure --enable-ipv6 --with-ssl --with-geoip --with-tfm --with-repro --with-mysql --with-popt CXXFLAGS="-I`pwd`/contrib/cajun/include"

或者,仿照github项目中的构建脚本,先安装如下依赖:

sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ bionic main universe"
sudo apt-get update -qq
sudo apt-get install -qq gperf libasio-dev libboost-dev libc-ares-dev libdb++-dev libpopt-dev libssl-dev perl libmysqlclient-dev libpq-dev libcppunit-dev autotools-dev libpcre3-dev libxerces-c-dev curl libcajun-dev python-cxx-dev libsrtp-dev libgloox-dev libtelepathy-qt5-dev
sudo apt-get install -qq debian-archive-keyring
wget -q -O - https://ftp-master.debian.org/keys/release-10.asc | sudo apt-key add -
wget -q -O - https://ftp-master.debian.org/keys/archive-key-10.asc | sudo apt-key add -
sudo add-apt-repository -y "deb http://http.us.debian.org/debian/ buster main"
sudo add-apt-repository -y "deb http://http.us.debian.org/debian/ buster-backports main"
curl -O http://apt.debify.org/debify/pool/main/d/debify-archive-keyring/debify-archive-keyring_2019.01_all.deb
sudo dpkg -i debify-archive-keyring_2019.01_all.deb
sudo add-apt-repository -y "deb http://apt.debify.org/debify debify-buster-backports main"
sudo apt-get update -qq
sudo apt-get install -qq --force-yes -t buster libradcli-dev libsoci-dev libqpid-proton-cpp12-dev
sudo apt-get install -qq --force-yes -t debify-buster-backports libsipxtapi-dev

再进行configure:

#build/travis/bootstrap
autoreconf --install
rm resip/stack/gen/*
ls -l /usr/include/asio.hpp#build/travis/configure
./configure --enable-assert-syslog --with-popt --with-ssl --with-mysql --with-postgresql --with-apps --with-telepathy --enable-dtls --enable-ipv6 --with-radcli --with-qpid-proton --with-repro --enable-repro-plugins DEPS_PYTHON_CFLAGS="`/usr/bin/python2.7-config --cflags`" DEPS_PYTHON_LIBS="`/usr/bin/python2.7-config --ldflags`" PYCXX_SRCDIR=/usr/share/python2.7/CXX/Python2 --with-python --with-rend --with-recon CPPFLAGS="-I/usr/include/postgresql -I/usr/include/sipxtapi -D__pingtel_on_posix__ -D_linux_ -D_REENTRANT -D_FILE_OFFS -DDEFAULT_BRIDGE_MAX_IN_OUTPUTS=20 -DRESIP_DIGEST_LOGGING -I/usr/include/soci -I/usr/include/mysql" CXXFLAGS="-Wformat -Werror=format-security -fpermissive" --with-c-ares

基于DUM库开始进行应用程序的开发

大多数应用都是基于DUM库进行业务的开发。主要有以下几个阶段:

程序的初始化

程序主程序的初始化阶段要进行如下的设置:

  1. Create a Security Object (if required)
  2. Create SipStack
  3. Create DialogUsageManager
  4. Add transports
  5. Create/Set MasterProfile
  6. Supported Methods, Mime Types, etc.
  7. Validation Settings, Advertised Capabilities
  8. Set Outbound Decorators
  9. Set Handlers (ie. InviteSessionHandler)
  10. Set Managers (ie. ClientAuth, KeepAlive)
  11. Set AppDialogSet Factory
  12. Start Stack Processing / Thread
  13. Start DUM Processing / Thread

程序的关闭

使用DUM的Shutdown Handler:

DUM Application Shutdown​www.resiprocate.org

DUM的handler

  1. Invite Session Handler
  2. Client/Server Registration Handlers
  3. Client/Server Subscription Handlers
  4. Default Server Refer Handler (?)
  5. Client/Server Publication Handlers
  6. Pager Message Handler
  7. Redirect Handler
  8. DialogSet Handler
  9. Out Of Dialog Handler
  10. Shutdown Handler

DUM的注册和鉴权

如果是UAS,则继承并实现ServerAuthManager中的相关API;如果是UAC,则继承并实现ClientAuthManager中的相关API。

GB28181 UAS的开发

设备注册

很简单,继承并实现resip::ServerAuthManager中的

requiresChallenge
requestCredential
onAuthSuccess
onAuthFailure

实时点播的invite信令

按照GB28181的标准,invite消息格式为:

INVITE sip:媒体流发送者设备编码@目的域名或IP地址端口 SIP/2.0

To:sip:媒体流发送者设备编码@目的域名
Content-Length:消息实体的字节长度
Contact:<sip:媒体流接收者设备编码@源IP地址端口>
CSeq:1 INVITE
Call-ID:xxxxxxxxxxxxxxxxxxxsss@ip
Via:SIP/2.0/UDP源域名或IP地址
From:<sip:媒体流接收者设备编码@源域名;tag=gemfield
Subject:媒体流发送者设备编码:发送端媒体流序列号,媒体流接收者设备编码:接收端媒体流序列号
Content-Type:application/sdp
Max-Forwards:70
#下面是SDP的定义,INVITE消息体中携带的SDP内容应符合RFC2327的相关要求,有如下字段:
------Session description, by Gemfield------
v=0
o=
s=Play
c=IN IP4 192.168.
--------Time description, by Gemfield--------
t=0 0
--------Media description,by Gemfield---------
m=video 6000 RTP/AVP 96 98 97
a=recvonly
a=rtpmap:96 PS/90000
a=rtpmap:98 H264/90000
a=rtpmap:97 MPEG4/90000
y=

其中,SDP部分的字段含义如下:

  1. v= 为protocol version;
  2. o= owner/creator and session identifier;
  3. s= 为Session name,如Play代表点播,Playback代表历史回放;Download代表文件下载;Talk代表语音对讲;
  4. u=* 为URI of description;
  5. c=* 为connection information-not required if included in all media;
  6. t= 为time the session is active;点播时00,回放或下载时,t的值为开始时间和结束时间,用空格分开;
  7. m= 为media name and transport address;
  8. c=* 为connection information-optional if included at session-level;
  9. b=* bandwidth information;
  10. a=* zero or more media attribute lines;这个字段的格式为rtpmap:(payload type)(encoding name)/(clock rate)[/(encoding parameters)]
  11. y=* SSRC;十进制整数字符串,格式为Dddddddddd(第一位为历史或实时媒体流的标识位,1为历史,0为实时);
  12. f=* 媒体描述:f=v/编码格式/分辨率/帧率/码率类型/码率大小 a/编码格式/码率大小/采样率。

开源协议栈 rlc rrc_从ReSIProcate SIP协议栈库到GB28181相关推荐

  1. 几种开源SIP协议栈对比OPAL,VOCAL,sipX,ReSIProcate,oSIP

    随着VoIP和NGN技术的发展,H.323时代即将过渡到SIP时代,在H.323的开源协议栈中,Openh323占统治地位,它把一个复杂而又先进 的H.323协议栈展现在普通程序员的眼前,为H.323 ...

  2. 智能视屏会议系统(19)---开源视频会议SIP协议栈

    开源视频会议SIP协议栈 最近接触了一些视频通讯方面的知识,为方便以后查阅,因此整理到这里.  以下是几个比较重要的开源SIP协议栈  视频会议系统由于需要与不同的终端进行连接,因此我们需要视频会议终 ...

  3. 几种开源SIP协议栈对比

    随着VoIP和NGN技术的发展,H.323时代即将过渡到SIP时代,在 H.323的开源协议栈中,Openh323占统治地位,它把一个复杂而又先进的H.323协议栈展现在普通程序员的眼前,为H.323 ...

  4. 开源的SIP协议栈 PJSIP

    PJSIP是一个开放源代码的SIP协议栈.它支持多种SIP的扩展功能,目前可说算是最流行的sip协议栈之一了. 下面列出其重要的几种优点: 1)代码层次非常清晰,从低级到高级都提供了很方便的接口供开发 ...

  5. SIP协议栈OSIP分析

    之前整理的linephone中使用的OSIP协议栈文档,版本为2-3.1.0,仅供参考. 一关于osip 2 二osip库的模块构成 2 三关键数据结构及其说明 2 四初始化所做的工作 6 五sip消 ...

  6. Asterisk 1.8 sip 协议栈分析

    引用自:http://blog.csdn.net/z1623866465/archive/2011/01/02/6113057.aspx 看了一下 asterisk 1.8 ,chan_sip 更新了 ...

  7. android sip协议栈,基于Android平台及SIP协议的软电话系统的研究

    摘要: 随着互联网通信技术不断发展以及智能手机的日益流行,VoIP(Voice Over InternetProtocol)技术得到了越来越广泛的应用.VoIP技术能结合这两者改变传统长途电话费用高昂 ...

  8. vant步进器传值_有赞开源的Vue 2.0 的 Mobile 组件库 Vant

    有赞开源的Vue 2.0 的 Mobile 组件库 Vant 是一个轻量.可靠的移动端 Vue 组件库.包括了基础组件.Button 按钮.Cell 单元格.Icon 图标.Image 图片.Layo ...

  9. 移动端cube界面设计html,滴滴开源基于 Vue.js 的移动端组件库 cube-ui

    原标题:滴滴开源基于 Vue.js 的移动端组件库 cube-ui 开源最前线(ID:OpenSourceTop) 猿妹 整编 综合自:https://didi.github.io/cube-ui/ ...

最新文章

  1. 企业分布式微服务云SpringCloud SpringBoot mybatis (九)Spring Boot多数据源配置与使用(JdbcTemplate支持)...
  2. DOM操作之CRUD操作
  3. 为安装创建软链接,迁移文件夹
  4. lisp 绘制立体感的五角星_[原创]圆内加五角星lsp代码,详细有注解
  5. [C++] this指针
  6. win7系统的CMD窗口切换目录--小计
  7. 【Flink】Flink checkpoint expired before completing
  8. 在线时序流程图制作工具
  9. bootstrap java web_JavaWEB开发05_Bootstrap
  10. 内存管理之memblock探寻
  11. MongoDB 在windows shell环境下的基本操作和命令的使用示例(四)
  12. 模糊数学模型(一): 隶属函数、模糊集合的表示方法、模糊关系、模糊矩阵
  13. QCSPCChart SPC for JS
  14. FreeImage的学习总结总结(一)
  15. XMind 8破解教程
  16. 203.为用户定义的数据类型绑定默认值案例
  17. MASKGROUP: HIERARCHICAL POINT GROUPING AND MASKING FOR 3D INSTANCE SEGMENTATION
  18. phpstorm2019--设置自动换行
  19. Python基于OpenCV的图像去雾算法[完整源码&部署教程]
  20. A Game of Thrones(9)

热门文章

  1. Spring Boot Swagger3启动出现警告Unable to interpret the implicit parameter configuration with dataType
  2. span标签的取值与赋值
  3. php 字符串分割出数字,php 字符串分割函数的总结
  4. oracle rman备份 归档模式,Oracle RMAN备份归档与非归档模式
  5. RabbitMQ 基本使用(注解的方式)
  6. java使用bks双向认证_客户端与服务器SSL双向认证(客户端:Android
  7. 再谈table组件:固定表头和表列
  8. Hyperledger Fabric服务器配置及修改Docker容器卷宗存储根目录/位置
  9. apple apns http2 java调用
  10. 第8周课堂测试3(课上未完成)