📄 rtp.c
字号:
* 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 + -