/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
#include"media/base/rtp_utils.h"
#include <string.h>
#include <cstdint> #include <vector>
// PacketTimeUpdateParams is defined in asyncpacketsocket.h. // TODO(sergeyu): Find more appropriate place for PacketTimeUpdateParams. #include"media/base/turn_utils.h" #include"modules/rtp_rtcp/source/rtp_util.h" #include"rtc_base/async_packet_socket.h" #include"rtc_base/byte_order.h" #include"rtc_base/checks.h" #include"rtc_base/message_digest.h"
// Fake auth tag written by the sender when external authentication is enabled. // HMAC in packet will be compared against this value before updating packet // with actual HMAC value. staticconst uint8_t kFakeAuthTag[10] = {0xba, 0xdd, 0xba, 0xdd, 0xba,
0xdd, 0xba, 0xdd, 0xba, 0xdd};
void UpdateAbsSendTimeExtensionValue(uint8_t* extension_data,
size_t length,
uint64_t time_us) { // Absolute send time in RTP streams. // // The absolute send time is signaled to the receiver in-band using the // general mechanism for RTP header extensions [RFC5285]. The payload // of this extension (the transmitted value) is a 24-bit unsigned integer // containing the sender's current time in seconds as a fixed point number // with 18 bits fractional part. // // The form of the absolute send time extension block: // // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | ID | len=2 | absolute send time | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ if (length != kAbsSendTimeExtensionLen) {
RTC_DCHECK_NOTREACHED(); return;
}
// Convert microseconds to a 6.18 fixed point value in seconds.
uint32_t send_time = ((time_us << 18) / 1000000) & 0x00FFFFFF;
extension_data[0] = static_cast<uint8_t>(send_time >> 16);
extension_data[1] = static_cast<uint8_t>(send_time >> 8);
extension_data[2] = static_cast<uint8_t>(send_time);
}
// Assumes `length` is actual packet length + tag length. Updates HMAC at end of // the RTP packet. void UpdateRtpAuthTag(uint8_t* rtp,
size_t length, const rtc::PacketTimeUpdateParams& packet_time_params) { // If there is no key, return. if (packet_time_params.srtp_auth_key.empty()) { return;
}
// ROC (rollover counter) is at the beginning of the auth tag. const size_t kRocLength = 4; if (tag_length < kRocLength || tag_length > length) {
RTC_DCHECK_NOTREACHED(); return;
}
uint8_t* auth_tag = rtp + (length - tag_length);
// We should have a fake HMAC value @ auth_tag.
RTC_DCHECK_EQ(0, memcmp(auth_tag, kFakeAuthTag, tag_length));
// Copy ROC after end of rtp packet.
memcpy(auth_tag, &packet_time_params.srtp_packet_index, kRocLength); // Authentication of a RTP packet will have RTP packet + ROC size.
size_t auth_required_length = length - tag_length + kRocLength;
if (result < tag_length) {
RTC_DCHECK_NOTREACHED(); return;
}
// Copy HMAC from output to packet. This is required as auth tag length // may not be equal to the actual HMAC length.
memcpy(auth_tag, output, tag_length);
}
// This method returns SSRC first of RTCP packet, except if packet is SDES. // TODO(mallinath) - Fully implement RFC 5506. This standard doesn't restrict // to send non-compound packets only to feedback messages. bool GetRtcpSsrc(constvoid* data, size_t len, uint32_t* value) { // Packet should be at least of 8 bytes, to get SSRC from a RTCP packet. if (!data || len < kMinRtcpPacketLen + 4 || !value) returnfalse; int pl_type; if (!GetRtcpType(data, len, &pl_type)) returnfalse; // SDES packet parsing is not supported. if (pl_type == kRtcpTypeSDES) returnfalse;
*value = rtc::GetBE32(static_cast<const uint8_t*>(data) + 4); returntrue;
}
// If extension bit is not set, we are done with header processing, as input // length is verified above. if (!(rtp[0] & 0x10)) { if (header_length)
*header_length = header_length_without_extension;
returntrue;
}
rtp += header_length_without_extension;
if (header_length_without_extension + kRtpExtensionHeaderLen > length) { returnfalse;
}
// Getting extension profile length. // Length is in 32 bit words.
uint16_t extension_length_in_32bits = rtc::GetBE16(rtp + 2);
size_t extension_length = extension_length_in_32bits * 4;
// if there is no valid `rtp_sendtime_extension_id` and `srtp_auth_key` in // PacketOptions, nothing to be updated in this packet. if (packet_time_params.rtp_sendtime_extension_id == -1 &&
packet_time_params.srtp_auth_key.empty()) { returntrue;
}
// If there is a srtp auth key present then the packet must be an RTP packet. // RTP packet may have been wrapped in a TURN Channel Data or TURN send // indication.
size_t rtp_start_pos;
size_t rtp_length; if (!UnwrapTurnPacket(data, length, &rtp_start_pos, &rtp_length)) {
RTC_DCHECK_NOTREACHED(); returnfalse;
}
// Making sure we have a valid RTP packet at the end. auto packet = rtc::MakeArrayView(data + rtp_start_pos, rtp_length); if (!webrtc::IsRtpPacket(packet) ||
!ValidateRtpHeader(data + rtp_start_pos, rtp_length, nullptr)) {
RTC_DCHECK_NOTREACHED(); returnfalse;
}
uint8_t* start = data + rtp_start_pos; // If packet option has non default value (-1) for sendtime extension id, // then we should parse the rtp packet to update the timestamp. Otherwise // just calculate HMAC and update packet with it. if (packet_time_params.rtp_sendtime_extension_id != -1) {
UpdateRtpAbsSendTimeExtension(start, rtp_length,
packet_time_params.rtp_sendtime_extension_id,
time_us);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.