Stop an SCTP connection when the DTLS transport closes.
This CL propagates a "closed" signal from DTLS up to the SCTP section of the data channel controller, where it causes closing of all open datachannels. Bug: chromium:1030631, webrtc:10360 Change-Id: I88bb9e1aff5c25f330edfd092ef609d4fcc3a9f8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/162206 Reviewed-by: Steve Anton <steveanton@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30099}
This commit is contained in:
committed by
Commit Bot
parent
8525a8028a
commit
2697ac1a1b
@ -84,6 +84,11 @@ class DataChannelSink {
|
|||||||
// invoked again following send errors (eg. due to the transport being
|
// invoked again following send errors (eg. due to the transport being
|
||||||
// temporarily blocked or unavailable).
|
// temporarily blocked or unavailable).
|
||||||
virtual void OnReadyToSend() = 0;
|
virtual void OnReadyToSend() = 0;
|
||||||
|
|
||||||
|
// Callback issued when the data channel becomes unusable (closed).
|
||||||
|
// TODO(https://crbug.com/webrtc/10360): Make pure virtual when all
|
||||||
|
// consumers updated.
|
||||||
|
virtual void OnTransportClosed() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Transport for data channels.
|
// Transport for data channels.
|
||||||
|
|||||||
@ -662,6 +662,7 @@ void SctpTransport::ConnectTransportSignals() {
|
|||||||
transport_->SignalWritableState.connect(this,
|
transport_->SignalWritableState.connect(this,
|
||||||
&SctpTransport::OnWritableState);
|
&SctpTransport::OnWritableState);
|
||||||
transport_->SignalReadPacket.connect(this, &SctpTransport::OnPacketRead);
|
transport_->SignalReadPacket.connect(this, &SctpTransport::OnPacketRead);
|
||||||
|
transport_->SignalClosed.connect(this, &SctpTransport::OnClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SctpTransport::DisconnectTransportSignals() {
|
void SctpTransport::DisconnectTransportSignals() {
|
||||||
@ -671,6 +672,7 @@ void SctpTransport::DisconnectTransportSignals() {
|
|||||||
}
|
}
|
||||||
transport_->SignalWritableState.disconnect(this);
|
transport_->SignalWritableState.disconnect(this);
|
||||||
transport_->SignalReadPacket.disconnect(this);
|
transport_->SignalReadPacket.disconnect(this);
|
||||||
|
transport_->SignalClosed.disconnect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SctpTransport::Connect() {
|
bool SctpTransport::Connect() {
|
||||||
@ -990,6 +992,10 @@ void SctpTransport::OnPacketRead(rtc::PacketTransportInternal* transport,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SctpTransport::OnClosed(rtc::PacketTransportInternal* transport) {
|
||||||
|
SignalClosedAbruptly();
|
||||||
|
}
|
||||||
|
|
||||||
void SctpTransport::OnSendThresholdCallback() {
|
void SctpTransport::OnSendThresholdCallback() {
|
||||||
RTC_DCHECK_RUN_ON(network_thread_);
|
RTC_DCHECK_RUN_ON(network_thread_);
|
||||||
if (partial_outgoing_message_.has_value()) {
|
if (partial_outgoing_message_.has_value()) {
|
||||||
|
|||||||
@ -164,6 +164,7 @@ class SctpTransport : public SctpTransportInternal,
|
|||||||
size_t len,
|
size_t len,
|
||||||
const int64_t& packet_time_us,
|
const int64_t& packet_time_us,
|
||||||
int flags);
|
int flags);
|
||||||
|
void OnClosed(rtc::PacketTransportInternal* transport);
|
||||||
|
|
||||||
// Methods related to usrsctp callbacks.
|
// Methods related to usrsctp callbacks.
|
||||||
void OnSendThresholdCallback();
|
void OnSendThresholdCallback();
|
||||||
|
|||||||
@ -134,6 +134,9 @@ class SctpTransportInternal {
|
|||||||
// Parameter is SID; fired when closing procedure is complete (both incoming
|
// Parameter is SID; fired when closing procedure is complete (both incoming
|
||||||
// and outgoing streams reset).
|
// and outgoing streams reset).
|
||||||
sigslot::signal1<int> SignalClosingProcedureComplete;
|
sigslot::signal1<int> SignalClosingProcedureComplete;
|
||||||
|
// Fired when the underlying DTLS transport has closed due to an error
|
||||||
|
// or an incoming DTLS disconnect.
|
||||||
|
sigslot::signal0<> SignalClosedAbruptly;
|
||||||
|
|
||||||
// Helper for debugging.
|
// Helper for debugging.
|
||||||
virtual void set_debug_name_for_testing(const char* debug_name) = 0;
|
virtual void set_debug_name_for_testing(const char* debug_name) = 0;
|
||||||
|
|||||||
@ -656,6 +656,7 @@ void DtlsTransport::OnDtlsEvent(rtc::StreamInterface* dtls, int sig, int err) {
|
|||||||
RTC_LOG(LS_INFO) << ToString() << ": DTLS transport closed by remote";
|
RTC_LOG(LS_INFO) << ToString() << ": DTLS transport closed by remote";
|
||||||
set_writable(false);
|
set_writable(false);
|
||||||
set_dtls_state(DTLS_TRANSPORT_CLOSED);
|
set_dtls_state(DTLS_TRANSPORT_CLOSED);
|
||||||
|
SignalClosed(this);
|
||||||
} else if (ret == rtc::SR_ERROR) {
|
} else if (ret == rtc::SR_ERROR) {
|
||||||
// Remote peer shut down the association with an error.
|
// Remote peer shut down the association with an error.
|
||||||
RTC_LOG(LS_INFO)
|
RTC_LOG(LS_INFO)
|
||||||
@ -664,6 +665,7 @@ void DtlsTransport::OnDtlsEvent(rtc::StreamInterface* dtls, int sig, int err) {
|
|||||||
<< read_error;
|
<< read_error;
|
||||||
set_writable(false);
|
set_writable(false);
|
||||||
set_dtls_state(DTLS_TRANSPORT_FAILED);
|
set_dtls_state(DTLS_TRANSPORT_FAILED);
|
||||||
|
SignalClosed(this);
|
||||||
}
|
}
|
||||||
} while (ret == rtc::SR_SUCCESS);
|
} while (ret == rtc::SR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,6 +95,9 @@ class RTC_EXPORT PacketTransportInternal : public sigslot::has_slots<> {
|
|||||||
// Signalled when the current network route has changed.
|
// Signalled when the current network route has changed.
|
||||||
sigslot::signal1<absl::optional<rtc::NetworkRoute>> SignalNetworkRouteChanged;
|
sigslot::signal1<absl::optional<rtc::NetworkRoute>> SignalNetworkRouteChanged;
|
||||||
|
|
||||||
|
// Signalled when the transport is closed.
|
||||||
|
sigslot::signal1<PacketTransportInternal*> SignalClosed;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PacketTransportInternal();
|
PacketTransportInternal();
|
||||||
~PacketTransportInternal() override;
|
~PacketTransportInternal() override;
|
||||||
|
|||||||
@ -181,6 +181,15 @@ void DataChannelController::OnReadyToSend() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataChannelController::OnTransportClosed() {
|
||||||
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
|
data_channel_transport_invoker_->AsyncInvoke<void>(
|
||||||
|
RTC_FROM_HERE, signaling_thread(), [this] {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
OnTransportChannelClosed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void DataChannelController::SetupDataChannelTransport_n() {
|
void DataChannelController::SetupDataChannelTransport_n() {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
data_channel_transport_invoker_ = std::make_unique<rtc::AsyncInvoker>();
|
data_channel_transport_invoker_ = std::make_unique<rtc::AsyncInvoker>();
|
||||||
|
|||||||
@ -46,6 +46,7 @@ class DataChannelController : public DataChannelProviderInterface,
|
|||||||
void OnChannelClosing(int channel_id) override;
|
void OnChannelClosing(int channel_id) override;
|
||||||
void OnChannelClosed(int channel_id) override;
|
void OnChannelClosed(int channel_id) override;
|
||||||
void OnReadyToSend() override;
|
void OnReadyToSend() override;
|
||||||
|
void OnTransportClosed() override;
|
||||||
|
|
||||||
// Called from PeerConnection::SetupDataChannelTransport_n
|
// Called from PeerConnection::SetupDataChannelTransport_n
|
||||||
void SetupDataChannelTransport_n();
|
void SetupDataChannelTransport_n();
|
||||||
|
|||||||
@ -5989,6 +5989,44 @@ TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
|
|||||||
ASSERT_TRUE(caller()->data_observer()->IsOpen());
|
ASSERT_TRUE(caller()->data_observer()->IsOpen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PeerConnectionIntegrationTestUnifiedPlan, DataChannelClosesWhenClosed) {
|
||||||
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||||
|
ConnectFakeSignaling();
|
||||||
|
caller()->CreateDataChannel();
|
||||||
|
caller()->CreateAndSetAndSignalOffer();
|
||||||
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||||
|
ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
|
||||||
|
ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
|
||||||
|
caller()->data_channel()->Close();
|
||||||
|
ASSERT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
|
||||||
|
DataChannelClosesWhenClosedReverse) {
|
||||||
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||||
|
ConnectFakeSignaling();
|
||||||
|
caller()->CreateDataChannel();
|
||||||
|
caller()->CreateAndSetAndSignalOffer();
|
||||||
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||||
|
ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
|
||||||
|
ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
|
||||||
|
callee()->data_channel()->Close();
|
||||||
|
ASSERT_TRUE_WAIT(!caller()->data_observer()->IsOpen(), kDefaultTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
|
||||||
|
DataChannelClosesWhenPeerConnectionClosed) {
|
||||||
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||||
|
ConnectFakeSignaling();
|
||||||
|
caller()->CreateDataChannel();
|
||||||
|
caller()->CreateAndSetAndSignalOffer();
|
||||||
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||||
|
ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
|
||||||
|
ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
|
||||||
|
caller()->pc()->Close();
|
||||||
|
ASSERT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_SCTP
|
#endif // HAVE_SCTP
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -24,6 +24,8 @@ SctpDataChannelTransport::SctpDataChannelTransport(
|
|||||||
this, &SctpDataChannelTransport::OnClosingProcedureStartedRemotely);
|
this, &SctpDataChannelTransport::OnClosingProcedureStartedRemotely);
|
||||||
sctp_transport_->SignalClosingProcedureComplete.connect(
|
sctp_transport_->SignalClosingProcedureComplete.connect(
|
||||||
this, &SctpDataChannelTransport::OnClosingProcedureComplete);
|
this, &SctpDataChannelTransport::OnClosingProcedureComplete);
|
||||||
|
sctp_transport_->SignalClosedAbruptly.connect(
|
||||||
|
this, &SctpDataChannelTransport::OnClosedAbruptly);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTCError SctpDataChannelTransport::OpenChannel(int channel_id) {
|
RTCError SctpDataChannelTransport::OpenChannel(int channel_id) {
|
||||||
@ -109,4 +111,10 @@ void SctpDataChannelTransport::OnClosingProcedureComplete(int channel_id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SctpDataChannelTransport::OnClosedAbruptly() {
|
||||||
|
if (sink_) {
|
||||||
|
sink_->OnTransportClosed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -38,6 +38,7 @@ class SctpDataChannelTransport : public DataChannelTransportInterface,
|
|||||||
const rtc::CopyOnWriteBuffer& buffer);
|
const rtc::CopyOnWriteBuffer& buffer);
|
||||||
void OnClosingProcedureStartedRemotely(int channel_id);
|
void OnClosingProcedureStartedRemotely(int channel_id);
|
||||||
void OnClosingProcedureComplete(int channel_id);
|
void OnClosingProcedureComplete(int channel_id);
|
||||||
|
void OnClosedAbruptly();
|
||||||
|
|
||||||
cricket::SctpTransportInternal* const sctp_transport_;
|
cricket::SctpTransportInternal* const sctp_transport_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user