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

📄 rtp.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Returns: The SSRC we are currently using in this session. Note that our * SSRC can change at any time (due to collisions) so applications must not * store the value returned, but rather should call this function each time  * they need it. */uint32_t rtp_my_ssrc(struct rtp *session){	check_database(session);	return session->my_ssrc;}static void process_rtp(struct rtp *session, uint32_t curr_rtp_ts, rtp_packet *packet, source *s){	int		 i, d, transit;	rtp_event	 event;	struct timeval	 event_ts;	if (packet->cc > 0) {		for (i = 0; i < packet->cc; i++) {			create_source(session, packet->csrc[i], FALSE);		}	}	/* Update the source database... */	if (s->sender == FALSE) {		s->sender = TRUE;		session->sender_count++;	}	transit    = curr_rtp_ts - packet->ts;	d      	   = transit - s->transit;	s->transit = transit;	if (d < 0) {		d = -d;	}	s->jitter += d - ((s->jitter + 8) / 16);		/* Callback to the application to process the packet... */	if (!filter_event(session, packet->ssrc)) {		gettimeofday(&event_ts, NULL);		event.ssrc = packet->ssrc;		event.type = RX_RTP;		event.data = (void *) packet;	/* The callback function MUST free this! */		event.ts   = &event_ts;		session->callback(session, &event);	}}static int validate_rtp2(rtp_packet *packet, int len){	/* Check for valid payload types..... 72-76 are RTCP payload type numbers, with */	/* the high bit missing so we report that someone is running on the wrong port. */	if (packet->pt >= 72 && packet->pt <= 76) {		debug_msg("rtp_header_validation: payload-type invalid");		if (packet->m) {			debug_msg(" (RTCP packet on RTP port?)");		}		debug_msg("\n");		return FALSE;	}	/* Check that the length of the packet is sensible... */	if (len < (12 + (4 * packet->cc))) {		debug_msg("rtp_header_validation: packet length is smaller than the header\n");		return FALSE;	}	/* Check that the amount of padding specified is sensible. */	/* Note: have to include the size of any extension header! */	if (packet->p) {		int	payload_len = len - 12 - (packet->cc * 4);                if (packet->x) {                        /* extension header and data */                        payload_len -= 4 * (1 + packet->extn_len);                }                if (packet->data[packet->data_len - 1] > payload_len) {                        debug_msg("rtp_header_validation: padding greater than payload length\n");                        return FALSE;                }                if (packet->data[packet->data_len - 1] < 1) {			debug_msg("rtp_header_validation: padding zero\n");			return FALSE;		}        }	return TRUE;}static inline int validate_rtp(struct rtp *session, rtp_packet *packet, int len){	/* This function checks the header info to make sure that the packet */	/* is valid. We return TRUE if the packet is valid, FALSE otherwise. */	/* See Appendix A.1 of the RTP specification.                        */	/* We only accept RTPv2 packets... */	if (packet->v != 2) {		debug_msg("rtp_header_validation: v != 2\n");		return FALSE;	}	if (!session->opt->wait_for_rtcp) {		/* We prefer speed over accuracy... */		return TRUE;	}	return validate_rtp2(packet, len);}static void rtp_recv_data(struct rtp *session, uint32_t curr_rtp_ts){	/* This routine preprocesses an incoming RTP packet, deciding whether to process it. */	static rtp_packet	*packet   = NULL;	static uint8_t		*buffer   = NULL;	static uint8_t		*buffer12 = NULL;	int			 buflen;	source			*s;	if (!session->opt->reuse_bufs || (packet == NULL)) {		packet   = (rtp_packet *) xmalloc(RTP_MAX_PACKET_LEN);		buffer   = ((uint8_t *) packet) + RTP_PACKET_HEADER_SIZE;		buffer12 = buffer + 12;	}	buflen = udp_recv(session->rtp_socket, buffer, RTP_MAX_PACKET_LEN - RTP_PACKET_HEADER_SIZE);	if (buflen > 0) {		if (session->encryption_enabled) {			uint8_t 	 initVec[8] = {0,0,0,0,0,0,0,0};			(session->decrypt_func)(session, buffer, buflen, initVec);		}		/* Convert header fields to host byte order... */		packet->seq      = ntohs(packet->seq);		packet->ts       = ntohl(packet->ts);		packet->ssrc     = ntohl(packet->ssrc);		/* Setup internal pointers, etc... */		if (packet->cc) {			int	i;			packet->csrc = (uint32_t *)(buffer12);			for (i = 0; i < packet->cc; i++) {				packet->csrc[i] = ntohl(packet->csrc[i]);			}		} else {			packet->csrc = NULL;		}		if (packet->x) {			packet->extn      = buffer12 + (packet->cc * 4);			packet->extn_len  = (packet->extn[2] << 8) | packet->extn[3];			packet->extn_type = (packet->extn[0] << 8) | packet->extn[1];		} else {			packet->extn      = NULL;			packet->extn_len  = 0;			packet->extn_type = 0;		}		packet->data     = buffer12 + (packet->cc * 4);		packet->data_len = buflen -  (packet->cc * 4) - 12;		if (packet->extn != NULL) {			packet->data += ((packet->extn_len + 1) * 4);			packet->data_len -= ((packet->extn_len + 1) * 4);		}		if (validate_rtp(session, packet, buflen)) {			if (session->opt->wait_for_rtcp) {				s = create_source(session, packet->ssrc, TRUE);			} else {				s = get_source(session, packet->ssrc);			}			if (session->opt->promiscuous_mode) {				if (s == NULL) {					create_source(session, packet->ssrc, FALSE);					s = get_source(session, packet->ssrc);				}				process_rtp(session, curr_rtp_ts, packet, s);				return; /* We don't free "packet", that's done by the callback function... */			} 			if (s != NULL) {				if (s->probation == -1) {					s->probation = MIN_SEQUENTIAL;					s->max_seq   = packet->seq - 1;				}				if (update_seq(s, packet->seq)) {					process_rtp(session, curr_rtp_ts, packet, s);					return;	/* we don't free "packet", that's done by the callback function... */				} else {					/* This source is still on probation... */					debug_msg("RTP packet from probationary source ignored...\n");				}			} else {				debug_msg("RTP packet from unknown source ignored\n");			}		} else {			session->invalid_rtp_count++;			debug_msg("Invalid RTP packet discarded\n");		}	}	if (!session->opt->reuse_bufs) {		xfree(packet);	}}static int validate_rtcp(uint8_t *packet, int len){	/* Validity check for a compound RTCP packet. This function returns */	/* TRUE if the packet is okay, FALSE if the validity check fails.   */        /*                                                                  */	/* The following checks can be applied to RTCP packets [RFC1889]:   */        /* o RTP version field must equal 2.                                */        /* o The payload type field of the first RTCP packet in a compound  */        /*   packet must be equal to SR or RR.                              */        /* o The padding bit (P) should be zero for the first packet of a   */        /*   compound RTCP packet because only the last should possibly     */        /*   need padding.                                                  */        /* o The length fields of the individual RTCP packets must total to */        /*   the overall length of the compound RTCP packet as received.    */	rtcp_t	*pkt  = (rtcp_t *) packet;	rtcp_t	*end  = (rtcp_t *) (((char *) pkt) + len);	rtcp_t	*r    = pkt;	int	 l    = 0;	int	 pc   = 1;	int	 p    = 0;	/* All RTCP packets must be compound packets (RFC1889, section 6.1) */	if (((ntohs(pkt->common.length) + 1) * 4) == len) {		debug_msg("Bogus RTCP packet: not a compound packet\n");		return FALSE;	}	/* Check the RTCP version, payload type and padding of the first in  */	/* the compund RTCP packet...                                        */	if (pkt->common.version != 2) {		debug_msg("Bogus RTCP packet: version number != 2 in the first sub-packet\n");		return FALSE;	}	if (pkt->common.p != 0) {		debug_msg("Bogus RTCP packet: padding bit is set on first packet in compound\n");		return FALSE;	}	if ((pkt->common.pt != RTCP_SR) && (pkt->common.pt != RTCP_RR)) {		debug_msg("Bogus RTCP packet: compund packet does not start with SR or RR\n");		return FALSE;	}	/* Check all following parts of the compund RTCP packet. The RTP version */	/* number must be 2, and the padding bit must be zero on all apart from  */	/* the last packet.                                                      */	do {		if (p == 1) {			debug_msg("Bogus RTCP packet: padding bit set before last in compound (sub-packet %d)\n", pc);			return FALSE;		}		if (r->common.p) {			p = 1;		}		if (r->common.version != 2) {			debug_msg("Bogus RTCP packet: version number != 2 in sub-packet %d\n", pc);			return FALSE;		}		l += (ntohs(r->common.length) + 1) * 4;		r  = (rtcp_t *) (((uint32_t *) r) + ntohs(r->common.length) + 1);		pc++;	/* count of sub-packets, for debugging... */	} while (r < end);	/* Check that the length of the packets matches the length of the UDP */	/* packet in which they were received...                              */	if (l != len) {		debug_msg("Bogus RTCP packet: RTCP packet length does not match UDP packet length (%d != %d)\n", l, len);		return FALSE;	}	if (r != end) {		debug_msg("Bogus RTCP packet: RTCP packet length does not match UDP packet length (%p != %p)\n", r, end);		return FALSE;	}	return TRUE;}static void process_report_blocks(struct rtp *session, rtcp_t *packet, uint32_t ssrc, rtcp_rr *rrp, struct timeval *event_ts){	int i;	rtp_event	 event;	rtcp_rr		*rr;	/* ...process RRs... */	if (packet->common.count == 0) {		if (!filter_event(session, ssrc)) {			event.ssrc = ssrc;			event.type = RX_RR_EMPTY;			event.data = NULL;			event.ts   = event_ts;			session->callback(session, &event);		}	} else {		for (i = 0; i < packet->common.count; i++, rrp++) {			rr = (rtcp_rr *) xmalloc(sizeof(rtcp_rr));			rr->ssrc          = ntohl(rrp->ssrc);			rr->fract_lost    = rrp->fract_lost;	/* Endian conversion handled in the */			rr->total_lost    = rrp->total_lost;	/* definition of the rtcp_rr type.  */			rr->last_seq      = ntohl(rrp->last_seq);			rr->jitter        = ntohl(rrp->jitter);			rr->lsr           = ntohl(rrp->lsr);			rr->dlsr          = ntohl(rrp->dlsr);			/* Create a database entry for this SSRC, if one doesn't already exist... */			create_source(session, rr->ssrc, FALSE);			/* Store the RR for later use... */			insert_rr(session, ssrc, rr, event_ts);			/* Call the event handler... */			if (!filter_event(session, ssrc)) {				event.ssrc = ssrc;				event.type = RX_RR;				event.data = (void *) rr;				event.ts   = event_ts;				session->callback(session, &event);			}		}	}}static void process_rtcp_sr(struct rtp *session, rtcp_t *packet, struct timeval *event_ts){	uint32_t	 ssrc;	rtp_event	 event;	rtcp_sr		*sr;	source		*s;	ssrc = ntohl(packet->r.sr.sr.ssrc);	s = create_source(session, ssrc, FALSE);	if (s == NULL) {		debug_msg("Source 0x%08x invalid, skipping...\n", ssrc);		return;	}	/* Mark as an active sender, if we get a sender report... */	if (s->sender == FALSE) {		s->sender = TRUE;		session->sender_count++;	}	/* Process the SR... */	sr = (rtcp_sr *) xmalloc(sizeof(rtcp_sr));	sr->ssrc          = ssrc;	sr->ntp_sec       = ntohl(packet->r.sr.sr.ntp_sec);	sr->ntp_frac      = ntohl(packet->r.sr.sr.ntp_frac);	sr->rtp_ts        = ntohl(packet->r.sr.sr.rtp_ts);	sr->sender_pcount = ntohl(packet->r.sr.sr.sender_pcount);	sr->sender_bcount = ntohl(packet->r.sr.sr.sender_bcount);	/* Store the SR for later retrieval... */	if (s->sr != NULL) {		xfree(s->sr);	}	s->sr = sr;	s->last_sr = *event_ts;	/* Call the event handler... */	if (!filter_event(session, ssrc)) {		event.ssrc = ssrc;		event.type = RX_SR;		event.data = (void *) sr;		event.ts   = event_ts;		session->callback(session, &event);	}	process_report_blocks(session, packet, ssrc, packet->r.sr.rr, event_ts);	if (((packet->common.count * 6) + 1) < (ntohs(packet->common.length) - 5)) {		debug_msg("Profile specific SR extension ignored\n");	}}static void process_rtcp_rr(struct rtp *session, rtcp_t *packet, struct timeval *event_ts){	uint32_t		 ssrc;	source		*s;	ssrc = ntohl(packet->r.rr.ssrc);	s = create_source(session, ssrc, FALSE);	if (s == NULL) {		debug_msg("Source 0x%08x invalid, skipping...\n", ssrc);		return;	}	process_report_blocks(session, packet, ssrc, packet->r.rr.rr, event_ts);	if (((packet->common.count * 6) + 1) < ntohs(packet->common.length)) {		debug_msg("Profile specific RR extension ignored\n");	}}static void process_rtcp_sdes(struct rtp *session, rtcp_t *packet, struct timeval *event_ts){	int 			count = packet->common.count;	struct rtcp_sdes_t 	*sd   = &packet->r.sdes;	rtcp_sdes_item 		*rsp; 	rtcp_sdes_item		*rspn;	rtcp_sdes_item 		*end  = (rtcp_sdes_item *) ((uint32_t *)packet + packet->common.length + 1);	source 			*s;	rtp_event		 event;	while (--count >= 0) {		rsp = &sd->item[0];		if (rsp >= end) {			break;		}		sd->ssrc = ntohl(sd->ssrc);		s = create_source(session, sd->ssrc, FALSE);		if (s == NULL) {			debug_msg("Can't get valid source entry for 0x%08x, skipping...\n", sd->ssrc);		} else {			for (; rsp->type; rsp = rspn ) {				rspn = (rtcp_sdes_item *)((char*)rsp+rsp->length+2);				if (rspn >= end) {					rsp = rspn;					break;				}				if (rtp_set_sdes(session, sd->ssrc, rsp->type, rsp->data, rsp->length)) {

⌨️ 快捷键说明

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