Replace DatagramDtlsAdaptor with DatagramRtpTransport.

DatagramDtlsAdaptor wraps a DatagramTransport in a DtlsTransport.  This
is only used by wrapping it again, in an RtpTransport.  It is simpler to
just wrap DatagramTransport directly into an RtpTransport.

DatagramTransport is never used as a DtlsTransport, and doesn't support
most of the functionality exposed by the DtlsTransport interface.

However, it supports *all* the functionality of the RtpTransport, making
this a much cleaner fit.

Bug: webrtc:9719
Change-Id: I699e8124ee4cb6c8c187162f9b444ff0431a4902
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/149400
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28921}
This commit is contained in:
Bjorn A Mellem 2019-08-20 16:58:03 -07:00 committed by Commit Bot
parent a310b388c0
commit 364b2673c0
8 changed files with 450 additions and 747 deletions

View File

@ -36,8 +36,8 @@ rtc_static_library("rtc_pc_base") {
"channel_manager.h",
"composite_rtp_transport.cc",
"composite_rtp_transport.h",
"datagram_dtls_adaptor.cc",
"datagram_dtls_adaptor.h",
"datagram_rtp_transport.cc",
"datagram_rtp_transport.h",
"dtls_srtp_transport.cc",
"dtls_srtp_transport.h",
"dtls_transport.cc",

View File

@ -1,610 +0,0 @@
/*
* Copyright 2018 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 "pc/datagram_dtls_adaptor.h"
#include <algorithm>
#include <memory>
#include <utility>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/rtc_error.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
#include "p2p/base/dtls_transport_internal.h"
#include "p2p/base/packet_transport_internal.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/dscp.h"
#include "rtc_base/logging.h"
#include "rtc_base/message_queue.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/stream.h"
#include "rtc_base/thread.h"
#include "system_wrappers/include/field_trial.h"
#ifdef BYPASS_DATAGRAM_DTLS_TEST_ONLY
// Send unencrypted packets directly to ICE, bypassing datagtram
// transport. Use in tests only.
constexpr bool kBypassDatagramDtlsTestOnly = true;
#else
constexpr bool kBypassDatagramDtlsTestOnly = false;
#endif
namespace cricket {
namespace {
// Field trials.
// Disable datagram to RTCP feedback translation and enable RTCP feedback loop
// on top of datagram feedback loop. Note that two
// feedback loops add unneccesary overhead, so it's preferable to use feedback
// loop provided by datagram transport and convert datagram ACKs to RTCP ACKs,
// but enabling RTCP feedback loop may be useful in tests and experiments.
const char kDisableDatagramToRtcpFeebackTranslationFieldTrial[] =
"WebRTC-kDisableDatagramToRtcpFeebackTranslation";
} // namespace
// Maximum packet size of RTCP feedback packet for allocation. We re-create RTCP
// feedback packets when we get ACK notifications from datagram transport. Our
// rtcp feedback packets contain only 1 ACK, so they are much smaller than 1250.
constexpr size_t kMaxRtcpFeedbackPacketSize = 1250;
DatagramDtlsAdaptor::DatagramDtlsAdaptor(
const std::vector<webrtc::RtpExtension>& rtp_header_extensions,
IceTransportInternal* ice_transport,
webrtc::DatagramTransportInterface* datagram_transport,
const webrtc::CryptoOptions& crypto_options,
webrtc::RtcEventLog* event_log)
: crypto_options_(crypto_options),
ice_transport_(ice_transport),
datagram_transport_(datagram_transport),
event_log_(event_log),
disable_datagram_to_rtcp_feeback_translation_(
webrtc::field_trial::IsEnabled(
kDisableDatagramToRtcpFeebackTranslationFieldTrial)) {
// Save extension map for parsing RTP packets (we only need transport
// sequence numbers).
const webrtc::RtpExtension* transport_sequence_number_extension =
webrtc::RtpExtension::FindHeaderExtensionByUri(
rtp_header_extensions, webrtc::TransportSequenceNumber::kUri);
if (transport_sequence_number_extension != nullptr) {
rtp_header_extension_map_.Register<webrtc::TransportSequenceNumber>(
transport_sequence_number_extension->id);
} else {
RTC_LOG(LS_ERROR) << "Transport sequence numbers are not supported in "
"datagram transport connection";
}
// TODO(sukhanov): Add CHECK to make sure that field trial
// WebRTC-ExcludeTransportSequenceNumberFromFecFieldTrial is enabled.
// If feedback loop is translation is enabled, FEC packets must exclude
// transport sequence numbers, otherwise recovered packets will be corrupt.
RTC_DCHECK(ice_transport_);
RTC_DCHECK(datagram_transport_);
ConnectToIceTransport();
}
void DatagramDtlsAdaptor::ConnectToIceTransport() {
ice_transport_->SignalWritableState.connect(
this, &DatagramDtlsAdaptor::OnWritableState);
ice_transport_->SignalReadyToSend.connect(
this, &DatagramDtlsAdaptor::OnReadyToSend);
ice_transport_->SignalReceivingState.connect(
this, &DatagramDtlsAdaptor::OnReceivingState);
// Datagram transport does not propagate network route change.
ice_transport_->SignalNetworkRouteChanged.connect(
this, &DatagramDtlsAdaptor::OnNetworkRouteChanged);
if (kBypassDatagramDtlsTestOnly) {
// In bypass mode we have to subscribe to ICE read and sent events.
// Test only case to use ICE directly instead of data transport.
ice_transport_->SignalReadPacket.connect(
this, &DatagramDtlsAdaptor::OnReadPacket);
ice_transport_->SignalSentPacket.connect(
this, &DatagramDtlsAdaptor::OnSentPacket);
} else {
// Subscribe to Data Transport read packets.
datagram_transport_->SetDatagramSink(this);
datagram_transport_->SetTransportStateCallback(this);
}
}
DatagramDtlsAdaptor::~DatagramDtlsAdaptor() {
// Unsubscribe from Datagram Transport dinks.
datagram_transport_->SetDatagramSink(nullptr);
datagram_transport_->SetTransportStateCallback(nullptr);
}
const webrtc::CryptoOptions& DatagramDtlsAdaptor::crypto_options() const {
return crypto_options_;
}
int DatagramDtlsAdaptor::SendPacket(const char* data,
size_t len,
const rtc::PacketOptions& options,
int flags) {
RTC_DCHECK_RUN_ON(&thread_checker_);
// TODO(sukhanov): Handle options and flags.
if (kBypassDatagramDtlsTestOnly) {
// In bypass mode sent directly to ICE.
return ice_transport_->SendPacket(data, len, options);
}
// Assign and increment datagram_id.
const webrtc::DatagramId datagram_id = current_datagram_id_++;
rtc::ArrayView<const uint8_t> original_data(
reinterpret_cast<const uint8_t*>(data), len);
// Send as is (without extracting transport sequence number) for
// - All RTCP packets, because they do not have transport sequence number.
// - RTP packets if we are not doing datagram => RTCP feedback translation.
if (disable_datagram_to_rtcp_feeback_translation_ ||
webrtc::RtpHeaderParser::IsRtcp(original_data.data(),
original_data.size())) {
// Even if we are not extracting transport sequence number we need to
// propagate "Sent" notification for both RTP and RTCP packets. For this
// reason we need save options.packet_id in packet map.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
return SendDatagram(original_data, datagram_id);
}
// Parse RTP packet.
webrtc::RtpPacket rtp_packet(&rtp_header_extension_map_);
if (!rtp_packet.Parse(original_data)) {
RTC_NOTREACHED() << "Failed to parse outgoing RtpPacket, len=" << len
<< ", options.packet_id=" << options.packet_id;
return -1;
}
// Try to get transport sequence number.
uint16_t transport_senquence_number;
if (!rtp_packet.GetExtension<webrtc::TransportSequenceNumber>(
&transport_senquence_number)) {
// Save packet info without transport sequence number.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
RTC_LOG(LS_VERBOSE)
<< "Sending rtp packet without transport sequence number, packet="
<< rtp_packet.ToString();
return SendDatagram(original_data, datagram_id);
}
// Save packet info with sequence number and ssrc so we could reconstruct
// RTCP feedback packet when we receive datagram ACK.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(
options.packet_id, rtp_packet.Ssrc(), transport_senquence_number);
// Since datagram transport provides feedback and timestamps, we do not need
// to send transport sequence number, so we remove it from RTP packet. Later
// when we get Ack for sent datagram, we will re-create RTCP feedback packet.
if (!rtp_packet.RemoveExtension(webrtc::TransportSequenceNumber::kId)) {
RTC_NOTREACHED() << "Failed to remove transport sequence number, packet="
<< rtp_packet.ToString();
return -1;
}
RTC_LOG(LS_VERBOSE) << "Removed transport_senquence_number="
<< transport_senquence_number
<< " from packet=" << rtp_packet.ToString()
<< ", saved bytes=" << len - rtp_packet.size();
return SendDatagram(
rtc::ArrayView<const uint8_t>(rtp_packet.data(), rtp_packet.size()),
datagram_id);
}
int DatagramDtlsAdaptor::SendDatagram(rtc::ArrayView<const uint8_t> data,
webrtc::DatagramId datagram_id) {
webrtc::RTCError error = datagram_transport_->SendDatagram(data, datagram_id);
return (error.ok() ? data.size() : -1);
}
void DatagramDtlsAdaptor::OnReadPacket(rtc::PacketTransportInternal* transport,
const char* data,
size_t size,
const int64_t& packet_time_us,
int flags) {
// Only used in bypass mode.
RTC_DCHECK(kBypassDatagramDtlsTestOnly);
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_DCHECK_EQ(transport, ice_transport_);
RTC_DCHECK(flags == 0);
PropagateReadPacket(
rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(data), size),
packet_time_us);
}
void DatagramDtlsAdaptor::OnDatagramReceived(
rtc::ArrayView<const uint8_t> data) {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_DCHECK(!kBypassDatagramDtlsTestOnly);
// TODO(sukhanov): I am not filling out time, but on my video quality
// test in WebRTC the time was not set either and higher layers of the stack
// overwrite -1 with current current rtc time. Leaveing comment for now to
// make sure it works as expected.
int64_t packet_time_us = -1;
PropagateReadPacket(data, packet_time_us);
}
void DatagramDtlsAdaptor::OnDatagramSent(webrtc::DatagramId datagram_id) {
RTC_DCHECK_RUN_ON(&thread_checker_);
// Find packet_id and propagate OnPacketSent notification.
const auto& it = sent_rtp_packet_map_.find(datagram_id);
if (it == sent_rtp_packet_map_.end()) {
RTC_NOTREACHED() << "Did not find sent packet info for sent datagram_id="
<< datagram_id;
return;
}
// Also see how DatagramDtlsAdaptor::OnSentPacket handles OnSentPacket
// notification from ICE in bypass mode.
rtc::SentPacket sent_packet(/*packet_id=*/it->second.packet_id,
rtc::TimeMillis());
PropagateOnSentNotification(sent_packet);
}
bool DatagramDtlsAdaptor::GetAndRemoveSentPacketInfo(
webrtc::DatagramId datagram_id,
SentPacketInfo* sent_packet_info) {
RTC_CHECK(sent_packet_info != nullptr);
const auto& it = sent_rtp_packet_map_.find(datagram_id);
if (it == sent_rtp_packet_map_.end()) {
return false;
}
*sent_packet_info = it->second;
sent_rtp_packet_map_.erase(it);
return true;
}
void DatagramDtlsAdaptor::OnDatagramAcked(const webrtc::DatagramAck& ack) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SentPacketInfo sent_packet_info;
if (!GetAndRemoveSentPacketInfo(ack.datagram_id, &sent_packet_info)) {
// TODO(sukhanov): If OnDatagramAck() can come after OnDatagramLost(),
// datagram_id is already deleted and we may need to relax the CHECK below.
// It's probably OK to ignore such datagrams, because it's been a few RTTs
// anyway since they were sent.
RTC_NOTREACHED() << "Did not find sent packet info for datagram_id="
<< ack.datagram_id;
return;
}
RTC_LOG(LS_VERBOSE) << "Datagram acked, ack.datagram_id=" << ack.datagram_id
<< ", sent_packet_info.packet_id="
<< sent_packet_info.packet_id
<< ", sent_packet_info.transport_sequence_number="
<< sent_packet_info.transport_sequence_number.value_or(-1)
<< ", sent_packet_info.ssrc="
<< sent_packet_info.ssrc.value_or(-1)
<< ", receive_timestamp_ms="
<< ack.receive_timestamp.ms();
// If transport sequence number was not present in RTP packet, we do not need
// to propagate RTCP feedback.
if (!sent_packet_info.transport_sequence_number) {
return;
}
// TODO(sukhanov): We noticed that datagram transport implementations can
// return zero timestamps in the middle of the call. This is workaround to
// avoid propagating zero timestamps, but we need to understand why we have
// them in the first place.
int64_t receive_timestamp_us = ack.receive_timestamp.us();
if (receive_timestamp_us == 0) {
receive_timestamp_us = previous_nonzero_timestamp_us_;
} else {
previous_nonzero_timestamp_us_ = receive_timestamp_us;
}
// Ssrc must be provided in packet info if transport sequence number is set,
// which is guaranteed by SentPacketInfo constructor.
RTC_CHECK(sent_packet_info.ssrc);
// Recreate RTCP feedback packet.
webrtc::rtcp::TransportFeedback feedback_packet;
feedback_packet.SetMediaSsrc(*sent_packet_info.ssrc);
const uint16_t transport_sequence_number =
sent_packet_info.transport_sequence_number.value();
feedback_packet.SetBase(transport_sequence_number, receive_timestamp_us);
feedback_packet.AddReceivedPacket(transport_sequence_number,
receive_timestamp_us);
rtc::Buffer buffer(kMaxRtcpFeedbackPacketSize);
size_t index = 0;
if (!feedback_packet.Create(buffer.data(), &index, buffer.capacity(),
nullptr)) {
RTC_NOTREACHED() << "Failed to create RTCP feedback packet";
return;
}
RTC_CHECK_GT(index, 0);
RTC_CHECK_LE(index, kMaxRtcpFeedbackPacketSize);
// Propagage created RTCP packet as normal incoming packet.
buffer.SetSize(index);
PropagateReadPacket(buffer, /*packet_time_us=*/-1);
}
void DatagramDtlsAdaptor::OnDatagramLost(webrtc::DatagramId datagram_id) {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_LOG(LS_INFO) << "Datagram lost, datagram_id=" << datagram_id;
SentPacketInfo sent_packet_info;
if (!GetAndRemoveSentPacketInfo(datagram_id, &sent_packet_info)) {
RTC_NOTREACHED() << "Did not find sent packet info for lost datagram_id="
<< datagram_id;
}
}
void DatagramDtlsAdaptor::OnSentPacket(rtc::PacketTransportInternal* transport,
const rtc::SentPacket& sent_packet) {
// Only used in bypass mode.
RTC_DCHECK(kBypassDatagramDtlsTestOnly);
RTC_DCHECK_RUN_ON(&thread_checker_);
PropagateOnSentNotification(sent_packet);
}
void DatagramDtlsAdaptor::PropagateOnSentNotification(
const rtc::SentPacket& sent_packet) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SignalSentPacket(this, sent_packet);
}
void DatagramDtlsAdaptor::PropagateReadPacket(
rtc::ArrayView<const uint8_t> data,
const int64_t& packet_time_us) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SignalReadPacket(this, reinterpret_cast<const char*>(data.data()),
data.size(), packet_time_us, /*flags=*/0);
}
int DatagramDtlsAdaptor::component() const {
return kDatagramDtlsAdaptorComponent;
}
bool DatagramDtlsAdaptor::IsDtlsActive() const {
return false;
}
bool DatagramDtlsAdaptor::GetDtlsRole(rtc::SSLRole* role) const {
return false;
}
bool DatagramDtlsAdaptor::SetDtlsRole(rtc::SSLRole role) {
return false;
}
bool DatagramDtlsAdaptor::GetSrtpCryptoSuite(int* cipher) {
return false;
}
bool DatagramDtlsAdaptor::GetSslCipherSuite(int* cipher) {
return false;
}
rtc::scoped_refptr<rtc::RTCCertificate>
DatagramDtlsAdaptor::GetLocalCertificate() const {
return nullptr;
}
bool DatagramDtlsAdaptor::SetLocalCertificate(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
return false;
}
std::unique_ptr<rtc::SSLCertChain> DatagramDtlsAdaptor::GetRemoteSSLCertChain()
const {
return nullptr;
}
bool DatagramDtlsAdaptor::ExportKeyingMaterial(const std::string& label,
const uint8_t* context,
size_t context_len,
bool use_context,
uint8_t* result,
size_t result_len) {
return false;
}
bool DatagramDtlsAdaptor::SetRemoteFingerprint(const std::string& digest_alg,
const uint8_t* digest,
size_t digest_len) {
// TODO(sukhanov): We probably should not called with fingerptints in
// datagram scenario, but we may need to change code up the stack before
// we can return false or DCHECK.
return true;
}
bool DatagramDtlsAdaptor::SetSslMaxProtocolVersion(
rtc::SSLProtocolVersion version) {
// TODO(sukhanov): We may be able to return false and/or DCHECK that we
// are not called if datagram transport is used, but we need to change
// integration before we can do it.
return true;
}
IceTransportInternal* DatagramDtlsAdaptor::ice_transport() {
return ice_transport_;
}
// Similar implementaton as in p2p/base/dtls_transport.cc.
void DatagramDtlsAdaptor::OnReadyToSend(
rtc::PacketTransportInternal* transport) {
RTC_DCHECK_RUN_ON(&thread_checker_);
if (writable()) {
SignalReadyToSend(this);
}
}
void DatagramDtlsAdaptor::OnWritableState(
rtc::PacketTransportInternal* transport) {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_DCHECK(transport == ice_transport_);
RTC_LOG(LS_VERBOSE) << "ice_transport writable state changed to "
<< ice_transport_->writable();
if (kBypassDatagramDtlsTestOnly) {
// Note: SignalWritableState fired by set_writable.
set_writable(ice_transport_->writable());
return;
}
switch (dtls_state()) {
case DTLS_TRANSPORT_NEW:
break;
case DTLS_TRANSPORT_CONNECTED:
// Note: SignalWritableState fired by set_writable.
// Do we also need set_receiving(ice_transport_->receiving()) here now, in
// case we lose that signal before "DTLS" connects?
// DtlsTransport::OnWritableState does not set_receiving in a similar
// case, so leaving it out for the time being, but it would be good to
// understand why.
set_writable(ice_transport_->writable());
break;
case DTLS_TRANSPORT_CONNECTING:
// Do nothing.
break;
case DTLS_TRANSPORT_FAILED:
case DTLS_TRANSPORT_CLOSED:
// Should not happen. Do nothing.
break;
}
}
void DatagramDtlsAdaptor::OnStateChanged(webrtc::MediaTransportState state) {
// Convert MediaTransportState to DTLS state.
switch (state) {
case webrtc::MediaTransportState::kPending:
set_dtls_state(DTLS_TRANSPORT_CONNECTING);
break;
case webrtc::MediaTransportState::kWritable:
// Since we do not set writable state until datagram transport is
// connected, we need to call set_writable first.
set_writable(ice_transport_->writable());
set_dtls_state(DTLS_TRANSPORT_CONNECTED);
break;
case webrtc::MediaTransportState::kClosed:
set_dtls_state(DTLS_TRANSPORT_CLOSED);
break;
}
}
DtlsTransportState DatagramDtlsAdaptor::dtls_state() const {
return dtls_state_;
}
const std::string& DatagramDtlsAdaptor::transport_name() const {
return ice_transport_->transport_name();
}
bool DatagramDtlsAdaptor::writable() const {
// NOTE that even if ice is writable, writable_ maybe false, because we
// propagte writable only after DTLS is connect (this is consistent with
// implementation in dtls_transport.cc).
return writable_;
}
bool DatagramDtlsAdaptor::receiving() const {
return receiving_;
}
int DatagramDtlsAdaptor::SetOption(rtc::Socket::Option opt, int value) {
return ice_transport_->SetOption(opt, value);
}
int DatagramDtlsAdaptor::GetError() {
return ice_transport_->GetError();
}
void DatagramDtlsAdaptor::OnNetworkRouteChanged(
absl::optional<rtc::NetworkRoute> network_route) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SignalNetworkRouteChanged(network_route);
}
void DatagramDtlsAdaptor::OnReceivingState(
rtc::PacketTransportInternal* transport) {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_DCHECK(transport == ice_transport_);
RTC_LOG(LS_VERBOSE) << "ice_transport receiving state changed to "
<< ice_transport_->receiving();
if (kBypassDatagramDtlsTestOnly || dtls_state() == DTLS_TRANSPORT_CONNECTED) {
// Note: SignalReceivingState fired by set_receiving.
set_receiving(ice_transport_->receiving());
}
}
void DatagramDtlsAdaptor::set_receiving(bool receiving) {
if (receiving_ == receiving) {
return;
}
receiving_ = receiving;
SignalReceivingState(this);
}
// Similar implementaton as in p2p/base/dtls_transport.cc.
void DatagramDtlsAdaptor::set_writable(bool writable) {
if (writable_ == writable) {
return;
}
if (event_log_) {
event_log_->Log(
absl::make_unique<webrtc::RtcEventDtlsWritableState>(writable));
}
RTC_LOG(LS_VERBOSE) << "set_writable to: " << writable;
writable_ = writable;
if (writable_) {
SignalReadyToSend(this);
}
SignalWritableState(this);
}
// Similar implementaton as in p2p/base/dtls_transport.cc.
void DatagramDtlsAdaptor::set_dtls_state(DtlsTransportState state) {
if (dtls_state_ == state) {
return;
}
if (event_log_) {
event_log_->Log(absl::make_unique<webrtc::RtcEventDtlsTransportState>(
ConvertDtlsTransportState(state)));
}
RTC_LOG(LS_VERBOSE) << "set_dtls_state from:" << dtls_state_ << " to "
<< state;
dtls_state_ = state;
SignalDtlsState(this, state);
}
} // namespace cricket

View File

@ -0,0 +1,387 @@
/*
* Copyright 2018 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 "pc/datagram_rtp_transport.h"
#include <algorithm>
#include <memory>
#include <utility>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/rtc_error.h"
#include "media/base/rtp_utils.h"
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "p2p/base/dtls_transport_internal.h"
#include "p2p/base/packet_transport_internal.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/dscp.h"
#include "rtc_base/logging.h"
#include "rtc_base/message_queue.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/stream.h"
#include "rtc_base/thread.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
// Field trials.
// Disable datagram to RTCP feedback translation and enable RTCP feedback loop
// on top of datagram feedback loop. Note that two
// feedback loops add unneccesary overhead, so it's preferable to use feedback
// loop provided by datagram transport and convert datagram ACKs to RTCP ACKs,
// but enabling RTCP feedback loop may be useful in tests and experiments.
const char kDisableDatagramToRtcpFeebackTranslationFieldTrial[] =
"WebRTC-kDisableDatagramToRtcpFeebackTranslation";
} // namespace
// Maximum packet size of RTCP feedback packet for allocation. We re-create RTCP
// feedback packets when we get ACK notifications from datagram transport. Our
// rtcp feedback packets contain only 1 ACK, so they are much smaller than 1250.
constexpr size_t kMaxRtcpFeedbackPacketSize = 1250;
DatagramRtpTransport::DatagramRtpTransport(
const std::vector<RtpExtension>& rtp_header_extensions,
cricket::IceTransportInternal* ice_transport,
DatagramTransportInterface* datagram_transport)
: ice_transport_(ice_transport),
datagram_transport_(datagram_transport),
disable_datagram_to_rtcp_feeback_translation_(field_trial::IsEnabled(
kDisableDatagramToRtcpFeebackTranslationFieldTrial)) {
// Save extension map for parsing RTP packets (we only need transport
// sequence numbers).
const RtpExtension* transport_sequence_number_extension =
RtpExtension::FindHeaderExtensionByUri(rtp_header_extensions,
TransportSequenceNumber::kUri);
if (transport_sequence_number_extension != nullptr) {
rtp_header_extension_map_.Register<TransportSequenceNumber>(
transport_sequence_number_extension->id);
} else {
RTC_LOG(LS_ERROR) << "Transport sequence numbers are not supported in "
"datagram transport connection";
}
// TODO(sukhanov): Add CHECK to make sure that field trial
// WebRTC-ExcludeTransportSequenceNumberFromFecFieldTrial is enabled.
// If feedback loop is translation is enabled, FEC packets must exclude
// transport sequence numbers, otherwise recovered packets will be corrupt.
RTC_DCHECK(ice_transport_);
RTC_DCHECK(datagram_transport_);
ice_transport_->SignalNetworkRouteChanged.connect(
this, &DatagramRtpTransport::OnNetworkRouteChanged);
// Subscribe to DatagramTransport to read incoming packets.
datagram_transport_->SetDatagramSink(this);
datagram_transport_->SetTransportStateCallback(this);
}
DatagramRtpTransport::~DatagramRtpTransport() {
// Unsubscribe from DatagramTransport sinks.
datagram_transport_->SetDatagramSink(nullptr);
datagram_transport_->SetTransportStateCallback(nullptr);
}
bool DatagramRtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
RTC_DCHECK_RUN_ON(&thread_checker_);
// Assign and increment datagram_id.
const DatagramId datagram_id = current_datagram_id_++;
// Send as is (without extracting transport sequence number) for
// RTP packets if we are not doing datagram => RTCP feedback translation.
if (disable_datagram_to_rtcp_feeback_translation_) {
// Even if we are not extracting transport sequence number we need to
// propagate "Sent" notification for both RTP and RTCP packets. For this
// reason we need save options.packet_id in packet map.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
return SendDatagram(*packet, datagram_id);
}
// Parse RTP packet.
RtpPacket rtp_packet(&rtp_header_extension_map_);
// TODO(mellem): Verify that this doesn't mangle something (it shouldn't).
if (!rtp_packet.Parse(*packet)) {
RTC_NOTREACHED() << "Failed to parse outgoing RtpPacket, len="
<< packet->size()
<< ", options.packet_id=" << options.packet_id;
return -1;
}
// Try to get transport sequence number.
uint16_t transport_senquence_number;
if (!rtp_packet.GetExtension<TransportSequenceNumber>(
&transport_senquence_number)) {
// Save packet info without transport sequence number.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
RTC_LOG(LS_VERBOSE)
<< "Sending rtp packet without transport sequence number, packet="
<< rtp_packet.ToString();
return SendDatagram(*packet, datagram_id);
}
// Save packet info with sequence number and ssrc so we could reconstruct
// RTCP feedback packet when we receive datagram ACK.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(
options.packet_id, rtp_packet.Ssrc(), transport_senquence_number);
// Since datagram transport provides feedback and timestamps, we do not need
// to send transport sequence number, so we remove it from RTP packet. Later
// when we get Ack for sent datagram, we will re-create RTCP feedback packet.
if (!rtp_packet.RemoveExtension(TransportSequenceNumber::kId)) {
RTC_NOTREACHED() << "Failed to remove transport sequence number, packet="
<< rtp_packet.ToString();
return -1;
}
RTC_LOG(LS_VERBOSE) << "Removed transport_senquence_number="
<< transport_senquence_number
<< " from packet=" << rtp_packet.ToString()
<< ", saved bytes=" << packet->size() - rtp_packet.size();
return SendDatagram(
rtc::ArrayView<const uint8_t>(rtp_packet.data(), rtp_packet.size()),
datagram_id);
}
bool DatagramRtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) {
RTC_DCHECK_RUN_ON(&thread_checker_);
// Assign and increment datagram_id.
const DatagramId datagram_id = current_datagram_id_++;
// Even if we are not extracting transport sequence number we need to
// propagate "Sent" notification for both RTP and RTCP packets. For this
// reason we need save options.packet_id in packet map.
sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id);
return SendDatagram(*packet, datagram_id);
}
bool DatagramRtpTransport::SendDatagram(rtc::ArrayView<const uint8_t> data,
DatagramId datagram_id) {
return datagram_transport_->SendDatagram(data, datagram_id).ok();
}
void DatagramRtpTransport::OnDatagramReceived(
rtc::ArrayView<const uint8_t> data) {
RTC_DCHECK_RUN_ON(&thread_checker_);
rtc::ArrayView<const char> cdata(reinterpret_cast<const char*>(data.data()),
data.size());
if (cricket::InferRtpPacketType(cdata) == cricket::RtpPacketType::kRtcp) {
rtc::CopyOnWriteBuffer buffer(data.data(), data.size());
SignalRtcpPacketReceived(&buffer, /*packet_time_us=*/-1);
return;
}
// TODO(sukhanov): I am not filling out time, but on my video quality
// test in WebRTC the time was not set either and higher layers of the stack
// overwrite -1 with current current rtc time. Leaveing comment for now to
// make sure it works as expected.
RtpPacketReceived parsed_packet(&rtp_header_extension_map_);
if (!parsed_packet.Parse(data)) {
RTC_LOG(LS_ERROR) << "Failed to parse incoming RTP packet";
return;
}
if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) {
RTC_LOG(LS_WARNING) << "Failed to demux RTP packet: "
<< RtpDemuxer::DescribePacket(parsed_packet);
}
}
void DatagramRtpTransport::OnDatagramSent(DatagramId datagram_id) {
RTC_DCHECK_RUN_ON(&thread_checker_);
// Find packet_id and propagate OnPacketSent notification.
const auto& it = sent_rtp_packet_map_.find(datagram_id);
if (it == sent_rtp_packet_map_.end()) {
RTC_NOTREACHED() << "Did not find sent packet info for sent datagram_id="
<< datagram_id;
return;
}
// Also see how DatagramRtpTransport::OnSentPacket handles OnSentPacket
// notification from ICE in bypass mode.
rtc::SentPacket sent_packet(/*packet_id=*/it->second.packet_id,
rtc::TimeMillis());
SignalSentPacket(sent_packet);
}
bool DatagramRtpTransport::GetAndRemoveSentPacketInfo(
DatagramId datagram_id,
SentPacketInfo* sent_packet_info) {
RTC_CHECK(sent_packet_info != nullptr);
const auto& it = sent_rtp_packet_map_.find(datagram_id);
if (it == sent_rtp_packet_map_.end()) {
return false;
}
*sent_packet_info = it->second;
sent_rtp_packet_map_.erase(it);
return true;
}
void DatagramRtpTransport::OnDatagramAcked(const DatagramAck& ack) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SentPacketInfo sent_packet_info;
if (!GetAndRemoveSentPacketInfo(ack.datagram_id, &sent_packet_info)) {
// TODO(sukhanov): If OnDatagramAck() can come after OnDatagramLost(),
// datagram_id is already deleted and we may need to relax the CHECK below.
// It's probably OK to ignore such datagrams, because it's been a few RTTs
// anyway since they were sent.
RTC_NOTREACHED() << "Did not find sent packet info for datagram_id="
<< ack.datagram_id;
return;
}
RTC_LOG(LS_VERBOSE) << "Datagram acked, ack.datagram_id=" << ack.datagram_id
<< ", sent_packet_info.packet_id="
<< sent_packet_info.packet_id
<< ", sent_packet_info.transport_sequence_number="
<< sent_packet_info.transport_sequence_number.value_or(-1)
<< ", sent_packet_info.ssrc="
<< sent_packet_info.ssrc.value_or(-1)
<< ", receive_timestamp_ms="
<< ack.receive_timestamp.ms();
// If transport sequence number was not present in RTP packet, we do not need
// to propagate RTCP feedback.
if (!sent_packet_info.transport_sequence_number) {
return;
}
// TODO(sukhanov): We noticed that datagram transport implementations can
// return zero timestamps in the middle of the call. This is workaround to
// avoid propagating zero timestamps, but we need to understand why we have
// them in the first place.
int64_t receive_timestamp_us = ack.receive_timestamp.us();
if (receive_timestamp_us == 0) {
receive_timestamp_us = previous_nonzero_timestamp_us_;
} else {
previous_nonzero_timestamp_us_ = receive_timestamp_us;
}
// Ssrc must be provided in packet info if transport sequence number is set,
// which is guaranteed by SentPacketInfo constructor.
RTC_CHECK(sent_packet_info.ssrc);
// Recreate RTCP feedback packet.
rtcp::TransportFeedback feedback_packet;
feedback_packet.SetMediaSsrc(*sent_packet_info.ssrc);
const uint16_t transport_sequence_number =
sent_packet_info.transport_sequence_number.value();
feedback_packet.SetBase(transport_sequence_number, receive_timestamp_us);
feedback_packet.AddReceivedPacket(transport_sequence_number,
receive_timestamp_us);
rtc::CopyOnWriteBuffer buffer(kMaxRtcpFeedbackPacketSize);
size_t index = 0;
if (!feedback_packet.Create(buffer.data(), &index, buffer.capacity(),
nullptr)) {
RTC_NOTREACHED() << "Failed to create RTCP feedback packet";
return;
}
RTC_CHECK_GT(index, 0);
RTC_CHECK_LE(index, kMaxRtcpFeedbackPacketSize);
// Propagage created RTCP packet as normal incoming packet.
buffer.SetSize(index);
SignalRtcpPacketReceived(&buffer, /*packet_time_us=*/-1);
}
void DatagramRtpTransport::OnDatagramLost(DatagramId datagram_id) {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_LOG(LS_INFO) << "Datagram lost, datagram_id=" << datagram_id;
SentPacketInfo sent_packet_info;
if (!GetAndRemoveSentPacketInfo(datagram_id, &sent_packet_info)) {
RTC_NOTREACHED() << "Did not find sent packet info for lost datagram_id="
<< datagram_id;
}
}
void DatagramRtpTransport::OnStateChanged(MediaTransportState state) {
state_ = state;
SignalWritableState(state_ == MediaTransportState::kWritable);
if (state_ == MediaTransportState::kWritable) {
SignalReadyToSend(true);
}
}
const std::string& DatagramRtpTransport::transport_name() const {
return ice_transport_->transport_name();
}
int DatagramRtpTransport::SetRtpOption(rtc::Socket::Option opt, int value) {
return ice_transport_->SetOption(opt, value);
}
int DatagramRtpTransport::SetRtcpOption(rtc::Socket::Option opt, int value) {
return -1;
}
bool DatagramRtpTransport::IsReadyToSend() const {
return state_ == MediaTransportState::kWritable;
}
bool DatagramRtpTransport::IsWritable(bool /*rtcp*/) const {
return state_ == MediaTransportState::kWritable;
}
void DatagramRtpTransport::UpdateRtpHeaderExtensionMap(
const cricket::RtpHeaderExtensions& header_extensions) {
rtp_header_extension_map_ = RtpHeaderExtensionMap(header_extensions);
}
bool DatagramRtpTransport::RegisterRtpDemuxerSink(
const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) {
rtp_demuxer_.RemoveSink(sink);
return rtp_demuxer_.AddSink(criteria, sink);
}
bool DatagramRtpTransport::UnregisterRtpDemuxerSink(
RtpPacketSinkInterface* sink) {
return rtp_demuxer_.RemoveSink(sink);
}
void DatagramRtpTransport::OnNetworkRouteChanged(
absl::optional<rtc::NetworkRoute> network_route) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SignalNetworkRouteChanged(network_route);
}
} // namespace webrtc

View File

@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef PC_DATAGRAM_DTLS_ADAPTOR_H_
#define PC_DATAGRAM_DTLS_ADAPTOR_H_
#ifndef PC_DATAGRAM_RTP_TRANSPORT_H_
#define PC_DATAGRAM_RTP_TRANSPORT_H_
#include <map>
#include <memory>
@ -20,9 +20,9 @@
#include "api/datagram_transport_interface.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "p2p/base/dtls_transport_internal.h"
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/packet_transport_internal.h"
#include "pc/rtp_transport_internal.h"
#include "rtc_base/buffer.h"
#include "rtc_base/buffer_queue.h"
#include "rtc_base/constructor_magic.h"
@ -31,31 +31,22 @@
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/thread_checker.h"
namespace cricket {
namespace webrtc {
constexpr int kDatagramDtlsAdaptorComponent = -1;
// DTLS wrapper around DatagramTransportInterface.
// Does not encrypt.
// Owns Datagram and Ice transports.
class DatagramDtlsAdaptor : public DtlsTransportInternal,
public webrtc::DatagramSinkInterface,
public webrtc::MediaTransportStateCallback {
// RTP transport which uses the DatagramTransportInterface to send and receive
// packets.
class DatagramRtpTransport : public RtpTransportInternal,
public webrtc::DatagramSinkInterface,
public webrtc::MediaTransportStateCallback {
public:
// TODO(sukhanov): Taking crypto options, because DtlsTransportInternal
// has a virtual getter crypto_options(). Consider removing getter and
// removing crypto_options from DatagramDtlsAdaptor.
DatagramDtlsAdaptor(
DatagramRtpTransport(
const std::vector<webrtc::RtpExtension>& rtp_header_extensions,
IceTransportInternal* ice_transport,
webrtc::DatagramTransportInterface* datagram_transport,
const webrtc::CryptoOptions& crypto_options,
webrtc::RtcEventLog* event_log);
cricket::IceTransportInternal* ice_transport,
DatagramTransportInterface* datagram_transport);
~DatagramDtlsAdaptor() override;
// Connects to ICE transport callbacks.
void ConnectToIceTransport();
~DatagramRtpTransport() override;
// =====================================================
// Overrides for webrtc::DatagramTransportSinkInterface
@ -72,35 +63,38 @@ class DatagramDtlsAdaptor : public DtlsTransportInternal,
void OnStateChanged(webrtc::MediaTransportState state) override;
// =====================================================
// DtlsTransportInternal overrides
// RtpTransportInternal overrides
// =====================================================
const webrtc::CryptoOptions& crypto_options() const override;
DtlsTransportState dtls_state() const override;
int component() const override;
bool IsDtlsActive() const override;
bool GetDtlsRole(rtc::SSLRole* role) const override;
bool SetDtlsRole(rtc::SSLRole role) override;
bool GetSrtpCryptoSuite(int* cipher) override;
bool GetSslCipherSuite(int* cipher) override;
rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override;
bool SetLocalCertificate(
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override;
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override;
bool ExportKeyingMaterial(const std::string& label,
const uint8_t* context,
size_t context_len,
bool use_context,
uint8_t* result,
size_t result_len) override;
bool SetRemoteFingerprint(const std::string& digest_alg,
const uint8_t* digest,
size_t digest_len) override;
bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override;
IceTransportInternal* ice_transport() override;
bool SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) override;
bool SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options,
int flags) override;
const std::string& transport_name() const override;
bool writable() const override;
bool receiving() const override;
// Datagram transport always muxes RTCP.
bool rtcp_mux_enabled() const override { return true; }
void SetRtcpMuxEnabled(bool enable) override {}
int SetRtpOption(rtc::Socket::Option opt, int value) override;
int SetRtcpOption(rtc::Socket::Option opt, int value) override;
bool IsReadyToSend() const override;
bool IsWritable(bool rtcp) const override;
bool IsSrtpActive() const override { return false; }
void UpdateRtpHeaderExtensionMap(
const cricket::RtpHeaderExtensions& header_extensions) override;
bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) override;
bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override;
private:
// RTP/RTCP packet info stored for each sent packet.
@ -137,60 +131,19 @@ class DatagramDtlsAdaptor : public DtlsTransportInternal,
SentPacketInfo* sent_packet_info);
// Sends datagram to datagram_transport.
int SendDatagram(rtc::ArrayView<const uint8_t> data,
webrtc::DatagramId datagram_id);
bool SendDatagram(rtc::ArrayView<const uint8_t> data,
webrtc::DatagramId datagram_id);
void set_receiving(bool receiving);
void set_writable(bool writable);
void set_dtls_state(DtlsTransportState state);
// Forwards incoming packet up the stack.
void PropagateReadPacket(rtc::ArrayView<const uint8_t> data,
const int64_t& packet_time_us);
// Signals SentPacket notification.
void PropagateOnSentNotification(const rtc::SentPacket& sent_packet);
// Listens to read packet notifications from ICE (only used in bypass mode).
void OnReadPacket(rtc::PacketTransportInternal* transport,
const char* data,
size_t size,
const int64_t& packet_time_us,
int flags);
void OnReadyToSend(rtc::PacketTransportInternal* transport);
void OnWritableState(rtc::PacketTransportInternal* transport);
// Propagates network route changes from ICE.
void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route);
void OnReceivingState(rtc::PacketTransportInternal* transport);
int SendPacket(const char* data,
size_t len,
const rtc::PacketOptions& options,
int flags) override;
int SetOption(rtc::Socket::Option opt, int value) override;
int GetError() override;
void OnSentPacket(rtc::PacketTransportInternal* transport,
const rtc::SentPacket& sent_packet);
rtc::ThreadChecker thread_checker_;
webrtc::CryptoOptions crypto_options_;
IceTransportInternal* ice_transport_;
cricket::IceTransportInternal* ice_transport_;
webrtc::DatagramTransportInterface* datagram_transport_;
// Current ICE writable state. Must be modified by calling set_ice_writable(),
// which propagates change notifications.
bool writable_ = false;
RtpDemuxer rtp_demuxer_;
// Current receiving state. Must be modified by calling set_receiving(), which
// propagates change notifications.
bool receiving_ = false;
// Current DTLS state. Must be modified by calling set_dtls_state(), which
// propagates change notifications.
DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW;
webrtc::RtcEventLog* const event_log_;
MediaTransportState state_ = MediaTransportState::kPending;
// Extension map for parsing transport sequence numbers.
webrtc::RtpHeaderExtensionMap rtp_header_extension_map_;
@ -214,6 +167,6 @@ class DatagramDtlsAdaptor : public DtlsTransportInternal,
const bool disable_datagram_to_rtcp_feeback_translation_;
};
} // namespace cricket
} // namespace webrtc
#endif // PC_DATAGRAM_DTLS_ADAPTOR_H_
#endif // PC_DATAGRAM_RTP_TRANSPORT_H_

View File

@ -99,10 +99,9 @@ JsepTransport::JsepTransport(
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
std::unique_ptr<webrtc::RtpTransport> datagram_rtp_transport,
std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport,
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
std::unique_ptr<DtlsTransportInternal> datagram_dtls_transport,
std::unique_ptr<webrtc::MediaTransportInterface> media_transport,
std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport)
: network_thread_(rtc::Thread::Current()),
@ -123,11 +122,6 @@ JsepTransport::JsepTransport(
? new rtc::RefCountedObject<webrtc::DtlsTransport>(
std::move(rtcp_dtls_transport))
: nullptr),
datagram_dtls_transport_(
datagram_dtls_transport
? new rtc::RefCountedObject<webrtc::DtlsTransport>(
std::move(datagram_dtls_transport))
: nullptr),
media_transport_(std::move(media_transport)),
datagram_transport_(std::move(datagram_transport)) {
RTC_DCHECK(ice_transport_);
@ -176,13 +170,8 @@ JsepTransport::~JsepTransport() {
rtcp_dtls_transport_->Clear();
}
// Datagram dtls transport must be disconnected before the datagram transport
// is released.
if (datagram_dtls_transport_) {
datagram_dtls_transport_->Clear();
}
// Delete datagram transport before ICE, but after DTLS transport.
// Delete datagram transport before ICE, but after its RTP transport.
datagram_rtp_transport_.reset();
datagram_transport_.reset();
// ICE will be the last transport to be deleted.
@ -533,9 +522,6 @@ void JsepTransport::ActivateRtcpMux() {
}
{
rtc::CritScope scope(&accessor_lock_);
if (datagram_rtp_transport_) {
datagram_rtp_transport_->SetRtcpPacketTransport(nullptr);
}
if (unencrypted_rtp_transport_) {
RTC_DCHECK(!sdes_transport_);
RTC_DCHECK(!dtls_srtp_transport_);
@ -822,9 +808,6 @@ void JsepTransport::NegotiateRtpTransport(SdpType type) {
RTC_LOG(INFO) << "Datagram transport rejected";
composite_rtp_transport_->RemoveTransport(datagram_rtp_transport_.get());
datagram_rtp_transport_ = nullptr;
// This one is ref-counted, so it can't be deleted directly.
datagram_dtls_transport_->Clear();
datagram_dtls_transport_ = nullptr;
datagram_transport_ = nullptr;
}
}

View File

@ -93,10 +93,9 @@ class JsepTransport : public sigslot::has_slots<>,
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
std::unique_ptr<webrtc::RtpTransport> datagram_rtp_transport,
std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport,
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
std::unique_ptr<DtlsTransportInternal> datagram_dtls_transport,
std::unique_ptr<webrtc::MediaTransportInterface> media_transport,
std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport);
@ -349,7 +348,7 @@ class JsepTransport : public sigslot::has_slots<>,
RTC_GUARDED_BY(accessor_lock_);
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport_
RTC_GUARDED_BY(accessor_lock_);
std::unique_ptr<webrtc::RtpTransport> datagram_rtp_transport_
std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport_
RTC_GUARDED_BY(accessor_lock_);
// If multiple RTP transports are in use, |composite_rtp_transport_| will be

View File

@ -20,7 +20,7 @@
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/no_op_dtls_transport.h"
#include "p2p/base/port.h"
#include "pc/datagram_dtls_adaptor.h"
#include "pc/datagram_rtp_transport.h"
#include "pc/srtp_filter.h"
#include "rtc_base/bind.h"
#include "rtc_base/checks.h"
@ -483,11 +483,6 @@ JsepTransportController::CreateDtlsTransport(
if (datagram_transport) {
RTC_DCHECK(config_.use_datagram_transport);
// Create DTLS wrapper around DatagramTransportInterface.
dtls = absl::make_unique<cricket::DatagramDtlsAdaptor>(
content_info.media_description()->rtp_header_extensions(), ice,
datagram_transport, config_.crypto_options, config_.event_log);
} else if (config_.media_transport_factory &&
config_.use_media_transport_for_media &&
config_.use_media_transport_for_data_channels) {
@ -1164,11 +1159,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
std::unique_ptr<DatagramTransportInterface> datagram_transport =
MaybeCreateDatagramTransport(content_info, description, local);
std::unique_ptr<cricket::DtlsTransportInternal> datagram_dtls_transport;
if (datagram_transport) {
datagram_transport->Connect(ice.get());
datagram_dtls_transport =
CreateDtlsTransport(content_info, ice.get(), datagram_transport.get());
}
std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
@ -1178,7 +1170,7 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
std::unique_ptr<SrtpTransport> sdes_transport;
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
std::unique_ptr<RtpTransport> datagram_rtp_transport;
std::unique_ptr<RtpTransportInternal> datagram_rtp_transport;
std::unique_ptr<cricket::IceTransportInternal> rtcp_ice;
if (config_.rtcp_mux_policy !=
@ -1202,8 +1194,9 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
RTC_LOG(LS_INFO) << "Creating UnencryptedRtpTransport, because datagram "
"transport is used.";
RTC_DCHECK(!rtcp_dtls_transport);
datagram_rtp_transport = CreateUnencryptedRtpTransport(
content_info.name, datagram_dtls_transport.get(), nullptr);
datagram_rtp_transport = absl::make_unique<DatagramRtpTransport>(
content_info.media_description()->rtp_header_extensions(), ice.get(),
datagram_transport.get());
}
if (config_.disable_encryption) {
@ -1227,8 +1220,7 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
std::move(unencrypted_rtp_transport), std::move(sdes_transport),
std::move(dtls_srtp_transport), std::move(datagram_rtp_transport),
std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport),
std::move(datagram_dtls_transport), std::move(media_transport),
std::move(datagram_transport));
std::move(media_transport), std::move(datagram_transport));
jsep_transport->SignalRtcpMuxActive.connect(
this, &JsepTransportController::UpdateAggregateStates_n);

View File

@ -111,7 +111,6 @@ class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
std::move(sdes_transport), std::move(dtls_srtp_transport),
/*datagram_rtp_transport=*/nullptr, std::move(rtp_dtls_transport),
std::move(rtcp_dtls_transport),
/*datagram_dtls_transport=*/nullptr,
/*media_transport=*/nullptr,
/*datagram_transport=*/nullptr);