背景
compression模块用于对 SIP 消息进行压缩,以减少网络传输量。
相比于上一章kamailio, opensips不仅可以压缩body,还能压缩header和调整压缩率,使用上更灵活。
依赖外部模块:zlib。
官方文档地址: compression模块
本次测试的opensips版本信息为:
version: opensips 3.5.5 (x86_64/linux)
重要参数解析
1
2
|
# 压缩等级1-9, 默认是6,等级越高,压缩耗时越长.
modparam("compression", "compression_level", 6)
|
官方文档写的是: modparam("mc", "mc_level", "3"),这个是错的,已提issue修正。
重要函数
mc_compress([algo], flags, [whitelist])
压缩当前的SIP消息
algo 压缩算法, 可选值为0(deflate), 1(gzip)
flags 压缩参数,设置压缩的范围
b 压缩body,如果没有body,则不压缩
h 压缩所有header,除了白名单中的
s header和body可以分开压缩,将创建新的Comp-Hdrs头存储压缩后的header
e 指定base64编码
whitelist 不压缩的白名单, 头可以使用"|“分隔。
mc_compact([whitelist], flags)
flags: ’n’不使用缩短名, 此函数有四种功能:
- 没有在白名单中的
header会被移除
- 相同类型的
header会合并,使用”,“分隔
- 有短名的
header会变成缩短名
sdp中小于96的rtpmap会被移除。
mc_decompress()
进行base64解码和gzip/deflate解压, 只能被用在REQUEST_ROUTE,LOCAL_ROUTE,FAILURE_ROUTE上.
实战
配置示例
整体配置使用opensips-基础代理设置章节的配置, 并添加如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
loadmodule "compression.so"
...
route {
...
if ($si != "172.16.4.114") {
$du = "sip:172.16.4.114:5060";
$socket_out="udp:172.16.4.111:5260";
}
if (!mc_compress(0, "b")) {
xlog("L_DBG","[$cfg_line][$ci]---main--: compress failed.\n");
}
# # do lookup with method filtering
# if (!lookup("location","method-filtering")) {
# t_newtran();
# t_reply(404, "Not Found");
# exit;
# }
route(relay);
}
|
在发送INVITE时, 设置mc_compress(0, "b")。
测试
测试的sip信令图为:

mc_compress
关于flags参数,
s只有和bh一起使用,才有效果,即:bhs。 此时消息体为:

新增了Comp-Hdrs,Headers-Encoding。
h,e: 单独用没有任何效果.
b: 压缩body,此时消息体为:

目前发送给freeswitch报错400 Bad Session Description:

已提交issue, 和kamailio对比了一下源码,虽然都是zlib库,但是kamailio用的是compress函数
1
2
3
4
5
6
|
ret = compress(
(unsigned char *)nbody.s, &nlen, (unsigned char *)obody.s, olen);
if(ret != Z_OK) {
LM_ERR("error compressing body (%d)\n", ret);
goto done;
}
|
opensips用的是compress2函数:
1
2
3
4
5
|
rc = compress2((unsigned char*)bufcompressed.s,
&temp,
(unsigned char*)buf2compress.s,
(unsigned long)buf2compress.len,
mc_level);
|
be: 以base64展示压缩后的body, 此时消息体为:

发送给freeswitch报错415 Unsupported Media Type:

说明freeswitch不支持这样的压缩方式。
mc_compact
把上面的mc_compress(0,"b")换成mc_compact()。
原始的INVITE的数据为:
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
|
2025/08/13 13:53:16.834540 172.16.4.111:5260 -> 172.16.4.114:5060
INVITE sip:1008@172.16.4.111:5261 SIP/2.0
Record-Route: <sip:172.16.4.111:5260;lr>
Via: SIP/2.0/UDP 172.16.4.111:5260;branch=z9hG4bK072a.b15e8867.0
Via: SIP/2.0/UDP 172.16.80.13:58807;received=172.16.80.13;rport=58807;branch=z9hG4bKPjf13de5761ca54d1895886f961b23ff64
Max-Forwards: 69
From: <sip:1005@172.16.4.111>;tag=9769c9c2b927412aaecd915eec7b1fb1
To: <sip:1008@172.16.4.111>
Contact: <sip:1005@172.16.80.13:58807;ob>
Call-ID: 970d5f96986b4b2aa5fa069dba9e2948
CSeq: 3216 INVITE
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Supported: replaces, 100rel, norefersub
User-Agent: MicroSIP/3.21.6
Content-Type: application/sdp
Content-Length: 321
v=0
o=- 3964082099 3964082099 IN IP4 172.16.4.111
s=pjmedia
b=AS:84
t=0 0
a=X-nat:0
m=audio 30988 RTP/AVP 8 0 101
c=IN IP4 172.16.4.111
b=TIAS:64000
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ssrc:580466598 cname:31a747bc699122c1
a=sendrecv
a=rtcp:30989
|
使用mc_compact()后的INVITE数据为:
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
|
2025/08/13 13:46:24.616445 172.16.4.111:5260 -> 172.16.4.114:5060
INVITE sip:1008@172.16.4.111:5261 SIP/2.0
v: SIP/2.0/UDP 172.16.4.111:5260;branch=z9hG4bKf914.0b281385.0, SIP/2.0/UDP 172.16.80.13:58807;received=172.16.80.13;rport=58807;
anch=z9hG4bKPj07898ec3e16c4350843b1a4de4a89ceb
t: <sip:1008@172.16.4.111>
f: <sip:1005@172.16.4.111>;tag=2b204cd2db594ce0bca55e8e525a1c14
CSeq: 6255 INVITE
i: 9a37bdb33bb7418d9b6e5c088c8312af
m: <sip:1005@172.16.80.13:58807;ob>
Record-Route: <sip:172.16.4.111:5260;lr>
c: application/sdp
l: 278
v=0
o=- 3964081686 3964081686 IN IP4 172.16.4.111
s=pjmedia
b=AS:84
t=0 0
a=X-nat:0
m=audio 31614 RTP/AVP 8 0 101
c=IN IP4 172.16.4.111
b=TIAS:64000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ssrc:1957038347 cname:2c067dcd05730c02
a=sendrecv
a=rtcp:31615
|
可以看到在opensips转发INVITE时,Via,From,To,Call-id,Contact等都被换成了缩略参数,
并且sdp中的rtpmap:PCMU/PCMA删除了.
在freeswitch往opensips发送183,200OK时,也带了缩略参数:
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
|
2025/08/13 13:46:25.451770 172.16.4.114:5060 -> 172.16.4.111:5260
SIP/2.0 183 Session Progress
v: SIP/2.0/UDP 172.16.4.111:5260;branch=z9hG4bKf914.0b281385.0, SIP/2.0/UDP 172.16.80.13:58807;received=172.16.80.13;rport=58807;
anch=z9hG4bKPj07898ec3e16c4350843b1a4de4a89ceb
Record-Route: <sip:172.16.4.111:5260;lr>
f: <sip:1005@172.16.4.111>;tag=2b204cd2db594ce0bca55e8e525a1c14
To: <sip:1008@172.16.4.111>;tag=tZ2epK6U1Dtae
i: 9a37bdb33bb7418d9b6e5c088c8312af
CSeq: 6255 INVITE
Contact: <sip:1008@172.16.4.114:5060;transport=udp>
User-Agent: FreeSWITCH-mod_sofia/1.10.2-release+git~20230615T110520Z~4ce1b74880~64bit
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, presence, as-feature-event, dialog, line-seize, call-info, sla, include-session-description
presence.winfo, message-summary, refer
Content-Type: application/sdp
Content-Disposition: session
Content-Length: 254
Remote-Party-ID: "1008" <sip:1008@172.16.4.111>;party=calling;privacy=off;screen=no
v=0
o=FreeSWITCH 1755033712 1755033713 IN IP4 172.16.4.114
s=FreeSWITCH
c=IN IP4 172.16.4.114
t=0 0
m=audio 30016 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=rtcp:30017 IN IP4 172.16.4.114
|
可以看到From,To, Via还是之前的缩略参数,其他的header参数被恢复了.
总结
- 虽然
opensips说可以压缩Header,但是实际测试过程中,并未生效此功能,但是缩略Header参数功能Ok.
opensips的压缩body, 确实是压缩了,但是压缩后的body,freeswitch并不能解析.应该是有问题的。
分别对比kamailio和opensips的压缩body功能抓包,发现kamailio的消息体能够被tcpdump正确解析,
但是opensips的消息体被tcpdump解析失败.
kamailio的压缩body功能抓包:

opensips的压缩body功能抓包:
