Revert "Reland "Refactor SCTP data channels to use DataChannelTransportInterface.""
This reverts commit 487f9a17e426fd14bb06b13e861071b3f15d119b.
Reason for revert: speculative revert
Original change's description:
> Reland "Refactor SCTP data channels to use DataChannelTransportInterface."
>
> Also clears SctpTransport before deleting JsepTransport.
>
> SctpTransport is ref-counted, but the underlying transport is deleted when
> JsepTransport clears the rtp_dtls_transport. This results in crashes when
> usrsctp attempts to send outgoing packets through a dangling pointer to the
> underlying transport.
>
> Clearing SctpTransport before DtlsTransport removes the pointer to the
> underlying transport before it becomes invalid.
>
> This fixes a crash in chromium's web platform tests (see
> https://chromium-review.googlesource.com/c/chromium/src/+/1776711).
>
> Original change's description:
> > Refactor SCTP data channels to use DataChannelTransportInterface.
> >
> > This change moves SctpTransport to be owned by JsepTransport, which now
> > holds a DataChannelTransport implementation for SCTP when it is used for
> > data channels.
> >
> > This simplifies negotiation and fallback to SCTP. Negotiation can now
> > use a composite DataChannelTransport, just as negotiation for RTP uses a
> > composite RTP transport.
> >
> > PeerConnection also has one fewer way it needs to manage data channels.
> > It now handles SCTP and datagram- or media-transport-based data channels
> > the same way.
> >
> > There are a few leaky abstractions left. For example, PeerConnection
> > calls Start() on the SctpTransport at a particular point in negotiation,
> > but does not need to call this for other transports. Similarly, PC
> > exposes an interface to the SCTP transport directly to the user; there
> > is no equivalent for other transports.
>
> Bug: webrtc:9719
> Change-Id: I64e94b88afb119fdbf5f22750f88c8a084d53937
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/151981
> Reviewed-by: Benjamin Wright <benwright@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Commit-Queue: Benjamin Wright <benwright@webrtc.org>
> Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#29120}
TBR=steveanton@webrtc.org,mellem@webrtc.org,benwright@webrtc.org
Change-Id: Ibd1a7f30931c114212c90824fec414d276d3f915
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:9719
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/152421
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Commit-Queue: Qingsi Wang <qingsi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29141}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index c3c4e53..6f868c2 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -34,8 +34,6 @@
"channel_interface.h",
"channel_manager.cc",
"channel_manager.h",
- "composite_data_channel_transport.cc",
- "composite_data_channel_transport.h",
"composite_rtp_transport.cc",
"composite_rtp_transport.h",
"datagram_rtp_transport.cc",
@@ -61,12 +59,8 @@
"rtp_transport.cc",
"rtp_transport.h",
"rtp_transport_internal.h",
- "sctp_data_channel_transport.cc",
- "sctp_data_channel_transport.h",
"sctp_transport.cc",
"sctp_transport.h",
- "sctp_utils.cc",
- "sctp_utils.h",
"session_description.cc",
"session_description.h",
"simulcast_description.cc",
@@ -194,6 +188,8 @@
"rtp_sender.h",
"rtp_transceiver.cc",
"rtp_transceiver.h",
+ "sctp_utils.cc",
+ "sctp_utils.h",
"sdp_serializer.cc",
"sdp_serializer.h",
"sdp_utils.cc",
diff --git a/pc/composite_data_channel_transport.cc b/pc/composite_data_channel_transport.cc
deleted file mode 100644
index 3a24589..0000000
--- a/pc/composite_data_channel_transport.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2019 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/composite_data_channel_transport.h"
-
-#include <utility>
-
-#include "absl/algorithm/container.h"
-
-namespace webrtc {
-
-CompositeDataChannelTransport::CompositeDataChannelTransport(
- std::vector<DataChannelTransportInterface*> transports)
- : transports_(std::move(transports)) {
- for (auto transport : transports_) {
- transport->SetDataSink(this);
- }
-}
-
-void CompositeDataChannelTransport::SetSendTransport(
- DataChannelTransportInterface* send_transport) {
- if (!absl::c_linear_search(transports_, send_transport)) {
- return;
- }
- send_transport_ = send_transport;
- // NB: OnReadyToSend() checks if we're actually ready to send, and signals
- // |sink_| if appropriate. This signal is required upon setting the sink.
- OnReadyToSend();
-}
-
-void CompositeDataChannelTransport::RemoveTransport(
- DataChannelTransportInterface* transport) {
- RTC_DCHECK(transport != send_transport_) << "Cannot remove send transport";
-
- auto it = absl::c_find(transports_, transport);
- if (it == transports_.end()) {
- return;
- }
-
- transport->SetDataSink(nullptr);
- transports_.erase(it);
-}
-
-RTCError CompositeDataChannelTransport::OpenChannel(int channel_id) {
- RTCError error = RTCError::OK();
- for (auto transport : transports_) {
- RTCError e = transport->OpenChannel(channel_id);
- if (!e.ok()) {
- error = std::move(e);
- }
- }
- return error;
-}
-
-RTCError CompositeDataChannelTransport::SendData(
- int channel_id,
- const SendDataParams& params,
- const rtc::CopyOnWriteBuffer& buffer) {
- if (send_transport_) {
- return send_transport_->SendData(channel_id, params, buffer);
- }
- return RTCError(RTCErrorType::NETWORK_ERROR, "Send transport is not ready");
-}
-
-RTCError CompositeDataChannelTransport::CloseChannel(int channel_id) {
- if (send_transport_) {
- return send_transport_->CloseChannel(channel_id);
- }
- return RTCError(RTCErrorType::NETWORK_ERROR, "Send transport is not ready");
-}
-
-void CompositeDataChannelTransport::SetDataSink(DataChannelSink* sink) {
- sink_ = sink;
- // NB: OnReadyToSend() checks if we're actually ready to send, and signals
- // |sink_| if appropriate. This signal is required upon setting the sink.
- OnReadyToSend();
-}
-
-void CompositeDataChannelTransport::OnDataReceived(
- int channel_id,
- DataMessageType type,
- const rtc::CopyOnWriteBuffer& buffer) {
- if (sink_) {
- sink_->OnDataReceived(channel_id, type, buffer);
- }
-}
-
-void CompositeDataChannelTransport::OnChannelClosing(int channel_id) {
- if (sink_) {
- sink_->OnChannelClosing(channel_id);
- }
-}
-
-void CompositeDataChannelTransport::OnChannelClosed(int channel_id) {
- if (sink_) {
- sink_->OnChannelClosed(channel_id);
- }
-}
-
-void CompositeDataChannelTransport::OnReadyToSend() {
- if (sink_ && send_transport_ && send_transport_->IsReadyToSend()) {
- sink_->OnReadyToSend();
- }
-}
-
-} // namespace webrtc
diff --git a/pc/composite_data_channel_transport.h b/pc/composite_data_channel_transport.h
deleted file mode 100644
index 0517ee7..0000000
--- a/pc/composite_data_channel_transport.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#ifndef PC_COMPOSITE_DATA_CHANNEL_TRANSPORT_H_
-#define PC_COMPOSITE_DATA_CHANNEL_TRANSPORT_H_
-
-#include <vector>
-
-#include "api/data_channel_transport_interface.h"
-#include "rtc_base/critical_section.h"
-
-namespace webrtc {
-
-// Composite implementation of DataChannelTransportInterface. Allows users to
-// receive data channel messages over multiple transports and send over one of
-// those transports.
-class CompositeDataChannelTransport : public DataChannelTransportInterface,
- public DataChannelSink {
- public:
- explicit CompositeDataChannelTransport(
- std::vector<DataChannelTransportInterface*> transports);
-
- // Specifies which transport to be used for sending. Must be called before
- // sending data.
- void SetSendTransport(DataChannelTransportInterface* send_transport);
-
- // Removes a given transport from the composite, if present.
- void RemoveTransport(DataChannelTransportInterface* transport);
-
- // DataChannelTransportInterface overrides.
- RTCError OpenChannel(int channel_id) override;
- RTCError SendData(int channel_id,
- const SendDataParams& params,
- const rtc::CopyOnWriteBuffer& buffer) override;
- RTCError CloseChannel(int channel_id) override;
- void SetDataSink(DataChannelSink* sink) override;
-
- // DataChannelSink overrides.
- void OnDataReceived(int channel_id,
- DataMessageType type,
- const rtc::CopyOnWriteBuffer& buffer) override;
- void OnChannelClosing(int channel_id) override;
- void OnChannelClosed(int channel_id) override;
- void OnReadyToSend() override;
-
- private:
- std::vector<DataChannelTransportInterface*> transports_;
- DataChannelTransportInterface* send_transport_ = nullptr;
- DataChannelSink* sink_ = nullptr;
-};
-
-} // namespace webrtc
-
-#endif // PC_COMPOSITE_DATA_CHANNEL_TRANSPORT_H_
diff --git a/pc/jsep_transport.cc b/pc/jsep_transport.cc
index 2fb4cba..5777873 100644
--- a/pc/jsep_transport.cc
+++ b/pc/jsep_transport.cc
@@ -22,7 +22,6 @@
#include "api/candidate.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/p2p_transport_channel.h"
-#include "pc/sctp_data_channel_transport.h"
#include "rtc_base/checks.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/logging.h"
@@ -103,10 +102,8 @@
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<SctpTransportInternal> sctp_transport,
std::unique_ptr<webrtc::MediaTransportInterface> media_transport,
- std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport,
- webrtc::DataChannelTransportInterface* data_channel_transport)
+ std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport)
: network_thread_(rtc::Thread::Current()),
mid_(mid),
local_certificate_(local_certificate),
@@ -125,17 +122,8 @@
? new rtc::RefCountedObject<webrtc::DtlsTransport>(
std::move(rtcp_dtls_transport))
: nullptr),
- sctp_data_channel_transport_(
- sctp_transport ? absl::make_unique<webrtc::SctpDataChannelTransport>(
- sctp_transport.get())
- : nullptr),
- sctp_transport_(sctp_transport
- ? new rtc::RefCountedObject<webrtc::SctpTransport>(
- std::move(sctp_transport))
- : nullptr),
media_transport_(std::move(media_transport)),
- datagram_transport_(std::move(datagram_transport)),
- data_channel_transport_(data_channel_transport) {
+ datagram_transport_(std::move(datagram_transport)) {
RTC_DCHECK(ice_transport_);
RTC_DCHECK(rtp_dtls_transport_);
// |rtcp_ice_transport_| must be present iff |rtcp_dtls_transport_| is
@@ -156,10 +144,6 @@
RTC_DCHECK(!sdes_transport);
}
- if (sctp_transport_) {
- sctp_transport_->SetDtlsTransport(rtp_dtls_transport_);
- }
-
if (datagram_rtp_transport_ && default_rtp_transport()) {
composite_rtp_transport_ = absl::make_unique<webrtc::CompositeRtpTransport>(
std::vector<webrtc::RtpTransportInternal*>{
@@ -169,13 +153,6 @@
if (media_transport_) {
media_transport_->SetMediaTransportStateCallback(this);
}
-
- if (data_channel_transport_ && sctp_data_channel_transport_) {
- composite_data_channel_transport_ =
- absl::make_unique<webrtc::CompositeDataChannelTransport>(
- std::vector<webrtc::DataChannelTransportInterface*>{
- data_channel_transport_, sctp_data_channel_transport_.get()});
- }
}
JsepTransport::~JsepTransport() {
@@ -186,10 +163,6 @@
media_transport_.reset();
}
- if (sctp_transport_) {
- sctp_transport_->Clear();
- }
-
// Clear all DtlsTransports. There may be pointers to these from
// other places, so we can't assume they'll be deleted by the destructor.
rtp_dtls_transport_->Clear();
@@ -817,20 +790,26 @@
use_datagram_transport ? datagram_rtp_transport_.get()
: default_rtp_transport());
}
- if (composite_data_channel_transport_) {
- composite_data_channel_transport_->SetSendTransport(
- use_datagram_transport ? data_channel_transport_
- : sctp_data_channel_transport_.get());
- }
if (type != SdpType::kAnswer) {
+ // A provisional answer lets the peer start sending on the chosen
+ // transport, but does not allow it to destroy other transports yet.
+ SignalDataChannelTransportNegotiated(
+ this, use_datagram_transport ? datagram_transport_.get() : nullptr,
+ /*provisional=*/true);
return;
}
+ // A full answer lets the peer delete the remaining transports.
+ // First, signal that the transports will be deleted so the application can
+ // stop using them.
+ SignalDataChannelTransportNegotiated(
+ this, use_datagram_transport ? datagram_transport_.get() : nullptr,
+ /*provisional=*/false);
+
if (use_datagram_transport) {
if (composite_rtp_transport_) {
- // Negotiated use of datagram transport for RTP, so remove the
- // non-datagram RTP transport.
+ // Remove and delete the non-datagram RTP transport.
composite_rtp_transport_->RemoveTransport(default_rtp_transport());
if (unencrypted_rtp_transport_) {
unencrypted_rtp_transport_ = nullptr;
@@ -840,29 +819,12 @@
dtls_srtp_transport_ = nullptr;
}
}
- if (composite_data_channel_transport_) {
- // Negotiated use of datagram transport for data channels, so remove the
- // non-datagram data channel transport.
- composite_data_channel_transport_->RemoveTransport(
- sctp_data_channel_transport_.get());
- sctp_data_channel_transport_ = nullptr;
- sctp_transport_ = nullptr;
- }
} else {
// Remove and delete the datagram transport.
if (composite_rtp_transport_) {
composite_rtp_transport_->RemoveTransport(datagram_rtp_transport_.get());
}
- if (composite_data_channel_transport_) {
- composite_data_channel_transport_->RemoveTransport(
- data_channel_transport_);
- } else {
- // If there's no composite data channel transport, we need to signal that
- // the data channel is about to be deleted.
- SignalDataChannelTransportNegotiated(this, nullptr);
- }
datagram_rtp_transport_ = nullptr;
- data_channel_transport_ = nullptr;
datagram_transport_ = nullptr;
}
}
diff --git a/pc/jsep_transport.h b/pc/jsep_transport.h
index fc11c31..1a0e7b4 100644
--- a/pc/jsep_transport.h
+++ b/pc/jsep_transport.h
@@ -21,17 +21,14 @@
#include "api/datagram_transport_interface.h"
#include "api/jsep.h"
#include "api/media_transport_interface.h"
-#include "media/sctp/sctp_transport_internal.h"
#include "p2p/base/dtls_transport.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/transport_info.h"
-#include "pc/composite_data_channel_transport.h"
#include "pc/composite_rtp_transport.h"
#include "pc/dtls_srtp_transport.h"
#include "pc/dtls_transport.h"
#include "pc/rtcp_mux_filter.h"
#include "pc/rtp_transport.h"
-#include "pc/sctp_transport.h"
#include "pc/session_description.h"
#include "pc/srtp_filter.h"
#include "pc/srtp_transport.h"
@@ -99,10 +96,8 @@
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<SctpTransportInternal> sctp_transport,
std::unique_ptr<webrtc::MediaTransportInterface> media_transport,
- std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport,
- webrtc::DataChannelTransportInterface* data_channel_transport);
+ std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport);
~JsepTransport() override;
@@ -220,21 +215,6 @@
return rtp_dtls_transport_;
}
- rtc::scoped_refptr<webrtc::SctpTransport> SctpTransport() const {
- rtc::CritScope scope(&accessor_lock_);
- return sctp_transport_;
- }
-
- webrtc::DataChannelTransportInterface* data_channel_transport() const {
- rtc::CritScope scope(&accessor_lock_);
- if (composite_data_channel_transport_) {
- return composite_data_channel_transport_.get();
- } else if (sctp_data_channel_transport_) {
- return sctp_data_channel_transport_.get();
- }
- return data_channel_transport_;
- }
-
// Returns media transport, if available.
// Note that media transport is owned by jseptransport and the pointer
// to media transport will becomes invalid after destruction of jseptransport.
@@ -269,7 +249,7 @@
// channel transport. The third parameter (bool) indicates whether the
// negotiation was provisional or final. If true, it is provisional, if
// false, it is final.
- sigslot::signal2<JsepTransport*, webrtc::DataChannelTransportInterface*>
+ sigslot::signal3<JsepTransport*, webrtc::DataChannelTransportInterface*, bool>
SignalDataChannelTransportNegotiated;
// TODO(deadbeef): The methods below are only public for testing. Should make
@@ -395,11 +375,6 @@
rtc::scoped_refptr<webrtc::DtlsTransport> datagram_dtls_transport_
RTC_GUARDED_BY(accessor_lock_);
- std::unique_ptr<webrtc::DataChannelTransportInterface>
- sctp_data_channel_transport_ RTC_GUARDED_BY(accessor_lock_);
- rtc::scoped_refptr<webrtc::SctpTransport> sctp_transport_
- RTC_GUARDED_BY(accessor_lock_);
-
SrtpFilter sdes_negotiator_ RTC_GUARDED_BY(network_thread_);
RtcpMuxFilter rtcp_mux_negotiator_ RTC_GUARDED_BY(network_thread_);
@@ -417,16 +392,6 @@
std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport_
RTC_GUARDED_BY(accessor_lock_);
- // Non-SCTP data channel transport. Set to one of |media_transport_| or
- // |datagram_transport_| if that transport should be used for data chanels.
- // Unset if neither should be used for data channels.
- webrtc::DataChannelTransportInterface* data_channel_transport_
- RTC_GUARDED_BY(accessor_lock_) = nullptr;
-
- // Composite data channel transport, used during negotiation.
- std::unique_ptr<webrtc::CompositeDataChannelTransport>
- composite_data_channel_transport_ RTC_GUARDED_BY(accessor_lock_);
-
// If |media_transport_| is provided, this variable represents the state of
// media transport.
//
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc
index 6bdd950..cfb971a 100644
--- a/pc/jsep_transport_controller.cc
+++ b/pc/jsep_transport_controller.cc
@@ -175,7 +175,14 @@
if (!jsep_transport) {
return nullptr;
}
- return jsep_transport->data_channel_transport();
+
+ if (config_.use_media_transport_for_data_channels) {
+ return jsep_transport->media_transport();
+ } else if (config_.use_datagram_transport_for_data_channels) {
+ return jsep_transport->datagram_transport();
+ }
+ // Not configured to use a data channel transport.
+ return nullptr;
}
MediaTransportState JsepTransportController::GetMediaTransportState(
@@ -214,15 +221,6 @@
return jsep_transport->RtpDtlsTransport();
}
-rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
- const std::string& mid) const {
- auto jsep_transport = GetJsepTransportForMid(mid);
- if (!jsep_transport) {
- return nullptr;
- }
- return jsep_transport->SctpTransport();
-}
-
void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
if (!network_thread_->IsCurrent()) {
network_thread_->Invoke<void>(RTC_FROM_HERE, [&] { SetIceConfig(config); });
@@ -875,13 +873,13 @@
mid_to_transport_[mid] = jsep_transport;
return config_.transport_observer->OnTransportChanged(
mid, jsep_transport->rtp_transport(), jsep_transport->RtpDtlsTransport(),
- jsep_transport->media_transport(),
- jsep_transport->data_channel_transport());
+ jsep_transport->media_transport(), jsep_transport->datagram_transport(),
+ NegotiationState::kInitial);
}
void JsepTransportController::RemoveTransportForMid(const std::string& mid) {
bool ret = config_.transport_observer->OnTransportChanged(
- mid, nullptr, nullptr, nullptr, nullptr);
+ mid, nullptr, nullptr, nullptr, nullptr, NegotiationState::kFinal);
// Calling OnTransportChanged with nullptr should always succeed, since it is
// only expected to fail when adding media to a transport (not removing).
RTC_DCHECK(ret);
@@ -1231,27 +1229,13 @@
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
}
- std::unique_ptr<cricket::SctpTransportInternal> sctp_transport;
- if (config_.sctp_factory) {
- sctp_transport =
- config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
- }
-
- DataChannelTransportInterface* data_channel_transport = nullptr;
- if (config_.use_datagram_transport_for_data_channels) {
- data_channel_transport = datagram_transport.get();
- } else if (config_.use_media_transport_for_data_channels) {
- data_channel_transport = media_transport.get();
- }
-
std::unique_ptr<cricket::JsepTransport> jsep_transport =
absl::make_unique<cricket::JsepTransport>(
content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
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(sctp_transport), std::move(media_transport),
- std::move(datagram_transport), data_channel_transport);
+ std::move(media_transport), std::move(datagram_transport));
jsep_transport->SignalRtcpMuxActive.connect(
this, &JsepTransportController::UpdateAggregateStates_n);
@@ -1290,7 +1274,8 @@
for (const auto& jsep_transport : jsep_transports_by_name_) {
config_.transport_observer->OnTransportChanged(
- jsep_transport.first, nullptr, nullptr, nullptr, nullptr);
+ jsep_transport.first, nullptr, nullptr, nullptr, nullptr,
+ NegotiationState::kFinal);
}
jsep_transports_by_name_.clear();
@@ -1468,12 +1453,15 @@
void JsepTransportController::OnDataChannelTransportNegotiated_n(
cricket::JsepTransport* transport,
- DataChannelTransportInterface* data_channel_transport) {
+ DataChannelTransportInterface* data_channel_transport,
+ bool provisional) {
for (auto it : mid_to_transport_) {
if (it.second == transport) {
config_.transport_observer->OnTransportChanged(
it.first, transport->rtp_transport(), transport->RtpDtlsTransport(),
- transport->media_transport(), data_channel_transport);
+ transport->media_transport(), data_channel_transport,
+ provisional ? NegotiationState::kProvisional
+ : NegotiationState::kFinal);
}
}
}
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h
index 4df3efe..de75db9 100644
--- a/pc/jsep_transport_controller.h
+++ b/pc/jsep_transport_controller.h
@@ -47,6 +47,18 @@
class JsepTransportController : public sigslot::has_slots<> {
public:
+ // State of negotiation for a transport.
+ enum class NegotiationState {
+ // Transport is in its initial state, not negotiated at all.
+ kInitial = 0,
+
+ // Transport is negotiated, but not finalized.
+ kProvisional = 1,
+
+ // Negotiation has completed for this transport.
+ kFinal = 2,
+ };
+
// Used when the RtpTransport/DtlsTransport of the m= section is changed
// because the section is rejected or BUNDLE is enabled.
class Observer {
@@ -72,7 +84,8 @@
RtpTransportInternal* rtp_transport,
rtc::scoped_refptr<DtlsTransport> dtls_transport,
MediaTransportInterface* media_transport,
- DataChannelTransportInterface* data_channel_transport) = 0;
+ DataChannelTransportInterface* data_channel_transport,
+ NegotiationState negotiation_state) = 0;
};
struct Config {
@@ -96,9 +109,6 @@
bool active_reset_srtp_params = false;
RtcEventLog* event_log = nullptr;
- // Factory for SCTP transports.
- cricket::SctpTransportInternalFactory* sctp_factory = nullptr;
-
// Whether media transport is used for media.
bool use_media_transport_for_media = false;
@@ -154,8 +164,6 @@
// Gets the externally sharable version of the DtlsTransport.
rtc::scoped_refptr<webrtc::DtlsTransport> LookupDtlsTransportByMid(
const std::string& mid);
- rtc::scoped_refptr<SctpTransport> GetSctpTransport(
- const std::string& mid) const;
MediaTransportConfig GetMediaTransportConfig(const std::string& mid) const;
@@ -424,7 +432,8 @@
const cricket::CandidatePairChangeEvent& event);
void OnDataChannelTransportNegotiated_n(
cricket::JsepTransport* transport,
- DataChannelTransportInterface* data_channel_transport);
+ DataChannelTransportInterface* data_channel_transport,
+ bool provisional);
void UpdateAggregateStates_n();
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc
index bf56536..887f12b 100644
--- a/pc/jsep_transport_controller_unittest.cc
+++ b/pc/jsep_transport_controller_unittest.cc
@@ -310,7 +310,8 @@
RtpTransportInternal* rtp_transport,
rtc::scoped_refptr<DtlsTransport> dtls_transport,
MediaTransportInterface* media_transport,
- DataChannelTransportInterface* data_channel_transport) override {
+ DataChannelTransportInterface* data_channel_transport,
+ JsepTransportController::NegotiationState negotiation_state) override {
changed_rtp_transport_by_mid_[mid] = rtp_transport;
if (dtls_transport) {
changed_dtls_transport_by_mid_[mid] = dtls_transport->internal();
diff --git a/pc/jsep_transport_unittest.cc b/pc/jsep_transport_unittest.cc
index cbe8659..1e51392 100644
--- a/pc/jsep_transport_unittest.cc
+++ b/pc/jsep_transport_unittest.cc
@@ -111,10 +111,8 @@
std::move(sdes_transport), std::move(dtls_srtp_transport),
/*datagram_rtp_transport=*/nullptr, std::move(rtp_dtls_transport),
std::move(rtcp_dtls_transport),
- /*sctp_transport=*/nullptr,
/*media_transport=*/nullptr,
- /*datagram_transport=*/nullptr,
- /*data_channel_transport=*/nullptr);
+ /*datagram_transport=*/nullptr);
signal_rtcp_mux_active_received_ = false;
jsep_transport->SignalRtcpMuxActive.connect(
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 465c092..0b943b51 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -610,6 +610,35 @@
return rtc_configuration_parameter;
}
+cricket::DataMessageType ToCricketDataMessageType(DataMessageType type) {
+ switch (type) {
+ case DataMessageType::kText:
+ return cricket::DMT_TEXT;
+ case DataMessageType::kBinary:
+ return cricket::DMT_BINARY;
+ case DataMessageType::kControl:
+ return cricket::DMT_CONTROL;
+ default:
+ return cricket::DMT_NONE;
+ }
+ return cricket::DMT_NONE;
+}
+
+DataMessageType ToWebrtcDataMessageType(cricket::DataMessageType type) {
+ switch (type) {
+ case cricket::DMT_TEXT:
+ return DataMessageType::kText;
+ case cricket::DMT_BINARY:
+ return DataMessageType::kBinary;
+ case cricket::DMT_CONTROL:
+ return DataMessageType::kControl;
+ case cricket::DMT_NONE:
+ default:
+ RTC_NOTREACHED();
+ }
+ return DataMessageType::kControl;
+}
+
void ReportSimulcastApiVersion(const char* name,
const SessionDescription& session) {
bool has_legacy = false;
@@ -894,7 +923,6 @@
remote_streams_(StreamCollection::Create()),
call_(std::move(call)),
call_ptr_(call_.get()),
- data_channel_transport_(nullptr),
local_ice_credentials_to_replace_(new LocalIceCredentialsToReplace()) {}
PeerConnection::~PeerConnection() {
@@ -921,6 +949,7 @@
RTC_LOG(LS_INFO) << "Session: " << session_id() << " is destroyed.";
webrtc_session_desc_factory_.reset();
+ sctp_invoker_.reset();
sctp_factory_.reset();
data_channel_transport_invoker_.reset();
transport_controller_.reset();
@@ -1098,64 +1127,6 @@
config.media_transport_factory = factory_->media_transport_factory();
}
- // Obtain a certificate from RTCConfiguration if any were provided (optional).
- rtc::scoped_refptr<rtc::RTCCertificate> certificate;
- if (!configuration.certificates.empty()) {
- // TODO(hbos,torbjorng): Decide on certificate-selection strategy instead of
- // just picking the first one. The decision should be made based on the DTLS
- // handshake. The DTLS negotiations need to know about all certificates.
- certificate = configuration.certificates[0];
- }
-
- if (options.disable_encryption) {
- dtls_enabled_ = false;
- } else {
- // Enable DTLS by default if we have an identity store or a certificate.
- dtls_enabled_ = (dependencies.cert_generator || certificate);
- // |configuration| can override the default |dtls_enabled_| value.
- if (configuration.enable_dtls_srtp) {
- dtls_enabled_ = *(configuration.enable_dtls_srtp);
- }
- }
-
- sctp_factory_ = factory_->CreateSctpTransportInternalFactory();
-
- if (use_datagram_transport_for_data_channels_) {
- if (configuration.enable_rtp_data_channel) {
- RTC_LOG(LS_ERROR) << "enable_rtp_data_channel and "
- "use_datagram_transport_for_data_channels are "
- "incompatible and cannot both be set to true";
- return false;
- }
- if (configuration.enable_dtls_srtp && !*configuration.enable_dtls_srtp) {
- RTC_LOG(LS_INFO) << "Using data channel transport with no fallback";
- data_channel_type_ = cricket::DCT_DATA_CHANNEL_TRANSPORT;
- } else {
- RTC_LOG(LS_INFO) << "Using data channel transport with fallback to SCTP";
- data_channel_type_ = cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP;
- config.sctp_factory = sctp_factory_.get();
- }
- } else if (configuration.use_media_transport_for_data_channels) {
- if (configuration.enable_rtp_data_channel) {
- RTC_LOG(LS_ERROR) << "enable_rtp_data_channel and "
- "use_media_transport_for_data_channels are "
- "incompatible and cannot both be set to true";
- return false;
- }
- data_channel_type_ = cricket::DCT_MEDIA_TRANSPORT;
- } else if (configuration.enable_rtp_data_channel) {
- // Enable creation of RTP data channels if the kEnableRtpDataChannels is
- // set. It takes precendence over the disable_sctp_data_channels
- // PeerConnectionFactoryInterface::Options.
- data_channel_type_ = cricket::DCT_RTP;
- } else {
- // DTLS has to be enabled to use SCTP.
- if (!options.disable_sctp_data_channels && dtls_enabled_) {
- data_channel_type_ = cricket::DCT_SCTP;
- config.sctp_factory = sctp_factory_.get();
- }
- }
-
transport_controller_.reset(new JsepTransportController(
signaling_thread(), network_thread(), port_allocator_.get(),
async_resolver_factory_.get(), config));
@@ -1178,14 +1149,70 @@
transport_controller_->SignalIceCandidatePairChanged.connect(
this, &PeerConnection::OnTransportControllerCandidateChanged);
+ sctp_factory_ = factory_->CreateSctpTransportInternalFactory();
+
stats_.reset(new StatsCollector(this));
stats_collector_ = RTCStatsCollector::Create(this);
configuration_ = configuration;
use_media_transport_ = configuration.use_media_transport;
+ // Obtain a certificate from RTCConfiguration if any were provided (optional).
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate;
+ if (!configuration.certificates.empty()) {
+ // TODO(hbos,torbjorng): Decide on certificate-selection strategy instead of
+ // just picking the first one. The decision should be made based on the DTLS
+ // handshake. The DTLS negotiations need to know about all certificates.
+ certificate = configuration.certificates[0];
+ }
+
transport_controller_->SetIceConfig(ParseIceConfig(configuration));
+ if (options.disable_encryption) {
+ dtls_enabled_ = false;
+ } else {
+ // Enable DTLS by default if we have an identity store or a certificate.
+ dtls_enabled_ = (dependencies.cert_generator || certificate);
+ // |configuration| can override the default |dtls_enabled_| value.
+ if (configuration.enable_dtls_srtp) {
+ dtls_enabled_ = *(configuration.enable_dtls_srtp);
+ }
+ }
+
+ if (use_datagram_transport_for_data_channels_) {
+ if (configuration.enable_rtp_data_channel) {
+ RTC_LOG(LS_ERROR) << "enable_rtp_data_channel and "
+ "use_datagram_transport_for_data_channels are "
+ "incompatible and cannot both be set to true";
+ return false;
+ }
+ if (configuration.enable_dtls_srtp && !*configuration.enable_dtls_srtp) {
+ RTC_LOG(LS_INFO) << "Using data channel transport with no fallback";
+ data_channel_type_ = cricket::DCT_DATA_CHANNEL_TRANSPORT;
+ } else {
+ RTC_LOG(LS_INFO) << "Using data channel transport with fallback to SCTP";
+ data_channel_type_ = cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP;
+ }
+ } else if (configuration.use_media_transport_for_data_channels) {
+ if (configuration.enable_rtp_data_channel) {
+ RTC_LOG(LS_ERROR) << "enable_rtp_data_channel and "
+ "use_media_transport_for_data_channels are "
+ "incompatible and cannot both be set to true";
+ return false;
+ }
+ data_channel_type_ = cricket::DCT_MEDIA_TRANSPORT;
+ } else if (configuration.enable_rtp_data_channel) {
+ // Enable creation of RTP data channels if the kEnableRtpDataChannels is
+ // set. It takes precendence over the disable_sctp_data_channels
+ // PeerConnectionFactoryInterface::Options.
+ data_channel_type_ = cricket::DCT_RTP;
+ } else {
+ // DTLS has to be enabled to use SCTP.
+ if (!options.disable_sctp_data_channels && dtls_enabled_) {
+ data_channel_type_ = cricket::DCT_SCTP;
+ }
+ }
+
video_options_.screencast_min_bitrate_kbps =
configuration.screencast_min_bitrate;
audio_options_.combined_audio_video_bwe =
@@ -3175,7 +3202,7 @@
RTC_LOG(LS_INFO) << "Rejected data channel, mid=" << content.mid();
DestroyDataChannel();
} else {
- if (!rtp_data_channel_ && !data_channel_transport_) {
+ if (!rtp_data_channel_ && !sctp_transport_ && !data_channel_transport_) {
RTC_LOG(LS_INFO) << "Creating data channel, mid=" << content.mid();
if (!CreateDataChannel(content.name)) {
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
@@ -3909,10 +3936,7 @@
rtc::scoped_refptr<SctpTransportInterface> PeerConnection::GetSctpTransport()
const {
RTC_DCHECK_RUN_ON(signaling_thread());
- if (!sctp_mid_) {
- return nullptr;
- }
- return transport_controller_->GetSctpTransport(*sctp_mid_);
+ return sctp_transport_;
}
const SessionDescriptionInterface* PeerConnection::local_description() const {
@@ -5672,18 +5696,19 @@
"SSL Role of the SCTP transport.";
return false;
}
- if (!data_channel_transport_) {
+ if (!sctp_transport_ && !data_channel_transport_) {
RTC_LOG(LS_INFO) << "Non-rejected SCTP m= section is needed to get the "
"SSL Role of the SCTP transport.";
return false;
}
absl::optional<rtc::SSLRole> dtls_role;
- if (sctp_mid_) {
+ if (sctp_mid_ && sctp_transport_) {
dtls_role = transport_controller_->GetDtlsRole(*sctp_mid_);
- if (!dtls_role && is_caller_.has_value()) {
- dtls_role = *is_caller_ ? rtc::SSL_SERVER : rtc::SSL_CLIENT;
- }
+ } else if (is_caller_) {
+ dtls_role = *is_caller_ ? rtc::SSL_SERVER : rtc::SSL_CLIENT;
+ }
+ if (dtls_role) {
*role = *dtls_role;
return true;
}
@@ -5809,14 +5834,12 @@
// Need complete offer/answer with an SCTP m= section before starting SCTP,
// according to https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-19
- if (sctp_mid_ && local_description() && remote_description()) {
- rtc::scoped_refptr<SctpTransport> sctp_transport =
- transport_controller_->GetSctpTransport(*sctp_mid_);
+ if (sctp_transport_ && local_description() && remote_description()) {
auto local_sctp_description = cricket::GetFirstSctpDataContentDescription(
local_description()->description());
auto remote_sctp_description = cricket::GetFirstSctpDataContentDescription(
remote_description()->description());
- if (sctp_transport && local_sctp_description && remote_sctp_description) {
+ if (local_sctp_description && remote_sctp_description) {
int max_message_size;
// A remote max message size of zero means "any size supported".
// We configure the connection with our own max message size.
@@ -5827,8 +5850,8 @@
std::min(local_sctp_description->max_message_size(),
remote_sctp_description->max_message_size());
}
- sctp_transport->Start(local_sctp_description->port(),
- remote_sctp_description->port(), max_message_size);
+ sctp_transport_->Start(local_sctp_description->port(),
+ remote_sctp_description->port(), max_message_size);
}
}
@@ -5916,7 +5939,7 @@
const rtc::CopyOnWriteBuffer& payload,
cricket::SendDataResult* result) {
RTC_DCHECK_RUN_ON(signaling_thread());
- if (data_channel_transport_) {
+ if (data_channel_transport_ && data_channel_transport_negotiated_) {
SendDataParams send_params;
send_params.type = ToWebrtcDataMessageType(params.type);
send_params.ordered = params.ordered;
@@ -5925,24 +5948,12 @@
} else if (params.max_rtx_ms >= 0) {
send_params.max_rtx_ms = params.max_rtx_ms;
}
-
- RTCError error = network_thread()->Invoke<RTCError>(
- RTC_FROM_HERE, [this, params, send_params, payload] {
- return data_channel_transport_->SendData(params.sid, send_params,
- payload);
- });
-
- if (error.ok()) {
- *result = cricket::SendDataResult::SDR_SUCCESS;
- return true;
- } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
- // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
- // TODO(mellem): Stop using RTCError here and get rid of the mapping.
- *result = cricket::SendDataResult::SDR_BLOCK;
- return false;
- }
- *result = cricket::SendDataResult::SDR_ERROR;
- return false;
+ return data_channel_transport_->SendData(params.sid, send_params, payload)
+ .ok();
+ } else if (sctp_transport_ && sctp_negotiated_) {
+ return network_thread()->Invoke<bool>(
+ RTC_FROM_HERE, Bind(&cricket::SctpTransportInternal::SendData,
+ cricket_sctp_transport(), params, payload, result));
} else if (rtp_data_channel_) {
return rtp_data_channel_->SendData(params, payload, result);
}
@@ -5952,7 +5963,7 @@
bool PeerConnection::ConnectDataChannel(DataChannel* webrtc_data_channel) {
RTC_DCHECK_RUN_ON(signaling_thread());
- if (!rtp_data_channel_ && !data_channel_transport_) {
+ if (!rtp_data_channel_ && !sctp_transport_ && !data_channel_transport_) {
// Don't log an error here, because DataChannels are expected to call
// ConnectDataChannel in this state. It's the only way to initially tell
// whether or not the underlying transport is ready.
@@ -5974,12 +5985,22 @@
rtp_data_channel_->SignalDataReceived.connect(webrtc_data_channel,
&DataChannel::OnDataReceived);
}
+ if (sctp_transport_) {
+ SignalSctpReadyToSendData.connect(webrtc_data_channel,
+ &DataChannel::OnChannelReady);
+ SignalSctpDataReceived.connect(webrtc_data_channel,
+ &DataChannel::OnDataReceived);
+ SignalSctpClosingProcedureStartedRemotely.connect(
+ webrtc_data_channel, &DataChannel::OnClosingProcedureStartedRemotely);
+ SignalSctpClosingProcedureComplete.connect(
+ webrtc_data_channel, &DataChannel::OnClosingProcedureComplete);
+ }
return true;
}
void PeerConnection::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
RTC_DCHECK_RUN_ON(signaling_thread());
- if (!rtp_data_channel_ && !data_channel_transport_) {
+ if (!rtp_data_channel_ && !sctp_transport_ && !data_channel_transport_) {
RTC_LOG(LS_ERROR)
<< "DisconnectDataChannel called when rtp_data_channel_ and "
"sctp_transport_ are NULL.";
@@ -5995,32 +6016,48 @@
rtp_data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
rtp_data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
}
+ if (sctp_transport_) {
+ SignalSctpReadyToSendData.disconnect(webrtc_data_channel);
+ SignalSctpDataReceived.disconnect(webrtc_data_channel);
+ SignalSctpClosingProcedureStartedRemotely.disconnect(webrtc_data_channel);
+ SignalSctpClosingProcedureComplete.disconnect(webrtc_data_channel);
+ }
}
void PeerConnection::AddSctpDataStream(int sid) {
if (data_channel_transport_) {
- network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
- if (data_channel_transport_) {
- data_channel_transport_->OpenChannel(sid);
- }
- });
+ data_channel_transport_->OpenChannel(sid);
}
+ if (!sctp_transport_) {
+ RTC_LOG(LS_ERROR)
+ << "AddSctpDataStream called when sctp_transport_ is NULL.";
+ return;
+ }
+ network_thread()->Invoke<void>(
+ RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::OpenStream,
+ cricket_sctp_transport(), sid));
}
void PeerConnection::RemoveSctpDataStream(int sid) {
if (data_channel_transport_) {
- network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
- if (data_channel_transport_) {
- data_channel_transport_->CloseChannel(sid);
- }
- });
+ data_channel_transport_->CloseChannel(sid);
}
+ if (!sctp_transport_) {
+ RTC_LOG(LS_ERROR) << "RemoveSctpDataStream called when sctp_transport_ is "
+ "NULL.";
+ return;
+ }
+ network_thread()->Invoke<void>(
+ RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::ResetStream,
+ cricket_sctp_transport(), sid));
}
bool PeerConnection::ReadyToSendData() const {
RTC_DCHECK_RUN_ON(signaling_thread());
return (rtp_data_channel_ && rtp_data_channel_->ready_to_send_data()) ||
- (data_channel_transport_ && data_channel_transport_ready_to_send_);
+ (data_channel_transport_ && data_channel_transport_ready_to_send_ &&
+ data_channel_transport_negotiated_) ||
+ (sctp_ready_to_send_data_ && sctp_negotiated_);
}
void PeerConnection::OnDataReceived(int channel_id,
@@ -6063,8 +6100,10 @@
RTC_FROM_HERE, signaling_thread(), [this] {
RTC_DCHECK_RUN_ON(signaling_thread());
data_channel_transport_ready_to_send_ = true;
- SignalDataChannelTransportWritable_s(
- data_channel_transport_ready_to_send_);
+ if (data_channel_transport_negotiated_) {
+ SignalDataChannelTransportWritable_s(
+ data_channel_transport_ready_to_send_);
+ }
});
}
@@ -6104,7 +6143,7 @@
transport_names_by_mid[rtp_data_channel_->content_name()] =
rtp_data_channel_->transport_name();
}
- if (data_channel_transport_) {
+ if (sctp_transport_) {
absl::optional<std::string> transport_name = sctp_transport_name();
RTC_DCHECK(transport_name);
transport_names_by_mid[*sctp_mid_] = *transport_name;
@@ -6475,7 +6514,7 @@
const cricket::ContentInfo* data = cricket::GetFirstDataContent(&desc);
if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected &&
- !rtp_data_channel_ && !data_channel_transport_) {
+ !rtp_data_channel_ && !sctp_transport_ && !data_channel_transport_) {
if (!CreateDataChannel(data->name)) {
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
"Failed to create data channel.");
@@ -6535,21 +6574,32 @@
bool PeerConnection::CreateDataChannel(const std::string& mid) {
switch (data_channel_type_) {
case cricket::DCT_SCTP:
- case cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP:
- case cricket::DCT_DATA_CHANNEL_TRANSPORT:
- case cricket::DCT_MEDIA_TRANSPORT:
- if (!network_thread()->Invoke<bool>(
- RTC_FROM_HERE,
- rtc::Bind(&PeerConnection::SetupDataChannelTransport_n, this,
- mid))) {
+ // Only using SCTP transport. No more setup required. Since SCTP is
+ // the only option, it doesn't need to wait for negotiation.
+ sctp_negotiated_ = true;
+ if (!CreateSctpDataChannel(mid)) {
return false;
}
-
- // All non-RTP data channels must initialize |sctp_data_channels_|.
- for (const auto& channel : sctp_data_channels_) {
- channel->OnTransportChannelCreated();
+ break;
+ case cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP:
+ // Setup a data channel transport with SCTP as a fallback. Which one is
+ // used will be determined later in negotiation.
+ if (!CreateSctpDataChannel(mid)) {
+ return false;
}
- return true;
+ if (!SetupDataChannelTransport(mid)) {
+ return false;
+ }
+ break;
+ case cricket::DCT_DATA_CHANNEL_TRANSPORT:
+ case cricket::DCT_MEDIA_TRANSPORT:
+ // Using data channel transport without a fallback. It is the only
+ // option. Data channel transport doesn't need to be negotiated.
+ data_channel_transport_negotiated_ = true;
+ if (!SetupDataChannelTransport(mid)) {
+ return false;
+ }
+ break;
case cricket::DCT_RTP:
default:
RtpTransportInternal* rtp_transport = GetRtpTransport(mid);
@@ -6566,7 +6616,36 @@
rtp_data_channel_->SetRtpTransport(rtp_transport);
return true;
}
- return false;
+
+ // All non-RTP data channels must initialize |sctp_data_channels_|.
+ for (const auto& channel : sctp_data_channels_) {
+ channel->OnTransportChannelCreated();
+ }
+ return true;
+}
+
+bool PeerConnection::CreateSctpDataChannel(const std::string& mid) {
+ if (!sctp_factory_) {
+ RTC_LOG(LS_ERROR)
+ << "Trying to create SCTP transport, but didn't compile with "
+ "SCTP support (HAVE_SCTP)";
+ return false;
+ }
+ if (!network_thread()->Invoke<bool>(
+ RTC_FROM_HERE,
+ rtc::Bind(&PeerConnection::CreateSctpTransport_n, this, mid))) {
+ return false;
+ }
+ return true;
+}
+
+bool PeerConnection::SetupDataChannelTransport(const std::string& mid) {
+ if (!network_thread()->Invoke<bool>(
+ RTC_FROM_HERE,
+ rtc::Bind(&PeerConnection::SetupDataChannelTransport_n, this, mid))) {
+ return false;
+ }
+ return true;
}
Call::Stats PeerConnection::GetCallStats() {
@@ -6582,10 +6661,124 @@
}
}
+bool PeerConnection::CreateSctpTransport_n(const std::string& mid) {
+ RTC_DCHECK_RUN_ON(network_thread());
+ RTC_DCHECK(sctp_factory_);
+ RTC_LOG(LS_INFO) << "Creating SCTP transport for mid=" << mid;
+
+ rtc::scoped_refptr<DtlsTransport> webrtc_dtls_transport =
+ transport_controller_->LookupDtlsTransportByMid(mid);
+ cricket::DtlsTransportInternal* dtls_transport =
+ webrtc_dtls_transport->internal();
+ RTC_DCHECK(dtls_transport);
+ std::unique_ptr<cricket::SctpTransportInternal> cricket_sctp_transport =
+ sctp_factory_->CreateSctpTransport(dtls_transport);
+ RTC_DCHECK(cricket_sctp_transport);
+ sctp_invoker_.reset(new rtc::AsyncInvoker());
+ cricket_sctp_transport->SignalReadyToSendData.connect(
+ this, &PeerConnection::OnSctpTransportReadyToSendData_n);
+ cricket_sctp_transport->SignalDataReceived.connect(
+ this, &PeerConnection::OnSctpTransportDataReceived_n);
+ // TODO(deadbeef): All we do here is AsyncInvoke to fire the signal on
+ // another thread. Would be nice if there was a helper class similar to
+ // sigslot::repeater that did this for us, eliminating a bunch of boilerplate
+ // code.
+ cricket_sctp_transport->SignalClosingProcedureStartedRemotely.connect(
+ this, &PeerConnection::OnSctpClosingProcedureStartedRemotely_n);
+ cricket_sctp_transport->SignalClosingProcedureComplete.connect(
+ this, &PeerConnection::OnSctpClosingProcedureComplete_n);
+ sctp_mid_ = mid;
+ sctp_transport_ = new rtc::RefCountedObject<SctpTransport>(
+ std::move(cricket_sctp_transport));
+ sctp_transport_->SetDtlsTransport(std::move(webrtc_dtls_transport));
+ return true;
+}
+
+void PeerConnection::DestroySctpTransport_n() {
+ RTC_DCHECK_RUN_ON(network_thread());
+ RTC_LOG(LS_INFO) << "Destroying SCTP transport for mid=" << *sctp_mid_;
+
+ sctp_transport_->Clear();
+ sctp_transport_ = nullptr;
+ // |sctp_mid_| may still be active through a data channel transport. If not,
+ // unset it.
+ if (!data_channel_transport_) {
+ sctp_mid_.reset();
+ }
+ sctp_invoker_.reset(nullptr);
+}
+
+void PeerConnection::OnSctpTransportReadyToSendData_n() {
+ RTC_DCHECK_RUN_ON(network_thread());
+ RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP ||
+ data_channel_type_ == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP);
+ // Note: Cannot use rtc::Bind here because it will grab a reference to
+ // PeerConnection and potentially cause PeerConnection to live longer than
+ // expected. It is safe not to grab a reference since the sctp_invoker_ will
+ // be destroyed before PeerConnection is destroyed, and at that point all
+ // pending tasks will be cleared.
+ sctp_invoker_->AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread(), [this] {
+ OnSctpTransportReadyToSendData_s(true);
+ });
+}
+
+void PeerConnection::OnSctpTransportReadyToSendData_s(bool ready) {
+ RTC_DCHECK_RUN_ON(signaling_thread());
+ sctp_ready_to_send_data_ = ready;
+ if (sctp_negotiated_) {
+ SignalSctpReadyToSendData(ready);
+ }
+}
+
+void PeerConnection::OnSctpTransportDataReceived_n(
+ const cricket::ReceiveDataParams& params,
+ const rtc::CopyOnWriteBuffer& payload) {
+ RTC_DCHECK_RUN_ON(network_thread());
+ RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP ||
+ data_channel_type_ == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP);
+ // Note: Cannot use rtc::Bind here because it will grab a reference to
+ // PeerConnection and potentially cause PeerConnection to live longer than
+ // expected. It is safe not to grab a reference since the sctp_invoker_ will
+ // be destroyed before PeerConnection is destroyed, and at that point all
+ // pending tasks will be cleared.
+ sctp_invoker_->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread(), [this, params, payload] {
+ OnSctpTransportDataReceived_s(params, payload);
+ });
+}
+
+void PeerConnection::OnSctpTransportDataReceived_s(
+ const cricket::ReceiveDataParams& params,
+ const rtc::CopyOnWriteBuffer& payload) {
+ RTC_DCHECK_RUN_ON(signaling_thread());
+ if (!HandleOpenMessage_s(params, payload)) {
+ SignalSctpDataReceived(params, payload);
+ }
+}
+
+void PeerConnection::OnSctpClosingProcedureStartedRemotely_n(int sid) {
+ RTC_DCHECK_RUN_ON(network_thread());
+ RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP ||
+ data_channel_type_ == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP);
+ sctp_invoker_->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread(),
+ rtc::Bind(&sigslot::signal1<int>::operator(),
+ &SignalSctpClosingProcedureStartedRemotely, sid));
+}
+
+void PeerConnection::OnSctpClosingProcedureComplete_n(int sid) {
+ RTC_DCHECK_RUN_ON(network_thread());
+ RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP ||
+ data_channel_type_ == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP);
+ sctp_invoker_->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread(),
+ rtc::Bind(&sigslot::signal1<int>::operator(),
+ &SignalSctpClosingProcedureComplete, sid));
+}
+
bool PeerConnection::SetupDataChannelTransport_n(const std::string& mid) {
- DataChannelTransportInterface* transport =
- transport_controller_->GetDataChannelTransport(mid);
- if (!transport) {
+ data_channel_transport_ = transport_controller_->GetDataChannelTransport(mid);
+ if (!data_channel_transport_) {
RTC_LOG(LS_ERROR)
<< "Data channel transport is not available for data channels, mid="
<< mid;
@@ -6593,9 +6786,8 @@
}
RTC_LOG(LS_INFO) << "Setting up data channel transport for mid=" << mid;
- transport->SetDataSink(this);
- data_channel_transport_ = transport;
data_channel_transport_invoker_ = absl::make_unique<rtc::AsyncInvoker>();
+ data_channel_transport_->SetDataSink(this);
sctp_mid_ = mid;
// TODO(mellem): Handling data channel state through media transport is
// deprecated. Delete these lines when downstream implementations call
@@ -6608,7 +6800,7 @@
}
void PeerConnection::TeardownDataChannelTransport_n() {
- if (!sctp_mid_ && !data_channel_transport_) {
+ if (!data_channel_transport_) {
return;
}
RTC_LOG(LS_INFO) << "Tearing down data channel transport for mid="
@@ -6619,11 +6811,11 @@
transport_controller_->SignalMediaTransportStateChanged.disconnect(this);
// |sctp_mid_| may still be active through an SCTP transport. If not, unset
// it.
- sctp_mid_.reset();
- data_channel_transport_invoker_ = nullptr;
- if (data_channel_transport_) {
- data_channel_transport_->SetDataSink(nullptr);
+ if (!sctp_transport_) {
+ sctp_mid_.reset();
}
+ data_channel_transport_->SetDataSink(nullptr);
+ data_channel_transport_invoker_ = nullptr;
data_channel_transport_ = nullptr;
}
@@ -6639,8 +6831,10 @@
RTC_FROM_HERE, signaling_thread(), [this] {
RTC_DCHECK_RUN_ON(signaling_thread());
data_channel_transport_ready_to_send_ = true;
- SignalDataChannelTransportWritable_s(
- data_channel_transport_ready_to_send_);
+ if (data_channel_transport_negotiated_) {
+ SignalDataChannelTransportWritable_s(
+ data_channel_transport_ready_to_send_);
+ }
});
}
@@ -7160,7 +7354,7 @@
if (channel) {
return channel->transport_name();
}
- if (data_channel_transport_) {
+ if (sctp_transport_) {
RTC_DCHECK(sctp_mid_);
if (content_name == *sctp_mid_) {
return *sctp_transport_name();
@@ -7195,7 +7389,14 @@
// been destroyed (since it is a subclass of PeerConnection) and using
// rtc::Bind will cause "Pure virtual function called" error to appear.
- if (sctp_mid_) {
+ if (sctp_transport_) {
+ OnDataChannelDestroyed();
+ network_thread()->Invoke<void>(RTC_FROM_HERE,
+ [this] { DestroySctpTransport_n(); });
+ sctp_ready_to_send_data_ = false;
+ }
+
+ if (data_channel_transport_) {
OnDataChannelDestroyed();
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
RTC_DCHECK_RUN_ON(network_thread());
@@ -7231,7 +7432,8 @@
RtpTransportInternal* rtp_transport,
rtc::scoped_refptr<DtlsTransport> dtls_transport,
MediaTransportInterface* media_transport,
- DataChannelTransportInterface* data_channel_transport) {
+ DataChannelTransportInterface* data_channel_transport,
+ JsepTransportController::NegotiationState negotiation_state) {
RTC_DCHECK_RUN_ON(network_thread());
RTC_DCHECK_RUNS_SERIALIZED(&use_media_transport_race_checker_);
bool ret = true;
@@ -7239,30 +7441,53 @@
if (base_channel) {
ret = base_channel->SetRtpTransport(rtp_transport);
}
+ if (sctp_transport_ && mid == sctp_mid_) {
+ sctp_transport_->SetDtlsTransport(dtls_transport);
+ }
if (use_media_transport_) {
RTC_LOG(LS_ERROR) << "Media transport isn't supported.";
}
- if (data_channel_transport_ && mid == sctp_mid_ &&
- data_channel_transport_ != data_channel_transport) {
- // Changed which data channel transport is used for |sctp_mid_| (eg. now
- // it's bundled).
- data_channel_transport_->SetDataSink(nullptr);
- data_channel_transport_ = data_channel_transport;
- if (data_channel_transport) {
- data_channel_transport->SetDataSink(this);
-
- // There's a new data channel transport. This needs to be signaled to the
- // |sctp_data_channels_| so that they can reopen and reconnect. This is
- // necessary when bundling is applied.
- data_channel_transport_invoker_->AsyncInvoke<void>(
- RTC_FROM_HERE, signaling_thread(), [this] {
- RTC_DCHECK_RUN_ON(signaling_thread());
- for (auto channel : sctp_data_channels_) {
- channel->OnTransportChannelCreated();
- }
- });
+ if (mid == sctp_mid_) {
+ switch (negotiation_state) {
+ case JsepTransportController::NegotiationState::kFinal:
+ if (data_channel_transport) {
+ if (sctp_transport_) {
+ DestroySctpTransport_n();
+ }
+ } else {
+ TeardownDataChannelTransport_n();
+ }
+ // We also need to mark the remaining transport as ready-to-send.
+ RTC_FALLTHROUGH();
+ case JsepTransportController::NegotiationState::kProvisional: {
+ rtc::AsyncInvoker* invoker = data_channel_transport_invoker_
+ ? data_channel_transport_invoker_.get()
+ : sctp_invoker_.get();
+ if (!invoker) {
+ break; // Have neither SCTP nor DataChannelTransport, nothing to do.
+ }
+ invoker->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread(), [this, data_channel_transport] {
+ RTC_DCHECK_RUN_ON(signaling_thread());
+ if (data_channel_transport) {
+ data_channel_transport_negotiated_ = true;
+ if (data_channel_transport_ready_to_send_) {
+ SignalDataChannelTransportWritable_s(
+ data_channel_transport_ready_to_send_);
+ }
+ } else {
+ sctp_negotiated_ = true;
+ if (sctp_ready_to_send_data_) {
+ SignalSctpReadyToSendData(sctp_ready_to_send_data_);
+ }
+ }
+ });
+ } break;
+ case JsepTransportController::NegotiationState::kInitial:
+ // Negotiation isn't finished. Nothing to do here.
+ break;
}
}
diff --git a/pc/peer_connection.h b/pc/peer_connection.h
index 1373870..550a9ee 100644
--- a/pc/peer_connection.h
+++ b/pc/peer_connection.h
@@ -1018,6 +1018,28 @@
cricket::VideoChannel* CreateVideoChannel(const std::string& mid)
RTC_RUN_ON(signaling_thread());
bool CreateDataChannel(const std::string& mid) RTC_RUN_ON(signaling_thread());
+ bool CreateSctpDataChannel(const std::string& mid)
+ RTC_RUN_ON(signaling_thread());
+ bool SetupDataChannelTransport(const std::string& mid)
+ RTC_RUN_ON(signaling_thread());
+
+ bool CreateSctpTransport_n(const std::string& mid);
+ // For bundling.
+ void DestroySctpTransport_n();
+ // SctpTransport signal handlers. Needed to marshal signals from the network
+ // to signaling thread.
+ void OnSctpTransportReadyToSendData_n();
+ // This may be called with "false" if the direction of the m= section causes
+ // us to tear down the SCTP connection.
+ void OnSctpTransportReadyToSendData_s(bool ready);
+ void OnSctpTransportDataReceived_n(const cricket::ReceiveDataParams& params,
+ const rtc::CopyOnWriteBuffer& payload);
+ // Beyond just firing the signal to the signaling thread, listens to SCTP
+ // CONTROL messages on unused SIDs and processes them as OPEN messages.
+ void OnSctpTransportDataReceived_s(const cricket::ReceiveDataParams& params,
+ const rtc::CopyOnWriteBuffer& payload);
+ void OnSctpClosingProcedureStartedRemotely_n(int sid);
+ void OnSctpClosingProcedureComplete_n(int sid);
bool SetupDataChannelTransport_n(const std::string& mid)
RTC_RUN_ON(network_thread());
@@ -1130,7 +1152,8 @@
RtpTransportInternal* rtp_transport,
rtc::scoped_refptr<DtlsTransport> dtls_transport,
MediaTransportInterface* media_transport,
- DataChannelTransportInterface* data_channel_transport) override;
+ DataChannelTransportInterface* data_channel_transport,
+ JsepTransportController::NegotiationState negotiation_state) override;
// RtpSenderBase::SetStreamsObserver override.
void OnSetStreams() override;
@@ -1301,6 +1324,13 @@
nullptr; // TODO(bugs.webrtc.org/9987): Accessed on both
// signaling and some other thread.
+ cricket::SctpTransportInternal* cricket_sctp_transport() {
+ return sctp_transport_->internal();
+ }
+ rtc::scoped_refptr<SctpTransport>
+ sctp_transport_; // TODO(bugs.webrtc.org/9987): Accessed on both
+ // signaling and network thread.
+
// |sctp_mid_| is the content name (MID) in SDP.
// Note: this is used as the data channel MID by both SCTP and data channel
// transports. It is set when either transport is initialized and unset when
@@ -1309,25 +1339,56 @@
sctp_mid_; // TODO(bugs.webrtc.org/9987): Accessed on both signaling
// and network thread.
+ // Value cached on signaling thread. Only updated when SctpReadyToSendData
+ // fires on the signaling thread.
+ bool sctp_ready_to_send_data_ RTC_GUARDED_BY(signaling_thread()) = false;
+
+ // Whether the use of SCTP has been successfully negotiated.
+ bool sctp_negotiated_ RTC_GUARDED_BY(signaling_thread()) = false;
+
+ // Same as signals provided by SctpTransport, but these are guaranteed to
+ // fire on the signaling thread, whereas SctpTransport fires on the networking
+ // thread.
+ // |sctp_invoker_| is used so that any signals queued on the signaling thread
+ // from the network thread are immediately discarded if the SctpTransport is
+ // destroyed (due to m= section being rejected).
+ // TODO(deadbeef): Use a proxy object to ensure that method calls/signals
+ // are marshalled to the right thread. Could almost use proxy.h for this,
+ // but it doesn't have a mechanism for marshalling sigslot::signals
+ std::unique_ptr<rtc::AsyncInvoker> sctp_invoker_
+ RTC_GUARDED_BY(network_thread());
+ sigslot::signal1<bool> SignalSctpReadyToSendData
+ RTC_GUARDED_BY(signaling_thread());
+ sigslot::signal2<const cricket::ReceiveDataParams&,
+ const rtc::CopyOnWriteBuffer&>
+ SignalSctpDataReceived RTC_GUARDED_BY(signaling_thread());
+ sigslot::signal1<int> SignalSctpClosingProcedureStartedRemotely
+ RTC_GUARDED_BY(signaling_thread());
+ sigslot::signal1<int> SignalSctpClosingProcedureComplete
+ RTC_GUARDED_BY(signaling_thread());
+
// Whether this peer is the caller. Set when the local description is applied.
absl::optional<bool> is_caller_ RTC_GUARDED_BY(signaling_thread());
- // Plugin transport used for data channels. Pointer may be accessed and
- // checked from any thread, but the object may only be touched on the
- // network thread.
- // TODO(bugs.webrtc.org/9987): Accessed on both signaling and network thread.
- DataChannelTransportInterface* data_channel_transport_;
+ // Plugin transport used for data channels. Thread-safe.
+ DataChannelTransportInterface* data_channel_transport_ =
+ nullptr; // TODO(bugs.webrtc.org/9987): Object is thread safe, but
+ // pointer accessed on both signaling and network thread.
// Cached value of whether the data channel transport is ready to send.
bool data_channel_transport_ready_to_send_
RTC_GUARDED_BY(signaling_thread()) = false;
+ // Whether the use of the data channel transport has been successfully
+ // negotiated.
+ bool data_channel_transport_negotiated_ RTC_GUARDED_BY(signaling_thread()) =
+ false;
+
// Used to invoke data channel transport signals on the signaling thread.
std::unique_ptr<rtc::AsyncInvoker> data_channel_transport_invoker_
RTC_GUARDED_BY(network_thread());
- // Signals from |data_channel_transport_|. These are invoked on the signaling
- // thread.
+ // Identical to the signals for SCTP, but from media transport:
sigslot::signal1<bool> SignalDataChannelTransportWritable_s
RTC_GUARDED_BY(signaling_thread());
sigslot::signal2<const cricket::ReceiveDataParams&,
diff --git a/pc/peer_connection_data_channel_unittest.cc b/pc/peer_connection_data_channel_unittest.cc
index 4af8489..787e5ba 100644
--- a/pc/peer_connection_data_channel_unittest.cc
+++ b/pc/peer_connection_data_channel_unittest.cc
@@ -240,20 +240,6 @@
EXPECT_FALSE(caller->sctp_transport_factory()->last_fake_sctp_transport());
}
-TEST_P(PeerConnectionDataChannelTest, InternalSctpTransportDeletedOnTeardown) {
- auto caller = CreatePeerConnectionWithDataChannel();
-
- ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
- EXPECT_TRUE(caller->sctp_transport_factory()->last_fake_sctp_transport());
-
- rtc::scoped_refptr<SctpTransportInterface> sctp_transport =
- caller->GetInternalPeerConnection()->GetSctpTransport();
-
- caller.reset();
- EXPECT_EQ(static_cast<SctpTransport*>(sctp_transport.get())->internal(),
- nullptr);
-}
-
// Test that sctp_content_name/sctp_transport_name (used for stats) are correct
// before and after BUNDLE is negotiated.
TEST_P(PeerConnectionDataChannelTest, SctpContentAndTransportNameSetCorrectly) {
diff --git a/pc/sctp_data_channel_transport.cc b/pc/sctp_data_channel_transport.cc
deleted file mode 100644
index d1505f3..0000000
--- a/pc/sctp_data_channel_transport.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2019 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/sctp_data_channel_transport.h"
-#include "pc/sctp_utils.h"
-
-namespace webrtc {
-
-SctpDataChannelTransport::SctpDataChannelTransport(
- cricket::SctpTransportInternal* sctp_transport)
- : sctp_transport_(sctp_transport) {
- sctp_transport_->SignalReadyToSendData.connect(
- this, &SctpDataChannelTransport::OnReadyToSendData);
- sctp_transport_->SignalDataReceived.connect(
- this, &SctpDataChannelTransport::OnDataReceived);
- sctp_transport_->SignalClosingProcedureStartedRemotely.connect(
- this, &SctpDataChannelTransport::OnClosingProcedureStartedRemotely);
- sctp_transport_->SignalClosingProcedureComplete.connect(
- this, &SctpDataChannelTransport::OnClosingProcedureComplete);
-}
-
-RTCError SctpDataChannelTransport::OpenChannel(int channel_id) {
- sctp_transport_->OpenStream(channel_id);
- return RTCError::OK();
-}
-
-RTCError SctpDataChannelTransport::SendData(
- int channel_id,
- const SendDataParams& params,
- const rtc::CopyOnWriteBuffer& buffer) {
- // Map webrtc::SendDataParams to cricket::SendDataParams.
- // TODO(mellem): See about unifying these structs.
- cricket::SendDataParams sd_params;
- sd_params.sid = channel_id;
- sd_params.type = ToCricketDataMessageType(params.type);
- sd_params.ordered = params.ordered;
- sd_params.reliable = !(params.max_rtx_count || params.max_rtx_ms);
- sd_params.max_rtx_count = params.max_rtx_count.value_or(-1);
- sd_params.max_rtx_ms = params.max_rtx_ms.value_or(-1);
-
- cricket::SendDataResult result;
- sctp_transport_->SendData(sd_params, buffer, &result);
-
- // TODO(mellem): See about changing the interfaces to not require mapping
- // SendDataResult to RTCError and back again.
- switch (result) {
- case cricket::SendDataResult::SDR_SUCCESS:
- return RTCError::OK();
- case cricket::SendDataResult::SDR_BLOCK: {
- // Send buffer is full.
- ready_to_send_ = false;
- return RTCError(RTCErrorType::RESOURCE_EXHAUSTED);
- }
- case cricket::SendDataResult::SDR_ERROR:
- return RTCError(RTCErrorType::NETWORK_ERROR);
- }
- return RTCError(RTCErrorType::NETWORK_ERROR);
-}
-
-RTCError SctpDataChannelTransport::CloseChannel(int channel_id) {
- sctp_transport_->ResetStream(channel_id);
- return RTCError::OK();
-}
-
-void SctpDataChannelTransport::SetDataSink(DataChannelSink* sink) {
- sink_ = sink;
- if (sink_ && ready_to_send_) {
- sink_->OnReadyToSend();
- }
-}
-
-bool SctpDataChannelTransport::IsReadyToSend() const {
- return ready_to_send_;
-}
-
-void SctpDataChannelTransport::OnReadyToSendData() {
- ready_to_send_ = true;
- if (sink_) {
- sink_->OnReadyToSend();
- }
-}
-
-void SctpDataChannelTransport::OnDataReceived(
- const cricket::ReceiveDataParams& params,
- const rtc::CopyOnWriteBuffer& buffer) {
- if (sink_) {
- sink_->OnDataReceived(params.sid, ToWebrtcDataMessageType(params.type),
- buffer);
- }
-}
-
-void SctpDataChannelTransport::OnClosingProcedureStartedRemotely(
- int channel_id) {
- if (sink_) {
- sink_->OnChannelClosing(channel_id);
- }
-}
-
-void SctpDataChannelTransport::OnClosingProcedureComplete(int channel_id) {
- if (sink_) {
- sink_->OnChannelClosed(channel_id);
- }
-}
-
-} // namespace webrtc
diff --git a/pc/sctp_data_channel_transport.h b/pc/sctp_data_channel_transport.h
deleted file mode 100644
index 2d54be9..0000000
--- a/pc/sctp_data_channel_transport.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#ifndef PC_SCTP_DATA_CHANNEL_TRANSPORT_H_
-#define PC_SCTP_DATA_CHANNEL_TRANSPORT_H_
-
-#include "api/data_channel_transport_interface.h"
-#include "media/sctp/sctp_transport_internal.h"
-#include "rtc_base/third_party/sigslot/sigslot.h"
-
-namespace webrtc {
-
-// SCTP implementation of DataChannelTransportInterface.
-class SctpDataChannelTransport : public DataChannelTransportInterface,
- public sigslot::has_slots<> {
- public:
- explicit SctpDataChannelTransport(
- cricket::SctpTransportInternal* sctp_transport);
-
- RTCError OpenChannel(int channel_id) override;
- RTCError SendData(int channel_id,
- const SendDataParams& params,
- const rtc::CopyOnWriteBuffer& buffer) override;
- RTCError CloseChannel(int channel_id) override;
- void SetDataSink(DataChannelSink* sink) override;
- bool IsReadyToSend() const override;
-
- private:
- void OnReadyToSendData();
- void OnDataReceived(const cricket::ReceiveDataParams& params,
- const rtc::CopyOnWriteBuffer& buffer);
- void OnClosingProcedureStartedRemotely(int channel_id);
- void OnClosingProcedureComplete(int channel_id);
-
- cricket::SctpTransportInternal* const sctp_transport_;
-
- DataChannelSink* sink_ = nullptr;
- bool ready_to_send_ = false;
-};
-
-} // namespace webrtc
-
-#endif // PC_SCTP_DATA_CHANNEL_TRANSPORT_H_
diff --git a/pc/sctp_utils.cc b/pc/sctp_utils.cc
index 129ee07..7b67fc1 100644
--- a/pc/sctp_utils.cc
+++ b/pc/sctp_utils.cc
@@ -189,33 +189,4 @@
payload->SetData(&data, sizeof(data));
}
-cricket::DataMessageType ToCricketDataMessageType(DataMessageType type) {
- switch (type) {
- case DataMessageType::kText:
- return cricket::DMT_TEXT;
- case DataMessageType::kBinary:
- return cricket::DMT_BINARY;
- case DataMessageType::kControl:
- return cricket::DMT_CONTROL;
- default:
- return cricket::DMT_NONE;
- }
- return cricket::DMT_NONE;
-}
-
-DataMessageType ToWebrtcDataMessageType(cricket::DataMessageType type) {
- switch (type) {
- case cricket::DMT_TEXT:
- return DataMessageType::kText;
- case cricket::DMT_BINARY:
- return DataMessageType::kBinary;
- case cricket::DMT_CONTROL:
- return DataMessageType::kControl;
- case cricket::DMT_NONE:
- default:
- RTC_NOTREACHED();
- }
- return DataMessageType::kControl;
-}
-
} // namespace webrtc
diff --git a/pc/sctp_utils.h b/pc/sctp_utils.h
index 6d41eb2..468c960 100644
--- a/pc/sctp_utils.h
+++ b/pc/sctp_utils.h
@@ -14,8 +14,6 @@
#include <string>
#include "api/data_channel_interface.h"
-#include "api/data_channel_transport_interface.h"
-#include "media/base/media_channel.h"
namespace rtc {
class CopyOnWriteBuffer;
@@ -38,11 +36,6 @@
rtc::CopyOnWriteBuffer* payload);
void WriteDataChannelOpenAckMessage(rtc::CopyOnWriteBuffer* payload);
-
-cricket::DataMessageType ToCricketDataMessageType(DataMessageType type);
-
-DataMessageType ToWebrtcDataMessageType(cricket::DataMessageType type);
-
} // namespace webrtc
#endif // PC_SCTP_UTILS_H_
diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn
index c90fe1d..7a0f332 100644
--- a/test/fuzzers/BUILD.gn
+++ b/test/fuzzers/BUILD.gn
@@ -608,7 +608,7 @@
deps = [
"../../api:libjingle_peerconnection_api",
"../../pc:libjingle_peerconnection",
- "../../pc:rtc_pc_base",
+ "../../pc:peerconnection",
"../../rtc_base:rtc_base_approved",
]
}