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

📄 rtpacket.c

📁 g729 coding ipaddressing
💻 C
📖 第 1 页 / 共 2 页
字号:
/*

			  RTP input packet construction and parsing

*/

#include "netfone.h"

static audio_descr_t adt[] = {
/* enc	   sample ch */
  {AE_PCMU,  8000, 1},	/*	0 PCMU */
  {AE_MAX,	 8000, 1},	/*	1 1016 */
  {AE_G721,  8000, 1},	/*	2 G721 */
  {AE_GSM,	 8000, 1},	/*	3 GSM */
  {AE_G723,  8000, 1},	/*	4 Unassigned */
  {AE_IDVI,  8000, 1},	/*	5 DVI4 */
  {AE_IDVI, 16000, 1},	/*	6 DVI4 */
  {AE_LPC,	 8000, 1},	/*	7 LPC */
  {AE_PCMA,  8000, 1},	/*	8 PCMA */
  {AE_MAX,		0, 1},	/*	9 G722 */
  {AE_L16,	44100, 2},	/* 10 L16 */
  {AE_L16,	44100, 1},	/* 11 L16 */
  {AE_MAX,		0, 1},	/* 12 */
};

#define bcopy(s, d, l)	memcpy(d, s, l)
#define bzero(d, l)		memset(d, 0, l)

#define MAX_MISORDER 100
#define MAX_DROPOUT  3000

/*	ISRTP  --  Determine if a packet is RTP or not.  If so, convert
			   in place into a sound buffer.  */

int isrtp(unsigned char *pkt, int len)
{
#ifdef RationalWorld
	rtp_hdr_t *rh = (rtp_hdr_t *) pkt;
#endif

	unsigned int r_version, r_p, r_x, r_cc, r_m, r_pt,
				 r_seq;
	long r_ts;

	/* Tear apart the header in a byte- and bit field-order
	   independent fashion. */

	r_version = (pkt[0] >> 6) & 3;
	r_p = !!(pkt[0] & 0x20);
	r_x = !!(pkt[0] & 0x10);
	r_cc = pkt[0] & 0xF;
	r_m = !!(pkt[1] & 0x80);
	r_pt = pkt[1] & 0x1F;
	r_seq = ntohs(*((short *) (pkt + 2)));
	r_ts = ntohl(*((long *) (pkt + 4)));

	if (
#ifdef RationalWorld
		rh->version == RTP_VERSION && /* Version ID correct */
		rh->pt < ELEMENTS(adt) &&	  /* Payload type credible */
		adt[rh->pt].sample_rate != 0 && /* Defined payload type */
									  /* Padding, if present, is plausible */
		(!rh->p || (pkt[len - 1] < (len - (12 + 4 * rh->cc))))
#else
		r_version == RTP_VERSION &&   /* Version ID correct */
		r_pt < ELEMENTS(adt) && 	  /* Payload type credible */
		adt[r_pt].sample_rate != 0 && /* Defined payload type */
									  /* Padding, if present, is plausible */
		(!r_p || (pkt[len - 1] < (len - (12 + 4 * r_cc))))
#endif
	   ) {
		struct soundbuf sb;
		unsigned char *payload;
		int lex, paylen;

							  /* Length of fixed header extension, if any */
		lex = r_x ? (ntohs(*((short *) (pkt + 2 + 12 + 4 * r_cc))) + 1) * 4 : 0;
		payload = pkt + (12 + 4 * r_cc) + lex; /* Start of payload */
		paylen = len - ((12 + 4 * r_cc) +	   /* Length of payload */
					lex + (r_p ? pkt[len - 1] : 0));
		sb.compression = fProtocol;
		sb.buffer.buffer_len = 0;

#ifdef NEEDED
		/* Fake an RTP unique host name from the SSRC identifier. */

        sprintf(sb.sendinghost, ".RTP:%02X%02X%02X%02X",
			pkt[8], pkt[9], pkt[10], pkt[11]);
#else
        strcpy(sb.sendinghost, ".RTP");
#endif

#ifdef RTP_PACKET_DUMP
		xd(pkt, len, TRUE);
#endif		  				
		switch (adt[r_pt].encoding) {

			case AE_PCMU:
				sb.buffer.buffer_len = paylen;
				bcopy(payload, sb.buffer.buffer_val, paylen);
				break;

			case AE_PCMA:
                /* Untested: I haven't found a program which sends in this
				   format. */
				{
					int i;
					unsigned char *op = (unsigned char *) sb.buffer.buffer_val;

					sb.buffer.buffer_len = paylen;
					for (i = 0; i < paylen; i++) {
						*op++ = alaw2ulaw(*payload++);
					}
				}
				break;

			case AE_GSM:
				sb.buffer.buffer_len = paylen + sizeof(short);
				bcopy(payload, sb.buffer.buffer_val + 2, paylen);
				*((short *) sb.buffer.buffer_val) =
					htons((short) ((((long) paylen) * 160) / 33));
				sb.compression |= fCompGSM;
				break;

			case AE_IDVI:
				bcopy(payload + 4, sb.buffer.buffer_val, paylen - 4);
				bcopy(payload, sb.buffer.buffer_val + (paylen - 4), 3);
				sb.buffer.buffer_len = paylen - 1;
				if (adt[r_pt].sample_rate == 8000) {
					sb.compression |= fCompADPCM;
				} else {

					/* Bogus attempt to convert sampling rate.	We
                       really need to do this in linear mode, which isn't
					   supported on all SPARCs.  This is better than
					   nothing, though. */

					int inc = adt[r_pt].sample_rate / 8000, i;
					unsigned char *in = (unsigned char *) sb.buffer.buffer_val,
								  *out = (unsigned char *) sb.buffer.buffer_val;

					adpcmdecomp(&sb);
					for (i = 0; i < (paylen - 4) / inc; i++) {
						*out++ = *in;
						in += inc;
					}
					sb.buffer.buffer_len /= inc;
				}
				break;

			case AE_LPC:
				{
					int i, n = paylen / 14;
					char *ip = (char *) payload,
						 *op = (char *) sb.buffer.buffer_val + 2;

					*((short *) sb.buffer.buffer_val) = htons((short) (160 * n));
					for (i = 0; i < n; i++) {
						bcopy(ip, op, 3);
						op[3] = 0;
						bcopy(ip + 3, op + 4, 10);
						ip += 14;
						op += 14;
					}
					sb.buffer.buffer_len = paylen + 2;
					sb.compression |= fCompLPC;
				}
				break;

			case AE_L16:
				if (adt[r_pt].channels == 1) {
					int i, j, k;
				
					for (i = j = k = 0; i < (paylen / 8); i++) {
						if ((k & 3) != 2  && ((i % 580) != 579)) {
							sb.buffer.buffer_val[j++] =
								audio_s2u((((unsigned short *) payload)[i * 4]));
						}
						k = (k + 1) % 11;
					}
					sb.buffer.buffer_len = j;
				} else if (adt[r_pt].channels == 2) {
					int i, j, k;
				
					for (i = j = k = 0; i < (paylen / 16); i++) {
						if ((k & 3) != 2  && ((i % 580) != 579)) {
							sb.buffer.buffer_val[j++] =
								audio_s2u(((((unsigned short *) payload)[i * 8]) +
										   (((unsigned short *) payload)[i * 8 + 1])) / 2);
						}
						k = (k + 1) % 11;
					}
					sb.buffer.buffer_len = j;
				}
				break;

			default:
				/* Unknown compression type. */
				break;
		}
		if (sb.buffer.buffer_len > 0) {
			bcopy(&sb, pkt, (int) (((sizeof sb - BUFL)) + sb.buffer.buffer_len));
#ifdef RTP_PACKET_DUMP			
			xd(&sb, (int) ((sizeof sb - BUFL) + sb.buffer.buffer_len), TRUE);
#endif			
		}  				
		return TRUE;
	}
	return FALSE;
}

/*	ISVALIDRTCPPACKET  --  Consistency check a packet to see if
						   is a compliant RTCP packet.	*/

int isValidRTCPpacket(unsigned char *p, int len)
{
	unsigned char *end;

	if (((((p[0] >> 6) & 3) != RTP_VERSION) &&	   /* Version incorrect ? */
		((((p[0] >> 6) & 3) != 1))) ||			   /* Allow Speak Freely too */
		((p[0] & 0x20) != 0) || 				   /* Padding in first packet ? */
		((p[1] != RTCP_SR) && (p[1] != RTCP_RR))) { /* First item not SR or RR ? */
		return FALSE;
	}
	end = p + len;

	do {
		/* Advance to next subpacket */
		p += (ntohs(*((short *) (p + 2))) + 1) * 4;
	} while (p < end && (((p[0] >> 6) & 3) == RTP_VERSION));

	return p == end;
}

/*	ISRTCPBYEPACKET  --  Test if this RTCP packet contains a BYE.  */

int isRTCPByepacket(unsigned char *p, int len)
{
	unsigned char *end;
	int sawbye = FALSE;

												   /* Version incorrect ? */
	if ((((p[0] >> 6) & 3) != RTP_VERSION && ((p[0] >> 6) & 3) != 1) ||
		((p[0] & 0x20) != 0) || 				   /* Padding in first packet ? */
		((p[1] != RTCP_SR) && (p[1] != RTCP_RR))) { /* First item not SR or RR ? */
		return FALSE;
	}
	end = p + len;

	do {
		if (p[1] == RTCP_BYE) {
			sawbye = TRUE;
		}
		/* Advance to next subpacket */
		p += (ntohs(*((short *) (p + 2))) + 1) * 4;
	} while (p < end && (((p[0] >> 6) & 3) == RTP_VERSION));

	return (p == end) && sawbye;
}

/*	ISRTCPAPPPACKET  --  Test if this RTCP packet contains a APP item
						 with a given name.  If so, returns a pointer
						 to the APP sub-packet in app_ptr.	*/

int isRTCPAPPpacket(unsigned char *p, int len, char *name, unsigned char **app_ptr)
{
	unsigned char *end;

	*app_ptr = NULL;
												   /* Version incorrect ? */
	if ((((p[0] >> 6) & 3) != RTP_VERSION && ((p[0] >> 6) & 3) != 1) ||
		((p[0] & 0x20) != 0) || 				   /* Padding in first packet ? */
		((p[1] != RTCP_SR) && (p[1] != RTCP_RR))) { /* First item not SR or RR ? */
		return FALSE;
	}
	end = p + len;

	do {
		if ((p[1] == RTCP_APP) && (memcmp(p + 8, name, 4) == 0)) {
			*app_ptr = p;
			return TRUE;
		}
		/* Advance to next subpacket */
		p += (ntohs(*((short *) (p + 2))) + 1) * 4;
	} while (p < end && (((p[0] >> 6) & 3) == RTP_VERSION));

	return FALSE;
}

/*	RTP_MAKE_SDES  --  Generate a source description for this
					   user, based either on information obtained
					   from the password file or supplied by
					   environment variables.  Strict construction
					   of the RTP specification requires every
					   SDES packet to be a composite which begins
					   with a sender or receiver report.  If the
                       "strict" argument is true, we'll comply with
                       this.  Unfortunately, Look Who's Listening
					   Server code was not aware of this little
					   twist when originally implemented, so it will
					   take some time to transition all the running
					   servers to composite packet aware code.	*/

int rtp_make_sdes(char **pkt, unsigned long ssrc_i, int port,
				  int exact, int strict)
{
	unsigned char zp[512];
	unsigned char *p = zp;
//	rtcp_t *rp;
	unsigned char *ap;
	int l, hl;
	char s[256];

#define addSDES(item, text) *ap++ = item; *ap++ = l = strlen(text); \
							bcopy(text, ap, l); ap += l

	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_SDES;
	rp->r.sdes.src = htonl(ssrc_i);
#else
	*((short *) p) = htons((u_short) ((RTP_VERSION << 14) | RTCP_SDES | (1 << 8)));
	*((long *) (p + 4)) = htonl(ssrc_i);
#endif	

	ap = p + 8;

	/* Build canonical name for this user.	This is generally
       a name which can be used for "talk" and "finger", and
       is not necessarily the user's E-mail address.  If the
       exact flag is set, we precede the name with an asterisk
       to inform the LWL server this name cannot be matched by
       a wild card. */
    
    if (exact) {
    	s[0] = '*';
    	strcpy(s + 1, lwl_s_email);
    	addSDES(RTCP_SDES_CNAME, s);
    } else {   
		addSDES(RTCP_SDES_CNAME, lwl_s_email);
	}
	if (lwl_s_fullname[0]) {
		addSDES(RTCP_SDES_NAME, lwl_s_fullname);
	}
	addSDES(RTCP_SDES_EMAIL, lwl_s_email);
	if (lwl_s_phone[0]) {
		addSDES(RTCP_SDES_PHONE, lwl_s_phone);
	}
	if (lwl_s_location[0]) {
		addSDES(RTCP_SDES_LOC, lwl_s_location);
	}

    addSDES(RTCP_SDES_TOOL, rstring(IDS_T_RTP_TOOL));

	/* If not strict, add a PRIV item indicating the port
	   we're communicating on. */
    
    if (!strict) {
	    sprintf(s, Format(59), port);
		addSDES(RTCP_SDES_PRIV, s);
	}

	*ap++ = RTCP_SDES_END;
	*ap++ = 0;

	l = ap - p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -