| Index: webrtc/p2p/base/transportcontroller.cc | 
| diff --git a/webrtc/p2p/base/transportcontroller.cc b/webrtc/p2p/base/transportcontroller.cc | 
| deleted file mode 100644 | 
| index 4d9e403d3b8abe53393d8f9445035e0a68ee35e3..0000000000000000000000000000000000000000 | 
| --- a/webrtc/p2p/base/transportcontroller.cc | 
| +++ /dev/null | 
| @@ -1,575 +0,0 @@ | 
| -/* | 
| - *  Copyright 2015 The WebRTC Project Authors. All rights reserved. | 
| - * | 
| - *  Use of this source code is governed by a BSD-style license | 
| - *  that can be found in the LICENSE file in the root of the source | 
| - *  tree. An additional intellectual property rights grant can be found | 
| - *  in the file PATENTS.  All contributing project authors may | 
| - *  be found in the AUTHORS file in the root of the source tree. | 
| - */ | 
| - | 
| -#include "webrtc/p2p/base/transportcontroller.h" | 
| - | 
| -#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" | 
| - | 
| -namespace cricket { | 
| - | 
| -enum { | 
| -  MSG_ICECONNECTIONSTATE, | 
| -  MSG_RECEIVING, | 
| -  MSG_ICEGATHERINGSTATE, | 
| -  MSG_CANDIDATESGATHERED, | 
| -}; | 
| - | 
| -struct CandidatesData : public rtc::MessageData { | 
| -  CandidatesData(const std::string& transport_name, | 
| -                 const Candidates& candidates) | 
| -      : transport_name(transport_name), candidates(candidates) {} | 
| - | 
| -  std::string transport_name; | 
| -  Candidates candidates; | 
| -}; | 
| - | 
| -TransportController::TransportController(rtc::Thread* signaling_thread, | 
| -                                         rtc::Thread* worker_thread, | 
| -                                         PortAllocator* port_allocator) | 
| -    : signaling_thread_(signaling_thread), | 
| -      worker_thread_(worker_thread), | 
| -      port_allocator_(port_allocator) {} | 
| - | 
| -TransportController::~TransportController() { | 
| -  worker_thread_->Invoke<void>( | 
| -      rtc::Bind(&TransportController::DestroyAllTransports_w, this)); | 
| -  signaling_thread_->Clear(this); | 
| -} | 
| - | 
| -bool TransportController::SetSslMaxProtocolVersion( | 
| -    rtc::SSLProtocolVersion version) { | 
| -  return worker_thread_->Invoke<bool>(rtc::Bind( | 
| -      &TransportController::SetSslMaxProtocolVersion_w, this, version)); | 
| -} | 
| - | 
| -void TransportController::SetIceConnectionReceivingTimeout(int timeout_ms) { | 
| -  worker_thread_->Invoke<void>( | 
| -      rtc::Bind(&TransportController::SetIceConnectionReceivingTimeout_w, this, | 
| -                timeout_ms)); | 
| -} | 
| - | 
| -void TransportController::SetIceRole(IceRole ice_role) { | 
| -  worker_thread_->Invoke<void>( | 
| -      rtc::Bind(&TransportController::SetIceRole_w, this, ice_role)); | 
| -} | 
| - | 
| -bool TransportController::GetSslRole(rtc::SSLRole* role) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::GetSslRole_w, this, role)); | 
| -} | 
| - | 
| -bool TransportController::SetLocalCertificate( | 
| -    const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | 
| -  return worker_thread_->Invoke<bool>(rtc::Bind( | 
| -      &TransportController::SetLocalCertificate_w, this, certificate)); | 
| -} | 
| - | 
| -bool TransportController::GetLocalCertificate( | 
| -    const std::string& transport_name, | 
| -    rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::GetLocalCertificate_w, this, | 
| -                transport_name, certificate)); | 
| -} | 
| - | 
| -bool TransportController::GetRemoteSSLCertificate( | 
| -    const std::string& transport_name, | 
| -    rtc::SSLCertificate** cert) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::GetRemoteSSLCertificate_w, this, | 
| -                transport_name, cert)); | 
| -} | 
| - | 
| -bool TransportController::SetLocalTransportDescription( | 
| -    const std::string& transport_name, | 
| -    const TransportDescription& tdesc, | 
| -    ContentAction action, | 
| -    std::string* err) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::SetLocalTransportDescription_w, this, | 
| -                transport_name, tdesc, action, err)); | 
| -} | 
| - | 
| -bool TransportController::SetRemoteTransportDescription( | 
| -    const std::string& transport_name, | 
| -    const TransportDescription& tdesc, | 
| -    ContentAction action, | 
| -    std::string* err) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::SetRemoteTransportDescription_w, this, | 
| -                transport_name, tdesc, action, err)); | 
| -} | 
| - | 
| -void TransportController::MaybeStartGathering() { | 
| -  worker_thread_->Invoke<void>( | 
| -      rtc::Bind(&TransportController::MaybeStartGathering_w, this)); | 
| -} | 
| - | 
| -bool TransportController::AddRemoteCandidates(const std::string& transport_name, | 
| -                                              const Candidates& candidates, | 
| -                                              std::string* err) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::AddRemoteCandidates_w, this, | 
| -                transport_name, candidates, err)); | 
| -} | 
| - | 
| -bool TransportController::ReadyForRemoteCandidates( | 
| -    const std::string& transport_name) { | 
| -  return worker_thread_->Invoke<bool>(rtc::Bind( | 
| -      &TransportController::ReadyForRemoteCandidates_w, this, transport_name)); | 
| -} | 
| - | 
| -bool TransportController::GetStats(const std::string& transport_name, | 
| -                                   TransportStats* stats) { | 
| -  return worker_thread_->Invoke<bool>( | 
| -      rtc::Bind(&TransportController::GetStats_w, this, transport_name, stats)); | 
| -} | 
| - | 
| -TransportChannel* TransportController::CreateTransportChannel_w( | 
| -    const std::string& transport_name, | 
| -    int component) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  Transport* transport = GetOrCreateTransport_w(transport_name); | 
| -  return transport->CreateChannel(component); | 
| -} | 
| - | 
| -void TransportController::DestroyTransportChannel_w( | 
| -    const std::string& transport_name, | 
| -    int component) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (!transport) { | 
| -    ASSERT(false); | 
| -    return; | 
| -  } | 
| -  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); | 
| -  } | 
| -} | 
| - | 
| -const rtc::scoped_refptr<rtc::RTCCertificate>& | 
| -TransportController::certificate_for_testing() { | 
| -  return certificate_; | 
| -} | 
| - | 
| -Transport* TransportController::CreateTransport_w( | 
| -    const std::string& transport_name) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  Transport* transport = new DtlsTransport<P2PTransport>( | 
| -      transport_name, port_allocator(), certificate_); | 
| -  return transport; | 
| -} | 
| - | 
| -Transport* TransportController::GetTransport_w( | 
| -    const std::string& transport_name) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  auto iter = transports_.find(transport_name); | 
| -  return (iter != transports_.end()) ? iter->second : nullptr; | 
| -} | 
| - | 
| -void TransportController::OnMessage(rtc::Message* pmsg) { | 
| -  RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| - | 
| -  switch (pmsg->message_id) { | 
| -    case MSG_ICECONNECTIONSTATE: { | 
| -      rtc::TypedMessageData<IceConnectionState>* data = | 
| -          static_cast<rtc::TypedMessageData<IceConnectionState>*>(pmsg->pdata); | 
| -      SignalConnectionState(data->data()); | 
| -      delete data; | 
| -      break; | 
| -    } | 
| -    case MSG_RECEIVING: { | 
| -      rtc::TypedMessageData<bool>* data = | 
| -          static_cast<rtc::TypedMessageData<bool>*>(pmsg->pdata); | 
| -      SignalReceiving(data->data()); | 
| -      delete data; | 
| -      break; | 
| -    } | 
| -    case MSG_ICEGATHERINGSTATE: { | 
| -      rtc::TypedMessageData<IceGatheringState>* data = | 
| -          static_cast<rtc::TypedMessageData<IceGatheringState>*>(pmsg->pdata); | 
| -      SignalGatheringState(data->data()); | 
| -      delete data; | 
| -      break; | 
| -    } | 
| -    case MSG_CANDIDATESGATHERED: { | 
| -      CandidatesData* data = static_cast<CandidatesData*>(pmsg->pdata); | 
| -      SignalCandidatesGathered(data->transport_name, data->candidates); | 
| -      delete data; | 
| -      break; | 
| -    } | 
| -    default: | 
| -      ASSERT(false); | 
| -  } | 
| -} | 
| - | 
| -Transport* TransportController::GetOrCreateTransport_w( | 
| -    const std::string& transport_name) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (transport) { | 
| -    return transport; | 
| -  } | 
| - | 
| -  transport = CreateTransport_w(transport_name); | 
| -  // The stuff below happens outside of CreateTransport_w so that unit tests | 
| -  // can override CreateTransport_w to return a different type of transport. | 
| -  transport->SetSslMaxProtocolVersion(ssl_max_version_); | 
| -  transport->SetChannelReceivingTimeout(ice_receiving_timeout_ms_); | 
| -  transport->SetIceRole(ice_role_); | 
| -  transport->SetIceTiebreaker(ice_tiebreaker_); | 
| -  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; | 
| -} | 
| - | 
| -void TransportController::DestroyTransport_w( | 
| -    const std::string& transport_name) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  auto iter = transports_.find(transport_name); | 
| -  if (iter != transports_.end()) { | 
| -    delete iter->second; | 
| -    transports_.erase(transport_name); | 
| -  } | 
| -  // Destroying a transport may cause aggregate state to change. | 
| -  UpdateAggregateStates_w(); | 
| -} | 
| - | 
| -void TransportController::DestroyAllTransports_w() { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  for (const auto& kv : transports_) { | 
| -    delete kv.second; | 
| -  } | 
| -  transports_.clear(); | 
| -} | 
| - | 
| -bool TransportController::SetSslMaxProtocolVersion_w( | 
| -    rtc::SSLProtocolVersion version) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  // Max SSL version can only be set before transports are created. | 
| -  if (!transports_.empty()) { | 
| -    return false; | 
| -  } | 
| - | 
| -  ssl_max_version_ = version; | 
| -  return true; | 
| -} | 
| - | 
| -void TransportController::SetIceConnectionReceivingTimeout_w(int timeout_ms) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| -  ice_receiving_timeout_ms_ = timeout_ms; | 
| -  for (const auto& kv : transports_) { | 
| -    kv.second->SetChannelReceivingTimeout(timeout_ms); | 
| -  } | 
| -} | 
| - | 
| -void TransportController::SetIceRole_w(IceRole ice_role) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| -  ice_role_ = ice_role; | 
| -  for (const auto& kv : transports_) { | 
| -    kv.second->SetIceRole(ice_role_); | 
| -  } | 
| -} | 
| - | 
| -bool TransportController::GetSslRole_w(rtc::SSLRole* role) { | 
| -  RTC_DCHECK(worker_thread()->IsCurrent()); | 
| - | 
| -  if (transports_.empty()) { | 
| -    return false; | 
| -  } | 
| -  return transports_.begin()->second->GetSslRole(role); | 
| -} | 
| - | 
| -bool TransportController::SetLocalCertificate_w( | 
| -    const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  if (certificate_) { | 
| -    return false; | 
| -  } | 
| -  if (!certificate) { | 
| -    return false; | 
| -  } | 
| -  certificate_ = certificate; | 
| - | 
| -  for (const auto& kv : transports_) { | 
| -    kv.second->SetLocalCertificate(certificate_); | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -bool TransportController::GetLocalCertificate_w( | 
| -    const std::string& transport_name, | 
| -    rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  Transport* t = GetTransport_w(transport_name); | 
| -  if (!t) { | 
| -    return false; | 
| -  } | 
| - | 
| -  return t->GetLocalCertificate(certificate); | 
| -} | 
| - | 
| -bool TransportController::GetRemoteSSLCertificate_w( | 
| -    const std::string& transport_name, | 
| -    rtc::SSLCertificate** cert) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  Transport* t = GetTransport_w(transport_name); | 
| -  if (!t) { | 
| -    return false; | 
| -  } | 
| - | 
| -  return t->GetRemoteSSLCertificate(cert); | 
| -} | 
| - | 
| -bool TransportController::SetLocalTransportDescription_w( | 
| -    const std::string& transport_name, | 
| -    const TransportDescription& tdesc, | 
| -    ContentAction action, | 
| -    std::string* err) { | 
| -  RTC_DCHECK(worker_thread()->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (!transport) { | 
| -    // If we didn't find a transport, that's not an error; | 
| -    // it could have been deleted as a result of bundling. | 
| -    // TODO(deadbeef): Make callers smarter so they won't attempt to set a | 
| -    // description on a deleted transport. | 
| -    return true; | 
| -  } | 
| - | 
| -  return transport->SetLocalTransportDescription(tdesc, action, err); | 
| -} | 
| - | 
| -bool TransportController::SetRemoteTransportDescription_w( | 
| -    const std::string& transport_name, | 
| -    const TransportDescription& tdesc, | 
| -    ContentAction action, | 
| -    std::string* err) { | 
| -  RTC_DCHECK(worker_thread()->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (!transport) { | 
| -    // If we didn't find a transport, that's not an error; | 
| -    // it could have been deleted as a result of bundling. | 
| -    // TODO(deadbeef): Make callers smarter so they won't attempt to set a | 
| -    // description on a deleted transport. | 
| -    return true; | 
| -  } | 
| - | 
| -  return transport->SetRemoteTransportDescription(tdesc, action, err); | 
| -} | 
| - | 
| -void TransportController::MaybeStartGathering_w() { | 
| -  for (const auto& kv : transports_) { | 
| -    kv.second->MaybeStartGathering(); | 
| -  } | 
| -} | 
| - | 
| -bool TransportController::AddRemoteCandidates_w( | 
| -    const std::string& transport_name, | 
| -    const Candidates& candidates, | 
| -    std::string* err) { | 
| -  RTC_DCHECK(worker_thread()->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (!transport) { | 
| -    // If we didn't find a transport, that's not an error; | 
| -    // it could have been deleted as a result of bundling. | 
| -    return true; | 
| -  } | 
| - | 
| -  return transport->AddRemoteCandidates(candidates, err); | 
| -} | 
| - | 
| -bool TransportController::ReadyForRemoteCandidates_w( | 
| -    const std::string& transport_name) { | 
| -  RTC_DCHECK(worker_thread()->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (!transport) { | 
| -    return false; | 
| -  } | 
| -  return transport->ready_for_remote_candidates(); | 
| -} | 
| - | 
| -bool TransportController::GetStats_w(const std::string& transport_name, | 
| -                                     TransportStats* stats) { | 
| -  RTC_DCHECK(worker_thread()->IsCurrent()); | 
| - | 
| -  Transport* transport = GetTransport_w(transport_name); | 
| -  if (!transport) { | 
| -    return false; | 
| -  } | 
| -  return transport->GetStats(stats); | 
| -} | 
| - | 
| -void TransportController::OnTransportConnecting_w(Transport* transport) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| -  UpdateAggregateStates_w(); | 
| -} | 
| - | 
| -void TransportController::OnTransportWritableState_w(Transport* transport) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| -  UpdateAggregateStates_w(); | 
| -} | 
| - | 
| -void TransportController::OnTransportReceivingState_w(Transport* transport) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| -  UpdateAggregateStates_w(); | 
| -} | 
| - | 
| -void TransportController::OnTransportCompleted_w(Transport* transport) { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| -  UpdateAggregateStates_w(); | 
| -} | 
| - | 
| -void TransportController::OnTransportFailed_w(Transport* transport) { | 
| -  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); | 
| -  signaling_thread_->Post(this, MSG_CANDIDATESGATHERED, data); | 
| -} | 
| - | 
| -void TransportController::OnTransportRoleConflict_w() { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  if (ice_role_switch_) { | 
| -    LOG(LS_WARNING) << "Repeat of role conflict signal from Transport."; | 
| -    return; | 
| -  } | 
| - | 
| -  ice_role_switch_ = true; | 
| -  IceRole reversed_role = (ice_role_ == ICEROLE_CONTROLLING) | 
| -                              ? ICEROLE_CONTROLLED | 
| -                              : ICEROLE_CONTROLLING; | 
| -  for (const auto& kv : transports_) { | 
| -    kv.second->SetIceRole(reversed_role); | 
| -  } | 
| -} | 
| - | 
| -void TransportController::UpdateAggregateStates_w() { | 
| -  RTC_DCHECK(worker_thread_->IsCurrent()); | 
| - | 
| -  IceConnectionState new_connection_state = kIceConnectionConnecting; | 
| -  IceGatheringState new_gathering_state = kIceGatheringNew; | 
| -  bool any_receiving = false; | 
| -  bool any_failed = false; | 
| -  bool all_connected = HasChannels_w(); | 
| -  bool all_completed = HasChannels_w(); | 
| -  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(); | 
| -    any_gathering = | 
| -        any_gathering || kv.second->gathering_state() != kIceGatheringNew; | 
| -    all_done_gathering = all_done_gathering && | 
| -                         kv.second->gathering_state() == kIceGatheringComplete; | 
| -  } | 
| - | 
| -  if (any_failed) { | 
| -    new_connection_state = kIceConnectionFailed; | 
| -  } else if (all_completed) { | 
| -    new_connection_state = kIceConnectionCompleted; | 
| -  } else if (all_connected) { | 
| -    new_connection_state = kIceConnectionConnected; | 
| -  } | 
| -  if (connection_state_ != new_connection_state) { | 
| -    connection_state_ = new_connection_state; | 
| -    signaling_thread_->Post( | 
| -        this, MSG_ICECONNECTIONSTATE, | 
| -        new rtc::TypedMessageData<IceConnectionState>(new_connection_state)); | 
| -  } | 
| - | 
| -  if (receiving_ != any_receiving) { | 
| -    receiving_ = any_receiving; | 
| -    signaling_thread_->Post(this, MSG_RECEIVING, | 
| -                            new rtc::TypedMessageData<bool>(any_receiving)); | 
| -  } | 
| - | 
| -  if (all_done_gathering) { | 
| -    new_gathering_state = kIceGatheringComplete; | 
| -  } else if (any_gathering) { | 
| -    new_gathering_state = kIceGatheringGathering; | 
| -  } | 
| -  if (gathering_state_ != new_gathering_state) { | 
| -    gathering_state_ = new_gathering_state; | 
| -    signaling_thread_->Post( | 
| -        this, MSG_ICEGATHERINGSTATE, | 
| -        new rtc::TypedMessageData<IceGatheringState>(new_gathering_state)); | 
| -  } | 
| -} | 
| - | 
| -bool TransportController::HasChannels_w() { | 
| -  for (const auto& kv : transports_) { | 
| -    if (kv.second->HasChannels()) { | 
| -      return true; | 
| -    } | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -}  // namespace cricket | 
|  |