SDP协议
SDP协议版本
sdp协议最新链接:rfc8866
历史版本:rfc4566
rfc2327
特性 |
RFC 2327 (1998) |
RFC 4566 (2006) |
RFC 8866 (2021) |
IP 支持 |
仅 IPv4 |
IPv4 + IPv6 |
IPv4 + IPv6 |
安全机制 |
无 |
基础(如 k=) |
完善(DTLS-SRTP 等) |
ICE 支持 |
无 |
初步属性支持 |
完整规范 |
扩展性 |
有限 |
新增属性字段 |
明确的扩展规则 |
应用场景 |
传统 VoIP |
WebRTC 早期 |
现代 WebRTC/5G |
本次以rfc8866
为例学习
sdp 参数解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
v= (protocol version)
o= (originator and session identifier)
s= (session name)
i=* (session information)
u=* (URI of description)
e=* (email address)
p=* (phone number)
c=* (connection information -- not required if included in
all media descriptions)
b=* (zero or more bandwidth information lines)
One or more time descriptions:
("t=", "r=" and "z=" lines; see below)
k=* (obsolete)
a=* (zero or more session attribute lines)
Zero or more media descriptions
|
-
v=0
版本默认是0
-
o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
username
: 用户登录的原始host,默认’-'
sess-id
: 会话id,具备唯一性
sess-version
: 会话版本,可和sess-id
一致
nettype
: 网络类型,默认为IN
addrtype
: 地址类型,默认为IP4
or IP6
unicast-address
: ip地址
s=<session name>
必须填写,没有则为’s=’ or ’s=-'
i=<session information>
描述会话信息,可选
u=<uri>
描述会话uri, 可选
e=<email-address> p=<phone number>
, 可选
c=<nettype> <addrtype> <connection-address>
连接信息,为’IN IP4 xxxx’, c可以有多个
b=<bwtype>:<bandwidth>
带宽信息,可选
k=<keytype> <key>
加密信息,可选
1
2
3
|
t= (time the session is active)
r=* (zero or more repeat times)
z=* (optional time zone offset line)
|
t=<start-time> <stop-time>
会话开始和结束时间戳,可多个,开始和结束时间都为0,会话视为永久
r=<repeat interval> <active duration> <offsets from start-time>
重复时间间隔和持续时间,可选
z=<adjustment time> <offset> <adjustment time> <offset> ...
时区偏移,可选
1
2
3
4
5
6
7
|
m= (media name and transport address)
i=* (media title)
c=* (connection information -- optional if included at
session level)
b=* (zero or more bandwidth information lines)
k=* (obsolete)
a=* (zero or more media attribute lines)
|
m=<media> <port>/<numers of ports> <proto> <fmt> ...
媒体描述,必选.
media
: audio
、video
、text
、application
、message
port
: 端口号,0-65535,0表示不指定端口, numbers of ports
: rtp 会话数选择
proto
: 传输协议,udp
,RTP/AVP
,RTP/SAVP
,RTP/SAVPF
fmt
: 媒体格式,如 0
、8
、9
、97
、98
、99
、101
、102
、103
、104
、105
等
k=<method> k=<method>:<encryption key>
已过时,不要用
a=<aattribute-name> a=<attribute-name>:<aattribute-value>
扩展sdp信息,可多个
rtpmap
: 媒体格式的描述, 要和m=
里fmt
格式一致
详细示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
v=0
o=jdoe 3724394400 3724394405 IN IP4 198.51.100.1
s=Call to John Smith
i=SDP Offer #1
u=http://www.jdoe.example.com/home.html
e=Jane Doe <jane@jdoe.example.com>
p=+1 617 555-6011
c=IN IP4 198.51.100.1
t=0 0
m=audio 49170 RTP/AVP 0
m=audio 49180 RTP/AVP 0
m=video 51372 RTP/AVP 99
c=IN IP6 2001:db8::2
a=rtpmap:99 h263-1998/90000
|
RTP协议
RTP协议连接
协议地址:rfc3550
老协议:rfc1889
RTP协议结构
1
2
3
4
5
6
7
8
9
10
11
12
|
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
sequence number
: 初始值随机不可预测生成,用于标识一个RTP包,每次发送+1
timestamp
: 初始值随机时间戳,每次新增采样时钟,比如audio为160
SSRC
: 初始值随机,多个源时会有概率冲突,如果一个源修改源地址,那么要使用新SSRC.
CSRC
: 标识有效负载的贡献源
SSRC 生成算法
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
#include <sys/types.h> /* u_long */
#include <sys/time.h> /* gettimeofday() */
#include <unistd.h> /* get..() */
#include <stdio.h> /* printf() */
#include <time.h> /* clock() */
#include <sys/utsname.h> /* uname() */
#include "global.h" /* from RFC 1321 */
#include "md5.h" /* from RFC 1321 */
#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final
static u_long md_32(char *string, int length)
{
MD_CTX context;
union {
char c[16];
u_long x[4];
} digest;
u_long r;
int i;
MDInit (&context);
MDUpdate (&context, string, length);
MDFinal ((unsigned char *)&digest, &context);
r = 0;
for (i = 0; i < 3; i++) {
r ^= digest.x[i];
}
return r;
} /* md_32 */
/*
* Return random unsigned 32-bit quantity. Use 'type' argument if
* you need to generate several different values in close succession.
*/
u_int32 random32(int type)
{
struct {
int type;
struct timeval tv;
clock_t cpu;
pid_t pid;
u_long hid;
uid_t uid;
gid_t gid;
struct utsname name;
} s;
gettimeofday(&s.tv, 0);
uname(&s.name);
s.type = type;
s.cpu = clock();
s.pid = getpid();
s.hid = gethostid();
s.uid = getuid();
s.gid = getgid();
/* also: system uptime */
return md_32((char *)&s, sizeof(s));
} /* random32 */
|
在实际使用媒体服务中,有部分服务使用了SSRC
来区分数据,
业务表现就是媒体服务只用一个端口来接收RTP数据(比如:jitsi-videobridge
)。
好处: 当对接时,可以不需要开通太多端口区间。不足: 并发性能不高。
其余大部分的媒体服务都是使用多个端口来接收RTP数据(比如: rtpengine, rtpproxy, freeswitch
)。