/*
 *  Copyright 2004 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/session.h"

#include "webrtc/p2p/base/dtlstransport.h"
#include "webrtc/p2p/base/p2ptransport.h"
#include "webrtc/p2p/base/transport.h"
#include "webrtc/p2p/base/transportchannelproxy.h"
#include "webrtc/p2p/base/transportinfo.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/sslstreamadapter.h"

#include "webrtc/p2p/base/constants.h"

namespace cricket {

using rtc::Bind;

TransportProxy::~TransportProxy() {
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end(); ++iter) {
    iter->second->SignalDestroyed(iter->second);
    delete iter->second;
  }
}

const std::string& TransportProxy::type() const {
  return transport_->get()->type();
}

TransportChannel* TransportProxy::GetChannel(int component) {
  ASSERT(rtc::Thread::Current() == worker_thread_);
  return GetChannelProxy(component);
}

TransportChannel* TransportProxy::CreateChannel(const std::string& name,
                                                int component) {
  ASSERT(rtc::Thread::Current() == worker_thread_);
  ASSERT(GetChannel(component) == NULL);
  ASSERT(!transport_->get()->HasChannel(component));

  // We always create a proxy in case we need to change out the transport later.
  TransportChannelProxy* channel_proxy =
      new TransportChannelProxy(content_name(), name, component);
  channels_[component] = channel_proxy;

  // If we're already negotiated, create an impl and hook it up to the proxy
  // channel. If we're connecting, create an impl but don't hook it up yet.
  if (negotiated_) {
    CreateChannelImpl_w(component);
    SetChannelImplFromTransport_w(channel_proxy, component);
  } else if (connecting_) {
    CreateChannelImpl_w(component);
  }
  return channel_proxy;
}

bool TransportProxy::HasChannel(int component) {
  return transport_->get()->HasChannel(component);
}

void TransportProxy::DestroyChannel(int component) {
  ASSERT(rtc::Thread::Current() == worker_thread_);
  TransportChannelProxy* channel_proxy = GetChannelProxy(component);
  if (channel_proxy) {
    // If the state of TransportProxy is not NEGOTIATED then
    // TransportChannelProxy and its impl are not connected. Both must
    // be connected before deletion.
    //
    // However, if we haven't entered the connecting state then there
    // is no implementation to hook up.
    if (connecting_ && !negotiated_) {
      SetChannelImplFromTransport_w(channel_proxy, component);
    }

    channels_.erase(component);
    channel_proxy->SignalDestroyed(channel_proxy);
    delete channel_proxy;
  }
}

void TransportProxy::ConnectChannels() {
  if (!connecting_) {
    if (!negotiated_) {
      for (auto& iter : channels_) {
        CreateChannelImpl(iter.first);
      }
    }
    connecting_ = true;
  }
  // TODO(juberti): Right now Transport::ConnectChannels doesn't work if we
  // don't have any channels yet, so we need to allow this method to be called
  // multiple times. Once we fix Transport, we can move this call inside the
  // if (!connecting_) block.
  transport_->get()->ConnectChannels();
}

void TransportProxy::CompleteNegotiation() {
  if (!negotiated_) {
    // Negotiating assumes connecting_ has happened and
    // implementations exist. If not we need to create the
    // implementations.
    for (auto& iter : channels_) {
      if (!connecting_) {
        CreateChannelImpl(iter.first);
      }
      SetChannelImplFromTransport(iter.second, iter.first);
    }
    negotiated_ = true;
  }
}

void TransportProxy::AddSentCandidates(const Candidates& candidates) {
  for (Candidates::const_iterator cand = candidates.begin();
       cand != candidates.end(); ++cand) {
    sent_candidates_.push_back(*cand);
  }
}

void TransportProxy::AddUnsentCandidates(const Candidates& candidates) {
  for (Candidates::const_iterator cand = candidates.begin();
       cand != candidates.end(); ++cand) {
    unsent_candidates_.push_back(*cand);
  }
}

bool TransportProxy::GetChannelNameFromComponent(
    int component, std::string* channel_name) const {
  const TransportChannelProxy* channel = GetChannelProxy(component);
  if (channel == NULL) {
    return false;
  }

  *channel_name = channel->name();
  return true;
}

bool TransportProxy::GetComponentFromChannelName(
    const std::string& channel_name, int* component) const {
  const TransportChannelProxy* channel = GetChannelProxyByName(channel_name);
  if (channel == NULL) {
    return false;
  }

  *component = channel->component();
  return true;
}

TransportChannelProxy* TransportProxy::GetChannelProxy(int component) const {
  ChannelMap::const_iterator iter = channels_.find(component);
  return (iter != channels_.end()) ? iter->second : NULL;
}

TransportChannelProxy* TransportProxy::GetChannelProxyByName(
    const std::string& name) const {
  for (ChannelMap::const_iterator iter = channels_.begin();
       iter != channels_.end();
       ++iter) {
    if (iter->second->name() == name) {
      return iter->second;
    }
  }
  return NULL;
}

void TransportProxy::CreateChannelImpl(int component) {
  worker_thread_->Invoke<void>(Bind(
      &TransportProxy::CreateChannelImpl_w, this, component));
}

void TransportProxy::CreateChannelImpl_w(int component) {
  ASSERT(rtc::Thread::Current() == worker_thread_);
  transport_->get()->CreateChannel(component);
}

void TransportProxy::SetChannelImplFromTransport(TransportChannelProxy* proxy,
                                                 int component) {
  worker_thread_->Invoke<void>(Bind(
      &TransportProxy::SetChannelImplFromTransport_w, this, proxy, component));
}

void TransportProxy::SetChannelImplFromTransport_w(TransportChannelProxy* proxy,
                                                   int component) {
  ASSERT(rtc::Thread::Current() == worker_thread_);
  TransportChannelImpl* impl = transport_->get()->GetChannel(component);
  ASSERT(impl != NULL);
  ReplaceChannelImpl_w(proxy, impl);
}

void TransportProxy::ReplaceChannelImpl(TransportChannelProxy* proxy,
                                        TransportChannelImpl* impl) {
  worker_thread_->Invoke<void>(Bind(
      &TransportProxy::ReplaceChannelImpl_w, this, proxy, impl));
}

void TransportProxy::ReplaceChannelImpl_w(TransportChannelProxy* proxy,
                                          TransportChannelImpl* impl) {
  ASSERT(rtc::Thread::Current() == worker_thread_);
  ASSERT(proxy != NULL);
  proxy->SetImplementation(impl);
}

// This function muxes |this| onto |target| by repointing |this| at
// |target|'s transport and setting our TransportChannelProxies
// to point to |target|'s underlying implementations.
bool TransportProxy::SetupMux(TransportProxy* target) {
  // Bail out if there's nothing to do.
  if (transport_ == target->transport_) {
    return true;
  }

  // Run through all channels and remove any non-rtp transport channels before
  // setting target transport channels.
  for (ChannelMap::const_iterator iter = channels_.begin();
       iter != channels_.end(); ++iter) {
    if (!target->transport_->get()->HasChannel(iter->first)) {
      // Remove if channel doesn't exist in |transport_|.
      ReplaceChannelImpl(iter->second, NULL);
    } else {
      // Replace the impl for all the TransportProxyChannels with the channels
      // from |target|'s transport. Fail if there's not an exact match.
      ReplaceChannelImpl(
          iter->second, target->transport_->get()->CreateChannel(iter->first));
    }
  }

  // Now replace our transport. Must happen afterwards because
  // it deletes all impls as a side effect.
  transport_ = target->transport_;
  transport_->get()->SignalCandidatesReady.connect(
      this, &TransportProxy::OnTransportCandidatesReady);
  set_candidates_allocated(target->candidates_allocated());
  return true;
}

void TransportProxy::SetIceRole(IceRole role) {
  transport_->get()->SetIceRole(role);
}

bool TransportProxy::SetLocalTransportDescription(
    const TransportDescription& description,
    ContentAction action,
    std::string* error_desc) {
  // If this is an answer, finalize the negotiation.
  if (action == CA_ANSWER) {
    CompleteNegotiation();
  }
  bool result = transport_->get()->SetLocalTransportDescription(description,
                                                                action,
                                                                error_desc);
  if (result)
    local_description_set_ = true;
  return result;
}

bool TransportProxy::SetRemoteTransportDescription(
    const TransportDescription& description,
    ContentAction action,
    std::string* error_desc) {
  // If this is an answer, finalize the negotiation.
  if (action == CA_ANSWER) {
    CompleteNegotiation();
  }
  bool result = transport_->get()->SetRemoteTransportDescription(description,
                                                                 action,
                                                                 error_desc);
  if (result)
    remote_description_set_ = true;
  return result;
}

void TransportProxy::OnSignalingReady() {
  // If we're starting a new allocation sequence, reset our state.
  set_candidates_allocated(false);
  transport_->get()->OnSignalingReady();
}

bool TransportProxy::OnRemoteCandidates(const Candidates& candidates,
                                        std::string* error) {
  // Ensure the transport is negotiated before handling candidates.
  // TODO(juberti): Remove this once everybody calls SetLocalTD.
  CompleteNegotiation();

  // Verify each candidate before passing down to transport layer.
  for (Candidates::const_iterator cand = candidates.begin();
       cand != candidates.end(); ++cand) {
    if (!transport_->get()->VerifyCandidate(*cand, error))
      return false;
    if (!HasChannel(cand->component())) {
      *error = "Candidate has unknown component: " + cand->ToString() +
               " for content: " + content_name_;
      return false;
    }
  }
  transport_->get()->OnRemoteCandidates(candidates);
  return true;
}

void TransportProxy::SetIdentity(
    rtc::SSLIdentity* identity) {
  transport_->get()->SetIdentity(identity);
}

std::string BaseSession::StateToString(State state) {
  switch (state) {
    case STATE_INIT:
      return "STATE_INIT";
    case STATE_SENTINITIATE:
      return "STATE_SENTINITIATE";
    case STATE_RECEIVEDINITIATE:
      return "STATE_RECEIVEDINITIATE";
    case STATE_SENTPRACCEPT:
      return "STATE_SENTPRACCEPT";
    case STATE_SENTACCEPT:
      return "STATE_SENTACCEPT";
    case STATE_RECEIVEDPRACCEPT:
      return "STATE_RECEIVEDPRACCEPT";
    case STATE_RECEIVEDACCEPT:
      return "STATE_RECEIVEDACCEPT";
    case STATE_SENTMODIFY:
      return "STATE_SENTMODIFY";
    case STATE_RECEIVEDMODIFY:
      return "STATE_RECEIVEDMODIFY";
    case STATE_SENTREJECT:
      return "STATE_SENTREJECT";
    case STATE_RECEIVEDREJECT:
      return "STATE_RECEIVEDREJECT";
    case STATE_SENTREDIRECT:
      return "STATE_SENTREDIRECT";
    case STATE_SENTTERMINATE:
      return "STATE_SENTTERMINATE";
    case STATE_RECEIVEDTERMINATE:
      return "STATE_RECEIVEDTERMINATE";
    case STATE_INPROGRESS:
      return "STATE_INPROGRESS";
    case STATE_DEINIT:
      return "STATE_DEINIT";
    default:
      break;
  }
  return "STATE_" + rtc::ToString(state);
}

BaseSession::BaseSession(rtc::Thread* signaling_thread,
                         rtc::Thread* worker_thread,
                         PortAllocator* port_allocator,
                         const std::string& sid,
                         const std::string& content_type,
                         bool initiator)
    : state_(STATE_INIT),
      error_(ERROR_NONE),
      signaling_thread_(signaling_thread),
      worker_thread_(worker_thread),
      port_allocator_(port_allocator),
      sid_(sid),
      content_type_(content_type),
      transport_type_(NS_GINGLE_P2P),
      initiator_(initiator),
      identity_(NULL),
      ice_tiebreaker_(rtc::CreateRandomId64()),
      role_switch_(false) {
  ASSERT(signaling_thread->IsCurrent());
}

BaseSession::~BaseSession() {
  ASSERT(signaling_thread()->IsCurrent());

  ASSERT(state_ != STATE_DEINIT);
  LogState(state_, STATE_DEINIT);
  state_ = STATE_DEINIT;
  SignalState(this, state_);

  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    delete iter->second;
  }
}

const SessionDescription* BaseSession::local_description() const {
  // TODO(tommi): Assert on thread correctness.
  return local_description_.get();
}

const SessionDescription* BaseSession::remote_description() const {
  // TODO(tommi): Assert on thread correctness.
  return remote_description_.get();
}

SessionDescription* BaseSession::remote_description() {
  // TODO(tommi): Assert on thread correctness.
  return remote_description_.get();
}

void BaseSession::set_local_description(const SessionDescription* sdesc) {
  // TODO(tommi): Assert on thread correctness.
  if (sdesc != local_description_.get())
    local_description_.reset(sdesc);
}

void BaseSession::set_remote_description(SessionDescription* sdesc) {
  // TODO(tommi): Assert on thread correctness.
  if (sdesc != remote_description_)
    remote_description_.reset(sdesc);
}

const SessionDescription* BaseSession::initiator_description() const {
  // TODO(tommi): Assert on thread correctness.
  return initiator_ ? local_description_.get() : remote_description_.get();
}

bool BaseSession::SetIdentity(rtc::SSLIdentity* identity) {
  if (identity_)
    return false;
  identity_ = identity;
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    iter->second->SetIdentity(identity_);
  }
  return true;
}

bool BaseSession::PushdownTransportDescription(ContentSource source,
                                               ContentAction action,
                                               std::string* error_desc) {
  if (source == CS_LOCAL) {
    return PushdownLocalTransportDescription(local_description(),
                                             action,
                                             error_desc);
  }
  return PushdownRemoteTransportDescription(remote_description(),
                                            action,
                                            error_desc);
}

bool BaseSession::PushdownLocalTransportDescription(
    const SessionDescription* sdesc,
    ContentAction action,
    std::string* error_desc) {
  // Update the Transports with the right information, and trigger them to
  // start connecting.
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    // If no transport info was in this session description, ret == false
    // and we just skip this one.
    TransportDescription tdesc;
    bool ret = GetTransportDescription(
        sdesc, iter->second->content_name(), &tdesc);
    if (ret) {
      if (!iter->second->SetLocalTransportDescription(tdesc, action,
                                                      error_desc)) {
        return false;
      }

      iter->second->ConnectChannels();
    }
  }

  return true;
}

bool BaseSession::PushdownRemoteTransportDescription(
    const SessionDescription* sdesc,
    ContentAction action,
    std::string* error_desc) {
  // Update the Transports with the right information.
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    TransportDescription tdesc;

    // If no transport info was in this session description, ret == false
    // and we just skip this one.
    bool ret = GetTransportDescription(
        sdesc, iter->second->content_name(), &tdesc);
    if (ret) {
      if (!iter->second->SetRemoteTransportDescription(tdesc, action,
                                                       error_desc)) {
        return false;
      }
    }
  }

  return true;
}

TransportChannel* BaseSession::CreateChannel(const std::string& content_name,
                                             const std::string& channel_name,
                                             int component) {
  // We create the proxy "on demand" here because we need to support
  // creating channels at any time, even before we send or receive
  // initiate messages, which is before we create the transports.
  TransportProxy* transproxy = GetOrCreateTransportProxy(content_name);
  return transproxy->CreateChannel(channel_name, component);
}

TransportChannel* BaseSession::GetChannel(const std::string& content_name,
                                          int component) {
  TransportProxy* transproxy = GetTransportProxy(content_name);
  if (transproxy == NULL)
    return NULL;

  return transproxy->GetChannel(component);
}

void BaseSession::DestroyChannel(const std::string& content_name,
                                 int component) {
  TransportProxy* transproxy = GetTransportProxy(content_name);
  ASSERT(transproxy != NULL);
  transproxy->DestroyChannel(component);
}

TransportProxy* BaseSession::GetOrCreateTransportProxy(
    const std::string& content_name) {
  TransportProxy* transproxy = GetTransportProxy(content_name);
  if (transproxy)
    return transproxy;

  Transport* transport = CreateTransport(content_name);
  transport->SetIceRole(initiator_ ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED);
  transport->SetIceTiebreaker(ice_tiebreaker_);
  // TODO: Connect all the Transport signals to TransportProxy
  // then to the BaseSession.
  transport->SignalConnecting.connect(
      this, &BaseSession::OnTransportConnecting);
  transport->SignalWritableState.connect(
      this, &BaseSession::OnTransportWritable);
  transport->SignalRequestSignaling.connect(
      this, &BaseSession::OnTransportRequestSignaling);
  transport->SignalRouteChange.connect(
      this, &BaseSession::OnTransportRouteChange);
  transport->SignalCandidatesAllocationDone.connect(
      this, &BaseSession::OnTransportCandidatesAllocationDone);
  transport->SignalRoleConflict.connect(
      this, &BaseSession::OnRoleConflict);
  transport->SignalCompleted.connect(
      this, &BaseSession::OnTransportCompleted);
  transport->SignalFailed.connect(
      this, &BaseSession::OnTransportFailed);

  transproxy = new TransportProxy(worker_thread_, sid_, content_name,
                                  new TransportWrapper(transport));
  transproxy->SignalCandidatesReady.connect(
      this, &BaseSession::OnTransportProxyCandidatesReady);
  if (identity_)
    transproxy->SetIdentity(identity_);
  transports_[content_name] = transproxy;

  return transproxy;
}

Transport* BaseSession::GetTransport(const std::string& content_name) {
  TransportProxy* transproxy = GetTransportProxy(content_name);
  if (transproxy == NULL)
    return NULL;
  return transproxy->impl();
}

TransportProxy* BaseSession::GetTransportProxy(
    const std::string& content_name) {
  TransportMap::iterator iter = transports_.find(content_name);
  return (iter != transports_.end()) ? iter->second : NULL;
}

TransportProxy* BaseSession::GetTransportProxy(const Transport* transport) {
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    TransportProxy* transproxy = iter->second;
    if (transproxy->impl() == transport) {
      return transproxy;
    }
  }
  return NULL;
}

TransportProxy* BaseSession::GetFirstTransportProxy() {
  if (transports_.empty())
    return NULL;
  return transports_.begin()->second;
}

void BaseSession::DestroyTransportProxy(
    const std::string& content_name) {
  TransportMap::iterator iter = transports_.find(content_name);
  if (iter != transports_.end()) {
    delete iter->second;
    transports_.erase(content_name);
  }
}

cricket::Transport* BaseSession::CreateTransport(
    const std::string& content_name) {
  ASSERT(transport_type_ == NS_GINGLE_P2P);
  return new cricket::DtlsTransport<P2PTransport>(
      signaling_thread(), worker_thread(), content_name,
      port_allocator(), identity_);
}

bool BaseSession::GetStats(SessionStats* stats) {
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    std::string proxy_id = iter->second->content_name();
    // We are ignoring not-yet-instantiated transports.
    if (iter->second->impl()) {
      std::string transport_id = iter->second->impl()->content_name();
      stats->proxy_to_transport[proxy_id] = transport_id;
      if (stats->transport_stats.find(transport_id)
          == stats->transport_stats.end()) {
        TransportStats subinfos;
        if (!iter->second->impl()->GetStats(&subinfos)) {
          return false;
        }
        stats->transport_stats[transport_id] = subinfos;
      }
    }
  }
  return true;
}

void BaseSession::SetState(State state) {
  ASSERT(signaling_thread_->IsCurrent());
  if (state != state_) {
    LogState(state_, state);
    state_ = state;
    SignalState(this, state_);
    signaling_thread_->Post(this, MSG_STATE);
  }
  SignalNewDescription();
}

void BaseSession::SetError(Error error, const std::string& error_desc) {
  ASSERT(signaling_thread_->IsCurrent());
  if (error != error_) {
    error_ = error;
    error_desc_ = error_desc;
    SignalError(this, error);
  }
}

void BaseSession::OnSignalingReady() {
  ASSERT(signaling_thread()->IsCurrent());
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    iter->second->OnSignalingReady();
  }
}

// TODO(juberti): Since PushdownLocalTD now triggers the connection process to
// start, remove this method once everyone calls PushdownLocalTD.
void BaseSession::SpeculativelyConnectAllTransportChannels() {
  // Put all transports into the connecting state.
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    iter->second->ConnectChannels();
  }
}

bool BaseSession::OnRemoteCandidates(const std::string& content_name,
                                     const Candidates& candidates,
                                     std::string* error) {
  // Give candidates to the appropriate transport, and tell that transport
  // to start connecting, if it's not already doing so.
  TransportProxy* transproxy = GetTransportProxy(content_name);
  if (!transproxy) {
    *error = "Unknown content name " + content_name;
    return false;
  }
  if (!transproxy->OnRemoteCandidates(candidates, error)) {
    return false;
  }
  // TODO(juberti): Remove this call once we can be sure that we always have
  // a local transport description (which will trigger the connection).
  transproxy->ConnectChannels();
  return true;
}

bool BaseSession::MaybeEnableMuxingSupport() {
  // We need both a local and remote description to decide if we should mux.
  if ((state_ == STATE_SENTINITIATE ||
      state_ == STATE_RECEIVEDINITIATE) &&
      ((local_description_ == NULL) ||
      (remote_description_ == NULL))) {
    return false;
  }

  // In order to perform the multiplexing, we need all proxies to be in the
  // negotiated state, i.e. to have implementations underneath.
  // Ensure that this is the case, regardless of whether we are going to mux.
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    ASSERT(iter->second->negotiated());
    if (!iter->second->negotiated())
      return false;
  }

  // If both sides agree to BUNDLE, mux all the specified contents onto the
  // transport belonging to the first content name in the BUNDLE group.
  // If the contents are already muxed, this will be a no-op.
  // TODO(juberti): Should this check that local and remote have configured
  // BUNDLE the same way?
  bool candidates_allocated = IsCandidateAllocationDone();
  const ContentGroup* local_bundle_group =
      local_description()->GetGroupByName(GROUP_TYPE_BUNDLE);
  const ContentGroup* remote_bundle_group =
      remote_description()->GetGroupByName(GROUP_TYPE_BUNDLE);
  if (local_bundle_group && remote_bundle_group &&
      local_bundle_group->FirstContentName()) {
    const std::string* content_name = local_bundle_group->FirstContentName();
    const ContentInfo* content =
        local_description_->GetContentByName(*content_name);
    if (!content) {
      LOG(LS_WARNING) << "Content \"" << *content_name
                      << "\" referenced in BUNDLE group is not present";
      return false;
    }

    if (!SetSelectedProxy(content->name, local_bundle_group)) {
      LOG(LS_WARNING) << "Failed to set up BUNDLE";
      return false;
    }

    // If we weren't done gathering before, we might be done now, as a result
    // of enabling mux.
    LOG(LS_INFO) << "Enabling BUNDLE, bundling onto transport: "
                 << *content_name;
    if (!candidates_allocated) {
      MaybeCandidateAllocationDone();
    }
  } else {
    LOG(LS_INFO) << "No BUNDLE information, not bundling.";
  }
  return true;
}

bool BaseSession::SetSelectedProxy(const std::string& content_name,
                                   const ContentGroup* muxed_group) {
  TransportProxy* selected_proxy = GetTransportProxy(content_name);
  if (!selected_proxy) {
    return false;
  }

  ASSERT(selected_proxy->negotiated());
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    // If content is part of the mux group, then repoint its proxy at the
    // transport object that we have chosen to mux onto. If the proxy
    // is already pointing at the right object, it will be a no-op.
    if (muxed_group->HasContentName(iter->first) &&
        !iter->second->SetupMux(selected_proxy)) {
      return false;
    }
  }
  return true;
}

void BaseSession::OnTransportCandidatesAllocationDone(Transport* transport) {
  // TODO(juberti): This is a clunky way of processing the done signal. Instead,
  // TransportProxy should receive the done signal directly, set its allocated
  // flag internally, and then reissue the done signal to Session.
  // Overall we should make TransportProxy receive *all* the signals from
  // Transport, since this removes the need to manually iterate over all
  // the transports, as is needed to make sure signals are handled properly
  // when BUNDLEing.
  // TODO(juberti): Per b/7998978, devs and QA are hitting this assert in ways
  // that make it prohibitively difficult to run dbg builds. Disabled for now.
  //ASSERT(!IsCandidateAllocationDone());
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    if (iter->second->impl() == transport) {
      iter->second->set_candidates_allocated(true);
    }
  }
  MaybeCandidateAllocationDone();
}

bool BaseSession::IsCandidateAllocationDone() const {
  for (TransportMap::const_iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    if (!iter->second->candidates_allocated()) {
      LOG(LS_INFO) << "Candidate allocation not done for "
                   << iter->second->content_name();
      return false;
    }
  }
  return true;
}

void BaseSession::MaybeCandidateAllocationDone() {
  if (IsCandidateAllocationDone()) {
    LOG(LS_INFO) << "Candidate gathering is complete.";
    OnCandidatesAllocationDone();
  }
}

void BaseSession::OnRoleConflict() {
  if (role_switch_) {
    LOG(LS_WARNING) << "Repeat of role conflict signal from Transport.";
    return;
  }

  role_switch_ = true;
  for (TransportMap::iterator iter = transports_.begin();
       iter != transports_.end(); ++iter) {
    // Role will be reverse of initial role setting.
    IceRole role = initiator_ ? ICEROLE_CONTROLLED : ICEROLE_CONTROLLING;
    iter->second->SetIceRole(role);
  }
}

void BaseSession::LogState(State old_state, State new_state) {
  LOG(LS_INFO) << "Session:" << id()
               << " Old state:" << StateToString(old_state)
               << " New state:" << StateToString(new_state)
               << " Type:" << content_type()
               << " Transport:" << transport_type();
}

// static
bool BaseSession::GetTransportDescription(const SessionDescription* description,
                                          const std::string& content_name,
                                          TransportDescription* tdesc) {
  if (!description || !tdesc) {
    return false;
  }
  const TransportInfo* transport_info =
      description->GetTransportInfoByName(content_name);
  if (!transport_info) {
    return false;
  }
  *tdesc = transport_info->description;
  return true;
}

void BaseSession::SignalNewDescription() {
  ContentAction action;
  ContentSource source;
  if (!GetContentAction(&action, &source)) {
    return;
  }
  if (source == CS_LOCAL) {
    SignalNewLocalDescription(this, action);
  } else {
    SignalNewRemoteDescription(this, action);
  }
}

bool BaseSession::GetContentAction(ContentAction* action,
                                   ContentSource* source) {
  switch (state_) {
    // new local description
    case STATE_SENTINITIATE:
      *action = CA_OFFER;
      *source = CS_LOCAL;
      break;
    case STATE_SENTPRACCEPT:
      *action = CA_PRANSWER;
      *source = CS_LOCAL;
      break;
    case STATE_SENTACCEPT:
      *action = CA_ANSWER;
      *source = CS_LOCAL;
      break;
    // new remote description
    case STATE_RECEIVEDINITIATE:
      *action = CA_OFFER;
      *source = CS_REMOTE;
      break;
    case STATE_RECEIVEDPRACCEPT:
      *action = CA_PRANSWER;
      *source = CS_REMOTE;
      break;
    case STATE_RECEIVEDACCEPT:
      *action = CA_ANSWER;
      *source = CS_REMOTE;
      break;
    default:
      return false;
  }
  return true;
}

void BaseSession::OnMessage(rtc::Message *pmsg) {
  switch (pmsg->message_id) {
  case MSG_TIMEOUT:
    // Session timeout has occured.
    SetError(ERROR_TIME, "Session timeout has occured.");
    break;

  case MSG_STATE:
    switch (state_) {
    case STATE_SENTACCEPT:
    case STATE_RECEIVEDACCEPT:
      SetState(STATE_INPROGRESS);
      break;

    default:
      // Explicitly ignoring some states here.
      break;
    }
    break;
  }
}

}  // namespace cricket
