static int rtp_write(URLContext *h, const uint8_t *buf, int size) { RTPContext *s = h->priv_data; int ret; URLContext *hd; if (RTP_PT_IS_RTCP(buf[1])) { /* RTCP payload type */ hd = s->rtcp_hd; } else { /* RTP payload type */ hd = s->rtp_hd; } ret = ffurl_write(hd, buf, size); return ret; }
static int tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) { RTSPState *rt = s->priv_data; AVFormatContext *rtpctx = rtsp_st->transport_priv; uint8_t *buf, *ptr; int size; uint8_t *interleave_header, *interleaved_packet; size = avio_close_dyn_buf(rtpctx->pb, &buf); ptr = buf; while (size > 4) { uint32_t packet_len = AV_RB32(ptr); int id; /* The interleaving header is exactly 4 bytes, which happens to be * the same size as the packet length header from * ffio_open_dyn_packet_buf. So by writing the interleaving header * over these bytes, we get a consecutive interleaved packet * that can be written in one call. */ interleaved_packet = interleave_header = ptr; ptr += 4; size -= 4; if (packet_len > size || packet_len < 2) break; if (RTP_PT_IS_RTCP(ptr[1])) id = rtsp_st->interleaved_max; /* RTCP */ else id = rtsp_st->interleaved_min; /* RTP */ interleave_header[0] = '$'; interleave_header[1] = id; AV_WB16(interleave_header + 2, packet_len); ffurl_write(rt->rtsp_hd_out, interleaved_packet, 4 + packet_len); ptr += packet_len; size -= packet_len; } av_free(buf); ffio_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE); return 0; }
static int rtp_write(URLContext *h, const uint8_t *buf, int size) { RTPContext *s = h->priv_data; int ret; URLContext *hd; if (size < 2) return AVERROR(EINVAL); if (s->write_to_source) { int fd; struct sockaddr_storage *source, temp_source; socklen_t *source_len, temp_len; if (!s->last_rtp_source.ss_family && !s->last_rtcp_source.ss_family) { av_log(h, AV_LOG_ERROR, "Unable to send packet to source, no packets received yet\n"); // Intentionally not returning an error here return size; } if (RTP_PT_IS_RTCP(buf[1])) { fd = s->rtcp_fd; source = &s->last_rtcp_source; source_len = &s->last_rtcp_source_len; } else { fd = s->rtp_fd; source = &s->last_rtp_source; source_len = &s->last_rtp_source_len; } if (!source->ss_family) { source = &temp_source; source_len = &temp_len; if (RTP_PT_IS_RTCP(buf[1])) { temp_source = s->last_rtp_source; temp_len = s->last_rtp_source_len; set_port(source, get_port(source) + 1); av_log(h, AV_LOG_INFO, "Not received any RTCP packets yet, inferring peer port " "from the RTP port\n"); } else { temp_source = s->last_rtcp_source; temp_len = s->last_rtcp_source_len; set_port(source, get_port(source) - 1); av_log(h, AV_LOG_INFO, "Not received any RTP packets yet, inferring peer port " "from the RTCP port\n"); } } if (!(h->flags & AVIO_FLAG_NONBLOCK)) { ret = ff_network_wait_fd(fd, 1); if (ret < 0) return ret; } ret = sendto(fd, buf, size, 0, (struct sockaddr *) source, *source_len); return ret < 0 ? ff_neterrno() : ret; } if (RTP_PT_IS_RTCP(buf[1])) { /* RTCP payload type */ hd = s->rtcp_hd; } else { /* RTP payload type */ hd = s->rtp_hd; } ret = ffurl_write(hd, buf, size); return ret; }
/** * Write an RTP hint (that may contain one or more RTP packets) * for the packets in data. data contains one or more packets with a * BE32 size header. * * @param out buffer where the hints are written * @param data buffer containing RTP packets * @param size the size of the data buffer * @param trk the MOVTrack for the hint track * @param dts pointer where the timestamp for the written RTP hint is stored * @return the number of RTP packets in the written hint */ static int write_hint_packets(AVIOContext *out, const uint8_t *data, int size, MOVTrack *trk, int64_t *dts) { int64_t curpos; int64_t count_pos, entries_pos; int count = 0, entries; count_pos = avio_tell(out); /* RTPsample header */ avio_wb16(out, 0); /* packet count */ avio_wb16(out, 0); /* reserved */ while (size > 4) { uint32_t packet_len = AV_RB32(data); uint16_t seq; uint32_t ts; int32_t ts_diff; data += 4; size -= 4; if (packet_len > size || packet_len <= 12) break; if (RTP_PT_IS_RTCP(data[1])) { /* RTCP packet, just skip */ data += packet_len; size -= packet_len; continue; } if (packet_len > trk->max_packet_size) trk->max_packet_size = packet_len; seq = AV_RB16(&data[2]); ts = AV_RB32(&data[4]); if (trk->prev_rtp_ts == 0) trk->prev_rtp_ts = ts; /* Unwrap the 32-bit RTP timestamp that wraps around often * into a not (as often) wrapping 64-bit timestamp. */ ts_diff = ts - trk->prev_rtp_ts; if (ts_diff > 0) { trk->cur_rtp_ts_unwrapped += ts_diff; trk->prev_rtp_ts = ts; ts_diff = 0; } if (*dts == AV_NOPTS_VALUE) *dts = trk->cur_rtp_ts_unwrapped; count++; /* RTPpacket header */ avio_wb32(out, 0); /* relative_time */ avio_write(out, data, 2); /* RTP header */ avio_wb16(out, seq); /* RTPsequenceseed */ avio_wb16(out, ts_diff ? 4 : 0); /* reserved + flags (extra_flag) */ entries_pos = avio_tell(out); avio_wb16(out, 0); /* entry count */ if (ts_diff) { /* if extra_flag is set */ avio_wb32(out, 16); /* extra_information_length */ avio_wb32(out, 12); /* rtpoffsetTLV box */ avio_write(out, "rtpo", 4); avio_wb32(out, ts_diff); } data += 12; size -= 12; packet_len -= 12; entries = 0; /* Write one or more constructors describing the payload data */ describe_payload(data, packet_len, out, &entries, &trk->sample_queue); data += packet_len; size -= packet_len; curpos = avio_tell(out); avio_seek(out, entries_pos, SEEK_SET); avio_wb16(out, entries); avio_seek(out, curpos, SEEK_SET); } curpos = avio_tell(out); avio_seek(out, count_pos, SEEK_SET); avio_wb16(out, count); avio_seek(out, curpos, SEEK_SET); return count; }
static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt, uint8_t **bufptr, int len) { uint8_t *buf = bufptr ? *bufptr : NULL; int ret, flags = 0; uint32_t timestamp; int rv = 0; if (!buf) { /* If parsing of the previous packet actually returned 0 or an error, * there's nothing more to be parsed from that packet, but we may have * indicated that we can return the next enqueued packet. */ if (s->prev_ret <= 0) return rtp_parse_queued_packet(s, pkt); /* return the next packets, if any */ if (s->st && s->parse_packet) { /* timestamp should be overwritten by parse_packet, if not, * the packet is left with pts == AV_NOPTS_VALUE */ timestamp = RTP_NOTS_VALUE; rv = s->parse_packet(s->ic, s->dynamic_protocol_context, s->st, pkt, ×tamp, NULL, 0, 0, flags); finalize_packet(s, pkt, timestamp); return rv; } else { // TODO: Move to a dynamic packet handler (like above) if (s->read_buf_index >= s->read_buf_size) return AVERROR(EAGAIN); ret = ff_mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index, s->read_buf_size - s->read_buf_index); if (ret < 0) return AVERROR(EAGAIN); s->read_buf_index += ret; if (s->read_buf_index < s->read_buf_size) return 1; else return 0; } } if (len < 12) return -1; if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) return -1; if (RTP_PT_IS_RTCP(buf[1])) { return rtcp_parse_packet(s, buf, len); } if ((s->seq == 0 && !s->queue) || s->queue_size <= 1) { /* First packet, or no reordering */ return rtp_parse_packet_internal(s, pkt, buf, len); } else { uint16_t seq = AV_RB16(buf + 2); int16_t diff = seq - s->seq; if (diff < 0) { /* Packet older than the previously emitted one, drop */ av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING, "RTP: dropping old packet received too late\n"); return -1; } else if (diff <= 1) { /* Correct packet */ rv = rtp_parse_packet_internal(s, pkt, buf, len); return rv; } else { /* Still missing some packet, enqueue this one. */ enqueue_packet(s, buf, len); *bufptr = NULL; /* Return the first enqueued packet if the queue is full, * even if we're missing something */ if (s->queue_len >= s->queue_size) return rtp_parse_queued_packet(s, pkt); return -1; } } }
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen) { uint8_t iv[16] = { 0 }, hmac[20]; uint64_t index; uint32_t ssrc; int rtcp, hmac_size, padding; uint8_t *buf; if (len < 8) return AVERROR_INVALIDDATA; rtcp = RTP_PT_IS_RTCP(in[1]); hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size; padding = hmac_size; if (rtcp) padding += 4; // For the RTCP index if (len + padding > outlen) return 0; memcpy(out, in, len); buf = out; if (rtcp) { ssrc = AV_RB32(buf + 4); index = s->rtcp_index++; buf += 8; len -= 8; } else { int ext, csrc; int seq = AV_RB16(buf + 2); if (len < 12) return AVERROR_INVALIDDATA; ssrc = AV_RB32(buf + 8); if (seq < s->seq_largest) s->roc++; s->seq_largest = seq; index = seq + (((uint64_t)s->roc) << 16); csrc = buf[0] & 0x0f; ext = buf[0] & 0x10; buf += 12; len -= 12; buf += 4 * csrc; len -= 4 * csrc; if (len < 0) return AVERROR_INVALIDDATA; if (ext) { if (len < 4) return AVERROR_INVALIDDATA; ext = (AV_RB16(buf + 2) + 1) * 4; if (len < ext) return AVERROR_INVALIDDATA; len -= ext; buf += ext; } } create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc); av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0); encrypt_counter(s->aes, iv, buf, len); if (rtcp) { AV_WB32(buf + len, 0x80000000 | index); len += 4; } av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth)); av_hmac_update(s->hmac, out, buf + len - out); if (!rtcp) { uint8_t rocbuf[4]; AV_WB32(rocbuf, s->roc); av_hmac_update(s->hmac, rocbuf, 4); } av_hmac_final(s->hmac, hmac, sizeof(hmac)); memcpy(buf + len, hmac, hmac_size); len += hmac_size; return buf + len - out; }
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr) { uint8_t iv[16] = { 0 }, hmac[20]; int len = *lenptr; int av_uninit(seq_largest); uint32_t ssrc, av_uninit(roc); uint64_t index; int rtcp, hmac_size; // TODO: Missing replay protection if (len < 2) return AVERROR_INVALIDDATA; rtcp = RTP_PT_IS_RTCP(buf[1]); hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size; if (len < hmac_size) return AVERROR_INVALIDDATA; // Authentication HMAC av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth)); // If MKI is used, this should exclude the MKI as well av_hmac_update(s->hmac, buf, len - hmac_size); if (!rtcp) { int seq = AV_RB16(buf + 2); uint32_t v; uint8_t rocbuf[4]; // RFC 3711 section 3.3.1, appendix A seq_largest = s->seq_initialized ? s->seq_largest : seq; v = roc = s->roc; if (seq_largest < 32768) { if (seq - seq_largest > 32768) v = roc - 1; } else { if (seq_largest - 32768 > seq) v = roc + 1; } if (v == roc) { seq_largest = FFMAX(seq_largest, seq); } else if (v == roc + 1) { seq_largest = seq; roc = v; } index = seq + (((uint64_t)v) << 16); AV_WB32(rocbuf, roc); av_hmac_update(s->hmac, rocbuf, 4); } av_hmac_final(s->hmac, hmac, sizeof(hmac)); if (memcmp(hmac, buf + len - hmac_size, hmac_size)) { av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n"); return AVERROR_INVALIDDATA; } len -= hmac_size; *lenptr = len; if (len < 12) return AVERROR_INVALIDDATA; if (rtcp) { uint32_t srtcp_index = AV_RB32(buf + len - 4); len -= 4; *lenptr = len; ssrc = AV_RB32(buf + 4); index = srtcp_index & 0x7fffffff; buf += 8; len -= 8; if (!(srtcp_index & 0x80000000)) return 0; } else { int ext, csrc; s->seq_initialized = 1; s->seq_largest = seq_largest; s->roc = roc; csrc = buf[0] & 0x0f; ext = buf[0] & 0x10; ssrc = AV_RB32(buf + 8); buf += 12; len -= 12; buf += 4 * csrc; len -= 4 * csrc; if (len < 0) return AVERROR_INVALIDDATA; if (ext) { if (len < 4) return AVERROR_INVALIDDATA; ext = (AV_RB16(buf + 2) + 1) * 4; if (len < ext) return AVERROR_INVALIDDATA; len -= ext; buf += ext; } } create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc); av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0); encrypt_counter(s->aes, iv, buf, len); return 0; }