Compute RTCConnectionState and RTCIceConnectionState.

Compute these states in jseptransportController and store them. Eventually they should be passed on to the peer connection observer and exposed in the blink layer.

Bug: webrtc:9308
Change-Id: Ifdec39c24a607fcb8211c4acf6b9704eaff371b1
Reviewed-on: https://webrtc-review.googlesource.com/c/103506
Commit-Queue: Jonas Olsson <jonasolsson@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25288}
This commit is contained in:
Jonas Olsson 2018-10-18 15:58:17 +02:00 committed by Commit Bot
parent 800e121dca
commit 635474e3d5
12 changed files with 332 additions and 6 deletions

View File

@ -159,6 +159,11 @@ RTCError PeerConnectionInterface::SetBitrate(
return SetBitrate(bitrate);
}
PeerConnectionInterface::PeerConnectionState
PeerConnectionInterface::peer_connection_state() {
return PeerConnectionInterface::PeerConnectionState::kNew;
}
bool PeerConnectionInterface::StartRtcEventLog(rtc::PlatformFile file,
int64_t max_size_bytes) {
return false;

View File

@ -160,7 +160,7 @@ enum class SdpSemantics { kPlanB, kUnifiedPlan };
class PeerConnectionInterface : public rtc::RefCountInterface {
public:
// See https://w3c.github.io/webrtc-pc/#state-definitions
// See https://w3c.github.io/webrtc-pc/#dom-rtcsignalingstate
enum SignalingState {
kStable,
kHaveLocalOffer,
@ -170,12 +170,24 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
kClosed,
};
// See https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate
enum IceGatheringState {
kIceGatheringNew,
kIceGatheringGathering,
kIceGatheringComplete
};
// See https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnectionstate
enum class PeerConnectionState {
kNew,
kConnecting,
kConnected,
kDisconnected,
kFailed,
kClosed,
};
// See https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate
enum IceConnectionState {
kIceConnectionNew,
kIceConnectionChecking,
@ -978,11 +990,13 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
virtual SignalingState signaling_state() = 0;
// Returns the aggregate state of all ICE *and* DTLS transports.
// TODO(deadbeef): Implement "PeerConnectionState" according to the standard,
// to aggregate ICE+DTLS state, and change the scope of IceConnectionState to
// be just the ICE layer. See: crbug.com/webrtc/6145
// TODO(jonasolsson): Replace with standardized_ice_connection_state once it
// is ready, see crbug.com/webrtc/6145
virtual IceConnectionState ice_connection_state() = 0;
// Returns the aggregated state of all ICE and DTLS transports.
virtual PeerConnectionState peer_connection_state();
virtual IceGatheringState ice_gathering_state() = 0;
// Starts RtcEventLog using existing file. Takes ownership of |file| and
@ -1051,6 +1065,10 @@ class PeerConnectionObserver {
virtual void OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) = 0;
// Called any time the PeerConnectionState changes.
virtual void OnConnectionChange(
PeerConnectionInterface::PeerConnectionState new_state) {}
// Called any time the IceGatheringState changes.
virtual void OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) = 0;

View File

@ -83,6 +83,7 @@ class FakeDtlsTransport : public DtlsTransportInternal {
ice_transport_->SetReceiving(receiving);
set_receiving(receiving);
}
void SetDtlsState(DtlsTransportState state) { dtls_state_ = state; }
// Simulates the two DTLS transports connecting to each other.
// If |asymmetric| is true this method only affects this FakeDtlsTransport.

View File

@ -115,6 +115,15 @@ class FakeIceTransport : public IceTransportInternal {
}
webrtc::IceTransportState GetIceTransportState() const override {
if (connection_count_ == 0) {
return had_connection_ ? webrtc::IceTransportState::kFailed
: webrtc::IceTransportState::kNew;
}
if (connection_count_ == 1) {
return webrtc::IceTransportState::kCompleted;
}
return webrtc::IceTransportState::kConnected;
}

View File

@ -301,6 +301,8 @@ void DtlsSrtpTransport::OnDtlsState(cricket::DtlsTransportInternal* transport,
RTC_DCHECK(transport == rtp_dtls_transport_ ||
transport == rtcp_dtls_transport_);
SignalDtlsStateChange();
if (state != cricket::DTLS_TRANSPORT_CONNECTED) {
ResetParams();
return;

View File

@ -42,7 +42,8 @@ class DtlsSrtpTransport : public SrtpTransport {
void UpdateRecvEncryptedHeaderExtensionIds(
const std::vector<int>& recv_extension_ids);
sigslot::signal2<DtlsSrtpTransport*, bool> SignalDtlsSrtpSetupFailure;
sigslot::signal<DtlsSrtpTransport*, bool> SignalDtlsSrtpSetupFailure;
sigslot::signal<> SignalDtlsStateChange;
RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION,

View File

@ -488,6 +488,8 @@ JsepTransportController::CreateDtlsSrtpTransport(
rtcp_dtls_transport);
dtls_srtp_transport->SetActiveResetSrtpParams(
config_.active_reset_srtp_params);
dtls_srtp_transport->SignalDtlsStateChange.connect(
this, &JsepTransportController::UpdateAggregateStates_n);
return dtls_srtp_transport;
}
@ -1158,12 +1160,20 @@ void JsepTransportController::UpdateAggregateStates_n() {
auto dtls_transports = GetDtlsTransports();
cricket::IceConnectionState new_connection_state =
cricket::kIceConnectionConnecting;
PeerConnectionInterface::IceConnectionState new_ice_connection_state =
PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
PeerConnectionInterface::PeerConnectionState new_combined_state =
PeerConnectionInterface::PeerConnectionState::kNew;
cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
bool any_failed = false;
bool all_connected = !dtls_transports.empty();
bool all_completed = !dtls_transports.empty();
bool any_gathering = false;
bool all_done_gathering = !dtls_transports.empty();
std::map<IceTransportState, int> ice_state_counts;
std::map<cricket::DtlsTransportState, int> dtls_state_counts;
for (const auto& dtls : dtls_transports) {
any_failed = any_failed || dtls->ice_transport()->GetState() ==
cricket::IceTransportState::STATE_FAILED;
@ -1180,6 +1190,9 @@ void JsepTransportController::UpdateAggregateStates_n() {
all_done_gathering =
all_done_gathering && dtls->ice_transport()->gathering_state() ==
cricket::kIceGatheringComplete;
dtls_state_counts[dtls->dtls_state()]++;
ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
}
if (any_failed) {
new_connection_state = cricket::kIceConnectionFailed;
@ -1196,6 +1209,127 @@ void JsepTransportController::UpdateAggregateStates_n() {
});
}
// Compute the current RTCIceConnectionState as described in
// https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
// The PeerConnection is responsible for handling the "closed" state.
int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
int total_ice_disconnected =
ice_state_counts[IceTransportState::kDisconnected];
int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
int total_ice_new = ice_state_counts[IceTransportState::kNew];
int total_ice = dtls_transports.size();
if (total_ice_failed > 0) {
// Any of the RTCIceTransports are in the "failed" state.
new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
} else if (total_ice_disconnected > 0) {
// Any of the RTCIceTransports are in the "disconnected" state and none of
// them are in the "failed" state.
new_ice_connection_state =
PeerConnectionInterface::kIceConnectionDisconnected;
} else if (total_ice_checking > 0) {
// Any of the RTCIceTransports are in the "checking" state and none of them
// are in the "disconnected" or "failed" state.
new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
} else if (total_ice_completed + total_ice_closed == total_ice &&
total_ice_completed > 0) {
// All RTCIceTransports are in the "completed" or "closed" state and at
// least one of them is in the "completed" state.
new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
} else if (total_ice_connected + total_ice_completed + total_ice_closed ==
total_ice &&
total_ice_connected > 0) {
// All RTCIceTransports are in the "connected", "completed" or "closed"
// state and at least one of them is in the "connected" state.
new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
} else if ((total_ice_new > 0 &&
total_ice_checking + total_ice_disconnected + total_ice_failed ==
0) ||
total_ice == total_ice_closed) {
// Any of the RTCIceTransports are in the "new" state and none of them are
// in the "checking", "disconnected" or "failed" state, or all
// RTCIceTransports are in the "closed" state, or there are no transports.
new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
} else {
RTC_NOTREACHED();
}
if (standardized_ice_connection_state_ != new_ice_connection_state) {
standardized_ice_connection_state_ = new_ice_connection_state;
invoker_.AsyncInvoke<void>(
RTC_FROM_HERE, signaling_thread_, [this, new_ice_connection_state] {
SignalStandardizedIceConnectionState(new_ice_connection_state);
});
}
// Compute the current RTCPeerConnectionState as described in
// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
// The PeerConnection is responsible for handling the "closed" state.
// Note that "connecting" is only a valid state for DTLS transports while
// "checking", "completed" and "disconnected" are only valid for ICE
// transports.
int total_connected = total_ice_connected +
dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTED];
int total_dtls_connecting =
dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTING];
int total_failed =
total_ice_failed + dtls_state_counts[cricket::DTLS_TRANSPORT_FAILED];
int total_closed =
total_ice_closed + dtls_state_counts[cricket::DTLS_TRANSPORT_CLOSED];
int total_new =
total_ice_new + dtls_state_counts[cricket::DTLS_TRANSPORT_NEW];
int total_transports = total_ice * 2;
if (total_failed > 0) {
// Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
} else if (total_ice_disconnected > 0 &&
total_dtls_connecting + total_ice_checking == 0) {
// Any of the RTCIceTransports or RTCDtlsTransports are in the
// "disconnected" state and none of them are in the "failed" or "connecting"
// or "checking" state.
new_combined_state =
PeerConnectionInterface::PeerConnectionState::kDisconnected;
} else if (total_dtls_connecting + total_ice_checking > 0) {
// Any of the RTCIceTransports or RTCDtlsTransports are in the "connecting"
// or "checking" state and none of them is in the "failed" state.
new_combined_state =
PeerConnectionInterface::PeerConnectionState::kConnecting;
} else if (total_connected + total_ice_completed + total_closed ==
total_transports &&
total_connected + total_ice_completed > 0) {
// All RTCIceTransports and RTCDtlsTransports are in the "connected",
// "completed" or "closed" state and at least one of them is in the
// "connected" or "completed" state.
new_combined_state =
PeerConnectionInterface::PeerConnectionState::kConnected;
} else if ((total_new > 0 && total_dtls_connecting + total_ice_checking +
total_failed + total_ice_disconnected ==
0) ||
total_transports == total_closed) {
// Any of the RTCIceTransports or RTCDtlsTransports are in the "new" state
// and none of the transports are in the "connecting", "checking", "failed"
// or "disconnected" state, or all transports are in the "closed" state, or
// there are no transports.
//
// Note that if none of the other conditions hold this is guaranteed to be
// true.
new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
} else {
RTC_NOTREACHED();
}
if (combined_connection_state_ != new_combined_state) {
combined_connection_state_ = new_combined_state;
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
[this, new_combined_state] {
SignalConnectionState(new_combined_state);
});
}
if (all_done_gathering) {
new_gathering_state = cricket::kIceGatheringComplete;
} else if (any_gathering) {

View File

@ -181,6 +181,11 @@ class JsepTransportController : public sigslot::has_slots<> {
// Else => connecting
sigslot::signal1<cricket::IceConnectionState> SignalIceConnectionState;
sigslot::signal1<PeerConnectionInterface::PeerConnectionState>
SignalConnectionState;
sigslot::signal1<PeerConnectionInterface::IceConnectionState>
SignalStandardizedIceConnectionState;
// If all transports done gathering => complete,
// Else if any are gathering => gathering,
// Else => new
@ -322,9 +327,16 @@ class JsepTransportController : public sigslot::has_slots<> {
// (BaseChannel/SctpTransport) and the JsepTransport underneath.
std::map<std::string, cricket::JsepTransport*> mid_to_transport_;
// Aggregate state for Transports.
// Aggregate states for Transports.
// standardized_ice_connection_state_ is intended to replace
// ice_connection_state, see bugs.webrtc.org/9308
cricket::IceConnectionState ice_connection_state_ =
cricket::kIceConnectionConnecting;
PeerConnectionInterface::IceConnectionState
standardized_ice_connection_state_ =
PeerConnectionInterface::kIceConnectionNew;
PeerConnectionInterface::PeerConnectionState combined_connection_state_ =
PeerConnectionInterface::PeerConnectionState::kNew;
cricket::IceGatheringState ice_gathering_state_ = cricket::kIceGatheringNew;
Config config_;

View File

@ -84,6 +84,10 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
void ConnectTransportControllerSignals() {
transport_controller_->SignalIceConnectionState.connect(
this, &JsepTransportControllerTest::OnConnectionState);
transport_controller_->SignalStandardizedIceConnectionState.connect(
this, &JsepTransportControllerTest::OnStandardizedIceConnectionState);
transport_controller_->SignalConnectionState.connect(
this, &JsepTransportControllerTest::OnCombinedConnectionState);
transport_controller_->SignalIceGatheringState.connect(
this, &JsepTransportControllerTest::OnGatheringState);
transport_controller_->SignalIceCandidatesGathered.connect(
@ -243,6 +247,24 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
++connection_state_signal_count_;
}
void OnStandardizedIceConnectionState(
PeerConnectionInterface::IceConnectionState state) {
if (!signaling_thread_->IsCurrent()) {
signaled_on_non_signaling_thread_ = true;
}
ice_connection_state_ = state;
++ice_connection_state_signal_count_;
}
void OnCombinedConnectionState(
PeerConnectionInterface::PeerConnectionState state) {
if (!signaling_thread_->IsCurrent()) {
signaled_on_non_signaling_thread_ = true;
}
combined_connection_state_ = state;
++combined_connection_state_signal_count_;
}
void OnGatheringState(cricket::IceGatheringState state) {
if (!signaling_thread_->IsCurrent()) {
signaled_on_non_signaling_thread_ = true;
@ -274,12 +296,18 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
// Information received from signals from transport controller.
cricket::IceConnectionState connection_state_ =
cricket::kIceConnectionConnecting;
PeerConnectionInterface::IceConnectionState ice_connection_state_ =
PeerConnectionInterface::kIceConnectionNew;
PeerConnectionInterface::PeerConnectionState combined_connection_state_ =
PeerConnectionInterface::PeerConnectionState::kNew;
bool receiving_ = false;
cricket::IceGatheringState gathering_state_ = cricket::kIceGatheringNew;
// transport_name => candidates
std::map<std::string, Candidates> candidates_;
// Counts of each signal emitted.
int connection_state_signal_count_ = 0;
int ice_connection_state_signal_count_ = 0;
int combined_connection_state_signal_count_ = 0;
int receiving_signal_count_ = 0;
int gathering_state_signal_count_ = 0;
int candidates_signal_count_ = 0;
@ -617,6 +645,12 @@ TEST_F(JsepTransportControllerTest, SignalConnectionStateFailed) {
fake_ice->SetConnectionCount(0);
EXPECT_EQ_WAIT(cricket::kIceConnectionFailed, connection_state_, kTimeout);
EXPECT_EQ(1, connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::kIceConnectionFailed,
ice_connection_state_);
EXPECT_EQ(1, ice_connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::PeerConnectionState::kFailed,
combined_connection_state_);
EXPECT_EQ(1, combined_connection_state_signal_count_);
}
TEST_F(JsepTransportControllerTest, SignalConnectionStateConnected) {
@ -644,13 +678,27 @@ TEST_F(JsepTransportControllerTest, SignalConnectionStateConnected) {
EXPECT_EQ_WAIT(cricket::kIceConnectionFailed, connection_state_, kTimeout);
EXPECT_EQ(1, connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::kIceConnectionFailed,
ice_connection_state_);
EXPECT_EQ(1, ice_connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::PeerConnectionState::kFailed,
combined_connection_state_);
EXPECT_EQ(1, combined_connection_state_signal_count_);
fake_audio_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
fake_video_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
// Set the connection count to be 2 and the cricket::FakeIceTransport will set
// the transport state to be STATE_CONNECTING.
fake_video_dtls->fake_ice_transport()->SetConnectionCount(2);
fake_video_dtls->SetWritable(true);
EXPECT_EQ_WAIT(cricket::kIceConnectionConnected, connection_state_, kTimeout);
EXPECT_EQ(2, connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::kIceConnectionConnected,
ice_connection_state_);
EXPECT_EQ(2, ice_connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::PeerConnectionState::kConnected,
combined_connection_state_);
EXPECT_EQ(2, combined_connection_state_signal_count_);
}
TEST_F(JsepTransportControllerTest, SignalConnectionStateComplete) {
@ -678,13 +726,27 @@ TEST_F(JsepTransportControllerTest, SignalConnectionStateComplete) {
EXPECT_EQ_WAIT(cricket::kIceConnectionFailed, connection_state_, kTimeout);
EXPECT_EQ(1, connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::kIceConnectionFailed,
ice_connection_state_);
EXPECT_EQ(1, ice_connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::PeerConnectionState::kFailed,
combined_connection_state_);
EXPECT_EQ(1, combined_connection_state_signal_count_);
fake_audio_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
fake_video_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
// Set the connection count to be 1 and the cricket::FakeIceTransport will set
// the transport state to be STATE_COMPLETED.
fake_video_dtls->fake_ice_transport()->SetConnectionCount(1);
fake_video_dtls->SetWritable(true);
EXPECT_EQ_WAIT(cricket::kIceConnectionCompleted, connection_state_, kTimeout);
EXPECT_EQ(2, connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::kIceConnectionCompleted,
ice_connection_state_);
EXPECT_EQ(2, ice_connection_state_signal_count_);
EXPECT_EQ(PeerConnectionInterface::PeerConnectionState::kConnected,
combined_connection_state_);
EXPECT_EQ(2, combined_connection_state_signal_count_);
}
TEST_F(JsepTransportControllerTest, SignalIceGatheringStateGathering) {
@ -758,6 +820,7 @@ TEST_F(JsepTransportControllerTest,
fake_audio_dtls->SetWritable(true);
fake_audio_dtls->fake_ice_transport()->SetCandidatesGatheringComplete();
fake_audio_dtls->fake_ice_transport()->SetConnectionCount(1);
fake_audio_dtls->SetDtlsState(cricket::DTLS_TRANSPORT_CONNECTED);
EXPECT_EQ(1, gathering_state_signal_count_);
// Set the remote description and enable the bundle.
@ -770,6 +833,10 @@ TEST_F(JsepTransportControllerTest,
transport_controller_->GetDtlsTransport(kVideoMid1));
EXPECT_EQ(fake_audio_dtls, fake_video_dtls);
EXPECT_EQ_WAIT(cricket::kIceConnectionCompleted, connection_state_, kTimeout);
EXPECT_EQ(PeerConnectionInterface::kIceConnectionCompleted,
ice_connection_state_);
EXPECT_EQ(PeerConnectionInterface::PeerConnectionState::kConnected,
combined_connection_state_);
EXPECT_EQ_WAIT(cricket::kIceGatheringComplete, gathering_state_, kTimeout);
EXPECT_EQ(2, gathering_state_signal_count_);
}

View File

@ -956,6 +956,10 @@ bool PeerConnection::Initialize(
async_resolver_factory_.get(), config));
transport_controller_->SignalIceConnectionState.connect(
this, &PeerConnection::OnTransportControllerConnectionState);
transport_controller_->SignalStandardizedIceConnectionState.connect(
this, &PeerConnection::SetStandardizedIceConnectionState);
transport_controller_->SignalConnectionState.connect(
this, &PeerConnection::SetConnectionState);
transport_controller_->SignalIceGatheringState.connect(
this, &PeerConnection::OnTransportControllerGatheringState);
transport_controller_->SignalIceCandidatesGathered.connect(
@ -1707,6 +1711,16 @@ PeerConnection::ice_connection_state() {
return ice_connection_state_;
}
PeerConnectionInterface::IceConnectionState
PeerConnection::standardized_ice_connection_state() {
return standardized_ice_connection_state_;
}
PeerConnectionInterface::PeerConnectionState
PeerConnection::peer_connection_state() {
return connection_state_;
}
PeerConnectionInterface::IceGatheringState
PeerConnection::ice_gathering_state() {
return ice_gathering_state_;
@ -3528,6 +3542,29 @@ void PeerConnection::SetIceConnectionState(IceConnectionState new_state) {
Observer()->OnIceConnectionChange(ice_connection_state_);
}
void PeerConnection::SetStandardizedIceConnectionState(
PeerConnectionInterface::IceConnectionState new_state) {
RTC_DCHECK(signaling_thread()->IsCurrent());
if (standardized_ice_connection_state_ == new_state)
return;
if (IsClosed())
return;
standardized_ice_connection_state_ = new_state;
// TODO(jonasolsson): Pass this value on to OnIceConnectionChange instead of
// the old one once disconnects are handled properly.
}
void PeerConnection::SetConnectionState(
PeerConnectionInterface::PeerConnectionState new_state) {
RTC_DCHECK(signaling_thread()->IsCurrent());
if (connection_state_ == new_state)
return;
if (IsClosed())
return;
connection_state_ = new_state;
Observer()->OnConnectionChange(new_state);
}
void PeerConnection::OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) {
RTC_DCHECK(signaling_thread()->IsCurrent());
@ -3575,6 +3612,10 @@ void PeerConnection::ChangeSignalingState(
if (signaling_state == kClosed) {
ice_connection_state_ = kIceConnectionClosed;
Observer()->OnIceConnectionChange(ice_connection_state_);
standardized_ice_connection_state_ =
PeerConnectionInterface::IceConnectionState::kIceConnectionClosed;
connection_state_ = PeerConnectionInterface::PeerConnectionState::kClosed;
Observer()->OnConnectionChange(connection_state_);
if (ice_gathering_state_ != kIceGatheringComplete) {
ice_gathering_state_ = kIceGatheringComplete;
Observer()->OnIceGatheringChange(ice_gathering_state_);

View File

@ -146,6 +146,8 @@ class PeerConnection : public PeerConnectionInternal,
SignalingState signaling_state() override;
IceConnectionState ice_connection_state() override;
IceConnectionState standardized_ice_connection_state();
PeerConnectionState peer_connection_state() override;
IceGatheringState ice_gathering_state() override;
const SessionDescriptionInterface* local_description() const override;
@ -373,6 +375,11 @@ class PeerConnection : public PeerConnectionInternal,
receiver);
void SetIceConnectionState(IceConnectionState new_state);
void SetStandardizedIceConnectionState(
PeerConnectionInterface::IceConnectionState new_state);
void SetConnectionState(
PeerConnectionInterface::PeerConnectionState new_state);
// Called any time the IceGatheringState changes
void OnIceGatheringChange(IceGatheringState new_state);
// New ICE candidate has been gathered.
@ -950,6 +957,11 @@ class PeerConnection : public PeerConnectionInternal,
SignalingState signaling_state_ = kStable;
IceConnectionState ice_connection_state_ = kIceConnectionNew;
PeerConnectionInterface::IceConnectionState
standardized_ice_connection_state_ = kIceConnectionNew;
PeerConnectionInterface::PeerConnectionState connection_state_ =
PeerConnectionState::kNew;
IceGatheringState ice_gathering_state_ = kIceGatheringNew;
PeerConnectionInterface::RTCConfiguration configuration_;

View File

@ -318,6 +318,12 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver,
ice_connection_state_history_.clear();
}
// Every PeerConnection state in order that has been seen by the observer.
std::vector<PeerConnectionInterface::PeerConnectionState>
peer_connection_state_history() const {
return peer_connection_state_history_;
}
// Every ICE gathering state in order that has been seen by the observer.
std::vector<PeerConnectionInterface::IceGatheringState>
ice_gathering_state_history() const {
@ -914,6 +920,11 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver,
EXPECT_EQ(pc()->ice_connection_state(), new_state);
ice_connection_state_history_.push_back(new_state);
}
void OnConnectionChange(
webrtc::PeerConnectionInterface::PeerConnectionState new_state) override {
peer_connection_state_history_.push_back(new_state);
}
void OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state) override {
EXPECT_EQ(pc()->ice_gathering_state(), new_state);
@ -1010,6 +1021,8 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver,
std::vector<PeerConnectionInterface::IceConnectionState>
ice_connection_state_history_;
std::vector<PeerConnectionInterface::PeerConnectionState>
peer_connection_state_history_;
std::vector<PeerConnectionInterface::IceGatheringState>
ice_gathering_state_history_;
@ -3562,6 +3575,17 @@ TEST_P(PeerConnectionIntegrationIceStatesTest, VerifyIceStates) {
ElementsAre(PeerConnectionInterface::kIceConnectionChecking,
PeerConnectionInterface::kIceConnectionConnected,
PeerConnectionInterface::kIceConnectionCompleted));
// After the ice transport transitions from checking to connected we revert
// back to new as the standard requires, as at that point the DTLS transport
// is in the "new" state while no transports are "connecting", "checking",
// "failed" or disconnected. This is pretty unintuitive, and we might want to
// amend the spec to handle this case more gracefully.
EXPECT_THAT(
caller()->peer_connection_state_history(),
ElementsAre(PeerConnectionInterface::PeerConnectionState::kConnecting,
PeerConnectionInterface::PeerConnectionState::kNew,
PeerConnectionInterface::PeerConnectionState::kConnecting,
PeerConnectionInterface::PeerConnectionState::kConnected));
EXPECT_THAT(caller()->ice_gathering_state_history(),
ElementsAre(PeerConnectionInterface::kIceGatheringGathering,
PeerConnectionInterface::kIceGatheringComplete));