Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(365)

Unified Diff: webrtc/api/webrtcsession.cc

Issue 2564333002: Reland of: Separating SCTP code from BaseChannel/MediaChannel. (Closed)
Patch Set: Merge with master. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/api/webrtcsession.h ('k') | webrtc/api/webrtcsession_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/api/webrtcsession.cc
diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc
index 5d414baac2f89c60df48bfd9d451132eeb7d7b8b..5d67fef3d8595f3869b402f788df567517b22330 100644
--- a/webrtc/api/webrtcsession.cc
+++ b/webrtc/api/webrtcsession.cc
@@ -33,6 +33,7 @@
#include "webrtc/call/call.h"
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/media/base/videocapturer.h"
+#include "webrtc/media/sctp/sctptransportinternal.h"
#include "webrtc/p2p/base/portallocator.h"
#include "webrtc/p2p/base/transportchannel.h"
#include "webrtc/pc/channel.h"
@@ -74,9 +75,9 @@ const char kSdpWithoutIceUfragPwd[] =
"Called with SDP without ice-ufrag and ice-pwd.";
const char kSessionError[] = "Session error code: ";
const char kSessionErrorDesc[] = "Session error description: ";
-const char kDtlsSetupFailureRtp[] =
+const char kDtlsSrtpSetupFailureRtp[] =
"Couldn't set up DTLS-SRTP on RTP channel.";
-const char kDtlsSetupFailureRtcp[] =
+const char kDtlsSrtpSetupFailureRtcp[] =
"Couldn't set up DTLS-SRTP on RTCP channel.";
const char kEnableBundleFailed[] = "Failed to enable BUNDLE.";
@@ -291,6 +292,31 @@ static bool GetTrackIdBySsrc(const SessionDescription* session_description,
return false;
}
+// Get the SCTP port out of a SessionDescription.
+// Return -1 if not found.
+static int GetSctpPort(const SessionDescription* session_description) {
+ const ContentInfo* content_info = GetFirstDataContent(session_description);
+ RTC_DCHECK(content_info);
+ if (!content_info) {
+ return -1;
+ }
+ const cricket::DataContentDescription* data =
+ static_cast<const cricket::DataContentDescription*>(
+ (content_info->description));
+ std::string value;
+ cricket::DataCodec match_pattern(cricket::kGoogleSctpDataCodecPlType,
+ cricket::kGoogleSctpDataCodecName);
+ for (const cricket::DataCodec& codec : data->codecs()) {
+ if (!codec.Matches(match_pattern)) {
+ continue;
+ }
+ if (codec.GetParam(cricket::kCodecParamPort, &value)) {
+ return rtc::FromString<int>(value);
+ }
+ }
+ return -1;
+}
+
static bool BadSdp(const std::string& source,
const std::string& type,
const std::string& reason,
@@ -440,7 +466,8 @@ WebRtcSession::WebRtcSession(
rtc::Thread* worker_thread,
rtc::Thread* signaling_thread,
cricket::PortAllocator* port_allocator,
- std::unique_ptr<cricket::TransportController> transport_controller)
+ std::unique_ptr<cricket::TransportController> transport_controller,
+ std::unique_ptr<cricket::SctpTransportInternalFactory> sctp_factory)
: network_thread_(network_thread),
worker_thread_(worker_thread),
signaling_thread_(signaling_thread),
@@ -449,6 +476,7 @@ WebRtcSession::WebRtcSession(
// Due to this constraint session id |sid_| is max limited to LLONG_MAX.
sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
transport_controller_(std::move(transport_controller)),
+ sctp_factory_(std::move(sctp_factory)),
media_controller_(media_controller),
channel_manager_(media_controller_->channel_manager()),
ice_observer_(NULL),
@@ -470,7 +498,7 @@ WebRtcSession::WebRtcSession(
transport_controller_->SignalCandidatesRemoved.connect(
this, &WebRtcSession::OnTransportControllerCandidatesRemoved);
transport_controller_->SignalDtlsHandshakeError.connect(
- this, &WebRtcSession::OnDtlsHandshakeError);
+ this, &WebRtcSession::OnTransportControllerDtlsHandshakeError);
}
WebRtcSession::~WebRtcSession() {
@@ -485,9 +513,14 @@ WebRtcSession::~WebRtcSession() {
SignalVoiceChannelDestroyed();
channel_manager_->DestroyVoiceChannel(voice_channel_.release());
}
- if (data_channel_) {
+ if (rtp_data_channel_) {
+ SignalDataChannelDestroyed();
+ channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
+ }
+ if (sctp_transport_) {
SignalDataChannelDestroyed();
- channel_manager_->DestroyDataChannel(data_channel_.release());
+ network_thread_->Invoke<void>(
+ RTC_FROM_HERE, rtc::Bind(&WebRtcSession::DestroySctpTransport_n, this));
}
#ifdef HAVE_QUIC
if (quic_data_transport_) {
@@ -597,9 +630,10 @@ bool WebRtcSession::Initialize(
void WebRtcSession::Close() {
SetState(STATE_CLOSED);
RemoveUnusedChannels(nullptr);
- ASSERT(!voice_channel_);
- ASSERT(!video_channel_);
- ASSERT(!data_channel_);
+ RTC_DCHECK(!voice_channel_);
+ RTC_DCHECK(!video_channel_);
+ RTC_DCHECK(!rtp_data_channel_);
+ RTC_DCHECK(!sctp_transport_);
media_controller_->Close();
}
@@ -611,8 +645,9 @@ cricket::BaseChannel* WebRtcSession::GetChannel(
if (video_channel() && video_channel()->content_name() == content_name) {
return video_channel();
}
- if (data_channel() && data_channel()->content_name() == content_name) {
- return data_channel();
+ if (rtp_data_channel() &&
+ rtp_data_channel()->content_name() == content_name) {
+ return rtp_data_channel();
}
return nullptr;
}
@@ -621,20 +656,31 @@ cricket::SecurePolicy WebRtcSession::SdesPolicy() const {
return webrtc_session_desc_factory_->SdesPolicy();
}
-bool WebRtcSession::GetSslRole(const std::string& transport_name,
- rtc::SSLRole* role) {
+bool WebRtcSession::GetSctpSslRole(rtc::SSLRole* role) {
if (!local_description() || !remote_description()) {
- LOG(LS_INFO) << "Local and Remote descriptions must be applied to get "
- << "SSL Role of the session.";
+ LOG(LS_INFO) << "Local and Remote descriptions must be applied to get the "
+ << "SSL Role of the SCTP transport.";
+ return false;
+ }
+ if (!sctp_transport_) {
+ LOG(LS_INFO) << "Non-rejected SCTP m= section is needed to get the "
+ << "SSL Role of the SCTP transport.";
return false;
}
- return transport_controller_->GetSslRole(transport_name, role);
+ return transport_controller_->GetSslRole(*sctp_transport_name_, role);
}
-bool WebRtcSession::GetSslRole(const cricket::BaseChannel* channel,
+bool WebRtcSession::GetSslRole(const std::string& content_name,
rtc::SSLRole* role) {
- return channel && GetSslRole(channel->transport_name(), role);
+ if (!local_description() || !remote_description()) {
+ LOG(LS_INFO) << "Local and Remote descriptions must be applied to get the "
+ << "SSL Role of the session.";
+ return false;
+ }
+
+ return transport_controller_->GetSslRole(GetTransportName(content_name),
+ role);
}
void WebRtcSession::CreateOffer(
@@ -918,9 +964,29 @@ bool WebRtcSession::PushdownMediaDescription(
}
};
- return (set_content(voice_channel()) &&
- set_content(video_channel()) &&
- set_content(data_channel()));
+ bool ret = (set_content(voice_channel()) && set_content(video_channel()) &&
+ set_content(rtp_data_channel()));
+ // 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_transport_ && local_description() && remote_description() &&
+ cricket::GetFirstDataContent(local_description()->description()) &&
+ cricket::GetFirstDataContent(remote_description()->description())) {
+ ret &= network_thread_->Invoke<bool>(
+ RTC_FROM_HERE,
+ rtc::Bind(&WebRtcSession::PushdownSctpParameters_n, this, source));
+ }
+ return ret;
+}
+
+bool WebRtcSession::PushdownSctpParameters_n(cricket::ContentSource source) {
+ RTC_DCHECK(network_thread_->IsCurrent());
+ RTC_DCHECK(local_description());
+ RTC_DCHECK(remote_description());
+ // Apply the SCTP port (which is hidden inside a DataCodec structure...)
+ // When we support "max-message-size", that would also be pushed down here.
+ return sctp_transport_->Start(
+ GetSctpPort(local_description()->description()),
+ GetSctpPort(remote_description()->description()));
}
bool WebRtcSession::PushdownTransportDescription(cricket::ContentSource source,
@@ -992,46 +1058,6 @@ bool WebRtcSession::GetTransportDescription(
return true;
}
-std::unique_ptr<SessionStats> WebRtcSession::GetStats_s() {
- ASSERT(signaling_thread()->IsCurrent());
- ChannelNamePairs channel_name_pairs;
- if (voice_channel()) {
- channel_name_pairs.voice = rtc::Optional<ChannelNamePair>(ChannelNamePair(
- voice_channel()->content_name(), voice_channel()->transport_name()));
- }
- if (video_channel()) {
- channel_name_pairs.video = rtc::Optional<ChannelNamePair>(ChannelNamePair(
- video_channel()->content_name(), video_channel()->transport_name()));
- }
- if (data_channel()) {
- channel_name_pairs.data = rtc::Optional<ChannelNamePair>(ChannelNamePair(
- data_channel()->content_name(), data_channel()->transport_name()));
- }
- return GetStats(channel_name_pairs);
-}
-
-std::unique_ptr<SessionStats> WebRtcSession::GetStats(
- const ChannelNamePairs& channel_name_pairs) {
- if (network_thread()->IsCurrent()) {
- return GetStats_n(channel_name_pairs);
- }
- return network_thread()->Invoke<std::unique_ptr<SessionStats>>(
- RTC_FROM_HERE,
- rtc::Bind(&WebRtcSession::GetStats_n, this, channel_name_pairs));
-}
-
-bool WebRtcSession::GetLocalCertificate(
- const std::string& transport_name,
- rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
- return transport_controller_->GetLocalCertificate(transport_name,
- certificate);
-}
-
-std::unique_ptr<rtc::SSLCertificate> WebRtcSession::GetRemoteSSLCertificate(
- const std::string& transport_name) {
- return transport_controller_->GetRemoteSSLCertificate(transport_name);
-}
-
bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
const std::string* first_content_name = bundle.FirstContentName();
if (!first_content_name) {
@@ -1039,7 +1065,6 @@ bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
return false;
}
const std::string& transport_name = *first_content_name;
- cricket::BaseChannel* first_channel = GetChannel(transport_name);
#ifdef HAVE_QUIC
if (quic_data_transport_ &&
@@ -1050,8 +1075,8 @@ bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
}
#endif
- auto maybe_set_transport = [this, bundle, transport_name,
- first_channel](cricket::BaseChannel* ch) {
+ auto maybe_set_transport = [this, bundle,
+ transport_name](cricket::BaseChannel* ch) {
if (!ch || !bundle.HasContentName(ch->content_name())) {
return true;
}
@@ -1073,9 +1098,21 @@ bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
if (!maybe_set_transport(voice_channel()) ||
!maybe_set_transport(video_channel()) ||
- !maybe_set_transport(data_channel())) {
+ !maybe_set_transport(rtp_data_channel())) {
return false;
}
+ // For SCTP, transport creation/deletion happens here instead of in the
+ // object itself.
+ if (sctp_transport_) {
+ RTC_DCHECK(sctp_transport_name_);
+ RTC_DCHECK(sctp_content_name_);
+ if (transport_name != *sctp_transport_name_ &&
+ bundle.HasContentName(*sctp_content_name_)) {
+ network_thread_->Invoke<void>(
+ RTC_FROM_HERE, rtc::Bind(&WebRtcSession::ChangeSctpTransport_n, this,
+ transport_name));
+ }
+ }
return true;
}
@@ -1248,60 +1285,129 @@ sigslot::signal0<>* WebRtcSession::GetOnDestroyedSignal() {
bool WebRtcSession::SendData(const cricket::SendDataParams& params,
const rtc::CopyOnWriteBuffer& payload,
cricket::SendDataResult* result) {
- if (!data_channel_) {
- LOG(LS_ERROR) << "SendData called when data_channel_ is NULL.";
+ if (!rtp_data_channel_ && !sctp_transport_) {
+ LOG(LS_ERROR) << "SendData called when rtp_data_channel_ "
+ << "and sctp_transport_ are NULL.";
return false;
}
- return data_channel_->SendData(params, payload, result);
+ return rtp_data_channel_
+ ? rtp_data_channel_->SendData(params, payload, result)
+ : network_thread_->Invoke<bool>(
+ RTC_FROM_HERE,
+ Bind(&cricket::SctpTransportInternal::SendData,
+ sctp_transport_.get(), params, payload, result));
}
bool WebRtcSession::ConnectDataChannel(DataChannel* webrtc_data_channel) {
- if (!data_channel_) {
+ if (!rtp_data_channel_ && !sctp_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.
return false;
}
- data_channel_->SignalReadyToSendData.connect(webrtc_data_channel,
- &DataChannel::OnChannelReady);
- data_channel_->SignalDataReceived.connect(webrtc_data_channel,
- &DataChannel::OnDataReceived);
- data_channel_->SignalStreamClosedRemotely.connect(
- webrtc_data_channel, &DataChannel::OnStreamClosedRemotely);
+ if (rtp_data_channel_) {
+ rtp_data_channel_->SignalReadyToSendData.connect(
+ webrtc_data_channel, &DataChannel::OnChannelReady);
+ rtp_data_channel_->SignalDataReceived.connect(webrtc_data_channel,
+ &DataChannel::OnDataReceived);
+ } else {
+ SignalSctpReadyToSendData.connect(webrtc_data_channel,
+ &DataChannel::OnChannelReady);
+ SignalSctpDataReceived.connect(webrtc_data_channel,
+ &DataChannel::OnDataReceived);
+ SignalSctpStreamClosedRemotely.connect(
+ webrtc_data_channel, &DataChannel::OnStreamClosedRemotely);
+ }
return true;
}
void WebRtcSession::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
- if (!data_channel_) {
- LOG(LS_ERROR) << "DisconnectDataChannel called when data_channel_ is NULL.";
+ if (!rtp_data_channel_ && !sctp_transport_) {
+ LOG(LS_ERROR) << "DisconnectDataChannel called when rtp_data_channel_ and "
+ "sctp_transport_ are NULL.";
return;
}
- data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
- data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
- data_channel_->SignalStreamClosedRemotely.disconnect(webrtc_data_channel);
+ if (rtp_data_channel_) {
+ rtp_data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
+ rtp_data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
+ } else {
+ SignalSctpReadyToSendData.disconnect(webrtc_data_channel);
+ SignalSctpDataReceived.disconnect(webrtc_data_channel);
+ SignalSctpStreamClosedRemotely.disconnect(webrtc_data_channel);
+ }
}
void WebRtcSession::AddSctpDataStream(int sid) {
- if (!data_channel_) {
- LOG(LS_ERROR) << "AddDataChannelStreams called when data_channel_ is NULL.";
+ if (!sctp_transport_) {
+ LOG(LS_ERROR) << "AddSctpDataStream called when sctp_transport_ is NULL.";
return;
}
- data_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(sid));
- data_channel_->AddSendStream(cricket::StreamParams::CreateLegacy(sid));
+ network_thread_->Invoke<void>(
+ RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::OpenStream,
+ sctp_transport_.get(), sid));
}
void WebRtcSession::RemoveSctpDataStream(int sid) {
- if (!data_channel_) {
- LOG(LS_ERROR) << "RemoveDataChannelStreams called when data_channel_ is "
+ if (!sctp_transport_) {
+ LOG(LS_ERROR) << "RemoveSctpDataStream called when sctp_transport_ is "
<< "NULL.";
return;
}
- data_channel_->RemoveRecvStream(sid);
- data_channel_->RemoveSendStream(sid);
+ network_thread_->Invoke<void>(
+ RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::ResetStream,
+ sctp_transport_.get(), sid));
}
bool WebRtcSession::ReadyToSendData() const {
- return data_channel_ && data_channel_->ready_to_send_data();
+ return (rtp_data_channel_ && rtp_data_channel_->ready_to_send_data()) ||
+ sctp_ready_to_send_data_;
+}
+
+std::unique_ptr<SessionStats> WebRtcSession::GetStats_s() {
+ ASSERT(signaling_thread()->IsCurrent());
+ ChannelNamePairs channel_name_pairs;
+ if (voice_channel()) {
+ channel_name_pairs.voice = rtc::Optional<ChannelNamePair>(ChannelNamePair(
+ voice_channel()->content_name(), voice_channel()->transport_name()));
+ }
+ if (video_channel()) {
+ channel_name_pairs.video = rtc::Optional<ChannelNamePair>(ChannelNamePair(
+ video_channel()->content_name(), video_channel()->transport_name()));
+ }
+ if (rtp_data_channel()) {
+ channel_name_pairs.data = rtc::Optional<ChannelNamePair>(
+ ChannelNamePair(rtp_data_channel()->content_name(),
+ rtp_data_channel()->transport_name()));
+ }
+ if (sctp_transport_) {
+ RTC_DCHECK(sctp_content_name_);
+ RTC_DCHECK(sctp_transport_name_);
+ channel_name_pairs.data = rtc::Optional<ChannelNamePair>(
+ ChannelNamePair(*sctp_content_name_, *sctp_transport_name_));
+ }
+ return GetStats(channel_name_pairs);
+}
+
+std::unique_ptr<SessionStats> WebRtcSession::GetStats(
+ const ChannelNamePairs& channel_name_pairs) {
+ if (network_thread()->IsCurrent()) {
+ return GetStats_n(channel_name_pairs);
+ }
+ return network_thread()->Invoke<std::unique_ptr<SessionStats>>(
+ RTC_FROM_HERE,
+ rtc::Bind(&WebRtcSession::GetStats_n, this, channel_name_pairs));
+}
+
+bool WebRtcSession::GetLocalCertificate(
+ const std::string& transport_name,
+ rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
+ return transport_controller_->GetLocalCertificate(transport_name,
+ certificate);
+}
+
+std::unique_ptr<rtc::SSLCertificate> WebRtcSession::GetRemoteSSLCertificate(
+ const std::string& transport_name) {
+ return transport_controller_->GetRemoteSSLCertificate(transport_name);
}
cricket::DataChannelType WebRtcSession::data_channel_type() const {
@@ -1326,6 +1432,11 @@ void WebRtcSession::OnCertificateReady(
transport_controller_->SetLocalCertificate(certificate);
}
+void WebRtcSession::OnDtlsSrtpSetupFailure(cricket::BaseChannel*, bool rtcp) {
+ SetError(ERROR_TRANSPORT,
+ rtcp ? kDtlsSrtpSetupFailureRtcp : kDtlsSrtpSetupFailureRtp);
+}
+
bool WebRtcSession::waiting_for_certificate_for_testing() const {
return webrtc_session_desc_factory_->waiting_for_certificate_for_testing();
}
@@ -1455,7 +1566,16 @@ void WebRtcSession::OnTransportControllerCandidatesRemoved(
}
}
-// Enabling voice and video channel.
+void WebRtcSession::OnTransportControllerDtlsHandshakeError(
+ rtc::SSLHandshakeError error) {
+ if (metrics_observer_) {
+ metrics_observer_->IncrementEnumCounter(
+ webrtc::kEnumCounterDtlsHandshakeError, static_cast<int>(error),
+ static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
+ }
+}
+
+// Enabling voice and video (and RTP data) channel.
void WebRtcSession::EnableChannels() {
if (voice_channel_ && !voice_channel_->enabled())
voice_channel_->Enable(true);
@@ -1463,8 +1583,8 @@ void WebRtcSession::EnableChannels() {
if (video_channel_ && !video_channel_->enabled())
video_channel_->Enable(true);
- if (data_channel_ && !data_channel_->enabled())
- data_channel_->Enable(true);
+ if (rtp_data_channel_ && !rtp_data_channel_->enabled())
+ rtp_data_channel_->Enable(true);
}
// Returns the media index for a local ice candidate given the content name.
@@ -1574,9 +1694,15 @@ void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
const cricket::ContentInfo* data_info =
cricket::GetFirstDataContent(desc);
if (!data_info || data_info->rejected) {
- if (data_channel_) {
+ if (rtp_data_channel_) {
SignalDataChannelDestroyed();
- channel_manager_->DestroyDataChannel(data_channel_.release());
+ channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
+ }
+ if (sctp_transport_) {
+ SignalDataChannelDestroyed();
+ network_thread_->Invoke<void>(
+ RTC_FROM_HERE,
+ rtc::Bind(&WebRtcSession::DestroySctpTransport_n, this));
}
#ifdef HAVE_QUIC
// Clean up the existing QuicDataTransport and its QuicTransportChannels.
@@ -1637,8 +1763,8 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
}
const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc);
- if (data_channel_type_ != cricket::DCT_NONE &&
- data && !data->rejected && !data_channel_) {
+ if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected &&
+ !rtp_data_channel_ && !sctp_transport_) {
if (!CreateDataChannel(data, GetBundleTransportName(data, bundle_group))) {
LOG(LS_ERROR) << "Failed to create data channel.";
return false;
@@ -1664,8 +1790,8 @@ bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content,
voice_channel_->ActivateRtcpMux();
}
- voice_channel_->SignalDtlsSetupFailure.connect(
- this, &WebRtcSession::OnDtlsSetupFailure);
+ voice_channel_->SignalDtlsSrtpSetupFailure.connect(
+ this, &WebRtcSession::OnDtlsSrtpSetupFailure);
SignalVoiceChannelCreated();
voice_channel_->SignalSentPacket.connect(this,
@@ -1688,8 +1814,8 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
if (require_rtcp_mux) {
video_channel_->ActivateRtcpMux();
}
- video_channel_->SignalDtlsSetupFailure.connect(
- this, &WebRtcSession::OnDtlsSetupFailure);
+ video_channel_->SignalDtlsSrtpSetupFailure.connect(
+ this, &WebRtcSession::OnDtlsSrtpSetupFailure);
SignalVideoChannelCreated();
video_channel_->SignalSentPacket.connect(this,
@@ -1699,40 +1825,48 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content,
const std::string* bundle_transport) {
+ const std::string transport_name =
+ bundle_transport ? *bundle_transport : content->name;
#ifdef HAVE_QUIC
if (data_channel_type_ == cricket::DCT_QUIC) {
RTC_DCHECK(transport_controller_->quic());
- const std::string transport_name =
- bundle_transport ? *bundle_transport : content->name;
quic_data_transport_->SetTransport(transport_name);
return true;
}
#endif // HAVE_QUIC
bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
- bool require_rtcp_mux =
- rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
- bool create_rtcp_transport_channel = !sctp && !require_rtcp_mux;
- data_channel_.reset(channel_manager_->CreateDataChannel(
- media_controller_, transport_controller_.get(), content->name,
- bundle_transport, create_rtcp_transport_channel, SrtpRequired(),
- data_channel_type_));
- if (!data_channel_) {
- return false;
- }
- if (require_rtcp_mux) {
- data_channel_->ActivateRtcpMux();
- }
-
if (sctp) {
- data_channel_->SignalDataReceived.connect(
- this, &WebRtcSession::OnDataChannelMessageReceived);
+ if (!sctp_factory_) {
+ 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(&WebRtcSession::CreateSctpTransport_n,
+ this, content->name, transport_name))) {
+ return false;
+ };
+ } else {
+ bool require_rtcp_mux =
+ rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
+ bool create_rtcp_transport_channel = !sctp && !require_rtcp_mux;
+ rtp_data_channel_.reset(channel_manager_->CreateRtpDataChannel(
+ media_controller_, transport_controller_.get(), content->name,
+ bundle_transport, create_rtcp_transport_channel, SrtpRequired()));
+ if (!rtp_data_channel_) {
+ return false;
+ }
+ if (require_rtcp_mux) {
+ rtp_data_channel_->ActivateRtcpMux();
+ }
+ rtp_data_channel_->SignalDtlsSrtpSetupFailure.connect(
+ this, &WebRtcSession::OnDtlsSrtpSetupFailure);
+ rtp_data_channel_->SignalSentPacket.connect(this,
+ &WebRtcSession::OnSentPacket_w);
}
- data_channel_->SignalDtlsSetupFailure.connect(
- this, &WebRtcSession::OnDtlsSetupFailure);
-
SignalDataChannelCreated();
- data_channel_->SignalSentPacket.connect(this, &WebRtcSession::OnSentPacket_w);
return true;
}
@@ -1758,16 +1892,79 @@ std::unique_ptr<SessionStats> WebRtcSession::GetStats_n(
return session_stats;
}
-void WebRtcSession::OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp) {
- SetError(ERROR_TRANSPORT,
- rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);
+bool WebRtcSession::CreateSctpTransport_n(const std::string& content_name,
+ const std::string& transport_name) {
+ RTC_DCHECK(network_thread_->IsCurrent());
+ RTC_DCHECK(sctp_factory_);
+ cricket::TransportChannel* tc =
+ transport_controller_->CreateTransportChannel_n(
+ transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+ sctp_transport_ = sctp_factory_->CreateSctpTransport(tc);
+ RTC_DCHECK(sctp_transport_);
+ sctp_invoker_.reset(new rtc::AsyncInvoker());
+ sctp_transport_->SignalReadyToSendData.connect(
+ this, &WebRtcSession::OnSctpTransportReadyToSendData_n);
+ sctp_transport_->SignalDataReceived.connect(
+ this, &WebRtcSession::OnSctpTransportDataReceived_n);
+ sctp_transport_->SignalStreamClosedRemotely.connect(
+ this, &WebRtcSession::OnSctpStreamClosedRemotely_n);
+ sctp_transport_name_ = rtc::Optional<std::string>(transport_name);
+ sctp_content_name_ = rtc::Optional<std::string>(content_name);
+ return true;
+}
+
+void WebRtcSession::ChangeSctpTransport_n(const std::string& transport_name) {
+ RTC_DCHECK(network_thread_->IsCurrent());
+ RTC_DCHECK(sctp_transport_);
+ RTC_DCHECK(sctp_transport_name_);
+ std::string old_sctp_transport_name = *sctp_transport_name_;
+ sctp_transport_name_ = rtc::Optional<std::string>(transport_name);
+ cricket::TransportChannel* tc =
+ transport_controller_->CreateTransportChannel_n(
+ transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+ sctp_transport_->SetTransportChannel(tc);
+ transport_controller_->DestroyTransportChannel_n(
+ old_sctp_transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+}
+
+void WebRtcSession::DestroySctpTransport_n() {
+ RTC_DCHECK(network_thread_->IsCurrent());
+ sctp_transport_.reset(nullptr);
+ sctp_content_name_.reset();
+ sctp_transport_name_.reset();
+ sctp_invoker_.reset(nullptr);
+ sctp_ready_to_send_data_ = false;
+}
+
+void WebRtcSession::OnSctpTransportReadyToSendData_n() {
+ RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
+ RTC_DCHECK(network_thread_->IsCurrent());
+ sctp_invoker_->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread_,
+ rtc::Bind(&WebRtcSession::OnSctpTransportReadyToSendData_s, this, true));
}
-void WebRtcSession::OnDataChannelMessageReceived(
- cricket::DataChannel* channel,
+void WebRtcSession::OnSctpTransportReadyToSendData_s(bool ready) {
+ RTC_DCHECK(signaling_thread_->IsCurrent());
+ sctp_ready_to_send_data_ = ready;
+ SignalSctpReadyToSendData(ready);
+}
+
+void WebRtcSession::OnSctpTransportDataReceived_n(
const cricket::ReceiveDataParams& params,
const rtc::CopyOnWriteBuffer& payload) {
RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
+ RTC_DCHECK(network_thread_->IsCurrent());
+ sctp_invoker_->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread_,
+ rtc::Bind(&WebRtcSession::OnSctpTransportDataReceived_s, this, params,
+ payload));
+}
+
+void WebRtcSession::OnSctpTransportDataReceived_s(
+ const cricket::ReceiveDataParams& params,
+ const rtc::CopyOnWriteBuffer& payload) {
+ RTC_DCHECK(signaling_thread_->IsCurrent());
if (params.type == cricket::DMT_CONTROL && IsOpenMessage(payload)) {
// Received OPEN message; parse and signal that a new data channel should
// be created.
@@ -1781,8 +1978,19 @@ void WebRtcSession::OnDataChannelMessageReceived(
}
config.open_handshake_role = InternalDataChannelInit::kAcker;
SignalDataChannelOpenMessage(label, config);
+ } else {
+ // Otherwise just forward the signal.
+ SignalSctpDataReceived(params, payload);
}
- // Otherwise ignore the message.
+}
+
+void WebRtcSession::OnSctpStreamClosedRemotely_n(int sid) {
+ RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
+ RTC_DCHECK(network_thread_->IsCurrent());
+ sctp_invoker_->AsyncInvoke<void>(
+ RTC_FROM_HERE, signaling_thread_,
+ rtc::Bind(&sigslot::signal1<int>::operator(),
+ &SignalSctpStreamClosedRemotely, sid));
}
// Returns false if bundle is enabled and rtcp_mux is disabled.
@@ -1976,8 +2184,11 @@ void WebRtcSession::ReportTransportStats() {
if (video_channel()) {
transport_names.insert(video_channel()->transport_name());
}
- if (data_channel()) {
- transport_names.insert(data_channel()->transport_name());
+ if (rtp_data_channel()) {
+ transport_names.insert(rtp_data_channel()->transport_name());
+ }
+ if (sctp_transport_name_) {
+ transport_names.insert(*sctp_transport_name_);
}
for (const auto& name : transport_names) {
cricket::TransportStats stats;
@@ -2094,17 +2305,17 @@ const std::string WebRtcSession::GetTransportName(
return quic_data_transport_->transport_name();
}
#endif
+ if (sctp_transport_) {
+ RTC_DCHECK(sctp_content_name_);
+ RTC_DCHECK(sctp_transport_name_);
+ if (content_name == *sctp_content_name_) {
+ return *sctp_transport_name_;
+ }
+ }
// Return an empty string if failed to retrieve the transport name.
return "";
}
return channel->transport_name();
}
-void WebRtcSession::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
- if (metrics_observer_) {
- metrics_observer_->IncrementEnumCounter(
- webrtc::kEnumCounterDtlsHandshakeError, static_cast<int>(error),
- static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
- }
-}
} // namespace webrtc
« no previous file with comments | « webrtc/api/webrtcsession.h ('k') | webrtc/api/webrtcsession_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698