10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
37ce0f9ed8df94129fddd70cdf0a53aa86d6b9d48fischman@webrtc.org * Copyright 2004, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/transport.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/candidate.h"
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/constants.h"
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/parsing.h"
3358c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org#include "talk/p2p/base/port.h"
34cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/p2p/base/sessionmanager.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/transportchannelimpl.h"
3613b2d035e2e7f2f18e3a4d3377bc1a09f43a4ff9buildbot@webrtc.org#include "webrtc/libjingle/xmllite/xmlelement.h"
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/constants.h"
38cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/bind.h"
39cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/common.h"
40cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h"
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgusing rtc::Bind;
452007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum {
472007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_ONSIGNALINGREADY = 1,
482007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_ONREMOTECANDIDATE,
492007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_READSTATE,
502007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_WRITESTATE,
512007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_REQUESTSIGNALING,
522007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_CANDIDATEREADY,
532007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_ROUTECHANGE,
542007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_CONNECTING,
552007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_CANDIDATEALLOCATIONCOMPLETE,
562007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  MSG_ROLECONFLICT,
57f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  MSG_COMPLETED,
58f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  MSG_FAILED,
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgstruct ChannelParams : public rtc::MessageData {
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelParams() : channel(NULL), candidate(NULL) {}
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  explicit ChannelParams(int component)
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      : component(component), channel(NULL), candidate(NULL) {}
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  explicit ChannelParams(Candidate* candidate)
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      : channel(NULL), candidate(candidate) {
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~ChannelParams() {
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete candidate;
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string name;
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int component;
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportChannelImpl* channel;
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Candidate* candidate;
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
79f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgstatic std::string IceProtoToString(TransportProtocol proto) {
80f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  std::string proto_str;
81f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  switch (proto) {
82f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    case ICEPROTO_GOOGLE:
83f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      proto_str = "gice";
84f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      break;
85f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    case ICEPROTO_HYBRID:
86f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      proto_str = "hybrid";
87f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      break;
88f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    case ICEPROTO_RFC5245:
89f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      proto_str = "ice";
90f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      break;
91f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    default:
92f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      ASSERT(false);
93f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      break;
94f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  }
95f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  return proto_str;
96f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org}
97f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org
983922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.orgstatic bool VerifyIceParams(const TransportDescription& desc) {
993922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  // For legacy protocols.
1003922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  if (desc.ice_ufrag.empty() && desc.ice_pwd.empty())
1013922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org    return true;
1023922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org
1033922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  if (desc.ice_ufrag.length() < ICE_UFRAG_MIN_LENGTH ||
1043922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org      desc.ice_ufrag.length() > ICE_UFRAG_MAX_LENGTH) {
1053922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org    return false;
1063922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  }
1073922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  if (desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH ||
1083922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org      desc.ice_pwd.length() > ICE_PWD_MAX_LENGTH) {
1093922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org    return false;
1103922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  }
1113922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  return true;
1123922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org}
1133922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org
114f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool BadTransportDescription(const std::string& desc, std::string* err_desc) {
115f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  if (err_desc) {
116f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    *err_desc = desc;
117f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  }
118f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  LOG(LS_ERROR) << desc;
119f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  return false;
120f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org}
121f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org
12239c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.orgbool IceCredentialsChanged(const std::string& old_ufrag,
12339c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org                           const std::string& old_pwd,
12439c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org                           const std::string& new_ufrag,
12539c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org                           const std::string& new_pwd) {
12639c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  // TODO(jiayl): The standard (RFC 5245 Section 9.1.1.1) says that ICE should
12739c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  // restart when both the ufrag and password are changed, but we do restart
12839c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  // when either ufrag or passwrod is changed to keep compatible with GICE. We
12939c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  // should clean this up when GICE is no longer used.
13039c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  return (old_ufrag != new_ufrag) || (old_pwd != new_pwd);
13139c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org}
13239c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org
13339c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.orgstatic bool IceCredentialsChanged(const TransportDescription& old_desc,
13439c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org                                  const TransportDescription& new_desc) {
13539c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd,
13639c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org                               new_desc.ice_ufrag, new_desc.ice_pwd);
13739c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org}
13839c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org
1392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgTransport::Transport(rtc::Thread* signaling_thread,
1402a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                     rtc::Thread* worker_thread,
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     const std::string& content_name,
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     const std::string& type,
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     PortAllocator* allocator)
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  : signaling_thread_(signaling_thread),
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    worker_thread_(worker_thread),
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    content_name_(content_name),
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    type_(type),
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    allocator_(allocator),
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    destroyed_(false),
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    readable_(TRANSPORT_STATE_NONE),
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    writable_(TRANSPORT_STATE_NONE),
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    was_writable_(false),
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    connect_requested_(false),
154e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    ice_role_(ICEROLE_UNKNOWN),
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tiebreaker_(0),
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    protocol_(ICEPROTO_HYBRID),
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    remote_ice_mode_(ICEMODE_FULL) {
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransport::~Transport() {
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread_->IsCurrent());
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(destroyed_);
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
165e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.orgvoid Transport::SetIceRole(IceRole role) {
1662007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  worker_thread_->Invoke<void>(Bind(&Transport::SetIceRole_w, this, role));
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1692a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid Transport::SetIdentity(rtc::SSLIdentity* identity) {
1702007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  worker_thread_->Invoke<void>(Bind(&Transport::SetIdentity_w, this, identity));
1715aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org}
1725aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org
1732a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool Transport::GetIdentity(rtc::SSLIdentity** identity) {
17462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  // The identity is set on the worker thread, so for safety it must also be
17562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  // acquired on the worker thread.
17662fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  return worker_thread_->Invoke<bool>(
17762fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org      Bind(&Transport::GetIdentity_w, this, identity));
17862fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org}
17962fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
1802a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) {
18162fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  // Channels can be deleted on the worker thread, so for safety the remote
18262fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  // certificate is acquired on the worker thread.
18362fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  return worker_thread_->Invoke<bool>(
18462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org      Bind(&Transport::GetRemoteCertificate_w, this, cert));
18562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org}
18662fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
1872a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool Transport::GetRemoteCertificate_w(rtc::SSLCertificate** cert) {
18862fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  ASSERT(worker_thread()->IsCurrent());
18962fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  if (channels_.empty())
19062fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    return false;
19162fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
19262fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  ChannelMap::iterator iter = channels_.begin();
19362fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  return iter->second->GetRemoteCertificate(cert);
19462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org}
19562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::SetLocalTransportDescription(
197f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    const TransportDescription& description,
198f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ContentAction action,
199f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    std::string* error_desc) {
2002007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  return worker_thread_->Invoke<bool>(Bind(
201f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      &Transport::SetLocalTransportDescription_w, this,
202f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      description, action, error_desc));
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::SetRemoteTransportDescription(
206f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    const TransportDescription& description,
207f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ContentAction action,
208f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    std::string* error_desc) {
2092007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  return worker_thread_->Invoke<bool>(Bind(
210f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      &Transport::SetRemoteTransportDescription_w, this,
211f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      description, action, error_desc));
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransportChannelImpl* Transport::CreateChannel(int component) {
2152007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  return worker_thread_->Invoke<TransportChannelImpl*>(Bind(
2162007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      &Transport::CreateChannel_w, this, component));
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransportChannelImpl* Transport::CreateChannel_w(int component) {
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportChannelImpl *impl;
2222a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Create the entry if it does not exist.
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool impl_exists = false;
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channels_.find(component) == channels_.end()) {
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    impl = CreateTransportChannel(component);
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    channels_[component] = ChannelMapEntry(impl);
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    impl = channels_[component].get();
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    impl_exists = true;
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Increase the ref count.
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channels_[component].AddRef();
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  destroyed_ = false;
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (impl_exists) {
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If this is an existing channel, we should just return it without
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // connecting to all the signal again.
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return impl;
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Push down our transport state to the new channel.
245e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  impl->SetIceRole(ice_role_);
246e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  impl->SetIceTiebreaker(tiebreaker_);
247b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // TODO(ronghuawu): Change CreateChannel_w to be able to return error since
248b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // below Apply**Description_w calls can fail.
249b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (local_description_)
250f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ApplyLocalTransportDescription_w(impl, NULL);
251b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (remote_description_)
252b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    ApplyRemoteTransportDescription_w(impl, NULL);
253b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (local_description_ && remote_description_)
254b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    ApplyNegotiatedTransportDescription_w(impl, NULL);
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState);
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState);
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalRequestSignaling.connect(
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &Transport::OnChannelRequestSignaling);
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady);
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange);
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalCandidatesAllocationDone.connect(
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &Transport::OnChannelCandidatesAllocationDone);
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict);
265f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  impl->SignalConnectionRemoved.connect(
266f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      this, &Transport::OnChannelConnectionRemoved);
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connect_requested_) {
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    impl->Connect();
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (channels_.size() == 1) {
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // If this is the first channel, then indicate that we have started
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // connecting.
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      signaling_thread()->Post(this, MSG_CONNECTING, NULL);
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return impl;
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransportChannelImpl* Transport::GetChannel(int component) {
2802a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelMap::iterator iter = channels_.find(component);
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (iter != channels_.end()) ? iter->second.get() : NULL;
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::HasChannels() {
2862a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return !channels_.empty();
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::DestroyChannel(int component) {
2912007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  worker_thread_->Invoke<void>(Bind(
2922007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      &Transport::DestroyChannel_w, this, component));
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::DestroyChannel_w(int component) {
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportChannelImpl* impl = NULL;
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  {
3002a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&crit_);
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ChannelMap::iterator iter = channels_.find(component);
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (iter == channels_.end())
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iter->second.DecRef();
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!iter->second.ref()) {
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      impl = iter->second.get();
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      channels_.erase(iter);
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connect_requested_ && channels_.empty()) {
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We're no longer attempting to connect.
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    signaling_thread()->Post(this, MSG_CONNECTING, NULL);
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (impl) {
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Check in case the deleted channel was the only non-writable channel.
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnChannelWritableState(impl);
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    DestroyTransportChannel(impl);
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::ConnectChannels() {
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
3262007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  worker_thread_->Invoke<void>(Bind(&Transport::ConnectChannels_w, this));
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::ConnectChannels_w() {
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connect_requested_ || channels_.empty())
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  connect_requested_ = true;
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread()->Post(
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, MSG_CANDIDATEREADY, NULL);
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!local_description_) {
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here.
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // As Transport must know TD is offer or answer and cricket::Transport
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // doesn't have the capability to decide it. This should be set by the
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Session.
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Session must generate local TD before remote candidates pushed when
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // initiate request initiated by the remote.
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Transport::ConnectChannels_w: No local description has "
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << "been set. Will generate one.";
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportDescription desc(NS_GINGLE_P2P, std::vector<std::string>(),
3472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                              rtc::CreateRandomString(ICE_UFRAG_LENGTH),
3482a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                              rtc::CreateRandomString(ICE_PWD_LENGTH),
349a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org                              ICEMODE_FULL, CONNECTIONROLE_NONE, NULL,
350a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org                              Candidates());
351f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    SetLocalTransportDescription_w(desc, CA_OFFER, NULL);
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CallChannels_w(&TransportChannelImpl::Connect);
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!channels_.empty()) {
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    signaling_thread()->Post(this, MSG_CONNECTING, NULL);
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnConnecting_s() {
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalConnecting(this);
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::DestroyAllChannels() {
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
3672007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  worker_thread_->Invoke<void>(
3682007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      Bind(&Transport::DestroyAllChannels_w, this));
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread()->Clear(this);
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread()->Clear(this);
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  destroyed_ = true;
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::DestroyAllChannels_w() {
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<TransportChannelImpl*> impls;
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  {
3782a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&crit_);
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (ChannelMap::iterator iter = channels_.begin();
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         iter != channels_.end();
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         ++iter) {
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      iter->second.DecRef();
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!iter->second.ref())
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        impls.push_back(iter->second.get());
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channels_.clear();
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < impls.size(); ++i)
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    DestroyTransportChannel(impls[i]);
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::ResetChannels() {
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
3962007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  worker_thread_->Invoke<void>(Bind(&Transport::ResetChannels_w, this));
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::ResetChannels_w() {
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We are no longer attempting to connect
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  connect_requested_ = false;
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Clear out the old messages, they aren't relevant
4062a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ready_candidates_.clear();
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Reset all of the channels
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CallChannels_w(&TransportChannelImpl::Reset);
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnSignalingReady() {
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (destroyed_) return;
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL);
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Notify the subclass.
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  OnTransportSignalingReady();
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::CallChannels_w(TransportChannelFunc func) {
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
4252a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end();
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       ++iter) {
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ((iter->second.get())->*func)();
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::VerifyCandidate(const Candidate& cand, std::string* error) {
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // No address zero.
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (cand.address().IsNil() || cand.address().IsAny()) {
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *error = "candidate has address of zero";
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Disallow all ports below 1024, except for 80 and 443 on public addresses.
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int port = cand.address().port();
44258c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org  if (cand.protocol() == TCP_PROTOCOL_NAME &&
44358c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org      (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) {
4447ce0f9ed8df94129fddd70cdf0a53aa86d6b9d48fischman@webrtc.org    // Expected for active-only candidates per
4457ce0f9ed8df94129fddd70cdf0a53aa86d6b9d48fischman@webrtc.org    // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
44658c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org    // Libjingle clients emit port 0, in "active" mode.
44758c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org    return true;
4487ce0f9ed8df94129fddd70cdf0a53aa86d6b9d48fischman@webrtc.org  }
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port < 1024) {
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((port != 80) && (port != 443)) {
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *error = "candidate has port below 1024, but not 80 or 443";
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (cand.address().IsPrivateIP()) {
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *error = "candidate has port of 80 or 443 with private IP address";
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::GetStats(TransportStats* stats) {
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
4672007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  return worker_thread_->Invoke<bool>(Bind(
4682007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      &Transport::GetStats_w, this, stats));
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::GetStats_w(TransportStats* stats) {
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stats->content_name = content_name();
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stats->channel_stats.clear();
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end();
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       ++iter) {
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelStats substats;
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    substats.component = iter->second->component();
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!iter->second->GetStats(&substats.connection_infos)) {
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stats->channel_stats.push_back(substats);
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool Transport::GetSslRole(rtc::SSLRole* ssl_role) const {
4892007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org  return worker_thread_->Invoke<bool>(Bind(
4902007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org      &Transport::GetSslRole_w, this, ssl_role));
491a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org}
492a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnRemoteCandidates(const std::vector<Candidate>& candidates) {
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<Candidate>::const_iterator iter = candidates.begin();
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != candidates.end();
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       ++iter) {
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnRemoteCandidate(*iter);
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnRemoteCandidate(const Candidate& candidate) {
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (destroyed_) return;
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!HasChannel(candidate.component())) {
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Ignoring candidate for unknown component "
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << candidate.component();
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelParams* params = new ChannelParams(new Candidate(candidate));
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, params);
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnRemoteCandidate_w(const Candidate& candidate) {
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelMap::iterator iter = channels_.find(candidate.component());
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // It's ok for a channel to go away while this message is in transit.
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (iter != channels_.end()) {
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iter->second->OnCandidate(candidate);
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelReadableState(TransportChannel* channel) {
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread()->Post(this, MSG_READSTATE, NULL);
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelReadableState_s() {
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportState readable = GetTransportState_s(true);
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (readable_ != readable) {
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    readable_ = readable;
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalReadableState(this);
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelWritableState(TransportChannel* channel) {
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread()->Post(this, MSG_WRITESTATE, NULL);
541b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org
542b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  MaybeCompleted_w();
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelWritableState_s() {
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportState writable = GetTransportState_s(false);
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (writable_ != writable) {
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    was_writable_ = (writable_ == TRANSPORT_STATE_ALL);
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    writable_ = writable;
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalWritableState(this);
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransportState Transport::GetTransportState_s(bool read) {
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
5572a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool any = false;
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool all = !channels_.empty();
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end();
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       ++iter) {
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    bool b = (read ? iter->second->readable() :
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      iter->second->writable());
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    any = any || b;
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    all = all && b;
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (all) {
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return TRANSPORT_STATE_ALL;
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (any) {
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return TRANSPORT_STATE_SOME;
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return TRANSPORT_STATE_NONE;
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelRequestSignaling(TransportChannelImpl* channel) {
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelParams* params = new ChannelParams(channel->component());
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread()->Post(this, MSG_REQUESTSIGNALING, params);
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelRequestSignaling_s(int component) {
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates";
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Resetting ICE state for the channel.
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  {
5882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&crit_);
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ChannelMap::iterator iter = channels_.find(component);
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (iter != channels_.end())
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      iter->second.set_candidates_allocated(false);
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalRequestSignaling(this);
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelCandidateReady(TransportChannelImpl* channel,
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        const Candidate& candidate) {
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
5992a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ready_candidates_.push_back(candidate);
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We hold any messages until the client lets us connect.
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connect_requested_) {
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    signaling_thread()->Post(
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, MSG_CANDIDATEREADY, NULL);
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelCandidateReady_s() {
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(connect_requested_);
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<Candidate> candidates;
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  {
6152a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&crit_);
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    candidates.swap(ready_candidates_);
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // we do the deleting of Candidate* here to keep the new above and
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // delete below close to each other
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!candidates.empty()) {
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalCandidatesReady(this, candidates);
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelRouteChange(TransportChannel* channel,
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     const Candidate& remote_candidate) {
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelParams* params = new ChannelParams(new Candidate(remote_candidate));
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  params->channel = static_cast<cricket::TransportChannelImpl*>(channel);
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread()->Post(this, MSG_ROUTECHANGE, params);
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelRouteChange_s(const TransportChannel* channel,
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       const Candidate& remote_candidate) {
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalRouteChange(this, remote_candidate.component(), remote_candidate);
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelCandidatesAllocationDone(
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelImpl* channel) {
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
6432a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelMap::iterator iter = channels_.find(channel->component());
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(iter != channels_.end());
6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Transport: " << content_name_ << ", component "
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << channel->component() << " allocation complete";
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  iter->second.set_candidates_allocated(true);
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If all channels belonging to this Transport got signal, then
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // forward this signal to upper layer.
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Can this signal arrive before all transport channels are created?
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!iter->second.candidates_allocated())
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread_->Post(this, MSG_CANDIDATEALLOCATIONCOMPLETE);
658b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org
659b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  MaybeCompleted_w();
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnChannelCandidatesAllocationDone_s() {
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Transport: " << content_name_ << " allocation complete";
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalCandidatesAllocationDone(this);
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::OnRoleConflict(TransportChannelImpl* channel) {
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signaling_thread_->Post(this, MSG_ROLECONFLICT);
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
672f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.orgvoid Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) {
673f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  ASSERT(worker_thread()->IsCurrent());
674b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  MaybeCompleted_w();
675b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org
676b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  // Check if the state is now Failed.
677b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  // Failed is only available in the Controlling ICE role.
678f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  if (channel->GetIceRole() != ICEROLE_CONTROLLING) {
679f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    return;
680f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  }
681f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org
682f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  ChannelMap::iterator iter = channels_.find(channel->component());
683f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  ASSERT(iter != channels_.end());
684b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  // Failed can only occur after candidate allocation has stopped.
685f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  if (!iter->second.candidates_allocated()) {
686f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    return;
687f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  }
688f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org
689f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  size_t connections = channel->GetConnectionCount();
690f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  if (connections == 0) {
691f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    // A Transport has failed if any of its channels have no remaining
692f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    // connections.
693f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    signaling_thread_->Post(this, MSG_FAILED);
694f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  }
695f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org}
696f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org
697b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.orgvoid Transport::MaybeCompleted_w() {
698b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  ASSERT(worker_thread()->IsCurrent());
699b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org
700f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  // A Transport's ICE process is completed if all of its channels are writable,
701f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  // have finished allocating candidates, and have pruned all but one of their
702f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  // connections.
703f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  ChannelMap::const_iterator iter;
704f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
705f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    const TransportChannelImpl* channel = iter->second.get();
706b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org    if (!(channel->writable() &&
707b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org          channel->GetConnectionCount() == 1 &&
708f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org          channel->GetIceRole() == ICEROLE_CONTROLLING &&
709f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org          iter->second.candidates_allocated())) {
710b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org      return;
711f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    }
712f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  }
713b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org
714b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  signaling_thread_->Post(this, MSG_COMPLETED);
715f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org}
716f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org
717e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.orgvoid Transport::SetIceRole_w(IceRole role) {
7182a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
719e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  ice_role_ = role;
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end(); ++iter) {
722e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    iter->second->SetIceRole(ice_role_);
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid Transport::SetRemoteIceMode_w(IceMode mode) {
7272a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_ice_mode_ = mode;
7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Shouldn't channels be created after this method executed?
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end(); ++iter) {
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iter->second->SetRemoteIceMode(remote_ice_mode_);
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::SetLocalTransportDescription_w(
737f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    const TransportDescription& desc,
738f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ContentAction action,
739f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    std::string* error_desc) {
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool ret = true;
7412a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7433922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  if (!VerifyIceParams(desc)) {
7443922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org    return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
7453922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org                                   error_desc);
7463922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  }
7473922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org
74839c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  if (local_description_ && IceCredentialsChanged(*local_description_, desc)) {
74939c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org    IceRole new_ice_role = (action == CA_OFFER) ? ICEROLE_CONTROLLING
75039c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org                                                : ICEROLE_CONTROLLED;
75139c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org
75239c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org    // It must be called before ApplyLocalTransportDescription_w, which may
75339c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org    // trigger an ICE restart and depends on the new ICE role.
75439c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org    SetIceRole_w(new_ice_role);
75539c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org  }
75639c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org
7573922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  local_description_.reset(new TransportDescription(desc));
75839c443b6209621f0e8537e14514cc4c8b1dd5fadjiayl@webrtc.org
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end(); ++iter) {
761f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ret &= ApplyLocalTransportDescription_w(iter->second.get(), error_desc);
7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ret)
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If PRANSWER/ANSWER is set, we should decide transport protocol type.
7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (action == CA_PRANSWER || action == CA_ANSWER) {
768f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ret &= NegotiateTransportDescription_w(action, error_desc);
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool Transport::SetRemoteTransportDescription_w(
774f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    const TransportDescription& desc,
775f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ContentAction action,
776f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    std::string* error_desc) {
7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool ret = true;
7782a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&crit_);
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7803922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  if (!VerifyIceParams(desc)) {
7813922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org    return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
7823922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org                                   error_desc);
7833922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  }
7843922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org
7853922cbc3a79d8ed6052eaeaf3e3f297096162f10buildbot@webrtc.org  remote_description_.reset(new TransportDescription(desc));
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end(); ++iter) {
788f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ret &= ApplyRemoteTransportDescription_w(iter->second.get(), error_desc);
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If PRANSWER/ANSWER is set, we should decide transport protocol type.
7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (action == CA_PRANSWER || action == CA_ANSWER) {
793f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    ret = NegotiateTransportDescription_w(CA_OFFER, error_desc);
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
798f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch,
799f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                                 std::string* error_desc) {
800b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // If existing protocol_type is HYBRID, we may have not chosen the final
801b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // protocol type, so update the channel protocol type from the
802b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // local description. Otherwise, skip updating the protocol type.
803b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // We check for HYBRID to avoid accidental changes; in the case of a
804b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // session renegotiation, the new offer will have the google-ice ICE option,
805b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // so we need to make sure we don't switch back from ICE mode to HYBRID
806b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // when this happens.
807b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // There are some other ways we could have solved this, but this is the
808b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // simplest. The ultimate solution will be to get rid of GICE altogether.
809b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  IceProtocolType protocol_type;
810b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (ch->GetIceProtocolType(&protocol_type) &&
811b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      protocol_type == ICEPROTO_HYBRID) {
812b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    ch->SetIceProtocolType(
813b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        TransportProtocolFromDescription(local_description()));
814b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  }
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ch->SetIceCredentials(local_description_->ice_ufrag,
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        local_description_->ice_pwd);
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
820f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
821f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                                  std::string* error_desc) {
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ch->SetRemoteIceCredentials(remote_description_->ice_ufrag,
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              remote_description_->ice_pwd);
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
827a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.orgbool Transport::ApplyNegotiatedTransportDescription_w(
828f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    TransportChannelImpl* channel, std::string* error_desc) {
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel->SetIceProtocolType(protocol_);
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel->SetRemoteIceMode(remote_ice_mode_);
831a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  return true;
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
834f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool Transport::NegotiateTransportDescription_w(ContentAction local_role,
835f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                                std::string* error_desc) {
8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // P2PTransport.
8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const TransportDescription* offer;
8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const TransportDescription* answer;
8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
841a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  if (local_role == CA_OFFER) {
8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    offer = local_description_.get();
8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    answer = remote_description_.get();
8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    offer = remote_description_.get();
8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    answer = local_description_.get();
8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportProtocol offer_proto = TransportProtocolFromDescription(offer);
8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportProtocol answer_proto = TransportProtocolFromDescription(answer);
8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If offered protocol is gice/ice, then we expect to receive matching
8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // protocol in answer, anything else is treated as an error.
8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // HYBRID is not an option when offered specific protocol.
8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If offered protocol is HYBRID and answered protocol is HYBRID then
8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // gice is preferred protocol.
8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(mallinath) - Answer from local or remote should't have both ice
8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // and gice support. It should always pick which protocol it wants to use.
8590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Once WebRTC stops supporting gice (for backward compatibility), HYBRID in
8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // answer must be treated as error.
8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) &&
8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (offer_proto != answer_proto)) {
863f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    std::ostringstream desc;
864f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    desc << "Offer and answer protocol mismatch: "
865f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org         << IceProtoToString(offer_proto)
866f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org         << " vs "
867f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org         << IceProtoToString(answer_proto);
868f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    return BadTransportDescription(desc.str(), error_desc);
8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto;
8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
872e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  // If transport is in ICEROLE_CONTROLLED and remote end point supports only
8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // ice_lite, this local end point should take CONTROLLING role.
874e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  if (ice_role_ == ICEROLE_CONTROLLED &&
8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      remote_description_->ice_mode == ICEMODE_LITE) {
876e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    SetIceRole_w(ICEROLE_CONTROLLING);
8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Update remote ice_mode to all existing channels.
8800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_ice_mode_ = remote_description_->ice_mode;
8810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Now that we have negotiated everything, push it downward.
8830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Note that we cache the result so that if we have race conditions
8840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // between future SetRemote/SetLocal invocations and new channel
8850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // creation, we have the negotiation state saved until a new
8860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // negotiation happens.
8870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelMap::iterator iter = channels_.begin();
8880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != channels_.end();
8890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       ++iter) {
890f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    if (!ApplyNegotiatedTransportDescription_w(iter->second.get(), error_desc))
891a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      return false;
8920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8962a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid Transport::OnMessage(rtc::Message* msg) {
8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (msg->message_id) {
8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_ONSIGNALINGREADY:
8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CallChannels_w(&TransportChannelImpl::OnSignalingReady);
9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_ONREMOTECANDIDATE: {
9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
9030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        OnRemoteCandidate_w(*params->candidate);
9040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        delete params;
9050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
9060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_CONNECTING:
9080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      OnConnecting_s();
9090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_READSTATE:
9110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      OnChannelReadableState_s();
9120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_WRITESTATE:
9140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      OnChannelWritableState_s();
9150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_REQUESTSIGNALING: {
9170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
9180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        OnChannelRequestSignaling_s(params->component);
9190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        delete params;
9200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
9210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_CANDIDATEREADY:
9230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      OnChannelCandidateReady_s();
9240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_ROUTECHANGE: {
9260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
9270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        OnChannelRouteChange_s(params->channel, *params->candidate);
9280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        delete params;
9290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
9300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_CANDIDATEALLOCATIONCOMPLETE:
9320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      OnChannelCandidatesAllocationDone_s();
9330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case MSG_ROLECONFLICT:
9350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SignalRoleConflict();
9360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
937f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    case MSG_COMPLETED:
938f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      SignalCompleted(this);
939f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      break;
940f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    case MSG_FAILED:
941f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      SignalFailed(this);
942f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      break;
9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool TransportParser::ParseAddress(const buzz::XmlElement* elem,
9470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   const buzz::QName& address_name,
9480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   const buzz::QName& port_name,
9492a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                                   rtc::SocketAddress* address,
9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   ParseError* error) {
9510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!elem->HasAttr(address_name))
9520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadParse("address does not have " + address_name.LocalPart(), error);
9530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!elem->HasAttr(port_name))
9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadParse("address does not have " + port_name.LocalPart(), error);
9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  address->SetIP(elem->Attr(address_name));
9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::istringstream ist(elem->Attr(port_name));
9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int port = 0;
9590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ist >> port;
9600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  address->SetPort(port);
9610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
9630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// We're GICE if the namespace is NS_GOOGLE_P2P, or if NS_JINGLE_ICE_UDP is
9660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// used and the GICE ice-option is set.
9670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransportProtocol TransportProtocolFromDescription(
9680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const TransportDescription* desc) {
9690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(desc != NULL);
9700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (desc->transport_type == NS_JINGLE_ICE_UDP) {
9710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return (desc->HasOption(ICE_OPTION_GICE)) ?
9720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ICEPROTO_HYBRID : ICEPROTO_RFC5245;
9730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ICEPROTO_GOOGLE;
9750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
978