⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtpacket.c

📁 IP网络语音通讯软件源代码. 不可多得的语音源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -