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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#include <u.h>
#include <libc.h>
#include <ip.h>
#include "dat.h"
#include "protos.h"
typedef struct Hdr Hdr;
struct Hdr {
uchar hdr; /* RTCP header */
uchar pt; /* Packet type */
uchar len[2]; /* Report length */
uchar ssrc[4]; /* Synchronization source identifier */
uchar ntp[8]; /* NTP time stamp */
uchar rtp[4]; /* RTP time stamp */
uchar pktc[4]; /* Sender's packet count */
uchar octc[4]; /* Sender's octect count */
};
typedef struct Report Report;
struct Report {
uchar ssrc[4]; /* SSRC identifier */
uchar lost[4]; /* Fraction + cumu lost */
uchar seqhi[4]; /* Highest seq number received */
uchar jitter[4]; /* Interarrival jitter */
uchar lsr[4]; /* Last SR */
uchar dlsr[4]; /* Delay since last SR */
};
enum{
RTCPLEN = 28, /* Minimum size of an RTCP header */
REPORTLEN = 24
};
static int
p_seprint(Msg *m)
{
Hdr*h;
Report*r;
int rc, i, frac;
float dlsr;
if(m->pe - m->ps < RTCPLEN)
return -1;
h = (Hdr*)m->ps;
if(m->pe - m->ps < (NetS(h->len) + 1) * 4)
return -1;
rc = h->hdr & 0x1f;
m->ps += RTCPLEN;
m->p = seprint(m->p, m->e, "version=%d rc=%d tp=%d ssrc=%8ux ntp=%d.%.10ud rtp=%d pktc=%d octc=%d hlen=%d",
(h->hdr >> 6) & 3, rc, h->pt, NetL(h->ssrc),
NetL(h->ntp), (uint)NetL(&h->ntp[4]), NetL(h->rtp),
NetL(h->pktc), NetL(h->octc),
(NetS(h->len) + 1) * 4);
for(i = 0; i < rc; i++){
r = (Report*)m->ps;
m->ps += REPORTLEN;
frac = (int)(((float)r->lost[0] * 100.) / 256.);
r->lost[0] = 0;
dlsr = (float)NetL(r->dlsr) / 65536.;
m->p = seprint(m->p, m->e, "\n\trr(csrc=%8ux frac=%3d%% cumu=%10d seqhi=%10ud jitter=%10d lsr=%8ux dlsr=%f)",
NetL(r->ssrc), frac, NetL(r->lost), NetL(r->seqhi),
NetL(r->jitter), NetL(r->lsr),
dlsr);
}
m->pr = nil;
return 0;
}
Proto rtcp = {
"rtcp",
nil,
nil,
p_seprint,
nil,
nil,
nil,
defaultframer
};
|