webrtc详细教程
cdsn博客不支持word文件,所以这里显示不完全。可到本人资源中下载word文档:
v0.3:http://download.csdn.net/detail/kl222/6961491
v0.1:http://download.csdn.net/detail/kl222/6677635
下载完后评论,可以返还你的积分。此文档还在完善中,欢迎大家交流,共同完善。
Webrtc 教程
版本0.3(2014年2月)
康林 (16614119@qq.com)
本文博客地址:http://blog.csdn.net/kl222/article/details/17198873
版本 |
内容 |
时间 |
作者 |
V0.1 |
初建文档 |
2013年11月 |
康林 |
V0.2 |
增加协议文档 |
2014年2月8日 |
康林 |
V0.3 |
细化了windows下编译过程。 增加IDE工具用法。 重新排版整个文档。 |
2014年2月20日 |
康林 |
1 工具:...4
1.1 depot_tools:.4
1.1.1 目标:...4
1.1.2 chromium·使用它来...4
1.1.3 使用说明在这儿...4
1.1.4 下载:...4
1.1.4.1 linux下:...4
1.1.4.2 window下:...5
1.1.5 使用:...5
1.1.5.1 用gclient 获取代码...5
1.1.5.2 gclient 命令:...5
1.1.6 具体使用例子:.5
1.1.6.1 安装工具...5
1.1.6.2 .配置...6
1.2 Gyp工具...6
1.3 Python工具...6
1.4 本地集成开发环境(IDE)...6
1.4.1 Visual studio.6
1.4.2 Kdevelop.12
1.4.3 Eclipse.13
2 Webrtc.13
2.1 下载、编译:...13
2.1.1 Windows下:...13
2.1.2 ubuntu下编译:...17
2.1.3 编译Android(只能在linux下):.20
3 webrtc开发:...20
3.1 开发P2P视频软件需要处理的问题...20
3.1.1 用户列的获取、交换、信令的交换...20
3.1.2 P2P通信...20
3.1.3 多媒体处理...21
3.1.3.1 音视频捕获、播放...21
3.1.3.2 音视频编解码...21
3.1.3.3 音视频效果优化...21
3.2 webrtc架构:...21
3.2.1 WebRTC架构组件介绍...21
(1) 你的web应用程序...21
(2) Web API.21
(3) WebRTCNative C++ API.21
(4) Transport /Session.21
(5) VoiceEngine.22
(6) VideoEngine.23
3.2.2 WebRTC核心模块API介绍...23
(1) 网络传输模块:libjingle.23
(2) WebRTC Native C++ API.23
(3) 音频、视频图像处理的主要数据结构...23
(4) 音频引擎(VoiceEngine)模块 APIs.24
(5) 视频引擎(VideoEngine)模块 APIs.25
3.2.3 webRTC核心API详解...26
3.2.3.1 libjingle_peerconnection.26
3.2.3.2 libjingle_media库:...30
3.2.3.2.1 视频采集,处理、渲染类:...30
4 Libjingle详细介绍...34
4.1 重要组件:...34
4.1.1 信号:...34
4.1.2 线程和消息...34
4.1.3 名称转换...34
4.1.4 Ssl支持...34
4.1.5 连接...34
4.1.6 传输,通道,连接...35
4.1.7 候选项...35
4.1.8 数据包...35
4.2 如何工作:...35
4.2.1 Application模块...36
4.2.2 XMPP Messaging Component.模块...36
4.2.3 Session Logic and management commponent模块。...37
4.2.4 Peer to peer Component模块。...37
4.2.5 其他...38
4.3 建立libjingle应用程序...38
5 代码分析:...38
5.1 音频通道建立过程:...38
5.2 音频接收播放过程:...39
5.3 视频接收播放过程:...42
6 协议:.44
6.1 XMPP协议:.44
6.1.1 原理介绍...44
6.1.2 XMPP协议网络架构...45
6.1.3 XMPP协议的组成...47
6.1.4 Xmpp介绍...48
6.1.5 协议内容...48
6.2 Stun协议:.51
6.2.1 P2P实现的原理...52
6.2.2 P2P的常用实现...54
6.2.3 Stun uri.57
6.2.4 内容...57
6.2.5 中文内容...58
6.2.6 开源服务器...60
6.2.7 公开的免费STUN服务器...60
6.3 Turn协议...61
6.3.1 概念...61
6.3.2 Turn uri62
6.3.3 开源服务器工程...62
6.3.4 开源库...62
6.4 交互式连接建立(InteractiveConnectivity Establishment),一种综合性的NAT穿越的技术。 62
6.4.1 IETF 规格...67
6.4.2 开源工程:...68
6.5 XEP-0166 Jingle.69
6.5.1 绪论...70
6.5.2 需求...71
6.6 Sctp协议...95
6.7 Rtp协议...97
7 附件:...99
7.1 Gyp工具...99
7.2 Google test程序...101
7.3 Webrtc库介绍...102
7.4 webrtc代码相关基础知识...103
7.5 STUN和TURN技术浅析...105
7.6 基于ICE的VoIP穿越NAT改进方案...106
7.7 ubuntu安装使用stuntman.111
7.8 一个开源的ICE库——libnice介绍...111
7.9 4种利用TURN穿越对称型NAT方案的设计与实现...113
7.10 基于ICE方式SIP信令穿透Symmetric_NAT技术研究...114
chromium自己整了一套开发工具系统,原来叫gclient(名字好像让位给google桌面客户端了) ,现在改名depot_tools。
Wrapper script for checking out and updating source code frommultiple SCM repository locations.
chromium使用了(目前 @159834)107个代码仓库的代码,这些分散在多个代码仓库,chromiun不需要某些仓库的东西,google就封装个工具,这个工具既支持svn,也支持git,不光能down代码,也支持了
· patch
· cpplint,pylint
· apply_issue
· junction
· codereview
1.1.2 chromium使用它来
· 更新chromium代码
· 生成工程文件,windows上生产sln,mac生产xcode工程,linux生成scons或者makefile
· 其他的patch,codereview,管理分散开发人员的修改
1.1.3 使用说明在这儿
http://www.chromium.org/developers/how-tos/depottools
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
https://src.chromium.org/svn/trunk/tools/depot_tools.zip
1.1.5.1 用gclient获取代码
· 首先会更新 depot_tools,有两种 bat和sh,目的都一样
更新depot_tools,然后运行python版gclient.py,参数都传给gclient.py
这里解决了鸡生蛋还是蛋生鸡的问题,更新了gclient.py
· 生成.gclient文件,gclient指定了某个版本的chromium·代码
· 执行gclient sync,更新代码,生成工程文件,这里使用了另一个工具 GYP
1.1.5.2 gclient命令:
Commands are:
cleanup Cleans up allworking copies.
config Create a.gclient file in the current directory.
diff Displayslocal diff for every dependencies.
fetch Fetchesupstream commits for all modules.
help Prints listof commands or help for a specific command.
hookinfo Output the hooksthat would be run by `gclient runhooks`
pack Generate apatch which can be applied at the root of the tree.
recurse Operates on allthe entries.
revert Revert allmodifications in every dependencies.
revinfo Output revisioninfo mapping for the client and its dependencies.
runhooks Runs hooks for filesthat have been modified in the local working copy.
status Showmodification status for every dependencies.
sync Checkout/update all modules.
update Alias for thesync command. Deprecated.
Prints list of commands or help for aspecific command.
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-j JOBS, --jobs=JOBS Specifyhow many SCM commands can run in parallel;
default=8
-v, --verbose Produces additional output for diagnostics. Can be
used up to three times for morelogging info.
--gclientfile=CONFIG_FILENAME
Specify an alternate .gclient file
--spec=SPEC create a gclient file containing the provided string.
Due to Cygwin/Python brokenness, itprobably can't
contain any newlines.
1.1.6 具体使用例子:
1.1.6.1 安装工具
http://www.chromium.org/developers/how-tos/install-depot-tools
.gclient和DEPS python语法(精确点就是json语法+“#”型注释,list最末元素可以有,执行时使用python的eval来解释的)
Gyp工具简介见附件。Google自己搞的玩意。Webrtc不是直接用的gyp,而是又封装了一下。
Webrtc中的gyp工具是build/ gyp_chromium
整个webrtc工程是由python程序进行维护。而整个webrtc工程现在处理一个完全不稳定的阶段。所以需要了解一些基本的python语法知识。
一般的在windows本地开发环境(IDE)是visualstudio。然而webrtc默认的是ninja。虽然可以手工生成vs工程,但是经常出现兼容性问题。所以下面介绍下vs加ninja开发环境。
它是一个跨平台开源的集成开发环境。用c++开发。所以效率比较高。本人比较喜欢用它在linux下开发,或用它开发跨平台程序。它默认支持ninja。
原文地址:http://www.webrtc.org/reference/getting-started
http://www.microsoft.com/zh-cn/download/details.aspx?id=30678
Visual Studio 2012 Ultimate旗舰版序列号:
建立用最新版本vs,vs2008以前版本不能保证百分之百兼容。因为开发者用的是最新版本。
a) Windows SDK(主要是需要DirectX sdk,主要是捕获、Render时用的是DirectX)
http://msdn.microsoft.com/zh-cn/windows/bb980924.aspx
从 Windows 7开始,DirectX SDK 就作为 Windows SDK 的一部分包含在内。
注意:然而webrtc现在用的是directx9.0 sdk。所以只要在下面地址下载:
http://www.microsoft.com/en-us/download/details.aspx?id=6812
官网:http://msdn.microsoft.com/zh-cn/windows/hardware/gg454513
Vista以后的版本,可以用最新的windowswdk 8.0
如果是windows xp,则需要wdk7.1.0以前的版本。
git clonehttps://chromium.googlesource.com/chromium/tools/depot_tools.git
https://src.chromium.org/svn/trunk/tools/depot_tools.zip
5) 下载webrtc代码,最好选择稳定代码下载,trunk是当前开发代码库。
E:\source\muli\google>gclientconfighttp://webrtc.googlecode.com/svn/trunk/
这一步主要下载git、svn、python和配置文件.gconfig。
默认配置下载与平台相应的代码,如果要下其它平台代码。修改.gconfig文件,加入target_os = ['windows','android','unix']
E:\source\muli\google\trunk>setGYP_GENERATORS=msvs #设置产生者(可选)
msvs-ninja forVisual Studio project building with ninja
(Windows: ninja/Visual Studio, OSX: ninja/XCode, Linux: ninja/make, Android: ninja)
E:\source\muli\google\trunk>setGYP_MSVS_VERSION=2012 #设置vs产生者版本(可选)
E:\source\muli\google>gclient sync --force #同步源码
更新depot_tools工具、git、svn、python工具、下载webrtc代码及相关工具,有1G多大小。注意:如果下载中卡住了,需要FQ。
这步完成时,会自动调用gyp产生工程。如果没有设置前面两步,则默认的为ninja工程。
(Windows: ninja/Visual Studio, OSX: ninja/XCode, Linux: ninja/make, Android: ninja)
E:\source\muli\google>gclient runhooks --force #运行hooks,重新产生工程
-Gmsvs_version :vs的版本号。产生者由环境变量GYP_GENERATORS设置
--generator-output:工程产生目录,但是生成出来的工程有问题,所以不选。
Msvs版本:建议用最新的版本号,因为开发者用的是最近的版本,所以老版本的兼容性可能会有问题。
________ running'C:\openmeetings\google\depot_tools\python_bin\python.exe trunk
/webrtc/build/gyp_webrtc-Dextra_gyp_flag=0' in 'C:\openmeetings\google'
ERROR at//build/config/win/visual_studio_version.gni:33:24: Script returned non
visual_studio_path =exec_script("get_visual_studio_path.py",
Current dir:C:\openmeetings\google\trunk\out\gn_build.Debug64\
Command:"C:\openmeetings\google\depot_tools\python_bin\python.exe""C:\openmeet
ings\google\trunk\build\config\win\get_visual_studio_path.py"auto
原因是由于没有安装visual studio引起的。解决方法是安装vs2012。
E:\source\muli\google\trunk>pythonbuild\gyp_chromium.py --depth . -G msvs_versi
Traceback (most recent call last):
File "build\gyp_chromium.py", line 18, in <module>
execfile(os.path.join(path, 'gyp_chromium'))
File "E:\source\muli\google\trunk\build\gyp_chromium", line42, in <module>
ImportError: No module namedfind_depot_tools
sys.path.insert(1,os.path.join(chrome_src, 'webrtc', 'build'))
3>.\video_coding\main\source\receiver.cc(159): error C2668: “abs”:对重载函数的调用不明确
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\math.h(491):或 “float abs(float)”
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\math.h(487):或 “double abs(double)”
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\math.h(485):或 “long abs(long)”
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\stdlib.h(380):或 “int abs(int)”
3>.\video_coding\main\source\receiver.cc(164): error C2668: “abs”:对重载函数的调用不明确
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\math.h(491):或 “float abs(float)”
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\math.h(487):或 “double abs(double)”
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\math.h(485):或 “long abs(long)”
3> C:\Program Files\Microsoft VisualStudio 9.0\VC\include\stdlib.h(380):或 “int abs(int)”
以上问题是由于vs2008对C99支持不够,用最新版本vs2012就可以解决。也可以修改代码进行类型强制转换。
svnco http://src.chromium.org/svn/trunk/tools/depot_tools
git clonehttps://chromium.googlesource.com/chromium/tools/depot_tools.git
我的depot_tools下到了 /data/google/depot_tools 中。
exportPATH=$PATH:/data/google/depot_tools
3) 下载webrtc代码,最好选择稳定代码下载,trunk是当前开发代码库。
gclient config http://webrtc.googlecode.com/svn/trunk/(生成.gconfig文件)
默认配置下载与平台相应的代码,如果要下其它平台代码。修改.gconfig文件,加入target_os = ['windows','android','unix']
gclientsync --force(同步项目文件,要下载1个多G的文件,网速不好的,可以去玩一会再回来),注意:如果下载中卡住了,需要FQ。
gclientrunhooks --force (重新生成相应的工程文件,Linux的MakeFile文件)
k@k-C410:/data/google/webrtc/trunk$export GYP_GENERATORS=make
msvs-ninja forVisual Studio project building with ninja
k@k-C410:/data/google/webrtc/trunk$build/gyp_chromium --depth=. all.gyp
Updating projects from gypfiles...
Package nss was not found inthe pkg-config search path.
Perhaps you should add thedirectory containing `nss.pc'
to the PKG_CONFIG_PATHenvironment variable
k@k-C410:/data/google/webrtc/trunk$sudo apt-get install libnss3-dev
________ running'/usr/bin/python trunk/webrtc/build/gyp_webrtc -Dextra_gyp_flag=0' in'/home/google'
Generating gypfiles from GN...
Updating projectsfrom gyp files...
Package gconf-2.0was not found in the pkg-config search path.
Perhaps you shouldadd the directory containing `gconf-2.0.pc'
to thePKG_CONFIG_PATH environment variable
gyp: Call to'pkg-config --cflags gconf-2.0' returned exit status 1.
k@k-C410:/home/google$ sudoapt-get install gconf-2.0
k@k-C410:/data/google/webrtc/trunk$build/gyp_chromium --depth=. all.gyp
k@k-C410:/data/google/webrtc/trunk$make peerconnection_server
k@k-C410:/data/google/webrtc/trunk$make peerconnection_client
k@k-C410:/data/google/webrtc/trunk/out/Debug$ls
genmacro libvpx_obj_int_extract obj.target re2c
genmodule libyuv.a peerconnection_client yasm
genperf linker.lock peerconnection_server
peerconnection_client、 peerconnection_server两个应用程序。
k@k-C410:/data/google/webrtc/trunk/out/Debug$./peerconnection_server
k@k-C410:/data/google/webrtc/trunk/out/Debug$./peerconnection_client
也可以用trunk/talk/examples/peerconnection/server/server_test.html目录下的页面进行测试。
k@k-C410:/data/google/webrtc/trunk$build/gyp_chromium --depth=. all.gyp
Updating projectsfrom gyp files...
Package nss wasnot found in the pkg-config search path.
Perhaps you shouldadd the directory containing `nss.pc'
to thePKG_CONFIG_PATH environment variable
k@k-C410:/data/google/webrtc/trunk$sudo apt-get install libnss3-dev
k@k-C410:/data/google/webrtc/trunk$build/gyp_chromium --depth=. all.gyp
在当前目录下产生out目录,在out目录中有Debug、Release两个子目录,在子目录中有ninja工程文件build.ninja
k@k-C410:/data/google/webrtc/trunk$ninja -C out peerconnection_server
k@k-C410:/data/google/webrtc/trunk$ ninja -C outpeerconnection_client
k@k-C410:/data/google/webrtc/trunk$ ninja -C out All
设置环境变量:ANDROID_NDK_ROOT、ANDROID_SDK_ROOT、JAVA_HOME
k@k-C410:/data/google /webrtc/trunk$export JAVA_HOME=/data/jdk1.7.0_45
k@k-C410:/data/google/webrtc/trunk$exportANDROID_SDK_ROOT=/data/adt-bundle-linux-x86_64-20130917/sdk
k@k-C410:/data/google/webrtc/trunk$export ANDROID_NDK_ROOT=/data/android-ndk-r9
k@k-C410:/data/google/webrtc/trunk$source build/android/envsetup.sh
k@k-C410:/data/google/webrtc/trunk$ build/gyp_chromium --depth=. all.gyp#此步可省
k@k-C410:/data/google/webrtc/trunk$ ninja -C out/Debug All #此步可省
在编译过程中会有些类实例调用静态方法的警告错误。需要提示修改代码。
生成所有程序。
k@k-C410:/data/google/webrtc/trunk/out/Debug$ls *.apk
AppRTCDemo-debug.apk OpenSlDemo-debug.apk WebRTCDemo-debug.apk
在Debug下可以看到许多的测试程序。
XMPP协议主要用于解决获取用户列表、交换用户数、信令交换。
1. 公共网络:这类网络IP之间可以不受限制的进行直接访问。
2. NAT网络:这类网络主机在私有内网中,没有单独的公网IP。但可以通过打洞来找到它在公网中固定的网络地址。STUN协议就是解决些网络问题。
3. 严格的受限NAT网络:这类网络中的主机在私网内,只能单向访问外网。外网不能直接访问它。所以这类网络需要通过在公共网络上的TURN服务器来进行数据中转。TRUN协议就是解决此网络问题的。
为了解决地址转换、防火墙限制访问等问题。所以提供了ICE协议,ICE协议是一个框架,它依赖STUN协议解决完全锥形NAT、以及受限锥形NAT。TURN协议用于解决严格受限NAT网络的问题。
(2)蓝色实线部分是面向浏览器厂商的API层(本教程主要讲解的部分)
(1)你的web应用程序
Web开发者开发的程序,Web开发者可以基于集成WebRTC的浏览器提供的web API开发基于视频、音频的实时通信应用。
(2)WebAPI
面向第三方开发者的WebRTC标准API(Javascript),使开发者能够容易地开发出类似于网络视频聊天的web应用,最新的标准化进程可以查看这里。
(3)WebRTCNative C++ API
本地C++ API层,使浏览器厂商容易实现WebRTC标准的Web API,抽象地对数字信号过程进行处理。主要是 PeerConnection 对象。
(4)Transport/ Session
传输/会话层
会话层组件采用了libjingle库的部分组件实现,无须使用xmpp/jingle协议。
参见:https://developers.google.com/talk/talk_developers_home
现在libjingle已经移到webrtc项目中维护了。位于源码根目录的 talk 目录下。
a. RTPStack协议栈
Real Time Protocol
b. STUN/ICE
可以通过STUN和ICE组件来建立不同类型网络间的呼叫连接。现实网络环境有三种情况:
1. 公共网络:这类网络IP之间可以不受限制的进行直接访问。
2. NAT网络:这类网络主机在私有内网中,没有单独的公网IP。但可以通过打洞来找到它在公网中固定的网络地址。STUN协议就是解决些网络问题
3. 严格的受限NAT网络:这类网络中的主机在私网内,只能单向访问外网。外网不能直接访问它。所以这类网络需要通过在公共网络上的服务器来进行数据中转。TRUN协议就是解决此网络问题的。
ICE是一个框架,在这个框架中,它会判断主机是上面三种类型之一,并用相应的办法来建立主机之间的连接。
c. Session Management
一个抽象的会话层,提供会话建立和管理功能。该层协议留给应用开发者自定义实现。
(5)VoiceEngine
音频引擎是包含一系列音频多媒体处理的框架,包括从视频采集卡到网络传输端等整个解决方案。
PS:VoiceEngine是WebRTC极具价值的技术之一,是Google收购GIPS公司后开源的。在VoIP上,技术业界领先,后面的文章会详细了解
a. iSAC
InternetSpeech Audio Codec
针对VoIP和音频流的宽带和超宽带音频编解码器,是WebRTC音频引擎的默认的编解码器
采样频率:16khz,24khz,32khz;(默认为16khz)
自适应速率为10kbit/s ~ 52kbit/;
自适应包大小:30~60ms;
算法延时:frame + 3ms
b. iLBC
Internet Low Bitrate Codec
VoIP音频流的窄带语音编解码器
采样频率:8khz;
20ms帧比特率为15.2kbps
30ms帧比特率为13.33kbps
标准由IETF RFC3951和RFC3952定义
c. NetEQ for Voice
针对音频软件实现的语音信号处理元件
NetEQ算法:自适应抖动控制算法以及语音包丢失隐藏算法。使其能够快速且高解析度地适应不断变化的网络环境,确保音质优美且缓冲延迟最小。
是GIPS公司独步天下的技术,能够有效的处理由于网络抖动和语音包丢失时候对语音质量产生的影响。
PS:NetEQ 也是WebRTC中一个极具价值的技术,对于提高VoIP质量有明显效果,加以AEC\NR\AGC等模块集成使用,效果更好。
d. Acoustic Echo Canceler (AEC)
回声消除器是一个基于软件的信号处理元件,能实时的去除mic采集到的回声。
e. Noise Reduction (NR)
噪声抑制也是一个基于软件的信号处理元件,用于消除与相关VoIP的某些类型的背景噪声(嘶嘶声,风扇噪音等等… …)
(6)VideoEngine
WebRTC视频处理引擎
VideoEngine是包含一系列视频处理的整体框架,从摄像头采集视频到视频信息网络传输再到视频显示整个完整过程的解决方案。
a. VP8
视频图像编解码器,是WebRTC视频引擎的默认的编解码器
VP8适合实时通信应用场景,因为它主要是针对低延时而设计的编解码器。
PS:VPx编解码器是Google收购ON2公司后开源的,VPx现在是WebM项目的一部分,而WebM项目是Google致力于推动的HTML5标准之一
b. Video Jitter Buffer
视频抖动缓冲器,可以降低由于视频抖动和视频信息包丢失带来的不良影响。
c. Image enhancements
图像质量增强模块
对网络摄像头采集到的图像进行处理,包括明暗度检测、颜色增强、降噪处理等功能,用来提升视频质量。
现在这个模块已经放到webrtc中进行维护了。位于源码根目录的talk目录下。
(2) WebRTC Native C++ API
代码位于源码根目录的talk\app\webrtc 目录下。webrtc封装了peerconnection 对象,这个对象把流媒体传输也封装进去了。
PeerConnection类厂接口:
//PeerConnectionFactoryInterface is the factory interface use for creating
//PeerConnection, MediaStream and media tracks.
//PeerConnectionFactoryInterface will create required libjingle threads,
//socket and network manager factory classes for networking.
//If an application decides to provide its own threads and network
//implementation of these classes it should use the alternate
//CreatePeerConnectionFactory method which accepts threads as input and use the
//CreatePeerConnection version that takes a PortAllocatorFactoryInterface as
//argument.
PeerConnectionFactoryInterface
PeerConnectionInterface接口:
peerconnection API:talk/app/webrtc/peerconnectioninterface.h
webrtc本地API:talk/app/webrtc/mediastreaminterface.h
(3) 音频、视频图像处理的主要数据结构
常量\VideoEngine\VoiceEngine
注意:以下所有的方法、类、结构体、枚举常量等都在webrtc命名空间里
类、结构体、枚举常量 |
头文件 |
说明 |
Structures |
common_types.h |
Lists the structures common to the VoiceEngine & VideoEngine |
Enumerators |
common_types.h |
List the enumerators common to the VoiceEngine & VideoEngine |
Classes |
common_types.h |
List the classes common to VoiceEngine & VideoEngine |
class VoiceEngine |
voe_base.h |
How to allocate and release resources for the VoiceEngine using factory methods in the VoiceEngine class. It also lists the APIs which are required to enable file tracing and/or traces as callback messages |
class VideoEngine |
vie_base.h |
How to allocate and release resources for the VideoEngine using factory methods in the VideoEngine class. It also lists the APIs which are required to enable file tracing and/or traces as callback messages |
(4) 音频引擎(VoiceEngine)模块 APIs
下表列的是目前在 VoiceEngine中可用的sub APIs
sub-API |
头文件 |
说明 |
VoEAudioProcessing |
voe_audio_processing.h |
Adds support for Noise Suppression (NS), Automatic Gain Control (AGC) and Echo Control (EC). Receiving side VAD is also included. |
VoEBase |
voe_base.h |
Enables full duplex VoIP using G.711. |
VoECallReport |
voe_call_report.h |
Adds support for call reports which contains number of dead-or-alive detections, RTT measurements, and Echo metrics. |
VoECodec |
voe_codec.h |
Adds non-default codecs (e.g. iLBC, iSAC, G.722 etc.), Voice Activity Detection (VAD) support. |
VoEDTMF |
voe_dtmf.h |
Adds telephone event transmission, DTMF tone generation and telephone event detection. (Telephone events include DTMF.) |
VoEEncryption |
voe_encryption.h |
Adds external encryption/decryption support. |
VoEErrors |
voe_errors.h |
Error Codes for the VoiceEngine |
VoEExternalMedia |
voe_external_media.h |
Adds support for external media processing and enables utilization of an external audio resource. |
VoEFile |
voe_file.h |
Adds file playback, file recording and file conversion functions. |
VoEHardware |
voe_hardware.h |
Adds sound device handling, CPU load monitoring and device information functions. |
VoENetEqStats |
voe_neteq_stats.h |
Adds buffer statistics functions. |
VoENetwork |
voe_network.h |
Adds external transport, port and address filtering, Windows QoS support and packet timeout notifications. |
VoERTP_RTCP |
voe_rtp_rtcp.h |
Adds support for RTCP sender reports, SSRC handling, RTP/RTCP statistics, Forward Error Correction (FEC), RTCP APP, RTP capturing and RTP keepalive. |
VoEVideoSync |
voe_video_sync.h |
Adds RTP header modification support, playout-delay tuning and monitoring. |
VoEVolumeControl |
voe_volume_control.h |
Adds speaker volume controls, microphone volume controls, mute support, and additional stereo scaling methods. |
(5) 视频引擎(VideoEngine)模块 APIs
下表列的是目前在VideoEngine中可用的sub APIs
sub-API |
头文件 |
说明 |
ViEBase |
vie_base.h |
Basic functionality for creating a VideoEngine instance, channels and VoiceEngine interaction. NOTE: This API must always be created. |
ViECapture |
vie_capture.h |
Adds support for capture device allocation as well as capture device capabilities. |
ViECodec |
vie_codec.h |
Adds non-default codecs, codec settings and packet loss functionality. |
ViEEncryption |
vie_encryption.h |
Adds external encryption/decryption support. |
ViEErrors |
vie_errors.h |
Error codes for the VideoEngine |
ViEExternalCodec |
vie_external_codec.h |
Adds support for using external codecs. |
ViEFile |
vie_file.h |
Adds support for file recording, file playout, background images and snapshot. |
ViEImageProcess |
vie_image_process.h |
Adds effect filters, deflickering, denoising and color enhancement. |
ViENetwork |
vie_network.h |
Adds send and receive functionality, external transport, port and address filtering, Windows QoS support, packet timeout notification and changes to network settings. |
ViERender |
vie_render.h |
Adds rendering functionality. |
ViERTP_RTCP |
vie_rtp_rtcp.h |
Adds support for RTCP reports, SSRS handling RTP/RTCP statistics, NACK/FEC, keep-alive functionality and key frame request methods. |
webRTC本地API:http://www.webrtc.org/reference/native-apis。
翻译:http://www.cnblogs.com/longrenle/archive/2012/03/04/2378433.html 。
webRTC本地API是基于WebRTC spec的实现。webRTC的实现代码(包括流和PeerConnection API)是在libjingle中实现。
Stream APIs和PeerConnectionAPIs的调用会被代理到信令线程,这就意味着应用程序可以在任何线程调用这些APIs。
所有的回调函数都在信令线程调用。应用程序应当尽快地跳出回调函数以避免阻塞信令线程。严重消耗资源的过程都应当其他的线程执行。
3.2.3.1 libjingle_peerconnection
// The Following steps areneeded to setup a typical call usingJsep.
// 1. Create aPeerConnectionFactoryInterface. Check constructors for more
// information about inputparameters.
// 2. Create a PeerConnectionobject. Provide a configuration string which
// points either to stun orturn server to generate ICE candidates and provide
// an object that implementsthe PeerConnectionObserver interface.
// 3. Create localMediaStream and MediaTracks using the PeerConnectionFactory
// and add it toPeerConnection by calling AddStream.
// 4. Create an offer andserialize it and send it to the remote peer.
// 5. Once an ice candidatehave been found PeerConnection will call the
// observer functionOnIceCandidate. The candidates must also be serialized and
// 6. Once an answer isreceived from the remote peer, call
// SetLocalSessionDescriptionwith the offer and SetRemoteSessionDescription
// 7. Once a remote candidateis received from the remote peer, provide it to
// the peerconnectionby calling AddIceCandidate.
// The Receiver of a call candecide to accept or reject the call.
// This decision will betaken by the application notpeerconnection.
// If application decides toaccept the call
// 1. CreatePeerConnectionFactoryInterface if it doesn't exist.
// 2. Create a newPeerConnection.
// 3. Provide the remoteoffer to the new PeerConnection object by calling
//SetRemoteSessionDescription.
// 4. Generate an answer tothe remote offer by calling CreateAnswer and send it
// 5. Provide the localanswer to the new PeerConnection by calling
// SetLocalSessionDescriptionwith the answer.
// 6. Provide the remote icecandidates by calling AddIceCandidate.
// 7. Once a candidate havebeen found PeerConnection will call the observer
// function OnIceCandidate.Send these candidates to the remote peer.
cricket::VideoCapturer*Conductor::OpenVideoCaptureDevice() {
talk_base::scoped_ptr<cricket::DeviceManagerInterface>dev_manager(
cricket::DeviceManagerFactory::Create());
LOG(LS_ERROR) <<"Can't create devicemanager";
std::vector<cricket::Device>devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) <<"Can't enumerate videodevices";
std::vector<cricket::Device>::iteratordev_it = devs.begin();
cricket::VideoCapturer*capturer =NULL;
for (;dev_it !=devs.end(); ++dev_it) {
capturer =dev_manager->CreateVideoCapturer(*dev_it);
建立DeviceManagerFactory实例。Windows下在实例初始化时并实例化DefaultVideoCapturerFactory。
调用dev_manager->GetVideoCaptureDevices得到设备。
调用dev_manager->CreateVideoCapturer建立一个视频捕获对象。
在dev_manager->CreateVideoCapturer中,
classDefaultVideoCapturerFactory :publicVideoCapturerFactory {
DefaultVideoCapturerFactory() {}
virtual ~DefaultVideoCapturerFactory() {}
VideoCapturer*Create(constDevice&device) {
#ifdefined(VIDEO_CAPTURER_NAME)
VIDEO_CAPTURER_NAME*return_value =newVIDEO_CAPTURER_NAME;
if (!return_value->Init(device)) {
WebRtcVcmFactory->VideoCaptureFactory-> videocapturemodule::VideoCaptureImpl-> VideoCaptureDS
VideoCaptureModuleV4L2:linux下v4l2捕获设备。
VideoCaptureDS:windows下DirectxShow捕获设备。
VideoCaptureAndroid:android下捕获设备。
GdiVideoRenderer:windows gdi渲染
GtkVideoRenderer: GTK库渲染,这个用在linux平台。
Libjingle现在已转到webrtc项目中维护了。位于源码talk目录中。
数据通道是在点对点会话之间交换实际数据(音频、视频、文件等)。数据通道的数据依赖于传输协商,被捆绑在TCP或UDP包中。并且不经过XMPP服务器。
首先会话协商信道被建立,作为计算机协商数据信道的细节;数据连接后,大部分活动发生在数据信道,除非一个编解码器的改变,一个新的文件请求,偶尔请求重定向请求或终止请求。
对libjingle发出偶尔STUN数据包,以保持可写性,保持防火墙和NAT地址绑定活跃,并检查连接延迟。
https://developers.google.com/talk/libjingle/libjingle_applications?hl=zh-CN
其次,每个application可能包含一个或多个sessionclient用来做P2P操作,比如远程协助,视频会议,音频连接,文件共享等等。
4.2.2 XMPP MessagingComponent.模块
- XmppClient主要是代理登录,发送stanza,接收stanza。之所以说是代理,是因为真正发送,接收的消息都是通过XmppEngine来实现的。
- XmppEngine能注册多个XmppStanzaHandler回调,然后所有从服务器接收的Stanza都转发到已绑定的XmppStanzaHandler进行过滤,而实际上是回调XmppTask对象。
- XmppStanzaHandler类定义如下:
- //! Callback to deliver stanzas to an Xmpp application module.
- //! Register via XmppEngine.SetDefaultSessionHandler or via
- //! XmppEngine.AddSessionHAndler.
- class XmppStanzaHandler {
- public:
- virtual ~XmppStanzaHandler() {}
- //! Process the given stanza.
- //! The handler must return true if it has handled the stanza.
- //! A false return value causes the stanza to be passed on to
- //! the next registered handler.
- virtual bool HandleStanza(const XmlElement * stanza) = 0;
- };
- XmppTask是所有XmppHelperTask的基类,并继承自XmppStanzaHandler,主要有监听,过滤 XmppEngine对象转发过来的Stanza消息。XmppTask有多种类型,当取类型为HL_PEEK时,只有监听功能,无法做到过滤;而其他类 型可以做到过滤。过滤是有HandlerStanza函数来完成,当返回为true时,过滤,否则XmppEngine枚举下一个绑定的XmppTask 继续尝试分发、过滤。
- 所有XmppHelperTask都要继承XmppTask并要重载HandlerStanza函数和ProcessStart函数。
- HandlerStanza是用来过滤,相当于windows消息处理的GetMessage()
- 而ProcessStart是用来处理HandlerStanza过滤的消息。
- 比如在源代码example/call/presencepushtask.h里:
[cpp] view plaincopy
- class PresencePushTask : public XmppTask {
- public:
- PresencePushTask(XmppTaskParentInterface* parent, CallClient* client)
- : XmppTask(parent, XmppEngine::HL_TYPE),
- client_(client) {}
- virtual int ProcessStart();
- sigslot::signal1<const Status&> SignalStatusUpdate;
- sigslot::signal1<const Jid&> SignalMucJoined;
- sigslot::signal2<const Jid&, int> SignalMucLeft;
- sigslot::signal2<const Jid&, const MucStatus&> SignalMucStatusUpdate;
- protected:
- virtual bool HandleStanza(const XmlElement * stanza);
- void HandlePresence(const Jid& from, const XmlElement * stanza);
- void HandleMucPresence(buzz::Muc* muc,
- const Jid& from, const XmlElement * stanza);
- static void FillStatus(const Jid& from, const XmlElement * stanza,
- Status* status);
- static void FillMucStatus(const Jid& from, const XmlElement * stanza,
- MucStatus* status);
- private:
- CallClient* client_;
- };
- 这里PresencePushTask类,通过HandleStanza过滤所有presence相关的stanza并在ProcessStart里处理所有来自服务器的用户状态更新消息。
- LoginHandler部分是由XmppPump来负责的。主要调用XmppClient的connect和disconnect方法建立、断开连接,监听SignalStateChange事件来获取连接信息,类型为STATE_OPENED的事件表示连接成功。
4.2.3 Session Logicand management commponent模块。
所有p2p session逻辑相关的部分都放在了这个模块。可以session可能是处理文件传输的连接,或者可能是视频会话,或者音频会话等等。
- 我们需要继承SessionClient来处理每个Session相关具体任务,比如文件传输Session:当接收对端客户端建立一个文件传输 session的时候,如果此Session是新创建的,SessionManager对象会回调所有注册的SessionClient的 OnSessionCreate的接口,并以SessionManger创建的Session对象为参数穿进去;如果是已有的Session则会调用 Session的OnIncomingMessage方法。
- Session对象则抽象了两个peer之间的数据传输接口。当收到OnSessionCreate回调时,SessionClient可以通过Session的方法Accept来接受创建,Reject来拒绝。
- 那怎么读写p2p数据呢?
- 首先需要调用session的CreateChannel方法获取TransportChannel对象指针,然后监听TransportChannel的事件SignalReadPacket来接收数据,通过SendPacket方法来发送数据。
- class TransportChannel: public sigslot::has_slots<> {
- public:
- //......
- // Attempts to send the given packet. The return value is < 0 on failure.
- virtual int SendPacket(const char *data, size_t len) = 0;
- // Signalled each time a packet is received on this channel.
- sigslot::signal3<TransportChannel*, const char*, size_t> SignalReadPacket;
- //......
- };
4.2.4 Peer to peerComponent模块。
此模块才是libjingle核心,libjingle项目的初衷也是能够把模块设计得完美,使得所有需要通过P2P传输数据的应用层调用libjingle时,不用担心数据传输的稳定性,可靠性,高效性。
- class SessionManagerTask : public buzz::XmppTask {
- public:
- ......
- virtual int ProcessStart() {
- const buzz::XmlElement *stanza = NextStanza();
- if (stanza == NULL)
- return STATE_BLOCKED;
- session_manager_->OnIncomingMessage(stanza);
- return STATE_START;
- }
- protected:
- virtual bool HandleStanza(const buzz::XmlElement *stanza) {
- if (!session_manager_->IsSessionMessage(stanza))
- return false;
- QueueStanza(stanza);
- return true;
- }
- } // namespace cricket
- SessionManager类在这里起到连接上述3个模块的桥梁作用。
- 当上层调用SessionManager创建的Session对象的CreateChannel时,实际上是调用P2PTransport的CreateChannel方法。
- 上层通过P2PTransport创建P2pTransportChannel的类的。
- P2pTransportChannel 继承自TransportChannel,并创建多个不同的Connection,每个Connection代表一个TCP或者UDP或者SSL连接。上 层传输数据最终是调到P2pTransportChannel的相关方法,当发送,接收数据时,P2pTransportChannel选择表现最好的 Connection进行传输。
peerconnection_client.exe!cricket::WebRtcVoiceEngine::CreateMediaVoiceChannel() 行1657 C++
peerconnection_client.exe!cricket::WebRtcVoiceEngine::CreateChannel() 行635 + 0x22 字节 C++
peerconnection_client.exe!talk_base::Thread::ReceiveSends() 行456 + 0x13 字节 C++
peerconnection_client.exe!talk_base::Thread::ProcessMessages(intcmsLoop=-1) 行508 + 0x19 字节 C++
peerconnection_client.exe!talk_base::Thread::Run() 行371 C++
peerconnection_client.exe!talk_base::Thread::PreRun(void* pv=0x01a551f0) 行358 + 0x13 字节 C++
[下面的框架可能不正确和/或缺失,没有为 kernel32.dll 加载符号]
peerconnection_client.exe!talk_base::Thread::ProcessMessages(intcmsLoop=-1) 行508 + 0x19 字节 C++
peerconnection_client.exe!talk_base::Thread::Run() 行371 C++
peerconnection_client.exe!talk_base::Thread::PreRun(void* pv=0x00275080) 行358 + 0x13 字节 C++
[下面的框架可能不正确和/或缺失,没有为 kernel32.dll 加载符号]
peerconnection_client.exe!webrtc::FecReceiverImpl::ProcessReceivedFec() 行220 + 0x24 字节 C++
peerconnection_client.exe!talk_base::Thread::ProcessMessages(intcmsLoop=-1) 行508 + 0x19 字节 C++
peerconnection_client.exe!talk_base::Thread::Run() 行371 C++
peerconnection_client.exe!talk_base::Thread::PreRun(void* pv=0x00262510) 行358 + 0x13 字节 C++
[下面的框架可能不正确和/或缺失,没有为 kernel32.dll 加载符号]
XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。标准化的核心结果分为两部分;
XMPP 和SIMPLE 两种协议是架构,有助于实现IMPP协议所描述的规范。PRIM 最初是基于即时通信的协议,与XMPP 和SIMPLE 类似,但是己经不再使用
1. XMPP 协议是公开的,由JSF开源社区组织开发的。XMPP 协议并不属于任何的机构和个人,而是属于整个社区,这一点从根本上保证了其开放性。
3. 分布式的网络架构。XMPP 协议都是基于Client/Server 架构,但是XMPP协议本身并没有这样的限制。网络的架构和电子邮件十分相似,但没有结合任何特定的网络架构,适用范围非常广泛。
4.XMPP 具有很好的弹性。XMPP 除了可用在即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、档案共享、游戏、远端系统监控等。
6.1.2 XMPP协议网络架构
XMPP 是一个典型的C/S架构,而不是像大多数即时通讯软件一样,使用P2P客户端到客户端的架构,也就是说在大多数情况下,当两个客户端进行通讯时,他们的消息都是通过服务器传递的(也有例外,例如在两个客户端传输文件时).采用这种架构,主要是为了简化客户端,将大多数工作放在服务器端进行,这样,客户端的 工作就比较简单,而且,当增加功能时,多数是在服务器端进行.XMPP服务的框架结构如下图所示.XMPP中定义了三个角色,XMPP客户端,XMPP服 务器、网关.通信能够在这三者的任意两个之间双向发生.服务器同时承担了客户端信息记录、连接管理和信息的路由功能.网关承担着与异构即时通信系统的互联 互通,异构系统可以包括SMS(短信)、MSN、ICQ等.基本的网络形式是单客户端通过TCP/IP连接到单服务器,然后在之上传输XML,工作原理 是:
1) 节点连接到服务器;
2) 服务器利用本地目录系统中的证书对其认证;
3) 节点指定目标地址,让服务器告知目标状态;
4) 服务器查找、连接并进行相互认证;
5) 节点之间进行交互.
· XMPP客户端
XMPP 系统的一个设计标准是必须支持简单的客户端。事实上,XMPP 系统架构对客户端只有很少的几个限制。一个XMPP 客户端必须支持的功能有:
1) 通过 TCP 套接字与XMPP服务器进行通信;
2) 解析组织好的 XML 信息包;
3) 理解消息数据类型。
XMPP 将复杂性从客户端转移到服务器端。这使得客户端编写变得非常容易,更新系统功能也同样变得容易。XMPP 客户端与服务端通过XML 在TCP 套接字的5222 端口进行通信,而不需要客户端之间直接进行通信。
基本的XMPP 客户端必须实现以下标准协议(XEP-0211):
1) RFC3920 核心协议Core
2) RFC3921 即时消息和出席协议Instant Messaging andPresence
3) XEP-0030 服务发现Service Discovery
4) XEP-0115 实体能力Entity Capabilities
· XMPP服务器
XMPP 服务器遵循两个主要法则:
5) 监听客户端连接,并直接与客户端应用程序通信;
6) 与其他 XMPP 服务器通信;
XMPP开源服务器一般被设计成模块化,由各个不同的代码包构成,这些代码包分别处理Session管理、用户和服务器之间的通信、服务器之间的通信、DNS(Domain Name System)转换、存储用户的个人信息和朋友名单、保留用户在下线时收到的信息、用户注册、用户的身份和权限认证、根据用户的要求过滤信息和系统记录等。另外,服务器可以通过附加服务来进行扩展,如完整的安全策略,允许服务器组件的连接或客户端选择,通向其他消息系统的网关。
基本的XMPP 服务器必须实现以下标准协议
1) RFC3920 核心协议Core
2) RFC3921 即时消息和出席协议Instant Messaging andPresence
3) XEP-0030 服务发现Service Discovery
· XMPP网关
XMPP 突出的特点是可以和其他即时通信系统交换信息和用户在线状况。由于协议不同,XMPP 和其他系统交换信息必须通过协议的转换来实现,目前几种主流即时通信协议都没有公开,所以XMPP 服务器本身并没有实现和其他协议的转换,但它的架构允许转换的实现。实现这个特殊功能的服务端在XMPP 架构里叫做网关(gateway)。目前,XMPP 实现了和AIM、ICQ、IRC、MSN Massager、RSS0.9和Yahoo Massager 的协议转换。由于网关的存在,XMPP架构事实上兼容所有其他即时通信网络,这无疑大大提高了XMPP 的灵活性和可扩展性。
6.1.3 XMPP协议的组成
主要的XMPP 协议范本及当今应用很广的XMPP 扩展:
RFC 3920 :XMPP核心。全称:The Extensible Messaging andPresence Protocol,即可 扩展通讯和表示协议。说白了,就是规定基于XML流传输指定节点数据的协议。这么做的好处就是统一(注:大家都按照这个定义,做的东西就可以相互通讯、交流,这个应该很有发展前景!)。它是一个开放并且可扩展的协议,包括Jingle协议都是XMPP协议的扩展。(注:使用Wireshark抓包时,早期的版本可能找不到这个协议,这时候可以选择Jabber,它是XMPP协议的前身)。现在很多的IM都是基于XMPP协议开发的,包括gtalk等。定义了XMPP 协议框架下应用的网络架构,引入了XML Stream(XML 流)与XML Stanza(XML 节),并规定XMPP 协议在通信过程中使用的XML 标签。使用XML 标签从根本上说是协议开放性与扩展性的需要。此外,在通信的安全方面,把TLS 安全传输机制与SASL 认证机制引入到内核,与XMPP 进行无缝的连接,为协议的安全性、可靠性奠定了基础。核心 文档还规定了错误的定义及处理、XML 的使用规范、JID(Jabber Identifier,Jabber 标识符)的定义、命名规范等等。所以这是所有基于XMPP 协议的应用都必需支持的文档。
RFC 3921:用户成功登陆到服务器之后,发布更新自己的在线好友管理、发送即时聊天消息等业务。所有的这些业务都是通过三种基本的XML 节来完成的:IQ Stanza(IQ 节), Presence Stanza(Presence 节), Message Stanza(Message 节)。RFC3921 还对阻塞策略进行了定义,定义是多种阻塞方式。可以说,RFC3921 是RFC3920 的充分补充。两个文档结合起来,就形成了一个基本的即时通信协议平台,在这个平台上可以开发出各种各样的应用。
XEP-0030 服务搜索。一个强大的用来测定XMPP 网络中的其它实体所支持特性的协议。
XEP-0115 实体性能。XEP-0030 的一个通过即时出席的定制,可以实时改变交变广告功能。
XEP-0045 多人聊天。一组定义参与和管理多用户聊天室的协议,类似于Internet 的Relay Chat,具有很高的安全性。
XEP-0096 文件传输。定义了从一个XMPP 实体到另一个的文件传输。
XEP-0124 HTTP 绑定。将XMPP 绑定到HTTP 而不是TCP,主要用于不能够持久的维持与服务器TCP 连接的设备。
XEP-0166 Jingle。规定了多媒体通信协商的整体架构。Jingle协议是XMPP协议上的扩展协议,它着手解决在XMPP协议框架下的点对点的连接问题,也即P2P连接。在Jingle框架下,即使用户在防火墙或是NAT网络保护之下,也能够建立连接,从而提供文件传送、视频、音频服务等。
XEP-0167 Jingle Audio Content DescriptionFormat。定义了从一个XMPP 实体到另一个的语音传输过程。
TURN协议:全称:Traversal Using Relays around NAT,顾名思义,就是通过中继服务器来传输数据的协议。
STUN协议:全称:Simple Traversal of UDP over NATs,即NAT 的UDP简单穿越,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口。知道NAT类型并且有了公网IP和port,P2P就方便多了。
XEP-0176 Jingle ICE(Interactive Connectivity Establishment)Transport。即 交互式连接建立,说白了,它就是利用STUN和TURN等协议找到最适合的连接。
XEP-0177 Jingle Raw UDP Transport。纯UDP 传输机制,文件讲述了如何在没有防火墙且在同一网络下建立连接的。
XEP-0180 Jingle Video Content DescriptionFormat。定义了从一个XMPP 实体到另一个的视频传输过程。
XEP-0181 Jingle DTMF(Dual Tone Multi-Frequency)。
XEP-0183 Jingle Telepathy Transport Method。
一旦客户端得知了Internet端的UDP端口,通信就可以开始了。如果NAT是完全圆锥型的,那么双方中的任何一方都可以发起通信。如果NAT是受限圆锥型或端口受限圆锥型,双方必须一起开始传输。
需要注意的是,要使用STUN RFC中描述的技术并不一定需要使用STUN协议——还可以另外设计一个协议并把相同的功能集成到运行该协议的服务器上。
SIP之类的协议是使用UDP分组在Internet上传输音频和/或视频数据的。不幸的是,由于通信的两个末端往往位于NAT之后,因此用传统的方法是无法建立连接的。这也就是STUN发挥作用的地方。
接上面的例子,如果Client A的原来那个Socket(绑定了1234端口的那个UDPSocket)又接着向另外一个Server S2发送了一个UDP包,那么这个UDP包在通过NAT时会怎么样呢?
(1)全克隆( Full Cone) : NAT把所有来自相同内部IP地址和端口的请求映射到相同的外部IP地址和端口。任何一个外部主机均可通过该映射发送IP包到该内部主机。
Full cone NAT,亦即著名的一對一(one-to-one) · 一旦一个内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送.任意外部主机都能通过给eAddr:port2发包到达iAddr:port1 |
|
Address-Restricted cone NAT · 一旦一个内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送.任意外部主机(hostAddr:any)都能通过给eAddr:port2发包到达iAddr:port1的前提是:iAddr:port1之前发送过包到hostAddr:any. |
|
Port-Restricted cone NAT 类似受限制錐形NAT(Restricted cone NAT),但是还有端口限制。 · 一旦一个内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自iAddr:port1的包都经由eAddr:port2向外发送.一个外部主机(hostAddr:port3)能够发包到达iAddr:port1的前提是:iAddr:port1之前发送过包到hostAddr:port3. |
|
Symmetric NAT(對稱NAT) · 每一個來自相同內部IP與port的請求到一個特定目的地的IP地址和端口,映射到一個獨特的外部來源的IP地址和端口。 · 只有曾经收到过内部主机封包的外部主机,才能够把封包发回来 |
STUN是RFC3489规定的一种NAT穿透方式,它采用辅助的方法探测NAT的IP和端口。毫无疑问的,它对穿越早期的NAT起了巨大的作用,并且还将继续在NAT穿透中占有一席之地。
STEP4:B向C的IP2的一个端口PD发送一个数据请求包,要求C用IP2和不同于PD的port返回一个数据包给B。
STUN 使用下列的算法(取自RFC3489)来发现 NAT gateways 以及防火墙(firewalls):
一旦路径通过红色箱子的终点时,UDP的连通是沒有可能性的。一旦通过黄色或是绿色的箱子,就有连接的可能。
stunURI = scheme ":" host [ ":" port ]
STUNTMAN:http://www.stunprotocol.org/
https://github.com/jselbie/stunserver
http://sourceforge.net/projects/stun/
Stuntman- STUN server and client
High performance, production qualitySTUN server and client library
- mystun: STUN server and client library from the iptel.org guys. Old but mature. License: GPL, Homepage:http://developer.berlios.de/projects/mystun/. You have to download the file via CVS.
- Vovida STUN server (stund): STUN server and client library/application for Linux and Windows from the Vovida guys. Old but mature. License: Vovida Software License 1.0, Homepage:http://sourceforge.net/projects/stun/.
- WinSTUN: A Windows STUN client, part of the Vovida STUN server (see above). A nice application to test your NAT box. Homepage: http://sourceforge.net/projects/stun/files/WinStun/.
- reTurn: STUN/TURN server and client library, part of the resiprocate project. Server application is provided as well, but it seems incomplete (authentication). License: 3-clause BSD license. Homepage:http://www.resiprocate.org/ReTurn_Overview.
- restund: STUN/TURN server, supports authentication against a mysql DB. License: 3-clause BSD license. Homepage: http://www.creytiv.com/restund.html.
- TurnServer: STUN/TURN server. License: GPL3. Homepage: http://turnserver.sourceforge.net/.
- PJNATH : Open Source ICE, STUN, and TURN Library,http://www.pjsip.org/pjnath/docs/html/
- Numd:a free STUN/TURN serve, http://numb.viagenie.ca/
stun01.sipphone.com (no DNS SRV record)
stun.softjoys.com (no DNS SRV record)
stun.voipbuster.com (no DNS SRV record)
stun.voxgratia.org (no DNS SRV record)
//fromhttps://gist.github.com/zziuni/3741933
# source : http://code.google.com/p/natvpn/source/browse/trunk/stun_server_list
# A list of available STUN server.
TURN(全名 Traversal Using Relay NAT),是一种资料传输协议(data-transfer protocol)。允许在TCP或UDP的连线上跨越 NAT 或防火墙。
turnURI = scheme":" host [ ":" port ]
transport = "udp" /"tcp" / transport-ext
Table 1 shows how the <secure>,<port> and <transport> components are
populated from various URIs. For all these examples, the <host>
component is populated with"example.org".
+---------------------------------+----------+--------+-------------+
| URI | <secure> |<port> | <transport> |
+---------------------------------+----------+--------+-------------+
|turn:example.org |false | | |
| turns:example.org | true | | |
| turn:example.org:8000 | false | 8000 | |
| turn:example.org?transport=udp | false | | UDP |
| turn:example.org?transport=tcp | false | | TCP |
| turns:example.org?transport=tcp |true | | TLS |
+---------------------------------+----------+--------+-------------+
- Restund OpenSource Modular STUN/TURN Server (BSD License)
- Numb is a free STUN/TURN server.
- TurnServer - OpenSource TURN server.
- reTurn - opensource STUN/TURN server and client library (C++)
- TURN Server - High-Performance Open Source TURN/STUN server (BSD license) and client library (C)
https://code.google.com/p/rfc5766-turn-server/
搭建教程:http://www.dialogic.com/den/developer_forums/f/71/t/10238.aspx
http://zhangjunli177.blog.163.com/blog/static/138607308201341411384462/
- AnyFirewall - STUN, TURN & ICE library.
- Libnice - STUN, TURN & ICE library used in Pidgin, GNOME, MeeGo, etc.
- ice4j - STUN, TURN & ICE library in Java
6.4 交互式连接建立(Interactive Connectivity Establishment),一种综合性的NAT穿越的技术。
如下内容是ICE实现NAT穿透的所要完成的核心处理。包括收集地址,对地址进行排序、配对,然后执行连通性检查。
关于中继地址,STUN中继用法允许STUN服务器作为一个媒体中继器进行工作,在L与R之间进行转发。为了发送消息到L,R必须发送消息给媒体中继器,通过媒体中继器转发给L。反之亦然。
从L到R的消息其地址信息将两次被重写:第一次被NAT,第二次被STUN中继服务器。这样,R所了解的想与之通信的地址就是STUN中继服务器的地址。这个地址就是中继地址。
通常在对称NAT的情况下,在地址对验证过程中,会出现发现以前收集地址时没有收集到的地址对,这时就要对这些新的地址对进行连通性检查。
由于收集候选地址时,收集的是所有的候选地址,为了能够更快更好的找到能够正常工作的候选地址对,对所有组合进行排序是势在必行的。在此说明进行排序的两个基本原则,详细地排序算法将在后续文档中描述。
l Agent为它的每个候选地址设置一个数值的优先级,这个优先级连同候选地址对一起发送给通信的对端。
l 综合本地的和远程的候选地址的优先级,计算出候选地址对的优先级,这样,双方的同一个候选地址对的优先级相同。以此排序,则通信双方的排序结果相同。
为了实现基于ICE的NAT穿越,对SDP进行了扩展,主要增加了四个属性。分别是candidate属性、ice-ufrag属性、ice-pwd属性和remote-candidates属性。
candidate属性为通信提供多种可能的候选地址中的一个。这些地址是使用STUN的端到端的连通性检查为有效的。
remote-candidates属性提供请求者想要应答者在应答中使用的远程候选传输地址标识。
ice-ufrag属性提供在STUN连通性检查中组成用户名的片断。
STUN服务器有公网的传输层地址STUN-PUB-1(192.0.2.2:3478),绑定发现用法和中继用法都使用这个地址。但在此处,两个Agent都不使用中继用法。
在呼叫过程中,STUN消息有被许多属性注解。“S=”属性表明消息的源传输地址,“D=”属性表明消息的目标传输地址。“MA”属性用于STUN绑定响应消息,指明映射的地址。
双方都对获取的传输地址进行配对,确定优先级并排序。之后,R开始执行其连通性检查(消息9),由于来自L的候选地址是一个私有地址,所以此检查必定失败,而被丢弃。
ICE查看有效列表,发现有一对存在,就发送一个更新请求(消息14)给R,这个请求用于删除没有被选中的候选地址,并且指示远程地址。
6.4.1 IETF 规格
· InteractiveConnectivity Establishment (ICE): A Protocol for Network Address Translator(NAT) Traversal for Offer/Answer ProtocolsRFC5245
· SessionTraversal Utilities for NAT (STUN): RFC5389
· TraversalUsing Relays around NAT (TURN): Relay Extensions to STUN RFC5766
PJNATH- Open Source ICE, STUN, and TURN Library
本文档定义了在Jabber/XMPP客户间初始化及管理点对点的多媒体会话(sessions)(比如,声音和图像的交换)框架,它在一定程度上与现有的Internet标准具有互操作性。
警告:本标准跟踪文档是实验性的。作为XMPP扩展协议发表,并不意味着XMPP标准基金会批准了这个协议。我们鼓励对本协议进行探索性的实现,但在本协议的状态发展为草稿之前,产品性的系统不应实现本协议。
- 使得XMPP内多种点对点会话(不限于声音和视频)的管理成为可能\[6\]。
- 明确分离信号处理通道(XMPP)与数据通道(例如,在RFC3550中说明的实时传输协议\[7\])。
- 明确分离内容描述格式(例如,用于语音聊天的)与内容传输方法(比如,在RFC768\[8\]中说明的用户数据报协议)。
- 使得从现有会话中加入、修改、删除内容类型成为可能。
- 使得实现支持标准的Jabber/XMPP客户端中的协议相对容易。
- 当需要与非XMPP实体通讯的时候,尽可能将复杂性推到XMPP网络与非XMPP网络间的服务器端网关上。
Jingle有三部分组成,每部分由自己的语法、语义及状态机:
本文档定义了总会话管理的语义和语法。另有单独的文档,详细说明了用于内容描述和内容传输方法的可插入式“槽(slots)”。基于完整性的考虑,本文档也包含了与描述格式和传输方法有关的全部动作的示例。
1. 一个用户(“发起方”)向另一个用户(“接收方”)发送一个带内容类型的会话请求,会话请求至少包含一个内容类型。
1. 如果接收者想要处理,它会通过发送一个IQ结果暂时接受这个请求。
1. 发起方和接收方以尽可能快的速度交换可能的传输候选方法(进一步协商前的传输候选方法的快速发送,是为了缩短媒体数据可流动前的必要时间)。
1. 一旦接收方找到了媒体数据可流动的候选方法,接收方会向初始方发出一个“会话接受”动作。
如果双方随后发现了更好的候选方法,他们会进行“内容修改”协商,然后转到这个更好的候选方法上。自然他们也会修改与会话相关的其他参数(如给语音聊天加入视频)。
总会话管理的状态机(也即每个Session ID的状态)如下:
o
|
|会话开始
|
| +-----------+
|/ |
阻塞 o----------+ |
| |内容接受 | |
| |内容修改 | |
| |内容移除 | |
| |会话信息 | |
| |传输信息 | |
| +--------+ |
| |
|会话接受 |
| |
活动 o----------+ |
| |内容接受 | |
| |内容增加 | |
| |内容修改 | |
| |内容移除 | |
| |会话信息 | |
| |传输信息 | |
| +--------+ |
| |
+-------------+
|
|会话中止
|
o 结束
内容增加|增加一个或多个内容类型到会话中。这个动作 __不能__ 在会话的 __阻塞__ 状态时发出。当一方发出内容增加的时候,它 __必须__ 忽略从另一方收到的任何动作,直到收到内容增加的确认。
内容修改|改变现有的内容类型。接收方 __不能__ 以另一个内容修改来回应内容修改动作。
会话接受|最终接受会话协商。表明这个动作也适合内容接受(进而适合描述接受和传输接收)。
会话信息|发送会话级的信息/消息,如响铃消息(对Jingle音频来说)。
传输信息|交换传输候选方法;主要用在XEP-0176中,也可以用在其他规范中。
如果联系方有不止一种XMPP资源,可能仅有一种资源支持Jingle和想要的内容描述格式,在这种情况下,用户 __必须__ 用这一资源初始化Jingle信号处理。
如果联系方有超过一种XMPP资源支持Jingle和想要的内容描述格式, __建议__ 用 ~~资源应用优先权~~\[20\]来确定哪种资源最适合初始化Jingle会话。
下面是一个Jingle会话初始化请求的例子,会话包含了音频和视频:
<iqfrom='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='jingle1'type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-initiate'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-audio-content'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'/>
</content>
<content creator='initiator' name='this-is-the-video-content'>
<description xmlns='http://www.xmpp.org/extensions/xep-0180.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0176.html#ns'/>
</content>
</jingle>
注意:元素<description/>和<transport/>的语法、语义超出了本规范的范围,它们在相关的规范中定义。
<iq type='result'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'/>
如果接收方响应了发起请求,双方都必须认定会话处在 __阻塞__ 状态。
如果对接收方来说发起方是未知的(比如,通过在线订阅),并且接收方有不与未知实体经由Jingle通讯的策略,则接收方 __应该__ 返回一个<service-unavailable/>错误。
<iq type='error'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
如果接收方希望转向另一个地址,它 __应该__ 返回一个<redirect/>错误。
<iq type='error'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'>
<error type='cancel'>
<redirect xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>xmpp:voicemail@capulet.com</redirect>
</error>
如果接收方不支持Jingle,则 __必须__ 返回一个错误。
<iq type='error'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
<iq type='error'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported-content xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'/>
</error>
<iq type='error'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<unsupported-transports xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'/>
</error>
如果发起请求的格式错误,接收方 __必须__ 返回一个<bad-request/>错误。
<iq type='error'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='jingle1'>
<error type='cancel'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
为拒绝会话发起请求,接收方 __必须__ 响应收到的会话发起请求,然后按[中止|XMPP文档列表/XMPP扩展/XEP-0166#中止]中描述的方法中止会话。
一般情况下,双方在达成可接受的一系列内容类型、内容描述格式和内容传输方法前,协商是必要的。可能要协商的这些参数的组合是很多的,这里并没有列出全部(有些在各种内容描述格式和内容传输方法规范中列出)。
一个会话级的协商是移除一种内容类型。例如,让我们设想,有一天朱丽叶的心情很糟糕,她当然不想在和罗密欧的Jingle会话中包含视频,所以她给罗密欧发送了一个“内容移除”请求:
<iqfrom='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='reduce1'type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='content-remove'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-video-content'/>
</jingle>
<iqfrom='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='reduce1'type='result'/>
如果缩减的结果是会话不再有任何内容类型,收到会话缩减的实体 __应该__ 向另一方发送会话中止动作(因为没有内容类型的会话是无效的)。
另一个会话级的协商是增加一个内容类型;然而,这个动作__必不能__ 在会话处于 __阻塞__ 状态时来做,只有在会话处于 __活动__ 状态时才可以。
协商过内容传输方法和内容描述格式后,如果接收方确定能够建立连接,它将向发起方法送确定接受:
<iq type='set'from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'id='accept1'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-accept'
initiator='romeo@montague.net/orchard'
responder='juliet@capulet.com/balcony'
sid='a73sjjvkla37jfea'>
<content creator='initiator' name='this-is-the-audio-content'>
<description xmlns='http://www.xmpp.org/extensions/xep-0167.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0177.html#ns'>
<candidate .../>
</transport>
</content>
</jingle>
<iq type='result'to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard'id='accept1'/>
如果一方无法找到合适的内容传输方法,它 __应该__ 下面描述的那样中止会话。
如果双方同时发送了修改消息,那么会话发起方的修改消息__必须__ 胜过接收方的修改消息,发起方 __应该__ 返回一个<unexpected-request/>错误。
修改活动会话的一个例子是增加一个会话内容。例如,设想一下朱丽叶的心情好了,现在想加入视频。于是向罗密欧发送"content-add"请求:
<iqfrom='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='add1'type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='content-add'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='responder' name='video-is-back'>
<description xmlns='http://www.xmpp.org/extensions/xep-0180.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0177.html#ns'>
<candidate .../>
</transport>
</content>
</jingle>
实体接收到会话扩展请求,响应这个请求,如果可接受,返回一个内容接受:
<iqfrom='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='add1'type='result'/>
<iqfrom='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='add2'type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='content-accept'
initiator='romeo@montague.net/orchard'
sid='a73sjjvkla37jfea'>
<content creator='responder' name='video-is-back'>
<description xmlns='http://www.xmpp.org/extensions/xep-0180.html#ns'>
...
</description>
<transport xmlns='http://www.xmpp.org/extensions/xep-0177.html#ns'>
<candidate .../>
</transport>
</content>
</jingle>
<iqfrom='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='add2'type='result'/>
为了顺利地结束会话(在响应了初始化请求后的任何时候都__可以__ 这么做,包括立即想立刻拒绝请求的时候),无论接收方还是初始方都 __必须__ 向对方发送一个“中止”动作。
<iqfrom='juliet@capulet.com/balcony'
id='term1'
to='romeo@montague.net/orchard'
type='set'>
<jingle xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
action='session-terminate'
initiator='romeo@montague.net/orchard'
reason='Sorry, gotta go!'
sid='a73sjjvkla37jfea'/>
<iq type='result'to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard'id='term1'/>
不幸的是,并非所有会话都顺利地结束。下面的事件 __必须__ 认定为会话结束事件,对内容描述格式和内容传输方法的进一步协商 __必须__ 通过协商一个新会话来完成:
特别地,如果一方从对方收到的在线(presence)类型是"未知(unavailable)"的话,则它 __必须__ 认定会话处于 __结束__ 状态。
<presencefrom='juliet@capulet.com/balcony' to='romeo@montague.net/orchard'type='unavailable'/>
<out-of-order/>|<unexpected-request/>|请求不可能在状态机的这一点发生(比如,会话接受后再次初始化)。
<unknown-session/>|<bad-request/>|指定会话的‘sid’属性对接收方未知(例如,根据接收方的状态机会话已经不再有效,因为接收方先前已中止了会话)
<unsupported-content/>|<not-acceptable/>|接收方不支持任何期望的内容描述格式。
<unsupported-transports/>|<not-acceptable/>|接收方不支持任何期望的内容传输方法。
<iq from='romeo@montague.net/orchard'
id='disco1'
to='juliet@capulet.com/balcony'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
<iq from='juliet@capulet.com/balcony'
id='disco1'
to='romeo@montague.net/orchard'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='http://www.xmpp.org/extensions/xep-0166.html#ns'/>
...
</query>
1.1 8.使用协议的一致性{anchor:使用协议的一致性}
说明某种Jingle应用类型的文档(比如,经由RTP的音频) __必须__ 定义:
1. 为封装进Jingle,如何成功地进行内容协商。
1. 用于表现内容的<description/>元素及相关语义。
1. 能否及怎样将内容描述映射到会话描述协议上。
1. 是通过可靠的还是有损的传输方式(或两者都是)来传输内容。
1. 通过可靠或有损传输来收发内容的精确说明。
说明Jingle传输方法的文档(比如,纯UDP) __必须__ 定义:
1. 为封装进Jingle,怎样成功地进行传输协商。
1. 用于表现传输类型的<transport/>元素及相关语义。
1. 传输是可靠的还是有损的。
1. 传输是否及怎样处理在这定义的组件(例如,对实时控制协议来说)。
Jingle会话可能是资源密集型的。因此,有可能用增加过多Jingle会话负担的方法向一个实体发动决绝服务攻击。必须小心地只从已知的实体那接受内容,并且只接受实体设备能处理的会话。
Jingle通讯可通过网关与非XMPP网络完成,这些网络的安全特性与XMPP有很大的不同。(例如,在有些SIP网络中鉴定是可选的,“from”地址可轻易伪造。)与这些网通通讯时必须小心。
本文档要求不与{link:互联网指派数字授权(IANA)|http://www.iana.org/}\[23\]相互作用。
1.1 11. XMPP注册处事项{anchor:XMPP注册处事项}
1.1 1\1.1 协议命名空间{anchor:协议命名空间}
为提交注册的新值,注册人须按下面的格式定义一个XML段,内容包括相关的XMPP扩展协议,或者将它发送到<registrar@xmpp.org>。
<name>the name of the content description format</name>
<desc>a natural-language summary of the content description format</desc>
<transport>whether the content should be sent over a "reliable" or "lossy" transport</transport>
<doc>the document in which this content description format is specified</doc>
{code}
为提交注册的新值,注册人须按下面的格式定义一个XML段,内容包括相关的XMPP扩展协议,或者将它发送到<registrar@xmpp.org>。
<name>the name of the content transport method</name>
<desc>a natural-language summary of the content transport method</desc>
<type>whether the transport method is "reliable" or "lossy"</type>
<doc>the document in which this content transport method is specified</doc>
1.1 11.4 Jingle原因代码注册{anchor:Jingle原因代码注册}
为提交注册的新值,注册人须按下面的格式定义一个XML段,内容包括相关的XMPP扩展协议,或者将它发送到<registrar@xmpp.org>。
the value of the 'reasoncode' attribute</name>
<desc>a natural-language summary of the reason code</desc>
<doc>the document in which this reason code is specified</doc>
下面提交的原因代码注册从2007年4月开始使用。完整内容和最新的原因代码列表参见注册。
<code>connectivity-error
<desc>the action (e.g., session-terminate) is related to connectivity problems</desc>
<doc>XEP-0166</doc>
general-error
<desc>the action (e.g., session-terminate) is related to a non-specific application error</desc>
<doc>XEP-0166</doc>
media-error
<desc>the action (e.g., session-terminate) is related to media processing problems</desc>
<doc>XEP-0166</doc>
no-error
<desc>the action is generated during the normal course of state management</desc>
<doc>XEP-0166</doc>
1.1 12. XML方案(Schemas){anchor:XML Schemas}
1.1 12.1 Jingle{anchor:Jingle}
<?xml version='1.0'encoding='UTF-8'?>
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://www.xmpp.org/extensions/xep-0166.html#ns'
xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns'
elementFormDefault='qualified'>
<xs:element name='jingle'>
<xs:complexType>
<xs:sequence minOccurs='1' maxOccurs='unlimited'>
<xs:element ref='content'/>
</xs:sequence>
<xs:attribute name='action' use='required'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='content-accept'/>
<xs:enumeration value='content-add'/>
<xs:enumeration value='content-modify'/>
<xs:enumeration value='content-remove'/>
<xs:enumeration value='session-accept'/>
<xs:enumeration value='session-info'/>
<xs:enumeration value='session-initiate'/>
<xs:enumeration value='session-terminate'/>
<xs:enumeration value='transport-info'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='initiator' type='xs:string' use='required'/>
<xs:attribute name='reasoncode' type='xs:string' use='optional'/>
<xs:attribute name='reasontext' type='xs:string' use='optional'/>
<xs:attribute name='responder' type='xs:string' use='optional'/>
<xs:attribute name='sid' type='xs:NMTOKEN' use='required'/>
</xs:complexType>
</xs:element>
<xs:element name='content'>
<xs:complexType>
<xs:choice minOccurs='0'>
<xs:sequence>
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
</xs:sequence>
</xs:choice>
<xs:attribute name='creator' use='required'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='initiator'>
<xs:enumeration value='responder'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='name' use='required' type='xs:string'/>
<xs:attribute name='profile' use='optional' type='xs:string'/>
<xs:attribute name='senders' use='optional' default='both'>
<xs:simpleType>
<xs:restriction base='xs:NCName'>
<xs:enumeration value='both'>
<xs:enumeration value='initiator'>
<xs:enumeration value='responder'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
1.1 12.2 Jingle出错信息{anchor:Jingle出错信息}
<?xml version='1.0'encoding='UTF-8'?>
xmlns:xs='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'
xmlns='http://www.xmpp.org/extensions/xep-0166.html#ns-errors'
elementFormDefault='qualified'>
<xs:element name='out-of-order' type='empty'/>
<xs:element name='unknown-session' type='empty'/>
<xs:element name='unsupported-content' type='empty'/>
<xs:element name='unsupported-transports' type='empty'/>
<xs:simpleType name='empty'>
<xs:restriction base='xs:string'>
<xs:enumeration value=/>
</xs:restriction>
</xs:simpleType>
GYP 简介:转载自:http://blog.xiaogaozi.org/2011/10/29/introduction-to-gyp/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
cmake_minimum_required(VERSION 2.8) project(VP8 CXX) add_definitions(-Wall) cmake_policy(SET CMP0015 NEW) include_directories("include") link_directories("lib") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../lib") set(VP8SRC VP8Encoder.cpp VP8Decoder.cpp) if(X86) set(CMAKE_SYSTEM_NAME Darwin) set(CMAKE_SYSTEM_PROCESSOR i386) set(CMAKE_OSX_ARCHITECTURES "i386") add_library(vp8 STATIC ${VP8SRC}) elseif(IPHONE) if(SIMULATOR) set(PLATFORM "iPhoneSimulator") set(PROCESSOR i386) set(ARCH "i386") else() set(PLATFORM "iPhoneOS") set(PROCESSOR arm) set(ARCH "armv7") endif() set(SDKVER "4.0") set(DEVROOT "/Developer/Platforms/${PLATFORM}.platform/Developer") set(SDKROOT "${DEVROOT}/SDKs/${PLATFORM}${SDKVER}.sdk") set(CMAKE_OSX_SYSROOT "${SDKROOT}") set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR ${PROCESSOR}) set(CMAKE_CXX_COMPILER "${DEVROOT}/usr/bin/g++") set(CMAKE_OSX_ARCHITECTURES ${ARCH}) include_directories(SYSTEM "${SDKROOT}/usr/include") link_directories(SYSTEM "${SDKROOT}/usr/lib") add_definitions(-D_PHONE) add_library(vp8-armv7-darwin STATIC ${VP8SRC}) endif() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
{ 'targets': [ { 'target_name': 'foo', 'type': '<(library)', 'dependencies': [ 'bar', ], 'defines': [ 'DEFINE_FOO', 'DEFINE_A_VALUE=value', ], 'include_dirs': [ '..', ], 'sources': [ 'file1.cc', 'file2.cc', ], 'conditions': [ ['OS=="linux"', { 'defines': [ 'LINUX_DEFINE', ], 'include_dirs': [ 'include/linux', ], }], ['OS=="win"', { 'defines': [ 'WINDOWS_SPECIFIC_DEFINE', ], }, { # OS != "win", 'defines': [ 'NON_WINDOWS_DEFINE', ], }] ], } ], } |
当然 GYP 也不是没有缺点,相反,我觉得它的「缺点」一大堆:
文档不够完整,项目不够正式,某些地方还保留着 Chromium 的影子,看起来像是还没有完全独立出来。
大量的括号嵌套,很容易让人看晕,有过 Lisp 使用经验的同学可以对号入座。对于有括号恐惧症,或者不使用现代编辑器的同学基本可以绕行。
为了支持跨平台,有时不得不加入某些特定平台的配置信息,比如只适用于 Visual Studio 的 RuntimeLibrary 配置,这不利于跨平台配置文件的编写,也无形中增加了编写复杂度。
不支持 make clean,唯一的方法就是将输出目录整个删除或者手动删除其中的某些文件。
如果你已经打算尝试 GYP,那一定记得在生成项目工程文件时加上 --depth 参数,譬如:
玩转Google开源C++单元测试框架Google Test系列(gtest)(总)
网络传输与流控
对于网络视频来讲,数据的传输与控制是核心价值。WebRTC采用的是成熟的RTP/RTCP技术。
http://blog.csdn.net/chenyufei1013/article/category/1248211
本文试图寻找一种能够穿越各种类型的NAT/防火墙,无需对现有NAT/防火墙没备做任何改动的解决方案——ICE解决方案,这种方式比以前的解决方案更加灵活,具有广阔的应用前景。
主流的NAT穿越解决方案包括STUN、TURN、Proxy及隧道穿越等,这几种方式各具优缺点,比较如下:
会话者从服务器上获得主机上一个物理(或虚拟)接口绑定一个端口的本地传输地址。
与传统的STUN不同,ICE用户名和密码可以通过信令协议进行交换。
优先级反映了UA在该地址上接收媒体流的优先级别,取值范围0到1之间,按照被传输媒体流量来确定。
初始化消息由一系列媒体流组成,每个媒体流的任意Peer之间实现最人连通可能性的传输地址是由公网L转发服务器(如TURN)提供的地址。
若接受则发送Accept消息,其构造过程与InitiateMessage类似。
Initiate或Accept消息交换过程结束后,双方可能仍将继续收集传输地址。
送STUN check的包,其中STUN消息的用户名,密码从alt属性中得到,标识该地址对。(7)当检测到有效的地址对时(可以发送RTP媒体流的地址),停止接收线程STUN服务),开始传输RTP流。
类中m_nCandidateID对应地址序号,m_nPriority表示地址优先级,m_CandidateAddr表示地址(IP地址,端口)。实现ICE算法的实体算法描述为:
实现ICE中会话发起者和接收者的步骤基本一样,仅任处理流程中先后次序稍微有些不同,本文中实现的会话流程如图l所示。
以安装了SIP软终端的双方都在Full ConeNATNAT/防火墙后为例,进行实例测试。测试过程:
(1)将两台PC的IP的配置分别为公网59.64.148.187122和私网10.0.0.5/8l
(2)从公网中的用户代理向私网内的用户代理呼叫,结果能够建立会话,无明显的延时,话音质量良好;
(3)从私网内的用户代理向公网中的用户代理呼叫,结果能够建立会话,且话音质量良好;
通过抓包分析可以确定,使用该算法可以成功地穿越NAT/防火墙设备。
1. 官网地址(要FQ):STUNTMAN:http://www.stunprotocol.org/
从http://www.stunprotocol.org/stunserver-1.2.3.tgz 下载源码
sudo apt-get install libboost-dev # For Boost
sudo apt-get install libssl-dev # For OpenSSL
stunclient, stunserver, stuntestcode
5. run the unittest. Should HAVE NO "FAIL" in the end of any line
Result of CTestDataStream: PASS
Result of CTestIntegrity: PASS
Result of CTestMessageHandler: PASS
Result of CTestCmdLineParser: PASS
Testing detection for DirectMapping
Testing detection for EndpointIndependentmapping
Testing detection forAddressDependentMapping
Testing detection forAddressAndPortDependentMapping
Testing detection forEndpointIndependentFiltering
Testing detection forAddressDependentFiltering
Testing detection forAddressAndPortDependentFiltering
Result of CTestClientLogic: PASS
Result of CTestRecvFromEx(IPV4): PASS
Result of CTestRecvFromEx(IPV6): PASS
Result of CTestAtomicHelpers: PASS
nohup ./stunserver --mode full --primaryinterface eth0--altinterface eth1 &
用法:./stunclient --mode full --localport7777 stun.sipgate.net
NOTE: stuntman只具有stun功能,没有转发功能。支持UDP,TCP。兼容RFC3489。
原文地址:http://blog.csdn.net/kl222/article/details/19336179
官网地址:http://nice.freedesktop.org/wiki/
源码git库地址:http://cgit.collabora.com/git/libnice.git
git clonegit://git.collabora.co.uk/git/libnice.git
k@k-C410:/home/libnice$ ./autogen.sh
k@k-C410:/home/libnice$ ./configure
在nice/.libs目录下生成静态库libnice.a、动态库libnice.so
在example目录下生成三个例子程序。
k@k-C410:/home/libnice/examples$ ./simple-example0 stunserver.org
Copy this line to remote client:
Tyyp33oInvKVEn1Lo6LkVVy6P5 1,2013266431,192.168.10.17,47748,host
Enter remote data (single line, no wrapping):
>
红色部分表示提供给对等端协商时的验证用户名、密码、外网地址,以空格分隔。
k@k-C410:/home/libnice/examples$ ./simple-example0 stunserver.org
Copy this line to remote client:
Tyyp 33oInvKVEn1Lo6LkVVy6P5 1,2013266431,192.168.10.17,47748,host
Negotiation complete: ([192.168.10.17]:47748, [192.168.10.17]:47758)
Send lines to remote (Ctrl-D to quit):
> a
>
k@k-C410:/home/libnice/examples$ ./simple-example 0 stunserver.org
Copy this line to remote client:
h4p1 7M8uL1928RzeRv6cWRDqG8 1,2013266431,192.168.10.17,47758,host
Negotiation complete: ([192.168.10.17]:47758, [192.168.10.17]:47748)
Send lines to remote (Ctrl-D to quit):
> a
存在的问题:在linux下,stun服务器地址不能通过域名解析到IP地址。解决方法是,直接用stun服务器的IP地址。本人已向项目提交了补丁包。
7.10 基于ICE方式SIP信令穿透Symmetric_NAT技术研究
webrtc详细教程相关推荐
- WebRTC VideoEngine超详细教程(三)——集成X264编码和ffmpeg解码
转自:http://blog.csdn.net/nonmarking/article/details/47958395 本系列目前共三篇文章,后续还会更新 WebRTC VideoEngine超详细教 ...
- Kurento-6.7.1 媒体服务器搭建详细教程(Kurento-Media-Server)
< Kurento-6.7.1 媒体服务器搭建详细教程 > 关于 Kurento 媒体服务器 Kurento 架构的核心是媒体服务器,它被命名为Kurento媒体服务器,即 KMS.Kur ...
- 手把手从零开始搭建k8s集群超详细教程
本教程根据B站课程云原生Java架构师的第一课K8s+Docker+KubeSphere+DevOps同步所做笔记教程 k8s集群搭建超详细教程 1. 基本环境搭建 1. 创建私有网络 2. 创建服务 ...
- win10系统优化计算机,全面优化win10电脑系统详细教程 | 专业网吧维护
全面优化win10电脑系统详细教程 以下针对win10系统的电脑全面优化的步骤: 步骤1:禁止开机启动项 1.首先我们先来优化开机速度,拖慢开机速度的首先是开机自启动项,Ctrl + Shift + ...
- GPU运行Tensorflow详细教程及错误解决
GPU运行Tensorflow详细教程及错误解决 前提条件 配置GPU运行 确认是否成功配置 出现的错误及解决方案 前提条件 最重要的一点:CUDA与tensorflow的版本一点要对应,不然用不了! ...
- VMware虚拟机安装黑苹果MacOS Mojave系统详细教程
更多资源请百度搜索:前端资源网 欢迎关注我的博客:www.w3h5.com 最近遇到一个H5页面的 iPhone X 刘海兼容问题.查到一个 XCode 编辑器,可以模拟 iPhone X 环境运行. ...
- [分享] 从定制Win7母盘到封装详细教程 By BILL ( 10月23日补充说明 )
[分享] 从定制Win7母盘到封装详细教程 By BILL ( 10月23日补充说明 ) billcheung 发表于 2011-10-23 00:07:49 https://www.itsk.com ...
- win七系统如何卸载MySQL_win7系统卸载SQL2008R2数据库的详细教程
用过SQL2008R2数据库的朋友都知道,安装起来容易卸起来麻烦,可是在win7 32位旗舰版系统就不知道怎么卸载SQL2008R2数据库了.其实卸载SQL2008R2数据库的方法也很简单,可直接通过 ...
- Ubuntu系统安装搜狗输入法详细教程
Ubuntu16.04系统安装搜狗输入法详细教程 解决Ubuntu 18.04中文输入法的问题,安装搜狗拼音
最新文章
- 跨域策略文件crossdomain.xml文件
- pthread_cond_wait() 函数的使用
- 【Android游戏开发十五】关于Android 游戏开发中 OnTouchEvent() 触屏事件的性能优化笔记! .
- nginx的负载均衡
- translucent可以设置中文吗_物联卡可以作无线网卡使用吗?物联卡笔记本上网设置流程...
- linux获取java环境变量的值,linux获取java环境变量的值
- 英特尔核芯显卡控制面板没有了_「有趣」第41期:被英特尔取消发售的CPU长啥样?...
- Spring-boot中读取config配置文件的两种方式
- 拿什么来拯救你,电视!
- C++ —— 句柄类的实现方式 —— 类实现的隐藏
- 移动开发中“单位”的那些事儿
- VLOG的文字遮罩(利用文字显示内部)
- 基于HTML和CSS完成京东页面的制作
- Python输入一个字符串,输出其中每个字符的出现次数。要求使用标准库collotections中的Counter类...
- 微信小程序怎么实现防止截屏
- A Univariate Bound of Area Under ROC 论文小结
- 艾永亮:打造超级产品,互联网公司的风水转到哪儿了?
- 计算机网络(2)传输层
- 第十二章:项目采购管理 - (12.0 什么是项目采购管理)
- android contacts电话查询头像,Androidの通过查询电话号码或ID获取联系人头像