Index: webrtc/p2p/base/transportcontroller.cc |
diff --git a/webrtc/p2p/base/transportcontroller.cc b/webrtc/p2p/base/transportcontroller.cc |
index d84d574f153076ad01015ee7bd25ca89f8b0a0d3..22b827a1a5ac2bda29b14296788b15a24824ec33 100644 |
--- a/webrtc/p2p/base/transportcontroller.cc |
+++ b/webrtc/p2p/base/transportcontroller.cc |
@@ -10,11 +10,14 @@ |
#include "webrtc/p2p/base/transportcontroller.h" |
+#include <algorithm> |
+ |
#include "webrtc/base/bind.h" |
#include "webrtc/base/checks.h" |
#include "webrtc/base/thread.h" |
#include "webrtc/p2p/base/dtlstransport.h" |
#include "webrtc/p2p/base/p2ptransport.h" |
+#include "webrtc/p2p/base/port.h" |
namespace cricket { |
@@ -140,8 +143,32 @@ TransportChannel* TransportController::CreateTransportChannel_w( |
int component) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
+ auto it = FindChannel_w(transport_name, component); |
+ if (it != channels_.end()) { |
+ // Channel already exists; increment reference count and return. |
+ it->AddRef(); |
+ return it->get(); |
+ } |
+ |
+ // Need to create a new channel. |
Transport* transport = GetOrCreateTransport_w(transport_name); |
- return transport->CreateChannel(component); |
+ TransportChannelImpl* channel = transport->CreateChannel(component); |
+ channel->SignalWritableState.connect( |
+ this, &TransportController::OnChannelWritableState_w); |
+ channel->SignalReceivingState.connect( |
+ this, &TransportController::OnChannelReceivingState_w); |
+ channel->SignalGatheringState.connect( |
+ this, &TransportController::OnChannelGatheringState_w); |
+ channel->SignalCandidateGathered.connect( |
+ this, &TransportController::OnChannelCandidateGathered_w); |
+ channel->SignalRoleConflict.connect( |
+ this, &TransportController::OnChannelRoleConflict_w); |
+ channel->SignalConnectionRemoved.connect( |
+ this, &TransportController::OnChannelConnectionRemoved_w); |
+ channels_.insert(channels_.end(), RefCountedChannel(channel))->AddRef(); |
+ // Adding a channel could cause aggregate state to change. |
+ UpdateAggregateStates_w(); |
+ return channel; |
} |
void TransportController::DestroyTransportChannel_w( |
@@ -149,18 +176,29 @@ void TransportController::DestroyTransportChannel_w( |
int component) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
- Transport* transport = GetTransport_w(transport_name); |
- if (!transport) { |
- ASSERT(false); |
+ auto it = FindChannel_w(transport_name, component); |
+ if (it == channels_.end()) { |
+ LOG(LS_WARNING) << "Attempting to delete " << transport_name |
+ << " TransportChannel " << component |
+ << ", which doesn't exist."; |
+ return; |
+ } |
+ |
+ it->DecRef(); |
+ if (it->ref() > 0) { |
return; |
} |
- transport->DestroyChannel(component); |
+ channels_.erase(it); |
+ Transport* transport = GetTransport_w(transport_name); |
+ transport->DestroyChannel(component); |
// Just as we create a Transport when its first channel is created, |
// we delete it when its last channel is deleted. |
if (!transport->HasChannels()) { |
DestroyTransport_w(transport_name); |
} |
+ // Removing a channel could cause aggregate state to change. |
+ UpdateAggregateStates_w(); |
} |
const rtc::scoped_refptr<rtc::RTCCertificate>& |
@@ -221,6 +259,17 @@ void TransportController::OnMessage(rtc::Message* pmsg) { |
} |
} |
+std::vector<TransportController::RefCountedChannel>::iterator |
+TransportController::FindChannel_w(const std::string& transport_name, |
+ int component) { |
+ return std::find_if( |
+ channels_.begin(), channels_.end(), |
+ [transport_name, component](const RefCountedChannel& channel) { |
+ return channel->transport_name() == transport_name && |
+ channel->component() == component; |
+ }); |
+} |
+ |
Transport* TransportController::GetOrCreateTransport_w( |
const std::string& transport_name) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
@@ -240,22 +289,6 @@ Transport* TransportController::GetOrCreateTransport_w( |
if (certificate_) { |
transport->SetLocalCertificate(certificate_); |
} |
- transport->SignalConnecting.connect( |
- this, &TransportController::OnTransportConnecting_w); |
- transport->SignalWritableState.connect( |
- this, &TransportController::OnTransportWritableState_w); |
- transport->SignalReceivingState.connect( |
- this, &TransportController::OnTransportReceivingState_w); |
- transport->SignalCompleted.connect( |
- this, &TransportController::OnTransportCompleted_w); |
- transport->SignalFailed.connect(this, |
- &TransportController::OnTransportFailed_w); |
- transport->SignalGatheringState.connect( |
- this, &TransportController::OnTransportGatheringState_w); |
- transport->SignalCandidatesGathered.connect( |
- this, &TransportController::OnTransportCandidatesGathered_w); |
- transport->SignalRoleConflict.connect( |
- this, &TransportController::OnTransportRoleConflict_w); |
transports_[transport_name] = transport; |
return transport; |
@@ -270,8 +303,6 @@ void TransportController::DestroyTransport_w( |
delete iter->second; |
transports_.erase(transport_name); |
} |
- // Destroying a transport may cause aggregate state to change. |
- UpdateAggregateStates_w(); |
} |
void TransportController::DestroyAllTransports_w() { |
@@ -447,49 +478,49 @@ bool TransportController::GetStats_w(const std::string& transport_name, |
return transport->GetStats(stats); |
} |
-void TransportController::OnTransportConnecting_w(Transport* transport) { |
- RTC_DCHECK(worker_thread_->IsCurrent()); |
- UpdateAggregateStates_w(); |
-} |
- |
-void TransportController::OnTransportWritableState_w(Transport* transport) { |
+void TransportController::OnChannelWritableState_w(TransportChannel* channel) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
+ LOG(LS_INFO) << channel->transport_name() << " TransportChannel " |
+ << channel->component() << " writability changed to " |
+ << channel->writable() << "."; |
UpdateAggregateStates_w(); |
} |
-void TransportController::OnTransportReceivingState_w(Transport* transport) { |
+void TransportController::OnChannelReceivingState_w(TransportChannel* channel) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
UpdateAggregateStates_w(); |
} |
-void TransportController::OnTransportCompleted_w(Transport* transport) { |
+void TransportController::OnChannelGatheringState_w( |
+ TransportChannelImpl* channel) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
UpdateAggregateStates_w(); |
} |
-void TransportController::OnTransportFailed_w(Transport* transport) { |
+void TransportController::OnChannelCandidateGathered_w( |
+ TransportChannelImpl* channel, |
+ const Candidate& candidate) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
- UpdateAggregateStates_w(); |
-} |
- |
-void TransportController::OnTransportGatheringState_w(Transport* transport) { |
- RTC_DCHECK(worker_thread_->IsCurrent()); |
- UpdateAggregateStates_w(); |
-} |
-void TransportController::OnTransportCandidatesGathered_w( |
- Transport* transport, |
- const std::vector<Candidate>& candidates) { |
- RTC_DCHECK(worker_thread_->IsCurrent()); |
- CandidatesData* data = new CandidatesData(transport->name(), candidates); |
+ // We should never signal peer-reflexive candidates. |
+ if (candidate.type() == PRFLX_PORT_TYPE) { |
+ RTC_DCHECK(false); |
+ return; |
+ } |
+ std::vector<Candidate> candidates; |
+ candidates.push_back(candidate); |
+ CandidatesData* data = |
+ new CandidatesData(channel->transport_name(), candidates); |
signaling_thread_->Post(this, MSG_CANDIDATESGATHERED, data); |
} |
-void TransportController::OnTransportRoleConflict_w() { |
+void TransportController::OnChannelRoleConflict_w( |
+ TransportChannelImpl* channel) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
if (ice_role_switch_) { |
- LOG(LS_WARNING) << "Repeat of role conflict signal from Transport."; |
+ LOG(LS_WARNING) |
+ << "Repeat of role conflict signal from TransportChannelImpl."; |
return; |
} |
@@ -502,6 +533,15 @@ void TransportController::OnTransportRoleConflict_w() { |
} |
} |
+void TransportController::OnChannelConnectionRemoved_w( |
+ TransportChannelImpl* channel) { |
+ RTC_DCHECK(worker_thread_->IsCurrent()); |
+ LOG(LS_INFO) << channel->transport_name() << " TransportChannel " |
+ << channel->component() |
+ << " connection removed. Check if state is complete."; |
+ UpdateAggregateStates_w(); |
+} |
+ |
void TransportController::UpdateAggregateStates_w() { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
@@ -509,24 +549,24 @@ void TransportController::UpdateAggregateStates_w() { |
IceGatheringState new_gathering_state = kIceGatheringNew; |
bool any_receiving = false; |
bool any_failed = false; |
- bool all_connected = HasChannels_w(); |
- bool all_completed = HasChannels_w(); |
+ bool all_connected = !channels_.empty(); |
+ bool all_completed = !channels_.empty(); |
bool any_gathering = false; |
- bool all_done_gathering = HasChannels_w(); |
- for (const auto& kv : transports_) { |
- // Ignore transports without channels since they're about to be deleted, |
- // and their state is meaningless. |
- if (!kv.second->HasChannels()) { |
- continue; |
- } |
- any_receiving = any_receiving || kv.second->any_channel_receiving(); |
- any_failed = any_failed || kv.second->AnyChannelFailed(); |
- all_connected = all_connected && kv.second->all_channels_writable(); |
- all_completed = all_completed && kv.second->AllChannelsCompleted(); |
+ bool all_done_gathering = !channels_.empty(); |
+ for (const auto& channel : channels_) { |
+ any_receiving = any_receiving || channel->receiving(); |
+ any_failed = any_failed || |
+ channel->GetState() == TransportChannelState::STATE_FAILED; |
+ all_connected = all_connected && channel->writable(); |
+ all_completed = |
+ all_completed && channel->writable() && |
+ channel->GetState() == TransportChannelState::STATE_COMPLETED && |
+ channel->GetIceRole() == ICEROLE_CONTROLLING && |
+ channel->gathering_state() == kIceGatheringComplete; |
any_gathering = |
- any_gathering || kv.second->gathering_state() != kIceGatheringNew; |
+ any_gathering || channel->gathering_state() != kIceGatheringNew; |
all_done_gathering = all_done_gathering && |
- kv.second->gathering_state() == kIceGatheringComplete; |
+ channel->gathering_state() == kIceGatheringComplete; |
} |
if (any_failed) { |
@@ -562,13 +602,4 @@ void TransportController::UpdateAggregateStates_w() { |
} |
} |
-bool TransportController::HasChannels_w() { |
- for (const auto& kv : transports_) { |
- if (kv.second->HasChannels()) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
} // namespace cricket |