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