1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/*
2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *
4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */
10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/p2ptransportchannel.h"
12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
13cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef#include <algorithm>
14a58ea7806a039c14e1f92a0757123062963b44b1honghaiz#include <set>
15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/common.h"
16269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/relayport.h"  // For RELAY_PORT_TYPE.
17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/stunport.h"  // For STUN_PORT_TYPE.
18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/common.h"
19269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/crc32.h"
20269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h"
21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/stringencode.h"
2298f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/field_trial.h"
23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace {
25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// messages for queuing up work for ourselves
27a58ea7806a039c14e1f92a0757123062963b44b1honghaizenum { MSG_SORT = 1, MSG_CHECK_AND_PING };
28269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
29269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// The minimum improvement in RTT that justifies a switch.
30269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const double kMinImprovement = 10;
31269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgcricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port,
33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                         cricket::PortInterface* origin_port) {
34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!origin_port)
35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return cricket::PortInterface::ORIGIN_MESSAGE;
36269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  else if (port == origin_port)
37269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return cricket::PortInterface::ORIGIN_THIS_PORT;
38269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  else
39269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return cricket::PortInterface::ORIGIN_OTHER_PORT;
40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
41269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
42269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Compares two connections based only on static information about them.
43269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint CompareConnectionCandidates(cricket::Connection* a,
44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                cricket::Connection* b) {
45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Compare connection priority. Lower values get sorted last.
46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (a->priority() > b->priority())
47269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return 1;
48269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (a->priority() < b->priority())
49269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return -1;
50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
51269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If we're still tied at this point, prefer a younger generation.
52269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return (a->remote_candidate().generation() + a->port()->generation()) -
53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org         (b->remote_candidate().generation() + b->port()->generation());
54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
56a58ea7806a039c14e1f92a0757123062963b44b1honghaiz// Compare two connections based on their writing, receiving, and connected
57a58ea7806a039c14e1f92a0757123062963b44b1honghaiz// states.
58a58ea7806a039c14e1f92a0757123062963b44b1honghaizint CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) {
59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Sort based on write-state.  Better states have lower values.
60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (a->write_state() < b->write_state())
61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return 1;
62269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (a->write_state() > b->write_state())
63269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return -1;
64269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
65a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // We prefer a receiving connection to a non-receiving, higher-priority
66a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // connection when sorting connections and choosing which connection to
67a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // switch to.
68a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (a->receiving() && !b->receiving())
69a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    return 1;
70a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (!a->receiving() && b->receiving())
71a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    return -1;
72a58ea7806a039c14e1f92a0757123062963b44b1honghaiz
73be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // WARNING: Some complexity here about TCP reconnecting.
74be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // When a TCP connection fails because of a TCP socket disconnecting, the
75be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // active side of the connection will attempt to reconnect for 5 seconds while
76be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // pretending to be writable (the connection is not set to the unwritable
77be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // state).  On the passive side, the connection also remains writable even
78be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // though it is disconnected, and a new connection is created when the active
79be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // side connects.  At that point, there are two TCP connections on the passive
80be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // side: 1. the old, disconnected one that is pretending to be writable, and
81be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // 2.  the new, connected one that is maybe not yet writable.  For purposes of
82be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // pruning, pinging, and selecting the best connection, we want to treat the
83be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // new connection as "better" than the old one.  We could add a method called
84be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // something like Connection::ImReallyBadEvenThoughImWritable, but that is
85be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // equivalent to the existing Connection::connected(), which we already have.
86be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // So, in code throughout this file, we'll check whether the connection is
87be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // connected() or not, and if it is not, treat it as "worse" than a connected
88be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // one, even though it's writable.  In the code below, we're doing so to make
89be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // sure we treat a new writable connection as better than an old disconnected
90be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // connection.
91be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
92be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // In the case where we reconnect TCP connections, the original best
93be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // connection is disconnected without changing to WRITE_TIMEOUT. In this case,
94be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // the new connection, when it becomes writable, should have higher priority.
95be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  if (a->write_state() == cricket::Connection::STATE_WRITABLE &&
96be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      b->write_state() == cricket::Connection::STATE_WRITABLE) {
97be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    if (a->connected() && !b->connected()) {
98be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      return 1;
99be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    }
100be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    if (!a->connected() && b->connected()) {
101be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      return -1;
102be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    }
103be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
104a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  return 0;
105a58ea7806a039c14e1f92a0757123062963b44b1honghaiz}
106be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
107a58ea7806a039c14e1f92a0757123062963b44b1honghaizint CompareConnections(cricket::Connection* a, cricket::Connection* b) {
108a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  int state_cmp = CompareConnectionStates(a, b);
109a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (state_cmp != 0) {
110a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    return state_cmp;
111a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  }
112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Compare the candidate information.
113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return CompareConnectionCandidates(a, b);
114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Wraps the comparison connection into a less than operator that puts higher
117269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// priority writable connections first.
118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass ConnectionCompare {
119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public:
120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool operator()(const cricket::Connection *ca,
121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                  const cricket::Connection *cb) {
122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    cricket::Connection* a = const_cast<cricket::Connection*>(ca);
123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    cricket::Connection* b = const_cast<cricket::Connection*>(cb);
124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Compare first on writability and static preferences.
126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int cmp = CompareConnections(a, b);
127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (cmp > 0)
128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return true;
129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (cmp < 0)
130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return false;
131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Otherwise, sort based on latency estimate.
133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return a->rtt() < b->rtt();
134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Should we bother checking for the last connection that last received
136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // data? It would help rendezvous on the connection that is also receiving
137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // packets.
138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    //
139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // TODO: Yes we should definitely do this.  The TCP protocol gains
140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // efficiency by being used bidirectionally, as opposed to two separate
141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // unidirectional streams.  This test should probably occur before
142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // comparison of local prefs (assuming combined prefs are the same).  We
143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // need to be careful though, not to bounce back and forth with both sides
144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // trying to rendevous with the other.
145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org};
147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Determines whether we should switch between two connections, based first on
149a58ea7806a039c14e1f92a0757123062963b44b1honghaiz// connection states, static preferences, and then (if those are equal) on
150a58ea7806a039c14e1f92a0757123062963b44b1honghaiz// latency estimates.
151a58ea7806a039c14e1f92a0757123062963b44b1honghaizbool ShouldSwitch(cricket::Connection* a_conn,
152a58ea7806a039c14e1f92a0757123062963b44b1honghaiz                  cricket::Connection* b_conn,
153a58ea7806a039c14e1f92a0757123062963b44b1honghaiz                  cricket::IceRole ice_role) {
154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (a_conn == b_conn)
155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return false;
156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!a_conn || !b_conn)  // don't think the latter should happen
158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return true;
159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
160a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // We prefer to switch to a writable and receiving connection over a
161a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // non-writable or non-receiving connection, even if the latter has
162a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // been nominated by the controlling side.
163a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  int state_cmp = CompareConnectionStates(a_conn, b_conn);
164a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (state_cmp != 0) {
165a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    return state_cmp < 0;
166a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  }
167a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) {
168a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status";
169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return false;
170a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  }
171a58ea7806a039c14e1f92a0757123062963b44b1honghaiz
172a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn);
173a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (prefs_cmp != 0) {
174a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    return prefs_cmp < 0;
175a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  }
176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}  // unnamed namespace
181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace cricket {
183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
184b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
185b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// for pinging.  When the socket is writable, we will use only 1 Kbps because
186b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// we don't want to degrade the quality on a modem.  These numbers should work
187b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// well on a 28.8K modem, which is the slowest connection on which the voice
188b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// quality is reasonable at all.
189b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweisstatic const uint32_t PING_PACKET_SIZE = 60 * 8;
190381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// TODO(honghaiz): Change the word DELAY to INTERVAL whenever appropriate.
191b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// STRONG_PING_DELAY (480ms) is applied when the best connection is both
192b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// writable and receiving.
193b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweisstatic const uint32_t STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000;
194b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// WEAK_PING_DELAY (48ms) is applied when the best connection is either not
195b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// writable or not receiving.
196b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweisconst uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000;
197b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis
198b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// If the current best connection is both writable and receiving, then we will
199b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// also try hard to make sure it is pinged at this rate (a little less than
200b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis// 2 * STRONG_PING_DELAY).
201b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweisstatic const uint32_t MAX_CURRENT_STRONG_DELAY = 900;
202b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis
203b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweisstatic const int MIN_CHECK_RECEIVING_DELAY = 50;  // ms
204b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis
205cbecd358e032021eac11fb13e04ec7f070d4f407deadbeefP2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                         int component,
207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                         P2PTransport* transport,
208cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef                                         PortAllocator* allocator)
209cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    : TransportChannelImpl(transport_name, component),
210cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      transport_(transport),
211cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      allocator_(allocator),
212cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      worker_thread_(rtc::Thread::Current()),
213cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      incoming_only_(false),
214cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      error_(0),
215cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      best_connection_(NULL),
216cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      pending_best_connection_(NULL),
217cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      sort_dirty_(false),
218cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      remote_ice_mode_(ICEMODE_FULL),
219cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      ice_role_(ICEROLE_UNKNOWN),
220cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      tiebreaker_(0),
221cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      gathering_state_(kIceGatheringNew),
222cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5),
223381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang      receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50),
224381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang      backup_connection_ping_interval_(0) {
225b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis  uint32_t weak_ping_delay = ::strtoul(
226b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis      webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
227b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis      nullptr, 10);
228b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis  if (weak_ping_delay) {
229b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis    weak_ping_delay_ =  weak_ping_delay;
230b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis  }
231b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis}
232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgP2PTransportChannel::~P2PTransportChannel() {
234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < allocator_sessions_.size(); ++i)
237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    delete allocator_sessions_[i];
238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Add the allocator session to our list so that we know which sessions
241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// are still active.
242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::AddAllocatorSession(PortAllocatorSession* session) {
2439b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  ASSERT(worker_thread_ == rtc::Thread::Current());
2449b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz
2450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  session->set_generation(static_cast<uint32_t>(allocator_sessions_.size()));
246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  allocator_sessions_.push_back(session);
247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // We now only want to apply new candidates that we receive to the ports
249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // created by this new session because these are replacing those of the
250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // previous sessions.
251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ports_.clear();
252269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
253269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady);
254269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  session->SignalCandidatesReady.connect(
255269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnCandidatesReady);
256269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  session->SignalCandidatesAllocationDone.connect(
257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnCandidatesAllocationDone);
258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  session->StartGettingPorts();
259269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
260269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
261269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::AddConnection(Connection* connection) {
262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connections_.push_back(connection);
263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connection->set_remote_ice_mode(remote_ice_mode_);
26404ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher  connection->set_receiving_timeout(receiving_timeout_);
265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connection->SignalReadPacket.connect(
266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnReadPacket);
267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connection->SignalReadyToSend.connect(
268269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnReadyToSend);
269269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connection->SignalStateChange.connect(
270269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnConnectionStateChange);
271269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connection->SignalDestroyed.connect(
272269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnConnectionDestroyed);
2735a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
274cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  had_connection_ = true;
275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::SetIceRole(IceRole ice_role) {
278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (ice_role_ != ice_role) {
280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ice_role_ = ice_role;
281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    for (std::vector<PortInterface *>::iterator it = ports_.begin();
282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org         it != ports_.end(); ++it) {
283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      (*it)->SetIceRole(ice_role);
284269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
285269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
286269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
287269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2880c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) {
289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!ports_.empty()) {
291269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR)
292269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        << "Attempt to change tiebreaker after Port has been allocated.";
293269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
294269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  tiebreaker_ = tiebreaker;
297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
299381b4217cb36f434c56e399a852a0a15522a9596Honghai ZhangTransportChannelState P2PTransportChannel::GetState() const {
300381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  return state_;
301381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang}
302381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang
3032b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang// A channel is considered ICE completed once there is at most one active
3042b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang// connection per network and at least one active connection.
305381b4217cb36f434c56e399a852a0a15522a9596Honghai ZhangTransportChannelState P2PTransportChannel::ComputeState() const {
3062b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  if (!had_connection_) {
3072b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang    return TransportChannelState::STATE_INIT;
3082b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  }
3098c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org
3102b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  std::vector<Connection*> active_connections;
3112b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  for (Connection* connection : connections_) {
3122b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang    if (connection->active()) {
3132b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang      active_connections.push_back(connection);
3142b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang    }
3152b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  }
3162b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  if (active_connections.empty()) {
3172b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang    return TransportChannelState::STATE_FAILED;
3188c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org  }
3198c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org
3202b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  std::set<rtc::Network*> networks;
3212b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  for (Connection* connection : active_connections) {
3222b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang    rtc::Network* network = connection->port()->Network();
3238c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org    if (networks.find(network) == networks.end()) {
3248c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org      networks.insert(network);
3258c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org    } else {
3268c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org      LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as "
3278c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org                              << network->ToString()
3288c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org                              << " has more than 1 connection.";
3298c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org      return TransportChannelState::STATE_CONNECTING;
3308c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org    }
3318c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org  }
3328c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org
3332b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel.";
3348c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org  return TransportChannelState::STATE_COMPLETED;
3358c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org}
3368c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org
337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag,
338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                            const std::string& ice_pwd) {
339269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
340269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ice_ufrag_ = ice_ufrag;
341269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ice_pwd_ = ice_pwd;
342cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  // Note: Candidate gathering will restart when MaybeStartGathering is next
343cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  // called.
344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
346269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag,
347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                  const std::string& ice_pwd) {
348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
349a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  IceParameters* current_ice = remote_ice();
350a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  IceParameters new_ice(ice_ufrag, ice_pwd);
351a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (!current_ice || *current_ice != new_ice) {
352a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    // Keep the ICE credentials so that newer connections
353a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    // are prioritized over the older ones.
354a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    remote_ice_parameters_.push_back(new_ice);
355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
357112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  // Update the pwd of remote candidate if needed.
358112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  for (RemoteCandidate& candidate : remote_candidates_) {
359112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    if (candidate.username() == ice_ufrag && candidate.password().empty()) {
360112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz      candidate.set_password(ice_pwd);
361112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    }
362112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  }
363dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org  // We need to update the credentials for any peer reflexive candidates.
364112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  for (Connection* conn : connections_) {
365112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    conn->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd);
366dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org  }
367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  remote_ice_mode_ = mode;
371269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
3731f429e34180ca19a7fb98b89bacd34d42e9b01echonghaizvoid P2PTransportChannel::SetIceConfig(const IceConfig& config) {
3741f429e34180ca19a7fb98b89bacd34d42e9b01echonghaiz  gather_continually_ = config.gather_continually;
3751f429e34180ca19a7fb98b89bacd34d42e9b01echonghaiz  LOG(LS_INFO) << "Set gather_continually to " << gather_continually_;
3761f429e34180ca19a7fb98b89bacd34d42e9b01echonghaiz
377381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  if (config.backup_connection_ping_interval >= 0 &&
378381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang      backup_connection_ping_interval_ !=
379381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang          config.backup_connection_ping_interval) {
380381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    backup_connection_ping_interval_ = config.backup_connection_ping_interval;
381381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    LOG(LS_INFO) << "Set backup connection ping interval to "
382381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang                 << backup_connection_ping_interval_ << " milliseconds.";
383900996290c996193ac3e418f315354fd2bd0ea8ahonghaiz  }
38404ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher
385381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  if (config.receiving_timeout_ms >= 0 &&
386381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang      receiving_timeout_ != config.receiving_timeout_ms) {
387381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    receiving_timeout_ = config.receiving_timeout_ms;
388381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    check_receiving_delay_ =
389381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang        std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
390381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang
391381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    for (Connection* connection : connections_) {
392381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang      connection->set_receiving_timeout(receiving_timeout_);
393381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    }
394381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_
395381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang                 << " milliseconds";
39604ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher  }
39754360510ff9b7c61fc906d3ed360b06a5824bbf1Peter Thatcher}
39854360510ff9b7c61fc906d3ed360b06a5824bbf1Peter Thatcher
399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Go into the state of processing candidates, and running in general
400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::Connect() {
401269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (ice_ufrag_.empty() || ice_pwd_.empty()) {
403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(false);
404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
405269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                  << "ice_pwd_ are not set.";
406269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
409a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // Start checking and pinging as the ports come in.
410a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  thread()->Post(this, MSG_CHECK_AND_PING);
411269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
412269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
413cbecd358e032021eac11fb13e04ec7f070d4f407deadbeefvoid P2PTransportChannel::MaybeStartGathering() {
414cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  // Start gathering if we never started before, or if an ICE restart occurred.
415cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  if (allocator_sessions_.empty() ||
416cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(),
417cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef                            allocator_sessions_.back()->ice_pwd(), ice_ufrag_,
418cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef                            ice_pwd_)) {
419cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    if (gathering_state_ != kIceGatheringGathering) {
420cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      gathering_state_ = kIceGatheringGathering;
421cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      SignalGatheringState(this);
422cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    }
423cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    // Time for a new allocator
424cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    AddAllocatorSession(allocator_->CreateSession(
425cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef        SessionId(), transport_name(), component(), ice_ufrag_, ice_pwd_));
426cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  }
427cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef}
428cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef
429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// A new port is available, attempt to make connections for it
430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                      PortInterface* port) {
432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set in-effect options on the new port
435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (OptionMap::const_iterator it = options_.begin();
436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       it != options_.end();
437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       ++it) {
438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int val = port->SetOption(it->first, it->second);
439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (val < 0) {
440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      LOG_J(LS_WARNING, port) << "SetOption(" << it->first
441269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                              << ", " << it->second
442269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                              << ") failed: " << port->GetError();
443269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
445269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
446269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Remember the ports and candidates, and signal that candidates are ready.
447269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // The session will handle this, and send an initiate/accept/modify message
448269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // if one is pending.
449269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
450269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->SetIceRole(ice_role_);
451269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->SetIceTiebreaker(tiebreaker_);
452269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ports_.push_back(port);
453269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->SignalUnknownAddress.connect(
454269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnUnknownAddress);
455269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed);
456269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->SignalRoleConflict.connect(
457269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      this, &P2PTransportChannel::OnRoleConflict);
458c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  port->SignalSentPacket.connect(this, &P2PTransportChannel::OnSentPacket);
459269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Attempt to create a connection from this new port to all of the remote
461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // candidates that we were given so far.
462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<RemoteCandidate>::iterator iter;
464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
465269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       ++iter) {
46604ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher    CreateConnection(port, *iter, iter->origin_port());
467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
468269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
469269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SortConnections();
470269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
471269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
472269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// A new candidate is available, let listeners know
473269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnCandidatesReady(
474cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    PortAllocatorSession* session,
475cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    const std::vector<Candidate>& candidates) {
476269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
477269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (size_t i = 0; i < candidates.size(); ++i) {
478cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    SignalCandidateGathered(this, candidates[i]);
479269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
480269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
481269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
482269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnCandidatesAllocationDone(
483269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    PortAllocatorSession* session) {
484269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
485cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  gathering_state_ = kIceGatheringComplete;
486cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() << ", component "
487cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef               << component() << " gathering complete";
488cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef  SignalGatheringState(this);
489269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
490269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
491269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Handle stun packets
492269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnUnknownAddress(
493269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    PortInterface* port,
494269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const rtc::SocketAddress& address, ProtocolType proto,
495269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    IceMessage* stun_msg, const std::string &remote_username,
496269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    bool port_muxed) {
497269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
498269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
499269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Port has received a valid stun packet from an address that no Connection
500269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // is currently available for. See if we already have a candidate with the
501269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // address. If it isn't we need to create new candidate for it.
502269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
503269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Determine if the remote candidates use shared ufrag.
504269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool ufrag_per_port = false;
505269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<RemoteCandidate>::iterator it;
506269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (remote_candidates_.size() > 0) {
507269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    it = remote_candidates_.begin();
508269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    std::string username = it->username();
509269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    for (; it != remote_candidates_.end(); ++it) {
510269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      if (it->username() != username) {
511269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        ufrag_per_port = true;
512269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        break;
513269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
514269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
515269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
516269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
517269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const Candidate* candidate = NULL;
518269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string remote_password;
519269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) {
520269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (it->username() == remote_username) {
521269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      remote_password = it->password();
522269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      if (ufrag_per_port ||
523269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org          (it->address() == address &&
524269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org           it->protocol() == ProtoToString(proto))) {
525269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        candidate = &(*it);
526269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        break;
527269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
528269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // We don't want to break here because we may find a match of the address
529269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // later.
530269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
531269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
532269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
533112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  uint32_t remote_generation = 0;
534dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org  // The STUN binding request may arrive after setRemoteDescription and before
535dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org  // adding remote candidate, so we need to set the password to the shared
536dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org  // password if the user name matches.
537a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (remote_password.empty()) {
538112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    const IceParameters* ice_param =
539112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz        FindRemoteIceFromUfrag(remote_username, &remote_generation);
540112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    // Note: if not found, the remote_generation will still be 0.
541112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    if (ice_param != nullptr) {
542112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz      remote_password = ice_param->pwd;
543a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    }
544269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
545269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
546372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh  Candidate remote_candidate;
547372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh  bool remote_candidate_is_new = (candidate == nullptr);
548372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh  if (!remote_candidate_is_new) {
549372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh    remote_candidate = *candidate;
550269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (ufrag_per_port) {
551372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh      remote_candidate.set_address(address);
552269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
553269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
554269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Create a new candidate with this address.
555372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh    int remote_candidate_priority;
5567cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher
5577cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // The priority of the candidate is set to the PRIORITY attribute
5587cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // from the request.
5597cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    const StunUInt32Attribute* priority_attr =
5607cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher        stun_msg->GetUInt32(STUN_ATTR_PRIORITY);
5617cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    if (!priority_attr) {
5627cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - "
5637cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                      << "No STUN_ATTR_PRIORITY found in the "
5647cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                      << "stun request message";
565cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef      port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_BAD_REQUEST,
5667cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                                     STUN_ERROR_REASON_BAD_REQUEST);
5677cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      return;
568269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
5697cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    remote_candidate_priority = priority_attr->value();
570269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
5717cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // RFC 5245
5727cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // If the source transport address of the request does not match any
5737cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // existing remote candidates, it represents a new peer reflexive remote
5747cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // candidate.
575112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    remote_candidate = Candidate(component(), ProtoToString(proto), address, 0,
576112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz                                 remote_username, remote_password,
577112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz                                 PRFLX_PORT_TYPE, remote_generation, "");
57861c1247224e2b696b10303b0b5479b3a246f4ff0guoweis@webrtc.org
57961c1247224e2b696b10303b0b5479b3a246f4ff0guoweis@webrtc.org    // From RFC 5245, section-7.2.1.3:
58061c1247224e2b696b10303b0b5479b3a246f4ff0guoweis@webrtc.org    // The foundation of the candidate is set to an arbitrary value, different
58161c1247224e2b696b10303b0b5479b3a246f4ff0guoweis@webrtc.org    // from the foundation for all other remote candidates.
582372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh    remote_candidate.set_foundation(
5830c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        rtc::ToString<uint32_t>(rtc::ComputeCrc32(remote_candidate.id())));
58461c1247224e2b696b10303b0b5479b3a246f4ff0guoweis@webrtc.org
585372f2fcc59829f9eaa2b10519bebd0f71e915f93Guo-wei Shieh    remote_candidate.set_priority(remote_candidate_priority);
586269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
587269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
5887cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // RFC5245, the agent constructs a pair whose local candidate is equal to
5897cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // the transport address on which the STUN request was received, and a
5907cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // remote candidate equal to the source transport address where the
5917cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // request came from.
592269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
5937cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // There shouldn't be an existing connection with this remote address.
5947cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // When ports are muxed, this channel might get multiple unknown address
5957cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // signals. In that case if the connection is already exists, we should
5967cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // simply ignore the signal otherwise send server error.
5977cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  if (port->GetConnection(remote_candidate.address())) {
5987cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    if (port_muxed) {
5997cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      LOG(LS_INFO) << "Connection already exists for peer reflexive "
6007cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                   << "candidate: " << remote_candidate.ToString();
6017cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      return;
6027cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    } else {
603269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ASSERT(false);
604269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      port->SendBindingErrorResponse(stun_msg, address,
605269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                     STUN_ERROR_SERVER_ERROR,
606269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                     STUN_ERROR_REASON_SERVER_ERROR);
607269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return;
608269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
6097cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  }
610269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
6117cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  Connection* connection = port->CreateConnection(
6127cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT);
6137cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  if (!connection) {
6147cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    ASSERT(false);
615cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR,
6167cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                                   STUN_ERROR_REASON_SERVER_ERROR);
6177cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    return;
6187cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  }
619d12140a68efdcffa1c2c18f25149905e9dae1a9cguoweis
6207cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  LOG(LS_INFO) << "Adding connection from "
6217cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher               << (remote_candidate_is_new ? "peer reflexive" : "resurrected")
6227cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher               << " candidate: " << remote_candidate.ToString();
6237cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  AddConnection(connection);
6249b5ee9c0d988b1d0dc64920937448e301dd45bd9honghaiz  connection->HandleBindingRequest(stun_msg);
6257cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher
6267cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // Update the list of connections since we just added another.  We do this
6277cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // after sending the response since it could (in principle) delete the
6287cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  // connection in question.
6297cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  SortConnections();
630269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
631269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
632269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnRoleConflict(PortInterface* port) {
633269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SignalRoleConflict(this);  // STUN ping will be sent when SetRole is called
634269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                             // from Transport.
635269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
636269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
637112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaizconst IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag(
638112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    const std::string& ufrag,
639112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    uint32_t* generation) {
640112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  const auto& params = remote_ice_parameters_;
641112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  auto it = std::find_if(
642112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz      params.rbegin(), params.rend(),
643112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz      [ufrag](const IceParameters& param) { return param.ufrag == ufrag; });
644112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  if (it == params.rend()) {
645112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    // Not found.
646112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    return nullptr;
647112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  }
648112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  *generation = params.rend() - it - 1;
649112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  return &(*it);
650112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz}
651112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz
6525a3acd89648e7cff7e1b76b2da710be041be54a0honghaizvoid P2PTransportChannel::OnNominated(Connection* conn) {
653269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
654269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(ice_role_ == ICEROLE_CONTROLLED);
65542af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher
656269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (conn->write_state() == Connection::STATE_WRITABLE) {
657269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (best_connection_ != conn) {
658269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      pending_best_connection_ = NULL;
65942af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher      LOG(LS_INFO) << "Switching best connection on controlled side: "
66042af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher                   << conn->ToString();
661269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      SwitchBestConnectionTo(conn);
662269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // Now we have selected the best connection, time to prune other existing
663269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // connections and update the read/write state of the channel.
664269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      RequestSort();
665269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
666269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
66742af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher    LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
66842af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher                 << " because it's not writable: " << conn->ToString();
669269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    pending_best_connection_ = conn;
670269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
671269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
672269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
673cbecd358e032021eac11fb13e04ec7f070d4f407deadbeefvoid P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
674269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
675269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
676a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  uint32_t generation = GetRemoteCandidateGeneration(candidate);
677a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // If a remote candidate with a previous generation arrives, drop it.
678a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (generation < remote_ice_generation()) {
679a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
680a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz                    << candidate.username()
681a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz                    << " indicates it was for a previous generation.";
682503726c3498201822079c5abe9e528498846c9f2honghaiz    return;
683503726c3498201822079c5abe9e528498846c9f2honghaiz  }
684503726c3498201822079c5abe9e528498846c9f2honghaiz
685a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  Candidate new_remote_candidate(candidate);
686a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  new_remote_candidate.set_generation(generation);
687a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // ICE candidates don't need to have username and password set, but
688a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // the code below this (specifically, ConnectionRequest::Prepare in
689a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // port.cc) uses the remote candidates's username.  So, we set it
690a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // here.
691a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (remote_ice()) {
692a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    if (candidate.username().empty()) {
693a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz      new_remote_candidate.set_username(remote_ice()->ufrag);
694a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    }
695a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    if (new_remote_candidate.username() == remote_ice()->ufrag) {
696a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz      if (candidate.password().empty()) {
697a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz        new_remote_candidate.set_password(remote_ice()->pwd);
698a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz      }
699a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    } else {
700a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz      // The candidate belongs to the next generation. Its pwd will be set
701a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz      // when the new remote ICE credentials arrive.
702a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz      LOG(LS_WARNING) << "A remote candidate arrives with an unknown ufrag: "
703a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz                      << candidate.username();
704a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    }
705a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  }
706a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz
707269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Create connections to this remote candidate.
708a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  CreateConnections(new_remote_candidate, NULL);
709269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
710269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Resort the connections list, which may have new elements.
711269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SortConnections();
712269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
713269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
714269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Creates connections from all of the ports that we care about to the given
715269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// remote candidate.  The return value is true if we created a connection from
716269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// the origin port.
717269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
71804ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher                                            PortInterface* origin_port) {
719269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
720269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
721269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If we've already seen the new remote candidate (in the current candidate
722269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // generation), then we shouldn't try creating connections for it.
723269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // We either already have a connection for it, or we previously created one
724269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // and then later pruned it. If we don't return, the channel will again
725269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // re-create any connections that were previously pruned, which will then
726269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // immediately be re-pruned, churning the network for no purpose.
727269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // This only applies to candidates received over signaling (i.e. origin_port
728269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // is NULL).
729a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) {
730269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // return true to indicate success, without creating any new connections.
731269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return true;
732269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
733269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
734269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Add a new connection for this candidate to every port that allows such a
735269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // connection (i.e., if they have compatible protocols) and that does not
736269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // already have a connection to an equivalent candidate.  We must be careful
737269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // to make sure that the origin port is included, even if it was pruned,
738269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // since that may be the only port that can create this connection.
739269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool created = false;
740269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<PortInterface *>::reverse_iterator it;
741269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (it = ports_.rbegin(); it != ports_.rend(); ++it) {
742a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    if (CreateConnection(*it, remote_candidate, origin_port)) {
743269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      if (*it == origin_port)
744269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        created = true;
745269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
746269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
747269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
748269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if ((origin_port != NULL) &&
749269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
750a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    if (CreateConnection(origin_port, remote_candidate, origin_port))
751269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      created = true;
752269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
753269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
754269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Remember this remote candidate so that we can add it to future ports.
755a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  RememberRemoteCandidate(remote_candidate, origin_port);
756269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
757269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return created;
758269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
759269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
760269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Setup a connection object for the local and remote candidate combination.
761269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// And then listen to connection object for changes.
762269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool P2PTransportChannel::CreateConnection(PortInterface* port,
763269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                           const Candidate& remote_candidate,
76404ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher                                           PortInterface* origin_port) {
765f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  if (!port->SupportsProtocol(remote_candidate.protocol())) {
766f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang    return false;
767f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  }
768269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Look for an existing connection with this remote address.  If one is not
769269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // found, then we can create a new connection for this address.
770269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* connection = port->GetConnection(remote_candidate.address());
771269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (connection != NULL) {
772dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org    connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate);
773dacdd9403d30cdb13ab2de645841edd2ae76950djiayl@webrtc.org
774269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // It is not legal to try to change any of the parameters of an existing
775269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // connection; however, the other side can send a duplicate candidate.
776269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
777269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      LOG(INFO) << "Attempt to change a remote candidate."
778269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                << " Existing remote candidate: "
779269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                << connection->remote_candidate().ToString()
780269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                << "New remote candidate: "
781269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                << remote_candidate.ToString();
782269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return false;
783269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
784269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
785269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    PortInterface::CandidateOrigin origin = GetOrigin(port, origin_port);
786269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
787269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Don't create connection if this is a candidate we received in a
788269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // message and we are not allowed to make outgoing connections.
789269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (origin == cricket::PortInterface::ORIGIN_MESSAGE && incoming_only_)
790269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return false;
791269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
792269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    connection = port->CreateConnection(remote_candidate, origin);
793269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!connection)
794269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return false;
795269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
796269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    AddConnection(connection);
797269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
798269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", ("
799269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                         << connections_.size() << " total)";
800269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
801269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
802269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return true;
803269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
804269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
805269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool P2PTransportChannel::FindConnection(
806269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    cricket::Connection* connection) const {
807269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<Connection*>::const_iterator citer =
808269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      std::find(connections_.begin(), connections_.end(), connection);
809269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return citer != connections_.end();
810269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
811269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
8120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmuint32_t P2PTransportChannel::GetRemoteCandidateGeneration(
813269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const Candidate& candidate) {
814112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz  // If the candidate has a ufrag, use it to find the generation.
815a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (!candidate.username().empty()) {
816112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    uint32_t generation = 0;
817112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    if (!FindRemoteIceFromUfrag(candidate.username(), &generation)) {
818112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz      // If the ufrag is not found, assume the next/future generation.
819112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz      generation = static_cast<uint32_t>(remote_ice_parameters_.size());
820a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    }
821112fe43b9f3f04592f1ccff6b4f23fcd2890bf30honghaiz    return generation;
822a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  }
823a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // If candidate generation is set, use that.
824a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  if (candidate.generation() > 0) {
825a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz    return candidate.generation();
826a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  }
827a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  // Otherwise, assume the generation from remote ice parameters.
828a54a0801121e05f797e514731cc5c9bad2f5e597honghaiz  return remote_ice_generation();
829269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
830269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
831269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Check if remote candidate is already cached.
832269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool P2PTransportChannel::IsDuplicateRemoteCandidate(
833269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const Candidate& candidate) {
8340c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < remote_candidates_.size(); ++i) {
835269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (remote_candidates_[i].IsEquivalent(candidate)) {
836269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return true;
837269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
838269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
839269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return false;
840269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
841269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
842269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Maintain our remote candidate list, adding this new remote one.
843269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::RememberRemoteCandidate(
844269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const Candidate& remote_candidate, PortInterface* origin_port) {
845269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Remove any candidates whose generation is older than this one.  The
846269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // presence of a new generation indicates that the old ones are not useful.
8470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  size_t i = 0;
848269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  while (i < remote_candidates_.size()) {
849269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (remote_candidates_[i].generation() < remote_candidate.generation()) {
850269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      LOG(INFO) << "Pruning candidate from old generation: "
851269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                << remote_candidates_[i].address().ToSensitiveString();
852269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      remote_candidates_.erase(remote_candidates_.begin() + i);
853269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else {
854269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      i += 1;
855269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
856269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
857269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
858269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Make sure this candidate is not a duplicate.
859269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (IsDuplicateRemoteCandidate(remote_candidate)) {
860269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(INFO) << "Duplicate candidate: " << remote_candidate.ToString();
861269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
862269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
863269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
864269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Try this candidate for all future ports.
865269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port));
866269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
867269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
868269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Set options on ourselves is simply setting options on all of our available
869269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// port objects.
870269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) {
871877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
872269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  OptionMap::iterator it = options_.find(opt);
873269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (it == options_.end()) {
874269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    options_.insert(std::make_pair(opt, value));
875269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else if (it->second == value) {
876269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return 0;
877269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
878269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    it->second = value;
879269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
880269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
8810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < ports_.size(); ++i) {
882269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int val = ports_[i]->SetOption(opt, value);
883269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (val < 0) {
884269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // Because this also occurs deferred, probably no point in reporting an
885269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // error
886269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      LOG(WARNING) << "SetOption(" << opt << ", " << value << ") failed: "
887269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                   << ports_[i]->GetError();
888269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
889269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
890269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return 0;
891269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
892269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
893877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.orgbool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) {
894877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
895877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org
896877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  const auto& found = options_.find(opt);
897877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  if (found == options_.end()) {
898877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org    return false;
899877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  }
900877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  *value = found->second;
901877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org  return true;
902877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org}
903877ac765ad30a22148da41695fa607682af4a191pthatcher@webrtc.org
904269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Send data to the other side, using our best connection.
905269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint P2PTransportChannel::SendPacket(const char *data, size_t len,
906269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    const rtc::PacketOptions& options,
907269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    int flags) {
908269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
909269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (flags != 0) {
910269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    error_ = EINVAL;
911269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return -1;
912269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
913269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (best_connection_ == NULL) {
914269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    error_ = EWOULDBLOCK;
915269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return -1;
916269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
917269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
918269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int sent = best_connection_->Send(data, len, options);
919269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (sent <= 0) {
920269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(sent < 0);
921269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    error_ = best_connection_->GetError();
922269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
923269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return sent;
924269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
925269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
926269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
927269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
928269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Gather connection infos.
929269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  infos->clear();
930269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
931269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<Connection *>::const_iterator it;
9322b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  for (Connection* connection : connections_) {
933269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ConnectionInfo info;
934269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.best_connection = (best_connection_ == connection);
93504ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher    info.receiving = connection->receiving();
936269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.writable =
937269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        (connection->write_state() == Connection::STATE_WRITABLE);
938269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.timeout =
939269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
940269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.new_connection = !connection->reported();
941269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    connection->set_reported(true);
942269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.rtt = connection->rtt();
943269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.sent_total_bytes = connection->sent_total_bytes();
944269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.sent_bytes_second = connection->sent_bytes_second();
945930e004a817ed346a99ac8e56575326ca75e72aaguoweis@webrtc.org    info.sent_discarded_packets = connection->sent_discarded_packets();
946930e004a817ed346a99ac8e56575326ca75e72aaguoweis@webrtc.org    info.sent_total_packets = connection->sent_total_packets();
947269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.recv_total_bytes = connection->recv_total_bytes();
948269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.recv_bytes_second = connection->recv_bytes_second();
949269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.local_candidate = connection->local_candidate();
950269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.remote_candidate = connection->remote_candidate();
951269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    info.key = connection;
952269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    infos->push_back(info);
953269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
954269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
955269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return true;
956269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
957269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
958269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgrtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const {
959269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP);
960269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (it == options_.end()) {
961269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return rtc::DSCP_NO_CHANGE;
962269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
963269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return static_cast<rtc::DiffServCodePoint> (it->second);
964269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
965269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
966269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Monitor connection states.
967269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::UpdateConnectionStates() {
9680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t now = rtc::Time();
969269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
970269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // We need to copy the list of connections since some may delete themselves
971269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // when we call UpdateState.
9720c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < connections_.size(); ++i)
973269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    connections_[i]->UpdateState(now);
974269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
975269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
976269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Prepare for best candidate sorting.
977269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::RequestSort() {
978269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!sort_dirty_) {
979269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    worker_thread_->Post(this, MSG_SORT);
980269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    sort_dirty_ = true;
981269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
982269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
983269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
984269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Sort the available connections to find the best one.  We also monitor
985269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// the number of available connections and the current state.
986269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::SortConnections() {
987269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
988269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
989269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Make sure the connection states are up-to-date since this affects how they
990269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // will be sorted.
991269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UpdateConnectionStates();
992269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
993269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Any changes after this point will require a re-sort.
994269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  sort_dirty_ = false;
995269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
996269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Find the best alternative connection by sorting.  It is important to note
997269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // that amongst equal preference, writable connections, this will choose the
998269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // one whose estimated latency is lowest.  So it is the only one that we
999269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // need to consider switching to.
1000269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ConnectionCompare cmp;
1001269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::stable_sort(connections_.begin(), connections_.end(), cmp);
1002a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  LOG(LS_VERBOSE) << "Sorting " << connections_.size()
1003a58ea7806a039c14e1f92a0757123062963b44b1honghaiz                  << " available connections:";
10040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < connections_.size(); ++i) {
1005269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_VERBOSE) << connections_[i]->ToString();
1006269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1007269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
10085a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  Connection* top_connection =
10095a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz      (connections_.size() > 0) ? connections_[0] : nullptr;
1010269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1011269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If necessary, switch to the new choice.
10125a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // Note that |top_connection| doesn't have to be writable to become the best
10135a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // connection although it will have higher priority if it is writable.
1014a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (ShouldSwitch(best_connection_, top_connection, ice_role_)) {
10155a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
10165a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    SwitchBestConnectionTo(top_connection);
1017269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1018269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
10195a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // Controlled side can prune only if the best connection has been nominated.
10205a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // because otherwise it may delete the connection that will be selected by
10215a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // the controlling side.
10227cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
10235a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    PruneConnections();
1024269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1025269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1026269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Check if all connections are timedout.
1027269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool all_connections_timedout = true;
10280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < connections_.size(); ++i) {
1029269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1030269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      all_connections_timedout = false;
1031269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      break;
1032269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
1033269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1034269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1035269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now update the writable state of the channel with the information we have
1036269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // so far.
1037a8e9f5e4e4d57978bcee052e5af020a0cd960c52honghaiz  if (all_connections_timedout) {
1038269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    HandleAllTimedOut();
1039269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1040269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1041269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Update the state of this channel.  This method is called whenever the
1042269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // state of any connection changes, so this is a good place to do this.
1043381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  UpdateState();
1044269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1045269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
10465a3acd89648e7cff7e1b76b2da710be041be54a0honghaizConnection* P2PTransportChannel::best_nominated_connection() const {
10475a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  return (best_connection_ && best_connection_->nominated()) ? best_connection_
10485a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz                                                             : nullptr;
10495a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz}
10505a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz
10515a3acd89648e7cff7e1b76b2da710be041be54a0honghaizvoid P2PTransportChannel::PruneConnections() {
10525a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // We can prune any connection for which there is a connected, writable
10535a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // connection on the same network with better or equal priority.  We leave
10545a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // those with better priority just in case they become writable later (at
10555a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // which point, we would prune out the current best connection).  We leave
10565a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // connections on other networks because they may not be using the same
10575a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // resources and they may represent very distinct paths over which we can
10588937437872d8ff5b30866ae4de4abf005afc7539honghaiz  // switch. If the |premier| connection is not connected, we may be
10595a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // reconnecting a TCP connection and temporarily do not prune connections in
10605a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // this network. See the big comment in CompareConnections.
10615a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz
10625a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // Get a list of the networks that we are using.
10635a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  std::set<rtc::Network*> networks;
10645a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  for (const Connection* conn : connections_) {
10655a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    networks.insert(conn->port()->Network());
10665a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  }
10675a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  for (rtc::Network* network : networks) {
10688937437872d8ff5b30866ae4de4abf005afc7539honghaiz    Connection* premier = GetBestConnectionOnNetwork(network);
10698937437872d8ff5b30866ae4de4abf005afc7539honghaiz    // Do not prune connections if the current best connection is weak on this
10708937437872d8ff5b30866ae4de4abf005afc7539honghaiz    // network. Otherwise, it may delete connections prematurely.
10712b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang    if (!premier || premier->weak()) {
10725a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz      continue;
10735a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    }
10745a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz
10755a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    for (Connection* conn : connections_) {
10768937437872d8ff5b30866ae4de4abf005afc7539honghaiz      if ((conn != premier) && (conn->port()->Network() == network) &&
10778937437872d8ff5b30866ae4de4abf005afc7539honghaiz          (CompareConnectionCandidates(premier, conn) >= 0)) {
10785a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz        conn->Prune();
10795a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz      }
10805a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    }
10815a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  }
10825a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz}
1083269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1084269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Track the best connection, and let listeners know
1085269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1086269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1087269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // so don't use it.
1088269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* old_best_connection = best_connection_;
1089269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  best_connection_ = conn;
1090269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (best_connection_) {
1091269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (old_best_connection) {
1092269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      LOG_J(LS_INFO, this) << "Previous best connection: "
1093269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           << old_best_connection->ToString();
1094269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
1095269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG_J(LS_INFO, this) << "New best connection: "
1096269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                         << best_connection_->ToString();
1097269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    SignalRouteChange(this, best_connection_->remote_candidate());
1098269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
1099269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG_J(LS_INFO, this) << "No best connection";
1100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1103381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// Warning: UpdateState should eventually be called whenever a connection
1104381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// is added, deleted, or the write state of any connection changes so that the
1105381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// transport controller will get the up-to-date channel state. However it
1106381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// should not be called too often; in the case that multiple connection states
1107381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// change, it should be called after all the connection states have changed. For
1108381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// example, we call this at the end of SortConnections.
1109381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhangvoid P2PTransportChannel::UpdateState() {
1110381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  state_ = ComputeState();
1111381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang
1112a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  bool writable = best_connection_ && best_connection_->writable();
1113a8e9f5e4e4d57978bcee052e5af020a0cd960c52honghaiz  set_writable(writable);
1114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1115a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  bool receiving = false;
1116a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  for (const Connection* connection : connections_) {
1117a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    if (connection->receiving()) {
1118a58ea7806a039c14e1f92a0757123062963b44b1honghaiz      receiving = true;
1119a58ea7806a039c14e1f92a0757123062963b44b1honghaiz      break;
1120a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    }
1121a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  }
1122a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  set_receiving(receiving);
1123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11259b66957b4f7dfe40c17eed597826b3ed0faf5439honghaizvoid P2PTransportChannel::MaybeStopPortAllocatorSessions() {
11269b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  if (!IsGettingPorts()) {
112798db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    return;
112898db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz  }
112998db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz
113098db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz  for (PortAllocatorSession* session : allocator_sessions_) {
113198db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    if (!session->IsGettingPorts()) {
113298db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz      continue;
113398db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    }
113498db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    // If gathering continually, keep the last session running so that it
113598db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    // will gather candidates if the networks change.
113698db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    if (gather_continually_ && session == allocator_sessions_.back()) {
113798db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz      session->ClearGettingPorts();
113898db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz      break;
1139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
114098db68fdaa12c5bfca8b0004eba24d034f32de71honghaiz    session->StopGettingPorts();
1141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
11429b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz}
1143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
114477d0d6e858203cbc559b2f5d6ffabb7bc2fcb8e6honghaiz// If all connections timed out, delete them all.
1145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::HandleAllTimedOut() {
114677d0d6e858203cbc559b2f5d6ffabb7bc2fcb8e6honghaiz  for (Connection* connection : connections_) {
114777d0d6e858203cbc559b2f5d6ffabb7bc2fcb8e6honghaiz    connection->Destroy();
114877d0d6e858203cbc559b2f5d6ffabb7bc2fcb8e6honghaiz  }
1149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11512b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhangbool P2PTransportChannel::weak() const {
11522b342bf99c9578247940929c02a41ef9ccec6d6eHonghai Zhang  return !best_connection_ || best_connection_->weak();
1153a58ea7806a039c14e1f92a0757123062963b44b1honghaiz}
1154a58ea7806a039c14e1f92a0757123062963b44b1honghaiz
1155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// If we have a best connection, return it, otherwise return top one in the
1156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// list (later we will mark it best).
1157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgConnection* P2PTransportChannel::GetBestConnectionOnNetwork(
11588c9ff203c5f3c87891b46067ef6ec21b37d2dde4guoweis@webrtc.org    rtc::Network* network) const {
1159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If the best connection is on this network, then it wins.
1160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (best_connection_ && (best_connection_->port()->Network() == network))
1161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return best_connection_;
1162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Otherwise, we return the top-most in sorted order.
11640c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (size_t i = 0; i < connections_.size(); ++i) {
1165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (connections_[i]->port()->Network() == network)
1166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return connections_[i];
1167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return NULL;
1170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Handle any queued up requests
1173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  switch (pmsg->message_id) {
1175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    case MSG_SORT:
1176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      OnSort();
1177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      break;
1178a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    case MSG_CHECK_AND_PING:
1179a58ea7806a039c14e1f92a0757123062963b44b1honghaiz      OnCheckAndPing();
118054360510ff9b7c61fc906d3ed360b06a5824bbf1Peter Thatcher      break;
1181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    default:
1182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ASSERT(false);
1183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      break;
1184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Handle queued up sort request
1188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnSort() {
1189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Resort the connections based on the new statistics.
1190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SortConnections();
1191269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1192269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1193a58ea7806a039c14e1f92a0757123062963b44b1honghaiz// Handle queued up check-and-ping request
1194a58ea7806a039c14e1f92a0757123062963b44b1honghaizvoid P2PTransportChannel::OnCheckAndPing() {
1195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Make sure the states of the connections are up-to-date (since this affects
1196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // which ones are pingable).
1197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UpdateConnectionStates();
1198a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // When the best connection is either not receiving or not writable,
1199a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  // switch to weak ping delay.
1200b0bb77fd615c5ce413b16f6157b2ffc25898631fguoweis  int ping_delay = weak() ? weak_ping_delay_ : STRONG_PING_DELAY;
1201a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) {
1202a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    Connection* conn = FindNextPingableConnection();
1203a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    if (conn) {
1204a58ea7806a039c14e1f92a0757123062963b44b1honghaiz      PingConnection(conn);
1205a58ea7806a039c14e1f92a0757123062963b44b1honghaiz    }
120654360510ff9b7c61fc906d3ed360b06a5824bbf1Peter Thatcher  }
1207a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  int check_delay = std::min(ping_delay, check_receiving_delay_);
1208a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
120954360510ff9b7c61fc906d3ed360b06a5824bbf1Peter Thatcher}
121054360510ff9b7c61fc906d3ed360b06a5824bbf1Peter Thatcher
1211381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// A connection is considered a backup connection if the channel state
1212381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang// is completed, the connection is not the best connection and it is active.
1213381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhangbool P2PTransportChannel::IsBackupConnection(Connection* conn) const {
1214381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  return state_ == STATE_COMPLETED && conn != best_connection_ &&
1215381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang         conn->active();
1216381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang}
1217381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang
1218269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Is the connection in a state for us to even consider pinging the other side?
1219be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// We consider a connection pingable even if it's not connected because that's
1220be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// how a TCP connection is kicked into reconnecting on the active side.
1221381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhangbool P2PTransportChannel::IsPingable(Connection* conn, uint32_t now) {
12227351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher  const Candidate& remote = conn->remote_candidate();
12237351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher  // We should never get this far with an empty remote ufrag.
12247351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher  ASSERT(!remote.username().empty());
12257351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher  if (remote.username().empty() || remote.password().empty()) {
12267351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher    // If we don't have an ICE ufrag and pwd, there's no way we can ping.
12277351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher    return false;
12287351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher  }
12297351f4689caae2e53b3ee54874546e8aab769d22Peter Thatcher
1230be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // An never connected connection cannot be written to at all, so pinging is
1231be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // out of the question. However, if it has become WRITABLE, it is in the
1232be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // reconnecting state so ping is needed.
123304ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher  if (!conn->connected() && !conn->writable()) {
1234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return false;
1235be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
1236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1237381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  // If the channel is weakly connected, ping all connections.
1238381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  if (weak()) {
1239381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    return true;
1240381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  }
1241381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang
1242381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  // Always ping active connections regardless whether the channel is completed
1243381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  // or not, but backup connections are pinged at a slower rate.
1244381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  if (IsBackupConnection(conn)) {
1245381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    return (now >= conn->last_ping_response_received() +
1246381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang                       backup_connection_ping_interval_);
1247381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  }
1248381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  return conn->active();
1249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Returns the next pingable connection to ping.  This will be the oldest
1252be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// pingable connection unless we have a connected, writable connection that is
1253be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// past the maximum acceptable ping delay. When reconnecting a TCP connection,
1254be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// the best connection is disconnected, although still WRITABLE while
1255be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// reconnecting. The newly created connection should be selected as the ping
1256be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh// target to become writable instead. See the big comment in CompareConnections.
1257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgConnection* P2PTransportChannel::FindNextPingableConnection() {
12580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t now = rtc::Time();
1259be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  if (best_connection_ && best_connection_->connected() &&
1260a58ea7806a039c14e1f92a0757123062963b44b1honghaiz      best_connection_->writable() &&
1261a58ea7806a039c14e1f92a0757123062963b44b1honghaiz      (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) {
1262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return best_connection_;
1263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
12651fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  // First, find "triggered checks".  We ping first those connections
12661fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  // that have received a ping but have not sent a ping since receiving
12671fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  // it (last_received_ping > last_sent_ping).  But we shouldn't do
12681fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  // triggered checks if the connection is already writable.
12691fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  Connection* oldest_needing_triggered_check = nullptr;
12701fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  Connection* oldest = nullptr;
12711fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  for (Connection* conn : connections_) {
1272381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang    if (!IsPingable(conn, now)) {
12731fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher      continue;
12741fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    }
12751fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    bool needs_triggered_check =
12767cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher        (!conn->writable() &&
12771fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher         conn->last_ping_received() > conn->last_ping_sent());
12781fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    if (needs_triggered_check &&
12791fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher        (!oldest_needing_triggered_check ||
12801fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher         (conn->last_ping_received() <
12811fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher          oldest_needing_triggered_check->last_ping_received()))) {
12821fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher      oldest_needing_triggered_check = conn;
1283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
12841fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) {
12851fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher      oldest = conn;
12861fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    }
12871fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  }
12881fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher
12891fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  if (oldest_needing_triggered_check) {
12901fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    LOG(LS_INFO) << "Selecting connection for triggered check: " <<
12911fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher        oldest_needing_triggered_check->ToString();
12921fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher    return oldest_needing_triggered_check;
1293269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
12941fe120a6b9371819515f2f05beaf62ddcc9c9f30Peter Thatcher  return oldest;
1295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Apart from sending ping from |conn| this method also updates
1298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// |use_candidate_attr| flag. The criteria to update this flag is
1299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// explained below.
1300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND
1301269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//    a) Channel is in FULL ICE AND
1302269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//      a.1) |conn| is the best connection OR
1303269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//      a.2) there is no best connection OR
1304269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//      a.3) the best connection is unwritable OR
1305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//      a.4) |conn| has higher priority than best_connection.
1306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//    b) we're doing LITE ICE AND
1307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//      b.1) |conn| is the best_connection AND
1308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org//      b.2) |conn| is writable.
1309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::PingConnection(Connection* conn) {
1310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool use_candidate = false;
13117cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1312cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef    use_candidate = (conn == best_connection_) || (best_connection_ == NULL) ||
13137cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                    (!best_connection_->writable()) ||
13147cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                    (conn->priority() > best_connection_->priority());
13157cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) {
13167cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    use_candidate = best_connection_->writable();
1317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  conn->set_use_candidate_attr(use_candidate);
1319a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  last_ping_sent_ms_ = rtc::Time();
1320a58ea7806a039c14e1f92a0757123062963b44b1honghaiz  conn->Ping(last_ping_sent_ms_);
1321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// When a connection's state changes, we need to figure out who to use as
1324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// the best connection again.  It could have become usable, or become unusable.
1325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
1327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Update the best connection if the state change is from pending best
1329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // connection and role is controlled.
13307cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  if (ice_role_ == ICEROLE_CONTROLLED) {
1331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (connection == pending_best_connection_ && connection->writable()) {
1332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      pending_best_connection_ = NULL;
133342af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher      LOG(LS_INFO) << "Switching best connection on controlled side"
133442af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher                   << " because it's now writable: " << connection->ToString();
1335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      SwitchBestConnectionTo(connection);
1336269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
1337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
13399b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  // May stop the allocator session when at least one connection becomes
13409b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  // strongly connected after starting to get ports. It is not enough to check
13419b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  // that the connection becomes weakly connected because the connection may be
13429b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  // changing from (writable, receiving) to (writable, not receiving).
13439b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  if (!connection->weak()) {
13449b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz    MaybeStopPortAllocatorSessions();
13459b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz  }
13469b66957b4f7dfe40c17eed597826b3ed0faf5439honghaiz
1347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // We have to unroll the stack before doing this because we may be changing
1348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // the state of connections while sorting.
1349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  RequestSort();
1350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1351269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// When a connection is removed, edit it out, and then update our best
1353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// connection.
1354269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
1355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
1356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1357269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Note: the previous best_connection_ may be destroyed by now, so don't
1358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // use it.
1359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Remove this connection from the list.
1361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<Connection*>::iterator iter =
1362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      std::find(connections_.begin(), connections_.end(), connection);
1363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(iter != connections_.end());
1364269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  connections_.erase(iter);
1365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  LOG_J(LS_INFO, this) << "Removed connection ("
1367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    << static_cast<int>(connections_.size()) << " remaining)";
1368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (pending_best_connection_ == connection) {
1370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    pending_best_connection_ = NULL;
1371269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1373269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If this is currently the best connection, then we need to pick a new one.
1374269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // The call to SortConnections will pick a new one.  It looks at the current
1375269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // best connection in order to avoid switching between fairly similar ones.
1376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Since this connection is no longer an option, we can just set best to NULL
1377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // and re-choose a best assuming that there was no best connection.
1378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (best_connection_ == connection) {
137942af6caf5c6e67eb33fb5dba9d93f01be0e638b8Peter Thatcher    LOG(LS_INFO) << "Best connection destroyed.  Will choose a new one.";
1380269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    SwitchBestConnectionTo(NULL);
1381269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    RequestSort();
1382269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1383269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1384381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  UpdateState();
1385381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  // SignalConnectionRemoved should be called after the channel state is
1386381b4217cb36f434c56e399a852a0a15522a9596Honghai Zhang  // updated because the receiver of the event may access the channel state.
1387269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SignalConnectionRemoved(this);
1388269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1389269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1390269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// When a port is destroyed remove it from our list of ports to use for
1391269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// connection attempts.
1392269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1393269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
1394269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1395269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Remove this port from the list (if we didn't drop it already).
1396269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::vector<PortInterface*>::iterator iter =
1397269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      std::find(ports_.begin(), ports_.end(), port);
1398269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (iter != ports_.end())
1399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ports_.erase(iter);
1400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1401269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  LOG(INFO) << "Removed port from p2p socket: "
1402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            << static_cast<int>(ports_.size()) << " remaining";
1403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1405269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// We data is available, let listeners know
1406cbecd358e032021eac11fb13e04ec7f070d4f407deadbeefvoid P2PTransportChannel::OnReadPacket(Connection* connection,
1407cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef                                       const char* data,
1408cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef                                       size_t len,
1409cbecd358e032021eac11fb13e04ec7f070d4f407deadbeef                                       const rtc::PacketTime& packet_time) {
1410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(worker_thread_ == rtc::Thread::Current());
1411269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1412269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Do not deliver, if packet doesn't belong to the correct transport channel.
1413269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!FindConnection(connection))
1414269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
1415269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1416269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Let the client know of an incoming packet
1417269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SignalReadPacket(this, data, len, packet_time, 0);
14185a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz
14195a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // May need to switch the sending connection based on the receiving media path
14205a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  // if this is the controlled side.
14215a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() &&
14225a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz      connection->writable() && best_connection_ != connection) {
14235a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz    SwitchBestConnectionTo(connection);
14245a3acd89648e7cff7e1b76b2da710be041be54a0honghaiz  }
1425269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1426269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
142755674ffb32307c6f3efaab442340d3c5c075073bStefan Holmervoid P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
1428c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  ASSERT(worker_thread_ == rtc::Thread::Current());
1429c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan
1430c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  SignalSentPacket(this, sent_packet);
1431c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan}
1432c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan
1433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid P2PTransportChannel::OnReadyToSend(Connection* connection) {
1434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (connection == best_connection_ && writable()) {
1435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    SignalReadyToSend(this);
1436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}  // namespace cricket
1440