Browsed by
Tag: sip

openssl一二事

openssl一二事

由于工作上的需要,最近两天折腾openssl来实现一些信令加密解密的事情。总体来说,openssl是个很不错的库,也是个很不错的工具。使用openssl做tls客户端编程没有太大问题,而实现tls服务器端则有些地方需要注意。

首先要注意的一点就是:在握手之前(SSL_accept),绝对不能采用非阻塞方式。握手成功之后,才可以将socket修改为非阻塞方式,否则握手不会成功,服务器总是会向客户端返回“Engypted alert”消息并结束握手。

如果是在windows环境生成证书和密钥,建议使用SimpleCA工具,很好用。同时要注意:(1)客户端应安装或者使用该工具生成的根证书,例如ca.crt。(2)服务端需要使用生成的服务端证书和密钥,即.crt和.key文件。(3)生成证书时(无论是根证书还是服务端证书),Common Name都必须要设置为当前服务器的IP地址或者主机名,否则双方握手时,可能产生”certificate name mismatch”等错误。(4)如果需要将证书导入windows系统,必须导入为“受信任的根证书颁发机构”类型。

如果是Ubuntu等linux系统,可以直接安装使用openssl生成证书,如以下命令:

生成根证书:
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

生成服务端证书和密钥
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

理论上来说,可以将.crt和.key文件合并在一起,设置为.pem文件。不过实践证明,openssl的API是要求SSL_CTX_use_PrivateKey_file函数来加载密钥文件的,否则握手还是会出问题(当然,也可能是需要另外单独的设置)。

基于HTML5的SIP客户端

基于HTML5的SIP客户端

项目名称是:sipml5,地址:http://code.google.com/p/sipml5/

该项目基于Google的WebRTC项目。这点与我以前写的一篇blog吻合,将SIP引入WebRTC不仅是可能,而且已经有人搞定了!

粗略地看了一下该项目的情况,界面是比较丑陋,不过看介绍应该是基本可用的。这是个好消息啊,尤其对企业用户而言,可能都不需要每个员工安装部署SIP终端,直接部署该终端即可,再结合云通信平台,整个系统都能简化不少。

如果该项目能覆盖Chrome, Firefox以及IE三个主要平台,基本就可以在实际环境中部署。非常让人期待啊。

RFC4028的不足与SIP keep-alive方法

RFC4028的不足与SIP keep-alive方法

在SIP族协议中,只有RFC4028明确讨论了对话keep-alive问题。实际上这在工程应用、生产环境部署中,是个非常重要的话题,尤其是SIP基于UDP协议时,网络原因丢包是很常见的,另外还有软终端任意退出对话等情况。缺乏keep-alive保护的SIP服务器毫无疑问将会严重消耗资源,最终导致整个server被迫退出服务。

RFC4028协议考虑到有状态Proxy、无状态Proxy等情况,提出扩展Session-Expires以及Min-SE两个新的Header,并且通过reINVITE消息来keep-alive dialog。基本上,这个协议本身没有太多问题,按照它的思路,的确是可以解决keep-alive的问题,但是在实际部署中,该协议未必可取,有很大的缺陷:

(1)SIP运营商可能会拒绝reINVITE消息。实际上很多SIP运营商会拒绝reINVITE消息,这是出于SIP运营商媒体处理方面的考虑。最初应用reINVITE就是为了修改媒体流,而这毫无疑问会导致SIP运营商媒体服务器重新分配资源等情况出现。RFC4028中只是定义了新增Header和callFlow,不幸的是,却没有区分出这个reINVITE与更改媒体流的reINVITE,因此实际部署时是否有效,我们需要打一个很大的问号。

(2)采用reINVITE流程太过重型了。正如前面所说,keep-alive的reINVITE消息是没有与更改媒体流的reINVITE进行区分,因此可以肯定绝大部分SIP服务器或者终端,在收到这个reINVITE消息时,会启动媒体更改流程。对话内重改媒体毫无疑问是个很重型的流程,一旦对话内本身就可能有媒体类业务,例如Music On Hold等,就很有可能导致冲突。

如果不采用reINVITE消息,在4028协议中也同时建议可以采用UPDATE消息。在UPDATE消息中可以不携带SDP更改媒体。这种方式可能是比较可行,但是未必所有的SIP设备会支持UPDATE消息并用于keep-alive过程。

方案之二应该采用SIP最基础协议RFC3261中定义的OPTIONS消息。理由如下:

(1)该消息定义在RFC3261协议中,这个协议是整个SIP协议族的基础。基本上不可能有SIP设备(包括服务器、Proxy、终端等)会不支持这个消息。

(2)我们注意到,这个消息可以在对话内,也可以在对话外使用。在RFC3261中很明确地定义了:

An OPTIONS request received within a dialog generates a 200 (OK) response
that is identical to one constructed outside a dialog and does not
have any impact on the dialog.

(3)对话内使用OPTIONS,最显著的优点就是“does not have any impact on the dialog”,对现有对话没有任何影响,更不可能去更改媒体。

(4)对端设备如果由于某种原因已经退出,当然就不能产生200OK响应消息,此时可以理所当然地拆除当前对话,从而保护服务器自身资源,达到keep-alive的目的。

对于设备层级的keep-alive,采用OPTIONS没有任何问题。但是对于dialog层级的keep-alive,则会有问题。原因在于:dialog内的OPTIONS消息有可能被对端作为对话外的OPTIONS来处理。也就是说,如果设备是alive的,但是dialog的BYE消息丢失了,无论dialog内还是dialog外,设备对OPTIONS都可能会返回200OK。

Requests that do not change in any way the state of a dialog may be 
received within a dialog (for example, an OPTIONS request).  They are 
processed as if they had been received outside the dialog.

方案三是采用RFC5626协议,对于UDP-SIP的情况,该协议建议采用STUN keep-alive方式。缺陷在于:定义有些复杂,而且很多SIP设备未必会支持。

呼叫服务器和媒体服务器合一的情况下,当然也可以由媒体服务器检测RTP/RTCP来keep-alive,不过这是另外一个topic了,这种方式可能更合适于SIP终端设备。

RTMP

RTMP

RTMP全称是Real Time Messaging Protocol。这个协议由Macromedia公司开发,为Flash player以及Flash media server提供语音、视频流媒体服务的私有协议。目前Macromedia已经公开了这个协议的细节。

值得注意的是,虽然Flash player/media server/RTMP通常用于提供网络视频流媒体,例如各种各样的视频网站,它们的组合也可以提供在线会议的功能。考虑到几乎所有的浏览器都可能安装有flash,因此终端用户几乎不需要另外安装软件,就可以访问视频、会议等服务,对这些业务的在线部署实在是非常方便。

Macromedia公开RTMP协议,可能是出于与HTML5竞争的需要。这对最终用户而言,无疑是有利的。

而吸引我注意的则是另外一则消息:FreeSwitch最新版本中实现了mod_rtmp模块,通过这个模块,FreeSwitch可以成为RTMP Server,并与传统的SIP进行转换和互通。这是个很不错的想法,让人有很多想象空间。

Google开放实时通信框架WebRTC

Google开放实时通信框架WebRTC

据说WebRTC是Web方式进行语音、视频实时通信的框架。项目地址如下:

http://sites.google.com/site/webrtc/ (需翻墙浏览?)

暂时还不太清楚这个技术的细节,不过如果像Google宣传的那样,就可以实现高质量的web通信方式。传统的SIP软终端就面临很大的挑战,从另一方面来说,可能也是一次打破现有格局的机遇。

在ubuntu环境中运行SIPp

在ubuntu环境中运行SIPp

SIPp是一个非常好的SIP性能测试工具,我们一直用它,:-) 不过一直是在windows环境中使用这个软件。

而最近忙于将已有系统迁移到Linux环境,因此就有必要研究一下linux环境下的SIPp,我们以ubuntu环境为主。在ubuntu环境中安装、运行SIPp基本是非常简单的,因为ubuntu的软件源中已经加入了SIPp,不过运行时有些地方需要注意。

下面我们逐一进行介绍:

step 1: 安装SIPp

sudo apt-get install sip-tester

step 2: 运行SIPp

命令与windows环境的SIPp一样,需要注意的是Ubuntu/Kubuntu的网络环境中,缺省会安装一个循环网卡,如果运行SIPp时不指定本地地址,SIPp很可能会以该Loopback的地址填写SIP消息中的各项参数,导致大量呼损。因此我们只需注意以-i指定本地地址,以-p指定本地端口即可。下面是两个示例:

运行SIPp接收端程序:sipp -sn uas -i 192.168.1.10 -p 5060

运行SIPp发起端程序:sipp 192.168.1.20:5060 -sn uac -i 192.168.1.10 -p 5061 -r 3 -rp 1000 -m 30000

SIPp错误: Error opening terminal: cygwin

SIPp错误: Error opening terminal: cygwin

在运行SIPp进行测试时,经常有人会问到:“为什么我运行sipp会出现下面这个错误提示呢?”

Error opening terminal: cygwin

这个错误是说SIPp无法找到运行时必要的terminal信息,这有可能是由以下几方面的因素导致的:

(1)计算机上没有安装cygwin。cygwin是必须要有的。

(2)直接在command命令行窗口运行sipp。这个是最常见的错误。大家可能觉得把cygwin的bin目录以及sipp的目录加入到path路径就可以直接运行sipp了。直接运行时,还是没有指定cygwin的terminal信息,同样会出错。

那么该如何运行SIPp呢?

请注意SIPp安装后,在“start”程序组中建立了快捷方式“start sipp”,我们应点击这个快捷方式来运行SIPp。这个快捷方式,实际上是指向SIPp安装目录下的批处理文件:startterm.bat。打开这个批处理文件,我们可以很清楚地看到,首先进行了terminal信息的设置,然后进行了必要的mount操作,最后才能正常运行SIPp。

SIPp简单使用手册

SIPp简单使用手册

Windows下应用SIPp非常简单, 直接下载SIPp的安装文件安装即可。

需要注意的是,不要直接从cmd窗口启动SIPp,而是 点击SIPp的快捷方式“start sipp”,这样,它会将SIPp的安装目录加入路径中。或者,可以将sipp的安装目录加入系统的PATH路径,然后也可以直接在cmd窗口启动 SIPp。

sipp 192.168.1.100:5060 -sf caller_basic.xml -p 5062 -m 1 -r 1 -rp 2000 -d 2000

-sf     加载外部的xml定义文件
-inf    从外部csv文件导入数据信息
-p      指定本地端口。 如果不指定的话,系统使用一个随机的空闲端口;
-m  呼叫次数
-d  每个呼叫的保持时间(毫秒)

其他常用配置参数:

-r -rp Specify the rate period for the call rate.
Example: -r 7 -rp 2000 ==> 7 calls every 2 seconds.

实际上SIPp内置了缺省的UAS和UAC,因此,我们可以不需要定制xml脚本,直接用下面的命令进行测试:

启动SIPp做呼出:sipp 192.168.1.100:5060 -sn uac -p 5062 -r 1 -rp 2000 -d 2000

启动SIPp接受呼叫:sipp 192.168.1.100:5060 -sn uas -p 5063

应用在Fedora系统
下载sipp的源代码在Fedora 9下编译时,会有编译错误“INT_MAX未定义”。 解决方法:
修改sipp.hpp文件,增加以下宏定义即可:

#ifndef INT_MAX
#define INT_MAX 0xFFFFFFFF
#endif

直接使用命令make即可进行编译,在当前目录下产生sipp可执行文件。