📄 rtpacket.c
字号:
#ifdef RationalWorld
#define commonLength(pk) ((pk)->common.length)
#else
#define commonLength(pk) (*((unsigned short *) (((char *) (pk)) + 2)))
#endif
commonLength(p) = htons((short) (((l + 3) / 4) - 1));
l = hl + ((ntohs(commonLength(p)) + 1) * 4);
/* Okay, if the total length of this packet is not an odd
multiple of 4 bytes, we're going to put a pad at the
end of it. Why? Because we may encrypt the packet
later and that requires it be a multiple of 8 bytes,
and we don't want the encryption code to have to
know all about our weird composite packet structure.
Oh yes, there's no reason to do this if strict isn't
set, since we never encrypt packets sent to a Look
Who's Listening server.
Why an odd multiple of 4 bytes, I head you ask?
Because when we encrypt an RTCP packet, we're required
to prefix it with four random bytes to deter a known
plaintext attack, and since the total buffer we
encrypt, including the random bytes, has to be a
multiple of 8 bytes, the message needs to be an odd
multiple of 4. */
if (strict) {
int pl = (l & 4) ? l : l + 4;
if (pl > l) {
int pad = pl - l;
bzero(zp + l, pad); /* Clear pad area to zero */
zp[pl - 1] = pad; /* Put pad byte count at end of packet */
p[0] |= 0x20; /* Set the "P" bit in the header of the
SDES (last in message) packet */
/* If we've added an additional word to
the packet, adjust the length in the
SDES message, which must include the
pad */
commonLength(p) = htons((short) (ntohs(commonLength(p)) + ((pad) / 4)));
l = pl; /* Include pad in length of packet */
}
}
*pkt = (char *) malloc(l);
if (*pkt != NULL) {
bcopy(zp, *pkt, l);
return l;
}
return 0;
}
/* RTP_MAKE_BYE -- Create a "BYE" RTCP packet for this connection. */
int rtp_make_bye(unsigned char *p, unsigned long ssrc_i, char *raison, int strict)
{
// rtcp_t *rp;
unsigned char *ap, *zp;
int l, hl;
/* If requested, prefix the packet with a null receiver
report. This is required by the RTP spec, but is not
required in packets sent only to the Look Who's Listening
server. */
zp = p;
hl = 0;
if (strict) {
*p++ = RTP_VERSION << 6;
*p++ = RTCP_RR;
*p++ = 0;
*p++ = 1;
*((long *) p) = htonl(ssrc_i);
p += 4;
hl = 8;
}
#ifdef RationalWorld
rp = (rtcp_t *) p;
rp->common.version = RTP_VERSION;
rp->common.p = 0;
rp->common.count = 1;
rp->common.pt = RTCP_BYE;
rp->r.bye.src[0] = htonl(ssrc_i);
#else
*((short *) p) = htons((u_short) ((RTP_VERSION << 14) | RTCP_BYE | (1 << 8)));
*((long *) (p + 4)) = htonl(ssrc_i);
#endif
ap = p + 8;
l = 0;
if (raison != NULL) {
l = strlen(raison);
if (l > 0) {
*ap++ = l;
bcopy(raison, ap, l);
ap += l;
}
}
while ((ap - p) & 3) {
*ap++ = 0;
}
l = ap - p;
commonLength(p) = htons((short) ((l / 4) - 1));
l = hl + ((ntohs(commonLength(p)) + 1) * 4);
/* If strict, pad the composite packet to an odd multiple of 4
bytes so that if we decide to encrypt it we don't have to worry
about padding at that point. */
if (strict) {
int pl = (l & 4) ? l : l + 4;
if (pl > l) {
int pad = pl - l;
bzero(zp + l, pad); /* Clear pad area to zero */
zp[pl - 1] = pad; /* Put pad byte count at end of packet */
p[0] |= 0x20; /* Set the "P" bit in the header of the
SDES (last in message) packet */
/* If we've added an additional word to
the packet, adjust the length in the
SDES message, which must include the
pad */
commonLength(p) = htons((short) (ntohs(commonLength(p)) + ((pad) / 4)));
l = pl; /* Include pad in length of packet */
}
}
return l;
}
/* RTP_MAKE_APP -- Create a "APP" (application-defined) RTCP packet
for this connection with the given type (name)
and content. */
int rtp_make_app(unsigned char *p, unsigned long ssrc_i,
int strict, char *type, char *content)
{
unsigned char *ap, *zp;
int l, hl;
/* If requested, prefix the packet with a null receiver
report. This is required by the RTP spec, but is not
required in packets sent only to other copies of Speak
Freely. */
zp = p;
hl = 0;
if (strict) {
*p++ = RTP_VERSION << 6;
*p++ = RTCP_RR;
*p++ = 0;
*p++ = 1;
*((long *) p) = htonl(ssrc_i);
p += 4;
hl = 8;
}
*((short *) p) = htons((RTP_VERSION << 14) | RTCP_APP | (1 << 8));
*((long *) (p + 4)) = htonl(ssrc_i);
ap = p + 8;
bcopy(type, ap, 4);
ap += 4;
l = strlen(content);
strcpy((char *) ap, content);
ap += l + 1;
while ((ap - p) & 3) {
*ap++ = 0;
}
l = ap - p;
commonLength(p) = htons((short) ((l / 4) - 1));
l = hl + ((ntohs(commonLength(p)) + 1) * 4);
/* If strict, pad the composite packet to an odd multiple of 4
bytes so that if we decide to encrypt it we don't have to worry
about padding at that point. */
if (strict) {
int pl = (l & 4) ? l : l + 4;
if (pl > l) {
int pad = pl - l;
bzero(zp + l, pad); /* Clear pad area to zero */
zp[pl - 1] = pad; /* Put pad byte count at end of packet */
p[0] |= 0x20; /* Set the "P" bit in the header of the
SDES (last in message) packet */
/* If we've added an additional word to
the packet, adjust the length in the
SDES message, which must include the
pad */
commonLength(p) = htons((short) (ntohs(commonLength(p)) + ((pad) / 4)));
l = pl; /* Include pad in length of packet */
}
}
return l;
}
/* RTPOUT -- Convert a sound buffer into an RTP packet, given the
SSRC, timestamp, and sequence number appropriate for the
next packet sent to this connection. */
LONG rtpout(soundbuf *sb, unsigned long ssrc_i,
unsigned long timestamp_i, unsigned short seq_i,
int spurt)
{
soundbuf rp;
#ifdef RationalWorld
rtp_hdr_t *rh = (rtp_hdr_t *) &rp;
#else
char *rh = (char *) &rp;
#endif
LONG pl = 0;
#ifdef RationalWorld
rh->version = RTP_VERSION;
rh->p = 0;
rh->x = 0;
rh->cc = 0;
rh->m = !!spurt;
rh->seq = htons(seq_i);
rh->ts = htonl(timestamp_i);
rh->ssrc = htonl(ssrc_i);
#else
*((short *) rh) = htons((short) ((RTP_VERSION << 14) | (spurt ? 0x80 : 0)));
*((short *) (rh + 2)) = htons(seq_i);
*((long *) (rh + 4)) = htonl(timestamp_i);
*((long *) (rh + 8)) = htonl(ssrc_i);
#endif
/* GSM */
if (sb->compression & fCompGSM) {
#ifdef RationalWorld
rh->pt = 3;
#else
rh[1] = 3;
#endif
bcopy(sb->buffer.buffer_val + 2, ((char *) &rp) + 12,
(int) sb->buffer.buffer_len - 2);
pl = (sb->buffer.buffer_len - 2) + 12;
/* ADPCM */
} else if (sb->compression & fCompADPCM) {
#ifdef RationalWorld
rh->pt = 5;
#else
rh[1] = 5;
#endif
bcopy(sb->buffer.buffer_val, ((char *) &rp) + 12 + 4,
(int) sb->buffer.buffer_len - 3);
bcopy(sb->buffer.buffer_val + ((int) sb->buffer.buffer_len - 3),
((char *) &rp) + 12, 3);
((char *) &rp)[15] = 0;
pl = (sb->buffer.buffer_len + 1) + 12;
/* LPC */
} else if (sb->compression & fCompLPC) {
int i, n = (int) ((sb->buffer.buffer_len - 2) / 14);
char *ip = (char *) (sb->buffer.buffer_val + 2),
*op = (char *) &rp + 12;
#ifdef RationalWorld
rh->pt = 7;
#else
rh[1] = 7;
#endif
#ifdef OLDWAY
bcopy(sb->buffer.buffer_val + 2, ((char *) &rp) + 12,
(int) sb->buffer.buffer_len - 2);
pl = (sb->buffer.buffer_len - 2) + 12;
#else
for (i = 0; i < n; i++) {
bcopy(ip, op, 3);
bcopy(ip + 4, op + 3, 10);
op[13] = 0;
ip += 14;
op += 14;
}
pl = 12 + 14 * n;
#endif
/* PCMU Uncompressed */
} else { /* Uncompressed PCMU samples */
#ifdef RationalWorld
rh->pt = 0;
#else
/* Already zeroed above */
#endif
bcopy(sb->buffer.buffer_val, ((char *) &rp) + 12,
(int) sb->buffer.buffer_len);
pl = (int) sb->buffer.buffer_len + 12;
}
if (pl > 0) {
bcopy((char *) &rp, (char *) sb, (int) pl);
}
return pl;
}
/* PARSESDES -- Look for an SDES message in a possibly composite
RTCP packet and extract pointers to selected items
into the caller's structure. */
int parseSDES(unsigned char *packet,
struct rtcp_sdes_request *r)
{
int i, success = FALSE;
unsigned char *p = packet;
/* Initialise all the results in the request packet to NULL. */
for (i = 0; i < r->nitems; i++) {
r->item[i].r_text = NULL;
}
/* Walk through the individual items in a possibly composite
packet until we locate an SDES. This allows us to accept
packets that comply with the RTP standard that all RTCP packets
begin with an SR or RR. */
while ((p[0] >> 6 & 3) == RTP_VERSION || (p[0] >> 6 & 3) == 1) {
if ((p[1] == RTCP_SDES) && ((p[0] & 0x1F) > 0)) {
unsigned char *cp = p + 8,
*lp = cp + (ntohs(*((short *) (p + 2))) + 1) * 4;
bcopy(p + 4, r->ssrc, 4);
while (cp < lp) {
unsigned char itype = *cp;
if (itype == RTCP_SDES_END) {
break;
}
/* Search for a match in the request and fill the
first unused matching item. We do it this way to
permit retrieval of multiple PRIV items in the same
packet. */
for (i = 0; i < r->nitems; i++) {
if (r->item[i].r_item == itype &&
r->item[i].r_text == NULL) {
r->item[i].r_text = (char *) cp;
success = TRUE;
break;
}
}
cp += cp[1] + 2;
}
break;
}
/* If not of interest to us, skip to next subpacket. */
p += (ntohs(*((short *) (p + 2))) + 1) * 4;
}
return success;
}
/* COPYSDESITEM -- Copy an SDES item to a zero-terminated user
string. */
void copySDESitem(char *s, char *d)
{
int len = s[1] & 0xFF;
bcopy(s + 2, d, len);
d[len] = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -