diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h index 75c4d3c530..e815f19518 100644 --- a/api/peer_connection_interface.h +++ b/api/peer_connection_interface.h @@ -920,9 +920,24 @@ class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface { // Also, calling CreateDataChannel is the only way to get a data "m=" section // in SDP, so it should be done before CreateOffer is called, if the // application plans to use data channels. + virtual RTCErrorOr> + CreateDataChannelOrError(const std::string& label, + const DataChannelInit* config) { + return RTCError(RTCErrorType::INTERNAL_ERROR, "dummy function called"); + } + // TODO(crbug.com/788659): Remove "virtual" below and default implementation + // above once mock in Chrome is fixed. + ABSL_DEPRECATED("Use CreateDataChannelOrError") virtual rtc::scoped_refptr CreateDataChannel( const std::string& label, - const DataChannelInit* config) = 0; + const DataChannelInit* config) { + auto result = CreateDataChannelOrError(label, config); + if (!result.ok()) { + return nullptr; + } else { + return result.MoveValue(); + } + } // NOTE: For the following 6 methods, it's only safe to dereference the // SessionDescriptionInterface on signaling_thread() (for example, calling diff --git a/api/peer_connection_proxy.h b/api/peer_connection_proxy.h index cc9df10eed..de7664f4bf 100644 --- a/api/peer_connection_proxy.h +++ b/api/peer_connection_proxy.h @@ -76,8 +76,8 @@ PROXY_METHOD2(void, rtc::scoped_refptr, rtc::scoped_refptr) PROXY_METHOD0(void, ClearStatsCache) -PROXY_METHOD2(rtc::scoped_refptr, - CreateDataChannel, +PROXY_METHOD2(RTCErrorOr>, + CreateDataChannelOrError, const std::string&, const DataChannelInit*) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description) diff --git a/api/test/dummy_peer_connection.h b/api/test/dummy_peer_connection.h index 4d17aeddd0..80ae20c3c7 100644 --- a/api/test/dummy_peer_connection.h +++ b/api/test/dummy_peer_connection.h @@ -114,10 +114,10 @@ class DummyPeerConnection : public PeerConnectionInterface { } void ClearStatsCache() override {} - rtc::scoped_refptr CreateDataChannel( + RTCErrorOr> CreateDataChannelOrError( const std::string& label, const DataChannelInit* config) override { - return nullptr; + return RTCError(RTCErrorType::INTERNAL_ERROR, "Dummy function called"); } const SessionDescriptionInterface* local_description() const override { diff --git a/api/test/mock_peerconnectioninterface.h b/api/test/mock_peerconnectioninterface.h index be34df0b32..b5d94238c8 100644 --- a/api/test/mock_peerconnectioninterface.h +++ b/api/test/mock_peerconnectioninterface.h @@ -100,8 +100,8 @@ class MockPeerConnectionInterface GetSctpTransport, (), (const override)); - MOCK_METHOD(rtc::scoped_refptr, - CreateDataChannel, + MOCK_METHOD(RTCErrorOr>, + CreateDataChannelOrError, (const std::string&, const DataChannelInit*), (override)); MOCK_METHOD(const SessionDescriptionInterface*, diff --git a/examples/unityplugin/simple_peer_connection.cc b/examples/unityplugin/simple_peer_connection.cc index 128ca76881..c7e5185bdc 100644 --- a/examples/unityplugin/simple_peer_connection.cc +++ b/examples/unityplugin/simple_peer_connection.cc @@ -497,8 +497,9 @@ bool SimplePeerConnection::CreateDataChannel() { struct webrtc::DataChannelInit init; init.ordered = true; init.reliable = true; - data_channel_ = peer_connection_->CreateDataChannel("Hello", &init); - if (data_channel_.get()) { + auto result = peer_connection_->CreateDataChannelOrError("Hello", &init); + if (result.ok()) { + data_channel_ = result.MoveValue(); data_channel_->RegisterObserver(this); RTC_LOG(LS_INFO) << "Succeeds to create data channel"; return true; diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index e2b3b61058..0939f59812 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -1279,9 +1279,9 @@ absl::optional PeerConnection::can_trickle_ice_candidates() { "trickle"); } -rtc::scoped_refptr PeerConnection::CreateDataChannel( - const std::string& label, - const DataChannelInit* config) { +RTCErrorOr> +PeerConnection::CreateDataChannelOrError(const std::string& label, + const DataChannelInit* config) { RTC_DCHECK_RUN_ON(signaling_thread()); TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel"); @@ -1291,11 +1291,13 @@ rtc::scoped_refptr PeerConnection::CreateDataChannel( if (config) { internal_config.reset(new InternalDataChannelInit(*config)); } + // TODO(bugs.webrtc.org/12796): Return a more specific error. rtc::scoped_refptr channel( data_channel_controller_.InternalCreateDataChannelWithProxy( label, internal_config.get())); if (!channel.get()) { - return nullptr; + return RTCError(RTCErrorType::INTERNAL_ERROR, + "Data channel creation failed"); } // Trigger the onRenegotiationNeeded event for diff --git a/pc/peer_connection.h b/pc/peer_connection.h index 7be137a6a8..4476c5d8e1 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -167,7 +167,7 @@ class PeerConnection : public PeerConnectionInternal, std::vector> GetTransceivers() const override; - rtc::scoped_refptr CreateDataChannel( + RTCErrorOr> CreateDataChannelOrError( const std::string& label, const DataChannelInit* config) override; // WARNING: LEGACY. See peerconnectioninterface.h diff --git a/pc/peer_connection_wrapper.cc b/pc/peer_connection_wrapper.cc index 6aed8f1de7..3b4d28f0d9 100644 --- a/pc/peer_connection_wrapper.cc +++ b/pc/peer_connection_wrapper.cc @@ -306,7 +306,14 @@ rtc::scoped_refptr PeerConnectionWrapper::AddVideoTrack( rtc::scoped_refptr PeerConnectionWrapper::CreateDataChannel(const std::string& label) { - return pc()->CreateDataChannel(label, nullptr); + auto result = pc()->CreateDataChannelOrError(label, nullptr); + if (!result.ok()) { + RTC_LOG(LS_ERROR) << "CreateDataChannel failed: " + << ToString(result.error().type()) << " " + << result.error().message(); + return nullptr; + } + return result.MoveValue(); } PeerConnectionInterface::SignalingState diff --git a/pc/test/fake_peer_connection_base.h b/pc/test/fake_peer_connection_base.h index 1acf86fdac..7970dd0f0f 100644 --- a/pc/test/fake_peer_connection_base.h +++ b/pc/test/fake_peer_connection_base.h @@ -120,10 +120,11 @@ class FakePeerConnectionBase : public PeerConnectionInternal { return nullptr; } - rtc::scoped_refptr CreateDataChannel( + RTCErrorOr> CreateDataChannelOrError( const std::string& label, const DataChannelInit* config) override { - return nullptr; + return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, + "Fake function called"); } const SessionDescriptionInterface* local_description() const override { diff --git a/pc/test/peer_connection_test_wrapper.cc b/pc/test/peer_connection_test_wrapper.cc index 56e81ec0b3..8fdfb1bbb8 100644 --- a/pc/test/peer_connection_test_wrapper.cc +++ b/pc/test/peer_connection_test_wrapper.cc @@ -140,7 +140,14 @@ rtc::scoped_refptr PeerConnectionTestWrapper::CreateDataChannel( const std::string& label, const webrtc::DataChannelInit& init) { - return peer_connection_->CreateDataChannel(label, &init); + auto result = peer_connection_->CreateDataChannelOrError(label, &init); + if (!result.ok()) { + RTC_LOG(LS_ERROR) << "CreateDataChannel failed: " + << ToString(result.error().type()) << " " + << result.error().message(); + return nullptr; + } + return result.MoveValue(); } void PeerConnectionTestWrapper::WaitForNegotiation() { diff --git a/sdk/android/src/jni/pc/peer_connection.cc b/sdk/android/src/jni/pc/peer_connection.cc index 93c6eb3895..cee7a58a15 100644 --- a/sdk/android/src/jni/pc/peer_connection.cc +++ b/sdk/android/src/jni/pc/peer_connection.cc @@ -538,10 +538,12 @@ static ScopedJavaLocalRef JNI_PeerConnection_CreateDataChannel( const JavaParamRef& j_label, const JavaParamRef& j_init) { DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init); - rtc::scoped_refptr channel( - ExtractNativePC(jni, j_pc)->CreateDataChannel( - JavaToNativeString(jni, j_label), &init)); - return WrapNativeDataChannel(jni, channel); + auto result = ExtractNativePC(jni, j_pc)->CreateDataChannelOrError( + JavaToNativeString(jni, j_label), &init); + if (!result.ok()) { + return WrapNativeDataChannel(jni, nullptr); + } + return WrapNativeDataChannel(jni, result.MoveValue()); } static void JNI_PeerConnection_CreateOffer( diff --git a/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm b/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm index 1ded45d670..cb75f061d8 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm +++ b/sdk/objc/api/peerconnection/RTCPeerConnection+DataChannel.mm @@ -23,14 +23,12 @@ std::string labelString = [NSString stdStringForString:label]; const webrtc::DataChannelInit nativeInit = configuration.nativeDataChannelInit; - rtc::scoped_refptr dataChannel = - self.nativePeerConnection->CreateDataChannel(labelString, - &nativeInit); - if (!dataChannel) { + auto result = self.nativePeerConnection->CreateDataChannelOrError(labelString, &nativeInit); + if (!result.ok()) { return nil; } return [[RTC_OBJC_TYPE(RTCDataChannel) alloc] initWithFactory:self.factory - nativeDataChannel:dataChannel]; + nativeDataChannel:result.MoveValue()]; } @end