/*
 * libjingle
 * Copyright 2004, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/p2p/base/transport.h"

#include "talk/p2p/base/candidate.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/port.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/base/transportchannelimpl.h"
#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"

namespace cricket {

using rtc::Bind;

enum {
  MSG_ONSIGNALINGREADY = 1,
  MSG_ONREMOTECANDIDATE,
  MSG_READSTATE,
  MSG_WRITESTATE,
  MSG_REQUESTSIGNALING,
  MSG_CANDIDATEREADY,
  MSG_ROUTECHANGE,
  MSG_CONNECTING,
  MSG_CANDIDATEALLOCATIONCOMPLETE,
  MSG_ROLECONFLICT,
  MSG_COMPLETED,
  MSG_FAILED,
};

struct ChannelParams : public rtc::MessageData {
  ChannelParams() : channel(NULL), candidate(NULL) {}
  explicit ChannelParams(int component)
      : component(component), channel(NULL), candidate(NULL) {}
  explicit ChannelParams(Candidate* candidate)
      : channel(NULL), candidate(candidate) {
  }

  ~ChannelParams() {
    delete candidate;
  }

  std::string name;
  int component;
  TransportChannelImpl* channel;
  Candidate* candidate;
};

static std::string IceProtoToString(TransportProtocol proto) {
  std::string proto_str;
  switch (proto) {
    case ICEPROTO_GOOGLE:
      proto_str = "gice";
      break;
    case ICEPROTO_HYBRID:
      proto_str = "hybrid";
      break;
    case ICEPROTO_RFC5245:
      proto_str = "ice";
      break;
    default:
      ASSERT(false);
      break;
  }
  return proto_str;
}

static bool VerifyIceParams(const TransportDescription& desc) {
  // For legacy protocols.
  if (desc.ice_ufrag.empty() && desc.ice_pwd.empty())
    return true;

  if (desc.ice_ufrag.length() < ICE_UFRAG_MIN_LENGTH ||
      desc.ice_ufrag.length() > ICE_UFRAG_MAX_LENGTH) {
    return false;
  }
  if (desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH ||
      desc.ice_pwd.length() > ICE_PWD_MAX_LENGTH) {
    return false;
  }
  return true;
}

bool BadTransportDescription(const std::string& desc, std::string* err_desc) {
  if (err_desc) {
    *err_desc = desc;
  }
  LOG(LS_ERROR) << desc;
  return false;
}

bool IceCredentialsChanged(const std::string& old_ufrag,
                           const std::string& old_pwd,
                           const std::string& new_ufrag,
                           const std::string& new_pwd) {
  // TODO(jiayl): The standard (RFC 5245 Section 9.1.1.1) says that ICE should
  // restart when both the ufrag and password are changed, but we do restart
  // when either ufrag or passwrod is changed to keep compatible with GICE. We
  // should clean this up when GICE is no longer used.
  return (old_ufrag != new_ufrag) || (old_pwd != new_pwd);
}

static bool IceCredentialsChanged(const TransportDescription& old_desc,
                                  const TransportDescription& new_desc) {
  return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd,
                               new_desc.ice_ufrag, new_desc.ice_pwd);
}

Transport::Transport(rtc::Thread* signaling_thread,
                     rtc::Thread* worker_thread,
                     const std::string& content_name,
                     const std::string& type,
                     PortAllocator* allocator)
  : signaling_thread_(signaling_thread),
    worker_thread_(worker_thread),
    content_name_(content_name),
    type_(type),
    allocator_(allocator),
    destroyed_(false),
    readable_(TRANSPORT_STATE_NONE),
    writable_(TRANSPORT_STATE_NONE),
    was_writable_(false),
    connect_requested_(false),
    ice_role_(ICEROLE_UNKNOWN),
    tiebreaker_(0),
    protocol_(ICEPROTO_HYBRID),
    remote_ice_mode_(ICEMODE_FULL) {
}

Transport::~Transport() {
  ASSERT(signaling_thread_->IsCurrent());
  ASSERT(destroyed_);
}

void Transport::SetIceRole(IceRole role) {
  worker_thread_->Invoke<void>(Bind(&Transport::SetIceRole_w, this, role));
}

void Transport::SetIdentity(rtc::SSLIdentity* identity) {
  worker_thread_->Invoke<void>(Bind(&Transport::SetIdentity_w, this, identity));
}

bool Transport::GetIdentity(rtc::SSLIdentity** identity) {
  // The identity is set on the worker thread, so for safety it must also be
  // acquired on the worker thread.
  return worker_thread_->Invoke<bool>(
      Bind(&Transport::GetIdentity_w, this, identity));
}

bool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) {
  // Channels can be deleted on the worker thread, so for safety the remote
  // certificate is acquired on the worker thread.
  return worker_thread_->Invoke<bool>(
      Bind(&Transport::GetRemoteCertificate_w, this, cert));
}

bool Transport::GetRemoteCertificate_w(rtc::SSLCertificate** cert) {
  ASSERT(worker_thread()->IsCurrent());
  if (channels_.empty())
    return false;

  ChannelMap::iterator iter = channels_.begin();
  return iter->second->GetRemoteCertificate(cert);
}

bool Transport::SetLocalTransportDescription(
    const TransportDescription& description,
    ContentAction action,
    std::string* error_desc) {
  return worker_thread_->Invoke<bool>(Bind(
      &Transport::SetLocalTransportDescription_w, this,
      description, action, error_desc));
}

bool Transport::SetRemoteTransportDescription(
    const TransportDescription& description,
    ContentAction action,
    std::string* error_desc) {
  return worker_thread_->Invoke<bool>(Bind(
      &Transport::SetRemoteTransportDescription_w, this,
      description, action, error_desc));
}

TransportChannelImpl* Transport::CreateChannel(int component) {
  return worker_thread_->Invoke<TransportChannelImpl*>(Bind(
      &Transport::CreateChannel_w, this, component));
}

TransportChannelImpl* Transport::CreateChannel_w(int component) {
  ASSERT(worker_thread()->IsCurrent());
  TransportChannelImpl *impl;
  rtc::CritScope cs(&crit_);

  // Create the entry if it does not exist.
  bool impl_exists = false;
  if (channels_.find(component) == channels_.end()) {
    impl = CreateTransportChannel(component);
    channels_[component] = ChannelMapEntry(impl);
  } else {
    impl = channels_[component].get();
    impl_exists = true;
  }

  // Increase the ref count.
  channels_[component].AddRef();
  destroyed_ = false;

  if (impl_exists) {
    // If this is an existing channel, we should just return it without
    // connecting to all the signal again.
    return impl;
  }

  // Push down our transport state to the new channel.
  impl->SetIceRole(ice_role_);
  impl->SetIceTiebreaker(tiebreaker_);
  // TODO(ronghuawu): Change CreateChannel_w to be able to return error since
  // below Apply**Description_w calls can fail.
  if (local_description_)
    ApplyLocalTransportDescription_w(impl, NULL);
  if (remote_description_)
    ApplyRemoteTransportDescription_w(impl, NULL);
  if (local_description_ && remote_description_)
    ApplyNegotiatedTransportDescription_w(impl, NULL);

  impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState);
  impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState);
  impl->SignalRequestSignaling.connect(
      this, &Transport::OnChannelRequestSignaling);
  impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady);
  impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange);
  impl->SignalCandidatesAllocationDone.connect(
      this, &Transport::OnChannelCandidatesAllocationDone);
  impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict);
  impl->SignalConnectionRemoved.connect(
      this, &Transport::OnChannelConnectionRemoved);

  if (connect_requested_) {
    impl->Connect();
    if (channels_.size() == 1) {
      // If this is the first channel, then indicate that we have started
      // connecting.
      signaling_thread()->Post(this, MSG_CONNECTING, NULL);
    }
  }
  return impl;
}

TransportChannelImpl* Transport::GetChannel(int component) {
  rtc::CritScope cs(&crit_);
  ChannelMap::iterator iter = channels_.find(component);
  return (iter != channels_.end()) ? iter->second.get() : NULL;
}

bool Transport::HasChannels() {
  rtc::CritScope cs(&crit_);
  return !channels_.empty();
}

void Transport::DestroyChannel(int component) {
  worker_thread_->Invoke<void>(Bind(
      &Transport::DestroyChannel_w, this, component));
}

void Transport::DestroyChannel_w(int component) {
  ASSERT(worker_thread()->IsCurrent());

  TransportChannelImpl* impl = NULL;
  {
    rtc::CritScope cs(&crit_);
    ChannelMap::iterator iter = channels_.find(component);
    if (iter == channels_.end())
      return;

    iter->second.DecRef();
    if (!iter->second.ref()) {
      impl = iter->second.get();
      channels_.erase(iter);
    }
  }

  if (connect_requested_ && channels_.empty()) {
    // We're no longer attempting to connect.
    signaling_thread()->Post(this, MSG_CONNECTING, NULL);
  }

  if (impl) {
    // Check in case the deleted channel was the only non-writable channel.
    OnChannelWritableState(impl);
    DestroyTransportChannel(impl);
  }
}

void Transport::ConnectChannels() {
  ASSERT(signaling_thread()->IsCurrent());
  worker_thread_->Invoke<void>(Bind(&Transport::ConnectChannels_w, this));
}

void Transport::ConnectChannels_w() {
  ASSERT(worker_thread()->IsCurrent());
  if (connect_requested_ || channels_.empty())
    return;
  connect_requested_ = true;
  signaling_thread()->Post(
      this, MSG_CANDIDATEREADY, NULL);

  if (!local_description_) {
    // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here.
    // As Transport must know TD is offer or answer and cricket::Transport
    // doesn't have the capability to decide it. This should be set by the
    // Session.
    // Session must generate local TD before remote candidates pushed when
    // initiate request initiated by the remote.
    LOG(LS_INFO) << "Transport::ConnectChannels_w: No local description has "
                 << "been set. Will generate one.";
    TransportDescription desc(NS_GINGLE_P2P, std::vector<std::string>(),
                              rtc::CreateRandomString(ICE_UFRAG_LENGTH),
                              rtc::CreateRandomString(ICE_PWD_LENGTH),
                              ICEMODE_FULL, CONNECTIONROLE_NONE, NULL,
                              Candidates());
    SetLocalTransportDescription_w(desc, CA_OFFER, NULL);
  }

  CallChannels_w(&TransportChannelImpl::Connect);
  if (!channels_.empty()) {
    signaling_thread()->Post(this, MSG_CONNECTING, NULL);
  }
}

void Transport::OnConnecting_s() {
  ASSERT(signaling_thread()->IsCurrent());
  SignalConnecting(this);
}

void Transport::DestroyAllChannels() {
  ASSERT(signaling_thread()->IsCurrent());
  worker_thread_->Invoke<void>(
      Bind(&Transport::DestroyAllChannels_w, this));
  worker_thread()->Clear(this);
  signaling_thread()->Clear(this);
  destroyed_ = true;
}

void Transport::DestroyAllChannels_w() {
  ASSERT(worker_thread()->IsCurrent());
  std::vector<TransportChannelImpl*> impls;
  {
    rtc::CritScope cs(&crit_);
    for (ChannelMap::iterator iter = channels_.begin();
         iter != channels_.end();
         ++iter) {
      iter->second.DecRef();
      if (!iter->second.ref())
        impls.push_back(iter->second.get());
      }
    }
  channels_.clear();


  for (size_t i = 0; i < impls.size(); ++i)
    DestroyTransportChannel(impls[i]);
}

void Transport::ResetChannels() {
  ASSERT(signaling_thread()->IsCurrent());
  worker_thread_->Invoke<void>(Bind(&Transport::ResetChannels_w, this));
}

void Transport::ResetChannels_w() {
  ASSERT(worker_thread()->IsCurrent());

  // We are no longer attempting to connect
  connect_requested_ = false;

  // Clear out the old messages, they aren't relevant
  rtc::CritScope cs(&crit_);
  ready_candidates_.clear();

  // Reset all of the channels
  CallChannels_w(&TransportChannelImpl::Reset);
}

void Transport::OnSignalingReady() {
  ASSERT(signaling_thread()->IsCurrent());
  if (destroyed_) return;

  worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL);

  // Notify the subclass.
  OnTransportSignalingReady();
}

void Transport::CallChannels_w(TransportChannelFunc func) {
  ASSERT(worker_thread()->IsCurrent());
  rtc::CritScope cs(&crit_);
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end();
       ++iter) {
    ((iter->second.get())->*func)();
  }
}

bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) {
  // No address zero.
  if (cand.address().IsNil() || cand.address().IsAny()) {
    *error = "candidate has address of zero";
    return false;
  }

  // Disallow all ports below 1024, except for 80 and 443 on public addresses.
  int port = cand.address().port();
  if (cand.protocol() == TCP_PROTOCOL_NAME &&
      (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) {
    // Expected for active-only candidates per
    // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
    // Libjingle clients emit port 0, in "active" mode.
    return true;
  }
  if (port < 1024) {
    if ((port != 80) && (port != 443)) {
      *error = "candidate has port below 1024, but not 80 or 443";
      return false;
    }

    if (cand.address().IsPrivateIP()) {
      *error = "candidate has port of 80 or 443 with private IP address";
      return false;
    }
  }

  return true;
}


bool Transport::GetStats(TransportStats* stats) {
  ASSERT(signaling_thread()->IsCurrent());
  return worker_thread_->Invoke<bool>(Bind(
      &Transport::GetStats_w, this, stats));
}

bool Transport::GetStats_w(TransportStats* stats) {
  ASSERT(worker_thread()->IsCurrent());
  stats->content_name = content_name();
  stats->channel_stats.clear();
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end();
       ++iter) {
    TransportChannelStats substats;
    substats.component = iter->second->component();
    if (!iter->second->GetStats(&substats.connection_infos)) {
      return false;
    }
    stats->channel_stats.push_back(substats);
  }
  return true;
}

bool Transport::GetSslRole(rtc::SSLRole* ssl_role) const {
  return worker_thread_->Invoke<bool>(Bind(
      &Transport::GetSslRole_w, this, ssl_role));
}

void Transport::OnRemoteCandidates(const std::vector<Candidate>& candidates) {
  for (std::vector<Candidate>::const_iterator iter = candidates.begin();
       iter != candidates.end();
       ++iter) {
    OnRemoteCandidate(*iter);
  }
}

void Transport::OnRemoteCandidate(const Candidate& candidate) {
  ASSERT(signaling_thread()->IsCurrent());
  if (destroyed_) return;

  if (!HasChannel(candidate.component())) {
    LOG(LS_WARNING) << "Ignoring candidate for unknown component "
                    << candidate.component();
    return;
  }

  ChannelParams* params = new ChannelParams(new Candidate(candidate));
  worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, params);
}

void Transport::OnRemoteCandidate_w(const Candidate& candidate) {
  ASSERT(worker_thread()->IsCurrent());
  ChannelMap::iterator iter = channels_.find(candidate.component());
  // It's ok for a channel to go away while this message is in transit.
  if (iter != channels_.end()) {
    iter->second->OnCandidate(candidate);
  }
}

void Transport::OnChannelReadableState(TransportChannel* channel) {
  ASSERT(worker_thread()->IsCurrent());
  signaling_thread()->Post(this, MSG_READSTATE, NULL);
}

void Transport::OnChannelReadableState_s() {
  ASSERT(signaling_thread()->IsCurrent());
  TransportState readable = GetTransportState_s(true);
  if (readable_ != readable) {
    readable_ = readable;
    SignalReadableState(this);
  }
}

void Transport::OnChannelWritableState(TransportChannel* channel) {
  ASSERT(worker_thread()->IsCurrent());
  signaling_thread()->Post(this, MSG_WRITESTATE, NULL);

  MaybeCompleted_w();
}

void Transport::OnChannelWritableState_s() {
  ASSERT(signaling_thread()->IsCurrent());
  TransportState writable = GetTransportState_s(false);
  if (writable_ != writable) {
    was_writable_ = (writable_ == TRANSPORT_STATE_ALL);
    writable_ = writable;
    SignalWritableState(this);
  }
}

TransportState Transport::GetTransportState_s(bool read) {
  ASSERT(signaling_thread()->IsCurrent());
  rtc::CritScope cs(&crit_);
  bool any = false;
  bool all = !channels_.empty();
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end();
       ++iter) {
    bool b = (read ? iter->second->readable() :
      iter->second->writable());
    any = any || b;
    all = all && b;
  }
  if (all) {
    return TRANSPORT_STATE_ALL;
  } else if (any) {
    return TRANSPORT_STATE_SOME;
  } else {
    return TRANSPORT_STATE_NONE;
  }
}

void Transport::OnChannelRequestSignaling(TransportChannelImpl* channel) {
  ASSERT(worker_thread()->IsCurrent());
  ChannelParams* params = new ChannelParams(channel->component());
  signaling_thread()->Post(this, MSG_REQUESTSIGNALING, params);
}

void Transport::OnChannelRequestSignaling_s(int component) {
  ASSERT(signaling_thread()->IsCurrent());
  LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates";
  // Resetting ICE state for the channel.
  {
    rtc::CritScope cs(&crit_);
    ChannelMap::iterator iter = channels_.find(component);
    if (iter != channels_.end())
      iter->second.set_candidates_allocated(false);
  }
  SignalRequestSignaling(this);
}

void Transport::OnChannelCandidateReady(TransportChannelImpl* channel,
                                        const Candidate& candidate) {
  ASSERT(worker_thread()->IsCurrent());
  rtc::CritScope cs(&crit_);
  ready_candidates_.push_back(candidate);

  // We hold any messages until the client lets us connect.
  if (connect_requested_) {
    signaling_thread()->Post(
        this, MSG_CANDIDATEREADY, NULL);
  }
}

void Transport::OnChannelCandidateReady_s() {
  ASSERT(signaling_thread()->IsCurrent());
  ASSERT(connect_requested_);

  std::vector<Candidate> candidates;
  {
    rtc::CritScope cs(&crit_);
    candidates.swap(ready_candidates_);
  }

  // we do the deleting of Candidate* here to keep the new above and
  // delete below close to each other
  if (!candidates.empty()) {
    SignalCandidatesReady(this, candidates);
  }
}

void Transport::OnChannelRouteChange(TransportChannel* channel,
                                     const Candidate& remote_candidate) {
  ASSERT(worker_thread()->IsCurrent());
  ChannelParams* params = new ChannelParams(new Candidate(remote_candidate));
  params->channel = static_cast<cricket::TransportChannelImpl*>(channel);
  signaling_thread()->Post(this, MSG_ROUTECHANGE, params);
}

void Transport::OnChannelRouteChange_s(const TransportChannel* channel,
                                       const Candidate& remote_candidate) {
  ASSERT(signaling_thread()->IsCurrent());
  SignalRouteChange(this, remote_candidate.component(), remote_candidate);
}

void Transport::OnChannelCandidatesAllocationDone(
    TransportChannelImpl* channel) {
  ASSERT(worker_thread()->IsCurrent());
  rtc::CritScope cs(&crit_);
  ChannelMap::iterator iter = channels_.find(channel->component());
  ASSERT(iter != channels_.end());
  LOG(LS_INFO) << "Transport: " << content_name_ << ", component "
               << channel->component() << " allocation complete";
  iter->second.set_candidates_allocated(true);

  // If all channels belonging to this Transport got signal, then
  // forward this signal to upper layer.
  // Can this signal arrive before all transport channels are created?
  for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
    if (!iter->second.candidates_allocated())
      return;
  }
  signaling_thread_->Post(this, MSG_CANDIDATEALLOCATIONCOMPLETE);

  MaybeCompleted_w();
}

void Transport::OnChannelCandidatesAllocationDone_s() {
  ASSERT(signaling_thread()->IsCurrent());
  LOG(LS_INFO) << "Transport: " << content_name_ << " allocation complete";
  SignalCandidatesAllocationDone(this);
}

void Transport::OnRoleConflict(TransportChannelImpl* channel) {
  signaling_thread_->Post(this, MSG_ROLECONFLICT);
}

void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) {
  ASSERT(worker_thread()->IsCurrent());
  MaybeCompleted_w();

  // Check if the state is now Failed.
  // Failed is only available in the Controlling ICE role.
  if (channel->GetIceRole() != ICEROLE_CONTROLLING) {
    return;
  }

  ChannelMap::iterator iter = channels_.find(channel->component());
  ASSERT(iter != channels_.end());
  // Failed can only occur after candidate allocation has stopped.
  if (!iter->second.candidates_allocated()) {
    return;
  }

  size_t connections = channel->GetConnectionCount();
  if (connections == 0) {
    // A Transport has failed if any of its channels have no remaining
    // connections.
    signaling_thread_->Post(this, MSG_FAILED);
  }
}

void Transport::MaybeCompleted_w() {
  ASSERT(worker_thread()->IsCurrent());

  // A Transport's ICE process is completed if all of its channels are writable,
  // have finished allocating candidates, and have pruned all but one of their
  // connections.
  ChannelMap::const_iterator iter;
  for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
    const TransportChannelImpl* channel = iter->second.get();
    if (!(channel->writable() &&
          channel->GetConnectionCount() == 1 &&
          channel->GetIceRole() == ICEROLE_CONTROLLING &&
          iter->second.candidates_allocated())) {
      return;
    }
  }

  signaling_thread_->Post(this, MSG_COMPLETED);
}

void Transport::SetIceRole_w(IceRole role) {
  rtc::CritScope cs(&crit_);
  ice_role_ = role;
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end(); ++iter) {
    iter->second->SetIceRole(ice_role_);
  }
}

void Transport::SetRemoteIceMode_w(IceMode mode) {
  rtc::CritScope cs(&crit_);
  remote_ice_mode_ = mode;
  // Shouldn't channels be created after this method executed?
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end(); ++iter) {
    iter->second->SetRemoteIceMode(remote_ice_mode_);
  }
}

bool Transport::SetLocalTransportDescription_w(
    const TransportDescription& desc,
    ContentAction action,
    std::string* error_desc) {
  bool ret = true;
  rtc::CritScope cs(&crit_);

  if (!VerifyIceParams(desc)) {
    return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
                                   error_desc);
  }

  if (local_description_ && IceCredentialsChanged(*local_description_, desc)) {
    IceRole new_ice_role = (action == CA_OFFER) ? ICEROLE_CONTROLLING
                                                : ICEROLE_CONTROLLED;

    // It must be called before ApplyLocalTransportDescription_w, which may
    // trigger an ICE restart and depends on the new ICE role.
    SetIceRole_w(new_ice_role);
  }

  local_description_.reset(new TransportDescription(desc));

  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end(); ++iter) {
    ret &= ApplyLocalTransportDescription_w(iter->second.get(), error_desc);
  }
  if (!ret)
    return false;

  // If PRANSWER/ANSWER is set, we should decide transport protocol type.
  if (action == CA_PRANSWER || action == CA_ANSWER) {
    ret &= NegotiateTransportDescription_w(action, error_desc);
  }
  return ret;
}

bool Transport::SetRemoteTransportDescription_w(
    const TransportDescription& desc,
    ContentAction action,
    std::string* error_desc) {
  bool ret = true;
  rtc::CritScope cs(&crit_);

  if (!VerifyIceParams(desc)) {
    return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
                                   error_desc);
  }

  remote_description_.reset(new TransportDescription(desc));
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end(); ++iter) {
    ret &= ApplyRemoteTransportDescription_w(iter->second.get(), error_desc);
  }

  // If PRANSWER/ANSWER is set, we should decide transport protocol type.
  if (action == CA_PRANSWER || action == CA_ANSWER) {
    ret = NegotiateTransportDescription_w(CA_OFFER, error_desc);
  }
  return ret;
}

bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch,
                                                 std::string* error_desc) {
  // If existing protocol_type is HYBRID, we may have not chosen the final
  // protocol type, so update the channel protocol type from the
  // local description. Otherwise, skip updating the protocol type.
  // We check for HYBRID to avoid accidental changes; in the case of a
  // session renegotiation, the new offer will have the google-ice ICE option,
  // so we need to make sure we don't switch back from ICE mode to HYBRID
  // when this happens.
  // There are some other ways we could have solved this, but this is the
  // simplest. The ultimate solution will be to get rid of GICE altogether.
  IceProtocolType protocol_type;
  if (ch->GetIceProtocolType(&protocol_type) &&
      protocol_type == ICEPROTO_HYBRID) {
    ch->SetIceProtocolType(
        TransportProtocolFromDescription(local_description()));
  }
  ch->SetIceCredentials(local_description_->ice_ufrag,
                        local_description_->ice_pwd);
  return true;
}

bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
                                                  std::string* error_desc) {
  ch->SetRemoteIceCredentials(remote_description_->ice_ufrag,
                              remote_description_->ice_pwd);
  return true;
}

bool Transport::ApplyNegotiatedTransportDescription_w(
    TransportChannelImpl* channel, std::string* error_desc) {
  channel->SetIceProtocolType(protocol_);
  channel->SetRemoteIceMode(remote_ice_mode_);
  return true;
}

bool Transport::NegotiateTransportDescription_w(ContentAction local_role,
                                                std::string* error_desc) {
  // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
  // P2PTransport.
  const TransportDescription* offer;
  const TransportDescription* answer;

  if (local_role == CA_OFFER) {
    offer = local_description_.get();
    answer = remote_description_.get();
  } else {
    offer = remote_description_.get();
    answer = local_description_.get();
  }

  TransportProtocol offer_proto = TransportProtocolFromDescription(offer);
  TransportProtocol answer_proto = TransportProtocolFromDescription(answer);

  // If offered protocol is gice/ice, then we expect to receive matching
  // protocol in answer, anything else is treated as an error.
  // HYBRID is not an option when offered specific protocol.
  // If offered protocol is HYBRID and answered protocol is HYBRID then
  // gice is preferred protocol.
  // TODO(mallinath) - Answer from local or remote should't have both ice
  // and gice support. It should always pick which protocol it wants to use.
  // Once WebRTC stops supporting gice (for backward compatibility), HYBRID in
  // answer must be treated as error.
  if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) &&
      (offer_proto != answer_proto)) {
    std::ostringstream desc;
    desc << "Offer and answer protocol mismatch: "
         << IceProtoToString(offer_proto)
         << " vs "
         << IceProtoToString(answer_proto);
    return BadTransportDescription(desc.str(), error_desc);
  }
  protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto;

  // If transport is in ICEROLE_CONTROLLED and remote end point supports only
  // ice_lite, this local end point should take CONTROLLING role.
  if (ice_role_ == ICEROLE_CONTROLLED &&
      remote_description_->ice_mode == ICEMODE_LITE) {
    SetIceRole_w(ICEROLE_CONTROLLING);
  }

  // Update remote ice_mode to all existing channels.
  remote_ice_mode_ = remote_description_->ice_mode;

  // Now that we have negotiated everything, push it downward.
  // Note that we cache the result so that if we have race conditions
  // between future SetRemote/SetLocal invocations and new channel
  // creation, we have the negotiation state saved until a new
  // negotiation happens.
  for (ChannelMap::iterator iter = channels_.begin();
       iter != channels_.end();
       ++iter) {
    if (!ApplyNegotiatedTransportDescription_w(iter->second.get(), error_desc))
      return false;
  }
  return true;
}

void Transport::OnMessage(rtc::Message* msg) {
  switch (msg->message_id) {
    case MSG_ONSIGNALINGREADY:
      CallChannels_w(&TransportChannelImpl::OnSignalingReady);
      break;
    case MSG_ONREMOTECANDIDATE: {
        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
        OnRemoteCandidate_w(*params->candidate);
        delete params;
      }
      break;
    case MSG_CONNECTING:
      OnConnecting_s();
      break;
    case MSG_READSTATE:
      OnChannelReadableState_s();
      break;
    case MSG_WRITESTATE:
      OnChannelWritableState_s();
      break;
    case MSG_REQUESTSIGNALING: {
        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
        OnChannelRequestSignaling_s(params->component);
        delete params;
      }
      break;
    case MSG_CANDIDATEREADY:
      OnChannelCandidateReady_s();
      break;
    case MSG_ROUTECHANGE: {
        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
        OnChannelRouteChange_s(params->channel, *params->candidate);
        delete params;
      }
      break;
    case MSG_CANDIDATEALLOCATIONCOMPLETE:
      OnChannelCandidatesAllocationDone_s();
      break;
    case MSG_ROLECONFLICT:
      SignalRoleConflict();
      break;
    case MSG_COMPLETED:
      SignalCompleted(this);
      break;
    case MSG_FAILED:
      SignalFailed(this);
      break;
  }
}

bool TransportParser::ParseAddress(const buzz::XmlElement* elem,
                                   const buzz::QName& address_name,
                                   const buzz::QName& port_name,
                                   rtc::SocketAddress* address,
                                   ParseError* error) {
  if (!elem->HasAttr(address_name))
    return BadParse("address does not have " + address_name.LocalPart(), error);
  if (!elem->HasAttr(port_name))
    return BadParse("address does not have " + port_name.LocalPart(), error);

  address->SetIP(elem->Attr(address_name));
  std::istringstream ist(elem->Attr(port_name));
  int port = 0;
  ist >> port;
  address->SetPort(port);

  return true;
}

// We're GICE if the namespace is NS_GOOGLE_P2P, or if NS_JINGLE_ICE_UDP is
// used and the GICE ice-option is set.
TransportProtocol TransportProtocolFromDescription(
    const TransportDescription* desc) {
  ASSERT(desc != NULL);
  if (desc->transport_type == NS_JINGLE_ICE_UDP) {
    return (desc->HasOption(ICE_OPTION_GICE)) ?
        ICEPROTO_HYBRID : ICEPROTO_RFC5245;
  }
  return ICEPROTO_GOOGLE;
}

}  // namespace cricket
