• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/p2p/base/p2ptransportchannel.h"
12 
13 #include <algorithm>
14 #include <set>
15 #include "webrtc/p2p/base/common.h"
16 #include "webrtc/p2p/base/relayport.h"  // For RELAY_PORT_TYPE.
17 #include "webrtc/p2p/base/stunport.h"  // For STUN_PORT_TYPE.
18 #include "webrtc/base/common.h"
19 #include "webrtc/base/crc32.h"
20 #include "webrtc/base/logging.h"
21 #include "webrtc/base/stringencode.h"
22 #include "webrtc/system_wrappers/include/field_trial.h"
23 
24 namespace {
25 
26 // messages for queuing up work for ourselves
27 enum { MSG_SORT = 1, MSG_CHECK_AND_PING };
28 
29 // The minimum improvement in RTT that justifies a switch.
30 static const double kMinImprovement = 10;
31 
GetOrigin(cricket::PortInterface * port,cricket::PortInterface * origin_port)32 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port,
33                                          cricket::PortInterface* origin_port) {
34   if (!origin_port)
35     return cricket::PortInterface::ORIGIN_MESSAGE;
36   else if (port == origin_port)
37     return cricket::PortInterface::ORIGIN_THIS_PORT;
38   else
39     return cricket::PortInterface::ORIGIN_OTHER_PORT;
40 }
41 
42 // Compares two connections based only on static information about them.
CompareConnectionCandidates(cricket::Connection * a,cricket::Connection * b)43 int CompareConnectionCandidates(cricket::Connection* a,
44                                 cricket::Connection* b) {
45   // Compare connection priority. Lower values get sorted last.
46   if (a->priority() > b->priority())
47     return 1;
48   if (a->priority() < b->priority())
49     return -1;
50 
51   // If we're still tied at this point, prefer a younger generation.
52   return (a->remote_candidate().generation() + a->port()->generation()) -
53          (b->remote_candidate().generation() + b->port()->generation());
54 }
55 
56 // Compare two connections based on their writing, receiving, and connected
57 // states.
CompareConnectionStates(cricket::Connection * a,cricket::Connection * b)58 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) {
59   // Sort based on write-state.  Better states have lower values.
60   if (a->write_state() < b->write_state())
61     return 1;
62   if (a->write_state() > b->write_state())
63     return -1;
64 
65   // We prefer a receiving connection to a non-receiving, higher-priority
66   // connection when sorting connections and choosing which connection to
67   // switch to.
68   if (a->receiving() && !b->receiving())
69     return 1;
70   if (!a->receiving() && b->receiving())
71     return -1;
72 
73   // WARNING: Some complexity here about TCP reconnecting.
74   // When a TCP connection fails because of a TCP socket disconnecting, the
75   // active side of the connection will attempt to reconnect for 5 seconds while
76   // pretending to be writable (the connection is not set to the unwritable
77   // state).  On the passive side, the connection also remains writable even
78   // though it is disconnected, and a new connection is created when the active
79   // side connects.  At that point, there are two TCP connections on the passive
80   // side: 1. the old, disconnected one that is pretending to be writable, and
81   // 2.  the new, connected one that is maybe not yet writable.  For purposes of
82   // pruning, pinging, and selecting the best connection, we want to treat the
83   // new connection as "better" than the old one.  We could add a method called
84   // something like Connection::ImReallyBadEvenThoughImWritable, but that is
85   // equivalent to the existing Connection::connected(), which we already have.
86   // So, in code throughout this file, we'll check whether the connection is
87   // connected() or not, and if it is not, treat it as "worse" than a connected
88   // one, even though it's writable.  In the code below, we're doing so to make
89   // sure we treat a new writable connection as better than an old disconnected
90   // connection.
91 
92   // In the case where we reconnect TCP connections, the original best
93   // connection is disconnected without changing to WRITE_TIMEOUT. In this case,
94   // the new connection, when it becomes writable, should have higher priority.
95   if (a->write_state() == cricket::Connection::STATE_WRITABLE &&
96       b->write_state() == cricket::Connection::STATE_WRITABLE) {
97     if (a->connected() && !b->connected()) {
98       return 1;
99     }
100     if (!a->connected() && b->connected()) {
101       return -1;
102     }
103   }
104   return 0;
105 }
106 
CompareConnections(cricket::Connection * a,cricket::Connection * b)107 int CompareConnections(cricket::Connection* a, cricket::Connection* b) {
108   int state_cmp = CompareConnectionStates(a, b);
109   if (state_cmp != 0) {
110     return state_cmp;
111   }
112   // Compare the candidate information.
113   return CompareConnectionCandidates(a, b);
114 }
115 
116 // Wraps the comparison connection into a less than operator that puts higher
117 // priority writable connections first.
118 class ConnectionCompare {
119  public:
operator ()(const cricket::Connection * ca,const cricket::Connection * cb)120   bool operator()(const cricket::Connection *ca,
121                   const cricket::Connection *cb) {
122     cricket::Connection* a = const_cast<cricket::Connection*>(ca);
123     cricket::Connection* b = const_cast<cricket::Connection*>(cb);
124 
125     // Compare first on writability and static preferences.
126     int cmp = CompareConnections(a, b);
127     if (cmp > 0)
128       return true;
129     if (cmp < 0)
130       return false;
131 
132     // Otherwise, sort based on latency estimate.
133     return a->rtt() < b->rtt();
134 
135     // Should we bother checking for the last connection that last received
136     // data? It would help rendezvous on the connection that is also receiving
137     // packets.
138     //
139     // TODO: Yes we should definitely do this.  The TCP protocol gains
140     // efficiency by being used bidirectionally, as opposed to two separate
141     // unidirectional streams.  This test should probably occur before
142     // comparison of local prefs (assuming combined prefs are the same).  We
143     // need to be careful though, not to bounce back and forth with both sides
144     // trying to rendevous with the other.
145   }
146 };
147 
148 // Determines whether we should switch between two connections, based first on
149 // connection states, static preferences, and then (if those are equal) on
150 // latency estimates.
ShouldSwitch(cricket::Connection * a_conn,cricket::Connection * b_conn,cricket::IceRole ice_role)151 bool ShouldSwitch(cricket::Connection* a_conn,
152                   cricket::Connection* b_conn,
153                   cricket::IceRole ice_role) {
154   if (a_conn == b_conn)
155     return false;
156 
157   if (!a_conn || !b_conn)  // don't think the latter should happen
158     return true;
159 
160   // We prefer to switch to a writable and receiving connection over a
161   // non-writable or non-receiving connection, even if the latter has
162   // been nominated by the controlling side.
163   int state_cmp = CompareConnectionStates(a_conn, b_conn);
164   if (state_cmp != 0) {
165     return state_cmp < 0;
166   }
167   if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) {
168     LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status";
169     return false;
170   }
171 
172   int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn);
173   if (prefs_cmp != 0) {
174     return prefs_cmp < 0;
175   }
176 
177   return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
178 }
179 
180 }  // unnamed namespace
181 
182 namespace cricket {
183 
184 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
185 // for pinging.  When the socket is writable, we will use only 1 Kbps because
186 // we don't want to degrade the quality on a modem.  These numbers should work
187 // well on a 28.8K modem, which is the slowest connection on which the voice
188 // quality is reasonable at all.
189 static const uint32_t PING_PACKET_SIZE = 60 * 8;
190 // TODO(honghaiz): Change the word DELAY to INTERVAL whenever appropriate.
191 // STRONG_PING_DELAY (480ms) is applied when the best connection is both
192 // writable and receiving.
193 static const uint32_t STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000;
194 // WEAK_PING_DELAY (48ms) is applied when the best connection is either not
195 // writable or not receiving.
196 const uint32_t WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000;
197 
198 // If the current best connection is both writable and receiving, then we will
199 // also try hard to make sure it is pinged at this rate (a little less than
200 // 2 * STRONG_PING_DELAY).
201 static const uint32_t MAX_CURRENT_STRONG_DELAY = 900;
202 
203 static const int MIN_CHECK_RECEIVING_DELAY = 50;  // ms
204 
P2PTransportChannel(const std::string & transport_name,int component,P2PTransport * transport,PortAllocator * allocator)205 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
206                                          int component,
207                                          P2PTransport* transport,
208                                          PortAllocator* allocator)
209     : TransportChannelImpl(transport_name, component),
210       transport_(transport),
211       allocator_(allocator),
212       worker_thread_(rtc::Thread::Current()),
213       incoming_only_(false),
214       error_(0),
215       best_connection_(NULL),
216       pending_best_connection_(NULL),
217       sort_dirty_(false),
218       remote_ice_mode_(ICEMODE_FULL),
219       ice_role_(ICEROLE_UNKNOWN),
220       tiebreaker_(0),
221       gathering_state_(kIceGatheringNew),
222       check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5),
223       receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50),
224       backup_connection_ping_interval_(0) {
225   uint32_t weak_ping_delay = ::strtoul(
226       webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(),
227       nullptr, 10);
228   if (weak_ping_delay) {
229     weak_ping_delay_ =  weak_ping_delay;
230   }
231 }
232 
~P2PTransportChannel()233 P2PTransportChannel::~P2PTransportChannel() {
234   ASSERT(worker_thread_ == rtc::Thread::Current());
235 
236   for (size_t i = 0; i < allocator_sessions_.size(); ++i)
237     delete allocator_sessions_[i];
238 }
239 
240 // Add the allocator session to our list so that we know which sessions
241 // are still active.
AddAllocatorSession(PortAllocatorSession * session)242 void P2PTransportChannel::AddAllocatorSession(PortAllocatorSession* session) {
243   ASSERT(worker_thread_ == rtc::Thread::Current());
244 
245   session->set_generation(static_cast<uint32_t>(allocator_sessions_.size()));
246   allocator_sessions_.push_back(session);
247 
248   // We now only want to apply new candidates that we receive to the ports
249   // created by this new session because these are replacing those of the
250   // previous sessions.
251   ports_.clear();
252 
253   session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady);
254   session->SignalCandidatesReady.connect(
255       this, &P2PTransportChannel::OnCandidatesReady);
256   session->SignalCandidatesAllocationDone.connect(
257       this, &P2PTransportChannel::OnCandidatesAllocationDone);
258   session->StartGettingPorts();
259 }
260 
AddConnection(Connection * connection)261 void P2PTransportChannel::AddConnection(Connection* connection) {
262   connections_.push_back(connection);
263   connection->set_remote_ice_mode(remote_ice_mode_);
264   connection->set_receiving_timeout(receiving_timeout_);
265   connection->SignalReadPacket.connect(
266       this, &P2PTransportChannel::OnReadPacket);
267   connection->SignalReadyToSend.connect(
268       this, &P2PTransportChannel::OnReadyToSend);
269   connection->SignalStateChange.connect(
270       this, &P2PTransportChannel::OnConnectionStateChange);
271   connection->SignalDestroyed.connect(
272       this, &P2PTransportChannel::OnConnectionDestroyed);
273   connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
274   had_connection_ = true;
275 }
276 
SetIceRole(IceRole ice_role)277 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
278   ASSERT(worker_thread_ == rtc::Thread::Current());
279   if (ice_role_ != ice_role) {
280     ice_role_ = ice_role;
281     for (std::vector<PortInterface *>::iterator it = ports_.begin();
282          it != ports_.end(); ++it) {
283       (*it)->SetIceRole(ice_role);
284     }
285   }
286 }
287 
SetIceTiebreaker(uint64_t tiebreaker)288 void P2PTransportChannel::SetIceTiebreaker(uint64_t tiebreaker) {
289   ASSERT(worker_thread_ == rtc::Thread::Current());
290   if (!ports_.empty()) {
291     LOG(LS_ERROR)
292         << "Attempt to change tiebreaker after Port has been allocated.";
293     return;
294   }
295 
296   tiebreaker_ = tiebreaker;
297 }
298 
GetState() const299 TransportChannelState P2PTransportChannel::GetState() const {
300   return state_;
301 }
302 
303 // A channel is considered ICE completed once there is at most one active
304 // connection per network and at least one active connection.
ComputeState() const305 TransportChannelState P2PTransportChannel::ComputeState() const {
306   if (!had_connection_) {
307     return TransportChannelState::STATE_INIT;
308   }
309 
310   std::vector<Connection*> active_connections;
311   for (Connection* connection : connections_) {
312     if (connection->active()) {
313       active_connections.push_back(connection);
314     }
315   }
316   if (active_connections.empty()) {
317     return TransportChannelState::STATE_FAILED;
318   }
319 
320   std::set<rtc::Network*> networks;
321   for (Connection* connection : active_connections) {
322     rtc::Network* network = connection->port()->Network();
323     if (networks.find(network) == networks.end()) {
324       networks.insert(network);
325     } else {
326       LOG_J(LS_VERBOSE, this) << "Ice not completed yet for this channel as "
327                               << network->ToString()
328                               << " has more than 1 connection.";
329       return TransportChannelState::STATE_CONNECTING;
330     }
331   }
332 
333   LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel.";
334   return TransportChannelState::STATE_COMPLETED;
335 }
336 
SetIceCredentials(const std::string & ice_ufrag,const std::string & ice_pwd)337 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag,
338                                             const std::string& ice_pwd) {
339   ASSERT(worker_thread_ == rtc::Thread::Current());
340   ice_ufrag_ = ice_ufrag;
341   ice_pwd_ = ice_pwd;
342   // Note: Candidate gathering will restart when MaybeStartGathering is next
343   // called.
344 }
345 
SetRemoteIceCredentials(const std::string & ice_ufrag,const std::string & ice_pwd)346 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag,
347                                                   const std::string& ice_pwd) {
348   ASSERT(worker_thread_ == rtc::Thread::Current());
349   IceParameters* current_ice = remote_ice();
350   IceParameters new_ice(ice_ufrag, ice_pwd);
351   if (!current_ice || *current_ice != new_ice) {
352     // Keep the ICE credentials so that newer connections
353     // are prioritized over the older ones.
354     remote_ice_parameters_.push_back(new_ice);
355   }
356 
357   // Update the pwd of remote candidate if needed.
358   for (RemoteCandidate& candidate : remote_candidates_) {
359     if (candidate.username() == ice_ufrag && candidate.password().empty()) {
360       candidate.set_password(ice_pwd);
361     }
362   }
363   // We need to update the credentials for any peer reflexive candidates.
364   for (Connection* conn : connections_) {
365     conn->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd);
366   }
367 }
368 
SetRemoteIceMode(IceMode mode)369 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
370   remote_ice_mode_ = mode;
371 }
372 
SetIceConfig(const IceConfig & config)373 void P2PTransportChannel::SetIceConfig(const IceConfig& config) {
374   gather_continually_ = config.gather_continually;
375   LOG(LS_INFO) << "Set gather_continually to " << gather_continually_;
376 
377   if (config.backup_connection_ping_interval >= 0 &&
378       backup_connection_ping_interval_ !=
379           config.backup_connection_ping_interval) {
380     backup_connection_ping_interval_ = config.backup_connection_ping_interval;
381     LOG(LS_INFO) << "Set backup connection ping interval to "
382                  << backup_connection_ping_interval_ << " milliseconds.";
383   }
384 
385   if (config.receiving_timeout_ms >= 0 &&
386       receiving_timeout_ != config.receiving_timeout_ms) {
387     receiving_timeout_ = config.receiving_timeout_ms;
388     check_receiving_delay_ =
389         std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10);
390 
391     for (Connection* connection : connections_) {
392       connection->set_receiving_timeout(receiving_timeout_);
393     }
394     LOG(LS_INFO) << "Set ICE receiving timeout to " << receiving_timeout_
395                  << " milliseconds";
396   }
397 }
398 
399 // Go into the state of processing candidates, and running in general
Connect()400 void P2PTransportChannel::Connect() {
401   ASSERT(worker_thread_ == rtc::Thread::Current());
402   if (ice_ufrag_.empty() || ice_pwd_.empty()) {
403     ASSERT(false);
404     LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
405                   << "ice_pwd_ are not set.";
406     return;
407   }
408 
409   // Start checking and pinging as the ports come in.
410   thread()->Post(this, MSG_CHECK_AND_PING);
411 }
412 
MaybeStartGathering()413 void P2PTransportChannel::MaybeStartGathering() {
414   // Start gathering if we never started before, or if an ICE restart occurred.
415   if (allocator_sessions_.empty() ||
416       IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(),
417                             allocator_sessions_.back()->ice_pwd(), ice_ufrag_,
418                             ice_pwd_)) {
419     if (gathering_state_ != kIceGatheringGathering) {
420       gathering_state_ = kIceGatheringGathering;
421       SignalGatheringState(this);
422     }
423     // Time for a new allocator
424     AddAllocatorSession(allocator_->CreateSession(
425         SessionId(), transport_name(), component(), ice_ufrag_, ice_pwd_));
426   }
427 }
428 
429 // A new port is available, attempt to make connections for it
OnPortReady(PortAllocatorSession * session,PortInterface * port)430 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
431                                       PortInterface* port) {
432   ASSERT(worker_thread_ == rtc::Thread::Current());
433 
434   // Set in-effect options on the new port
435   for (OptionMap::const_iterator it = options_.begin();
436        it != options_.end();
437        ++it) {
438     int val = port->SetOption(it->first, it->second);
439     if (val < 0) {
440       LOG_J(LS_WARNING, port) << "SetOption(" << it->first
441                               << ", " << it->second
442                               << ") failed: " << port->GetError();
443     }
444   }
445 
446   // Remember the ports and candidates, and signal that candidates are ready.
447   // The session will handle this, and send an initiate/accept/modify message
448   // if one is pending.
449 
450   port->SetIceRole(ice_role_);
451   port->SetIceTiebreaker(tiebreaker_);
452   ports_.push_back(port);
453   port->SignalUnknownAddress.connect(
454       this, &P2PTransportChannel::OnUnknownAddress);
455   port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed);
456   port->SignalRoleConflict.connect(
457       this, &P2PTransportChannel::OnRoleConflict);
458   port->SignalSentPacket.connect(this, &P2PTransportChannel::OnSentPacket);
459 
460   // Attempt to create a connection from this new port to all of the remote
461   // candidates that we were given so far.
462 
463   std::vector<RemoteCandidate>::iterator iter;
464   for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
465        ++iter) {
466     CreateConnection(port, *iter, iter->origin_port());
467   }
468 
469   SortConnections();
470 }
471 
472 // A new candidate is available, let listeners know
OnCandidatesReady(PortAllocatorSession * session,const std::vector<Candidate> & candidates)473 void P2PTransportChannel::OnCandidatesReady(
474     PortAllocatorSession* session,
475     const std::vector<Candidate>& candidates) {
476   ASSERT(worker_thread_ == rtc::Thread::Current());
477   for (size_t i = 0; i < candidates.size(); ++i) {
478     SignalCandidateGathered(this, candidates[i]);
479   }
480 }
481 
OnCandidatesAllocationDone(PortAllocatorSession * session)482 void P2PTransportChannel::OnCandidatesAllocationDone(
483     PortAllocatorSession* session) {
484   ASSERT(worker_thread_ == rtc::Thread::Current());
485   gathering_state_ = kIceGatheringComplete;
486   LOG(LS_INFO) << "P2PTransportChannel: " << transport_name() << ", component "
487                << component() << " gathering complete";
488   SignalGatheringState(this);
489 }
490 
491 // Handle stun packets
OnUnknownAddress(PortInterface * port,const rtc::SocketAddress & address,ProtocolType proto,IceMessage * stun_msg,const std::string & remote_username,bool port_muxed)492 void P2PTransportChannel::OnUnknownAddress(
493     PortInterface* port,
494     const rtc::SocketAddress& address, ProtocolType proto,
495     IceMessage* stun_msg, const std::string &remote_username,
496     bool port_muxed) {
497   ASSERT(worker_thread_ == rtc::Thread::Current());
498 
499   // Port has received a valid stun packet from an address that no Connection
500   // is currently available for. See if we already have a candidate with the
501   // address. If it isn't we need to create new candidate for it.
502 
503   // Determine if the remote candidates use shared ufrag.
504   bool ufrag_per_port = false;
505   std::vector<RemoteCandidate>::iterator it;
506   if (remote_candidates_.size() > 0) {
507     it = remote_candidates_.begin();
508     std::string username = it->username();
509     for (; it != remote_candidates_.end(); ++it) {
510       if (it->username() != username) {
511         ufrag_per_port = true;
512         break;
513       }
514     }
515   }
516 
517   const Candidate* candidate = NULL;
518   std::string remote_password;
519   for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) {
520     if (it->username() == remote_username) {
521       remote_password = it->password();
522       if (ufrag_per_port ||
523           (it->address() == address &&
524            it->protocol() == ProtoToString(proto))) {
525         candidate = &(*it);
526         break;
527       }
528       // We don't want to break here because we may find a match of the address
529       // later.
530     }
531   }
532 
533   uint32_t remote_generation = 0;
534   // The STUN binding request may arrive after setRemoteDescription and before
535   // adding remote candidate, so we need to set the password to the shared
536   // password if the user name matches.
537   if (remote_password.empty()) {
538     const IceParameters* ice_param =
539         FindRemoteIceFromUfrag(remote_username, &remote_generation);
540     // Note: if not found, the remote_generation will still be 0.
541     if (ice_param != nullptr) {
542       remote_password = ice_param->pwd;
543     }
544   }
545 
546   Candidate remote_candidate;
547   bool remote_candidate_is_new = (candidate == nullptr);
548   if (!remote_candidate_is_new) {
549     remote_candidate = *candidate;
550     if (ufrag_per_port) {
551       remote_candidate.set_address(address);
552     }
553   } else {
554     // Create a new candidate with this address.
555     int remote_candidate_priority;
556 
557     // The priority of the candidate is set to the PRIORITY attribute
558     // from the request.
559     const StunUInt32Attribute* priority_attr =
560         stun_msg->GetUInt32(STUN_ATTR_PRIORITY);
561     if (!priority_attr) {
562       LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - "
563                       << "No STUN_ATTR_PRIORITY found in the "
564                       << "stun request message";
565       port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_BAD_REQUEST,
566                                      STUN_ERROR_REASON_BAD_REQUEST);
567       return;
568     }
569     remote_candidate_priority = priority_attr->value();
570 
571     // RFC 5245
572     // If the source transport address of the request does not match any
573     // existing remote candidates, it represents a new peer reflexive remote
574     // candidate.
575     remote_candidate = Candidate(component(), ProtoToString(proto), address, 0,
576                                  remote_username, remote_password,
577                                  PRFLX_PORT_TYPE, remote_generation, "");
578 
579     // From RFC 5245, section-7.2.1.3:
580     // The foundation of the candidate is set to an arbitrary value, different
581     // from the foundation for all other remote candidates.
582     remote_candidate.set_foundation(
583         rtc::ToString<uint32_t>(rtc::ComputeCrc32(remote_candidate.id())));
584 
585     remote_candidate.set_priority(remote_candidate_priority);
586   }
587 
588   // RFC5245, the agent constructs a pair whose local candidate is equal to
589   // the transport address on which the STUN request was received, and a
590   // remote candidate equal to the source transport address where the
591   // request came from.
592 
593   // There shouldn't be an existing connection with this remote address.
594   // When ports are muxed, this channel might get multiple unknown address
595   // signals. In that case if the connection is already exists, we should
596   // simply ignore the signal otherwise send server error.
597   if (port->GetConnection(remote_candidate.address())) {
598     if (port_muxed) {
599       LOG(LS_INFO) << "Connection already exists for peer reflexive "
600                    << "candidate: " << remote_candidate.ToString();
601       return;
602     } else {
603       ASSERT(false);
604       port->SendBindingErrorResponse(stun_msg, address,
605                                      STUN_ERROR_SERVER_ERROR,
606                                      STUN_ERROR_REASON_SERVER_ERROR);
607       return;
608     }
609   }
610 
611   Connection* connection = port->CreateConnection(
612       remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT);
613   if (!connection) {
614     ASSERT(false);
615     port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR,
616                                    STUN_ERROR_REASON_SERVER_ERROR);
617     return;
618   }
619 
620   LOG(LS_INFO) << "Adding connection from "
621                << (remote_candidate_is_new ? "peer reflexive" : "resurrected")
622                << " candidate: " << remote_candidate.ToString();
623   AddConnection(connection);
624   connection->HandleBindingRequest(stun_msg);
625 
626   // Update the list of connections since we just added another.  We do this
627   // after sending the response since it could (in principle) delete the
628   // connection in question.
629   SortConnections();
630 }
631 
OnRoleConflict(PortInterface * port)632 void P2PTransportChannel::OnRoleConflict(PortInterface* port) {
633   SignalRoleConflict(this);  // STUN ping will be sent when SetRole is called
634                              // from Transport.
635 }
636 
FindRemoteIceFromUfrag(const std::string & ufrag,uint32_t * generation)637 const IceParameters* P2PTransportChannel::FindRemoteIceFromUfrag(
638     const std::string& ufrag,
639     uint32_t* generation) {
640   const auto& params = remote_ice_parameters_;
641   auto it = std::find_if(
642       params.rbegin(), params.rend(),
643       [ufrag](const IceParameters& param) { return param.ufrag == ufrag; });
644   if (it == params.rend()) {
645     // Not found.
646     return nullptr;
647   }
648   *generation = params.rend() - it - 1;
649   return &(*it);
650 }
651 
OnNominated(Connection * conn)652 void P2PTransportChannel::OnNominated(Connection* conn) {
653   ASSERT(worker_thread_ == rtc::Thread::Current());
654   ASSERT(ice_role_ == ICEROLE_CONTROLLED);
655 
656   if (conn->write_state() == Connection::STATE_WRITABLE) {
657     if (best_connection_ != conn) {
658       pending_best_connection_ = NULL;
659       LOG(LS_INFO) << "Switching best connection on controlled side: "
660                    << conn->ToString();
661       SwitchBestConnectionTo(conn);
662       // Now we have selected the best connection, time to prune other existing
663       // connections and update the read/write state of the channel.
664       RequestSort();
665     }
666   } else {
667     LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
668                  << " because it's not writable: " << conn->ToString();
669     pending_best_connection_ = conn;
670   }
671 }
672 
AddRemoteCandidate(const Candidate & candidate)673 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
674   ASSERT(worker_thread_ == rtc::Thread::Current());
675 
676   uint32_t generation = GetRemoteCandidateGeneration(candidate);
677   // If a remote candidate with a previous generation arrives, drop it.
678   if (generation < remote_ice_generation()) {
679     LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
680                     << candidate.username()
681                     << " indicates it was for a previous generation.";
682     return;
683   }
684 
685   Candidate new_remote_candidate(candidate);
686   new_remote_candidate.set_generation(generation);
687   // ICE candidates don't need to have username and password set, but
688   // the code below this (specifically, ConnectionRequest::Prepare in
689   // port.cc) uses the remote candidates's username.  So, we set it
690   // here.
691   if (remote_ice()) {
692     if (candidate.username().empty()) {
693       new_remote_candidate.set_username(remote_ice()->ufrag);
694     }
695     if (new_remote_candidate.username() == remote_ice()->ufrag) {
696       if (candidate.password().empty()) {
697         new_remote_candidate.set_password(remote_ice()->pwd);
698       }
699     } else {
700       // The candidate belongs to the next generation. Its pwd will be set
701       // when the new remote ICE credentials arrive.
702       LOG(LS_WARNING) << "A remote candidate arrives with an unknown ufrag: "
703                       << candidate.username();
704     }
705   }
706 
707   // Create connections to this remote candidate.
708   CreateConnections(new_remote_candidate, NULL);
709 
710   // Resort the connections list, which may have new elements.
711   SortConnections();
712 }
713 
714 // Creates connections from all of the ports that we care about to the given
715 // remote candidate.  The return value is true if we created a connection from
716 // the origin port.
CreateConnections(const Candidate & remote_candidate,PortInterface * origin_port)717 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
718                                             PortInterface* origin_port) {
719   ASSERT(worker_thread_ == rtc::Thread::Current());
720 
721   // If we've already seen the new remote candidate (in the current candidate
722   // generation), then we shouldn't try creating connections for it.
723   // We either already have a connection for it, or we previously created one
724   // and then later pruned it. If we don't return, the channel will again
725   // re-create any connections that were previously pruned, which will then
726   // immediately be re-pruned, churning the network for no purpose.
727   // This only applies to candidates received over signaling (i.e. origin_port
728   // is NULL).
729   if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) {
730     // return true to indicate success, without creating any new connections.
731     return true;
732   }
733 
734   // Add a new connection for this candidate to every port that allows such a
735   // connection (i.e., if they have compatible protocols) and that does not
736   // already have a connection to an equivalent candidate.  We must be careful
737   // to make sure that the origin port is included, even if it was pruned,
738   // since that may be the only port that can create this connection.
739   bool created = false;
740   std::vector<PortInterface *>::reverse_iterator it;
741   for (it = ports_.rbegin(); it != ports_.rend(); ++it) {
742     if (CreateConnection(*it, remote_candidate, origin_port)) {
743       if (*it == origin_port)
744         created = true;
745     }
746   }
747 
748   if ((origin_port != NULL) &&
749       std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
750     if (CreateConnection(origin_port, remote_candidate, origin_port))
751       created = true;
752   }
753 
754   // Remember this remote candidate so that we can add it to future ports.
755   RememberRemoteCandidate(remote_candidate, origin_port);
756 
757   return created;
758 }
759 
760 // Setup a connection object for the local and remote candidate combination.
761 // And then listen to connection object for changes.
CreateConnection(PortInterface * port,const Candidate & remote_candidate,PortInterface * origin_port)762 bool P2PTransportChannel::CreateConnection(PortInterface* port,
763                                            const Candidate& remote_candidate,
764                                            PortInterface* origin_port) {
765   if (!port->SupportsProtocol(remote_candidate.protocol())) {
766     return false;
767   }
768   // Look for an existing connection with this remote address.  If one is not
769   // found, then we can create a new connection for this address.
770   Connection* connection = port->GetConnection(remote_candidate.address());
771   if (connection != NULL) {
772     connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate);
773 
774     // It is not legal to try to change any of the parameters of an existing
775     // connection; however, the other side can send a duplicate candidate.
776     if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
777       LOG(INFO) << "Attempt to change a remote candidate."
778                 << " Existing remote candidate: "
779                 << connection->remote_candidate().ToString()
780                 << "New remote candidate: "
781                 << remote_candidate.ToString();
782       return false;
783     }
784   } else {
785     PortInterface::CandidateOrigin origin = GetOrigin(port, origin_port);
786 
787     // Don't create connection if this is a candidate we received in a
788     // message and we are not allowed to make outgoing connections.
789     if (origin == cricket::PortInterface::ORIGIN_MESSAGE && incoming_only_)
790       return false;
791 
792     connection = port->CreateConnection(remote_candidate, origin);
793     if (!connection)
794       return false;
795 
796     AddConnection(connection);
797 
798     LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", ("
799                          << connections_.size() << " total)";
800   }
801 
802   return true;
803 }
804 
FindConnection(cricket::Connection * connection) const805 bool P2PTransportChannel::FindConnection(
806     cricket::Connection* connection) const {
807   std::vector<Connection*>::const_iterator citer =
808       std::find(connections_.begin(), connections_.end(), connection);
809   return citer != connections_.end();
810 }
811 
GetRemoteCandidateGeneration(const Candidate & candidate)812 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration(
813     const Candidate& candidate) {
814   // If the candidate has a ufrag, use it to find the generation.
815   if (!candidate.username().empty()) {
816     uint32_t generation = 0;
817     if (!FindRemoteIceFromUfrag(candidate.username(), &generation)) {
818       // If the ufrag is not found, assume the next/future generation.
819       generation = static_cast<uint32_t>(remote_ice_parameters_.size());
820     }
821     return generation;
822   }
823   // If candidate generation is set, use that.
824   if (candidate.generation() > 0) {
825     return candidate.generation();
826   }
827   // Otherwise, assume the generation from remote ice parameters.
828   return remote_ice_generation();
829 }
830 
831 // Check if remote candidate is already cached.
IsDuplicateRemoteCandidate(const Candidate & candidate)832 bool P2PTransportChannel::IsDuplicateRemoteCandidate(
833     const Candidate& candidate) {
834   for (size_t i = 0; i < remote_candidates_.size(); ++i) {
835     if (remote_candidates_[i].IsEquivalent(candidate)) {
836       return true;
837     }
838   }
839   return false;
840 }
841 
842 // Maintain our remote candidate list, adding this new remote one.
RememberRemoteCandidate(const Candidate & remote_candidate,PortInterface * origin_port)843 void P2PTransportChannel::RememberRemoteCandidate(
844     const Candidate& remote_candidate, PortInterface* origin_port) {
845   // Remove any candidates whose generation is older than this one.  The
846   // presence of a new generation indicates that the old ones are not useful.
847   size_t i = 0;
848   while (i < remote_candidates_.size()) {
849     if (remote_candidates_[i].generation() < remote_candidate.generation()) {
850       LOG(INFO) << "Pruning candidate from old generation: "
851                 << remote_candidates_[i].address().ToSensitiveString();
852       remote_candidates_.erase(remote_candidates_.begin() + i);
853     } else {
854       i += 1;
855     }
856   }
857 
858   // Make sure this candidate is not a duplicate.
859   if (IsDuplicateRemoteCandidate(remote_candidate)) {
860     LOG(INFO) << "Duplicate candidate: " << remote_candidate.ToString();
861     return;
862   }
863 
864   // Try this candidate for all future ports.
865   remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port));
866 }
867 
868 // Set options on ourselves is simply setting options on all of our available
869 // port objects.
SetOption(rtc::Socket::Option opt,int value)870 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) {
871   ASSERT(worker_thread_ == rtc::Thread::Current());
872   OptionMap::iterator it = options_.find(opt);
873   if (it == options_.end()) {
874     options_.insert(std::make_pair(opt, value));
875   } else if (it->second == value) {
876     return 0;
877   } else {
878     it->second = value;
879   }
880 
881   for (size_t i = 0; i < ports_.size(); ++i) {
882     int val = ports_[i]->SetOption(opt, value);
883     if (val < 0) {
884       // Because this also occurs deferred, probably no point in reporting an
885       // error
886       LOG(WARNING) << "SetOption(" << opt << ", " << value << ") failed: "
887                    << ports_[i]->GetError();
888     }
889   }
890   return 0;
891 }
892 
GetOption(rtc::Socket::Option opt,int * value)893 bool P2PTransportChannel::GetOption(rtc::Socket::Option opt, int* value) {
894   ASSERT(worker_thread_ == rtc::Thread::Current());
895 
896   const auto& found = options_.find(opt);
897   if (found == options_.end()) {
898     return false;
899   }
900   *value = found->second;
901   return true;
902 }
903 
904 // Send data to the other side, using our best connection.
SendPacket(const char * data,size_t len,const rtc::PacketOptions & options,int flags)905 int P2PTransportChannel::SendPacket(const char *data, size_t len,
906                                     const rtc::PacketOptions& options,
907                                     int flags) {
908   ASSERT(worker_thread_ == rtc::Thread::Current());
909   if (flags != 0) {
910     error_ = EINVAL;
911     return -1;
912   }
913   if (best_connection_ == NULL) {
914     error_ = EWOULDBLOCK;
915     return -1;
916   }
917 
918   int sent = best_connection_->Send(data, len, options);
919   if (sent <= 0) {
920     ASSERT(sent < 0);
921     error_ = best_connection_->GetError();
922   }
923   return sent;
924 }
925 
GetStats(ConnectionInfos * infos)926 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
927   ASSERT(worker_thread_ == rtc::Thread::Current());
928   // Gather connection infos.
929   infos->clear();
930 
931   std::vector<Connection *>::const_iterator it;
932   for (Connection* connection : connections_) {
933     ConnectionInfo info;
934     info.best_connection = (best_connection_ == connection);
935     info.receiving = connection->receiving();
936     info.writable =
937         (connection->write_state() == Connection::STATE_WRITABLE);
938     info.timeout =
939         (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
940     info.new_connection = !connection->reported();
941     connection->set_reported(true);
942     info.rtt = connection->rtt();
943     info.sent_total_bytes = connection->sent_total_bytes();
944     info.sent_bytes_second = connection->sent_bytes_second();
945     info.sent_discarded_packets = connection->sent_discarded_packets();
946     info.sent_total_packets = connection->sent_total_packets();
947     info.recv_total_bytes = connection->recv_total_bytes();
948     info.recv_bytes_second = connection->recv_bytes_second();
949     info.local_candidate = connection->local_candidate();
950     info.remote_candidate = connection->remote_candidate();
951     info.key = connection;
952     infos->push_back(info);
953   }
954 
955   return true;
956 }
957 
DefaultDscpValue() const958 rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const {
959   OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP);
960   if (it == options_.end()) {
961     return rtc::DSCP_NO_CHANGE;
962   }
963   return static_cast<rtc::DiffServCodePoint> (it->second);
964 }
965 
966 // Monitor connection states.
UpdateConnectionStates()967 void P2PTransportChannel::UpdateConnectionStates() {
968   uint32_t now = rtc::Time();
969 
970   // We need to copy the list of connections since some may delete themselves
971   // when we call UpdateState.
972   for (size_t i = 0; i < connections_.size(); ++i)
973     connections_[i]->UpdateState(now);
974 }
975 
976 // Prepare for best candidate sorting.
RequestSort()977 void P2PTransportChannel::RequestSort() {
978   if (!sort_dirty_) {
979     worker_thread_->Post(this, MSG_SORT);
980     sort_dirty_ = true;
981   }
982 }
983 
984 // Sort the available connections to find the best one.  We also monitor
985 // the number of available connections and the current state.
SortConnections()986 void P2PTransportChannel::SortConnections() {
987   ASSERT(worker_thread_ == rtc::Thread::Current());
988 
989   // Make sure the connection states are up-to-date since this affects how they
990   // will be sorted.
991   UpdateConnectionStates();
992 
993   // Any changes after this point will require a re-sort.
994   sort_dirty_ = false;
995 
996   // Find the best alternative connection by sorting.  It is important to note
997   // that amongst equal preference, writable connections, this will choose the
998   // one whose estimated latency is lowest.  So it is the only one that we
999   // need to consider switching to.
1000   ConnectionCompare cmp;
1001   std::stable_sort(connections_.begin(), connections_.end(), cmp);
1002   LOG(LS_VERBOSE) << "Sorting " << connections_.size()
1003                   << " available connections:";
1004   for (size_t i = 0; i < connections_.size(); ++i) {
1005     LOG(LS_VERBOSE) << connections_[i]->ToString();
1006   }
1007 
1008   Connection* top_connection =
1009       (connections_.size() > 0) ? connections_[0] : nullptr;
1010 
1011   // If necessary, switch to the new choice.
1012   // Note that |top_connection| doesn't have to be writable to become the best
1013   // connection although it will have higher priority if it is writable.
1014   if (ShouldSwitch(best_connection_, top_connection, ice_role_)) {
1015     LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
1016     SwitchBestConnectionTo(top_connection);
1017   }
1018 
1019   // Controlled side can prune only if the best connection has been nominated.
1020   // because otherwise it may delete the connection that will be selected by
1021   // the controlling side.
1022   if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
1023     PruneConnections();
1024   }
1025 
1026   // Check if all connections are timedout.
1027   bool all_connections_timedout = true;
1028   for (size_t i = 0; i < connections_.size(); ++i) {
1029     if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1030       all_connections_timedout = false;
1031       break;
1032     }
1033   }
1034 
1035   // Now update the writable state of the channel with the information we have
1036   // so far.
1037   if (all_connections_timedout) {
1038     HandleAllTimedOut();
1039   }
1040 
1041   // Update the state of this channel.  This method is called whenever the
1042   // state of any connection changes, so this is a good place to do this.
1043   UpdateState();
1044 }
1045 
best_nominated_connection() const1046 Connection* P2PTransportChannel::best_nominated_connection() const {
1047   return (best_connection_ && best_connection_->nominated()) ? best_connection_
1048                                                              : nullptr;
1049 }
1050 
PruneConnections()1051 void P2PTransportChannel::PruneConnections() {
1052   // We can prune any connection for which there is a connected, writable
1053   // connection on the same network with better or equal priority.  We leave
1054   // those with better priority just in case they become writable later (at
1055   // which point, we would prune out the current best connection).  We leave
1056   // connections on other networks because they may not be using the same
1057   // resources and they may represent very distinct paths over which we can
1058   // switch. If the |premier| connection is not connected, we may be
1059   // reconnecting a TCP connection and temporarily do not prune connections in
1060   // this network. See the big comment in CompareConnections.
1061 
1062   // Get a list of the networks that we are using.
1063   std::set<rtc::Network*> networks;
1064   for (const Connection* conn : connections_) {
1065     networks.insert(conn->port()->Network());
1066   }
1067   for (rtc::Network* network : networks) {
1068     Connection* premier = GetBestConnectionOnNetwork(network);
1069     // Do not prune connections if the current best connection is weak on this
1070     // network. Otherwise, it may delete connections prematurely.
1071     if (!premier || premier->weak()) {
1072       continue;
1073     }
1074 
1075     for (Connection* conn : connections_) {
1076       if ((conn != premier) && (conn->port()->Network() == network) &&
1077           (CompareConnectionCandidates(premier, conn) >= 0)) {
1078         conn->Prune();
1079       }
1080     }
1081   }
1082 }
1083 
1084 // Track the best connection, and let listeners know
SwitchBestConnectionTo(Connection * conn)1085 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1086   // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1087   // so don't use it.
1088   Connection* old_best_connection = best_connection_;
1089   best_connection_ = conn;
1090   if (best_connection_) {
1091     if (old_best_connection) {
1092       LOG_J(LS_INFO, this) << "Previous best connection: "
1093                            << old_best_connection->ToString();
1094     }
1095     LOG_J(LS_INFO, this) << "New best connection: "
1096                          << best_connection_->ToString();
1097     SignalRouteChange(this, best_connection_->remote_candidate());
1098   } else {
1099     LOG_J(LS_INFO, this) << "No best connection";
1100   }
1101 }
1102 
1103 // Warning: UpdateState should eventually be called whenever a connection
1104 // is added, deleted, or the write state of any connection changes so that the
1105 // transport controller will get the up-to-date channel state. However it
1106 // should not be called too often; in the case that multiple connection states
1107 // change, it should be called after all the connection states have changed. For
1108 // example, we call this at the end of SortConnections.
UpdateState()1109 void P2PTransportChannel::UpdateState() {
1110   state_ = ComputeState();
1111 
1112   bool writable = best_connection_ && best_connection_->writable();
1113   set_writable(writable);
1114 
1115   bool receiving = false;
1116   for (const Connection* connection : connections_) {
1117     if (connection->receiving()) {
1118       receiving = true;
1119       break;
1120     }
1121   }
1122   set_receiving(receiving);
1123 }
1124 
MaybeStopPortAllocatorSessions()1125 void P2PTransportChannel::MaybeStopPortAllocatorSessions() {
1126   if (!IsGettingPorts()) {
1127     return;
1128   }
1129 
1130   for (PortAllocatorSession* session : allocator_sessions_) {
1131     if (!session->IsGettingPorts()) {
1132       continue;
1133     }
1134     // If gathering continually, keep the last session running so that it
1135     // will gather candidates if the networks change.
1136     if (gather_continually_ && session == allocator_sessions_.back()) {
1137       session->ClearGettingPorts();
1138       break;
1139     }
1140     session->StopGettingPorts();
1141   }
1142 }
1143 
1144 // If all connections timed out, delete them all.
HandleAllTimedOut()1145 void P2PTransportChannel::HandleAllTimedOut() {
1146   for (Connection* connection : connections_) {
1147     connection->Destroy();
1148   }
1149 }
1150 
weak() const1151 bool P2PTransportChannel::weak() const {
1152   return !best_connection_ || best_connection_->weak();
1153 }
1154 
1155 // If we have a best connection, return it, otherwise return top one in the
1156 // list (later we will mark it best).
GetBestConnectionOnNetwork(rtc::Network * network) const1157 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1158     rtc::Network* network) const {
1159   // If the best connection is on this network, then it wins.
1160   if (best_connection_ && (best_connection_->port()->Network() == network))
1161     return best_connection_;
1162 
1163   // Otherwise, we return the top-most in sorted order.
1164   for (size_t i = 0; i < connections_.size(); ++i) {
1165     if (connections_[i]->port()->Network() == network)
1166       return connections_[i];
1167   }
1168 
1169   return NULL;
1170 }
1171 
1172 // Handle any queued up requests
OnMessage(rtc::Message * pmsg)1173 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1174   switch (pmsg->message_id) {
1175     case MSG_SORT:
1176       OnSort();
1177       break;
1178     case MSG_CHECK_AND_PING:
1179       OnCheckAndPing();
1180       break;
1181     default:
1182       ASSERT(false);
1183       break;
1184   }
1185 }
1186 
1187 // Handle queued up sort request
OnSort()1188 void P2PTransportChannel::OnSort() {
1189   // Resort the connections based on the new statistics.
1190   SortConnections();
1191 }
1192 
1193 // Handle queued up check-and-ping request
OnCheckAndPing()1194 void P2PTransportChannel::OnCheckAndPing() {
1195   // Make sure the states of the connections are up-to-date (since this affects
1196   // which ones are pingable).
1197   UpdateConnectionStates();
1198   // When the best connection is either not receiving or not writable,
1199   // switch to weak ping delay.
1200   int ping_delay = weak() ? weak_ping_delay_ : STRONG_PING_DELAY;
1201   if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) {
1202     Connection* conn = FindNextPingableConnection();
1203     if (conn) {
1204       PingConnection(conn);
1205     }
1206   }
1207   int check_delay = std::min(ping_delay, check_receiving_delay_);
1208   thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
1209 }
1210 
1211 // A connection is considered a backup connection if the channel state
1212 // is completed, the connection is not the best connection and it is active.
IsBackupConnection(Connection * conn) const1213 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const {
1214   return state_ == STATE_COMPLETED && conn != best_connection_ &&
1215          conn->active();
1216 }
1217 
1218 // Is the connection in a state for us to even consider pinging the other side?
1219 // We consider a connection pingable even if it's not connected because that's
1220 // how a TCP connection is kicked into reconnecting on the active side.
IsPingable(Connection * conn,uint32_t now)1221 bool P2PTransportChannel::IsPingable(Connection* conn, uint32_t now) {
1222   const Candidate& remote = conn->remote_candidate();
1223   // We should never get this far with an empty remote ufrag.
1224   ASSERT(!remote.username().empty());
1225   if (remote.username().empty() || remote.password().empty()) {
1226     // If we don't have an ICE ufrag and pwd, there's no way we can ping.
1227     return false;
1228   }
1229 
1230   // An never connected connection cannot be written to at all, so pinging is
1231   // out of the question. However, if it has become WRITABLE, it is in the
1232   // reconnecting state so ping is needed.
1233   if (!conn->connected() && !conn->writable()) {
1234     return false;
1235   }
1236 
1237   // If the channel is weakly connected, ping all connections.
1238   if (weak()) {
1239     return true;
1240   }
1241 
1242   // Always ping active connections regardless whether the channel is completed
1243   // or not, but backup connections are pinged at a slower rate.
1244   if (IsBackupConnection(conn)) {
1245     return (now >= conn->last_ping_response_received() +
1246                        backup_connection_ping_interval_);
1247   }
1248   return conn->active();
1249 }
1250 
1251 // Returns the next pingable connection to ping.  This will be the oldest
1252 // pingable connection unless we have a connected, writable connection that is
1253 // past the maximum acceptable ping delay. When reconnecting a TCP connection,
1254 // the best connection is disconnected, although still WRITABLE while
1255 // reconnecting. The newly created connection should be selected as the ping
1256 // target to become writable instead. See the big comment in CompareConnections.
FindNextPingableConnection()1257 Connection* P2PTransportChannel::FindNextPingableConnection() {
1258   uint32_t now = rtc::Time();
1259   if (best_connection_ && best_connection_->connected() &&
1260       best_connection_->writable() &&
1261       (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) {
1262     return best_connection_;
1263   }
1264 
1265   // First, find "triggered checks".  We ping first those connections
1266   // that have received a ping but have not sent a ping since receiving
1267   // it (last_received_ping > last_sent_ping).  But we shouldn't do
1268   // triggered checks if the connection is already writable.
1269   Connection* oldest_needing_triggered_check = nullptr;
1270   Connection* oldest = nullptr;
1271   for (Connection* conn : connections_) {
1272     if (!IsPingable(conn, now)) {
1273       continue;
1274     }
1275     bool needs_triggered_check =
1276         (!conn->writable() &&
1277          conn->last_ping_received() > conn->last_ping_sent());
1278     if (needs_triggered_check &&
1279         (!oldest_needing_triggered_check ||
1280          (conn->last_ping_received() <
1281           oldest_needing_triggered_check->last_ping_received()))) {
1282       oldest_needing_triggered_check = conn;
1283     }
1284     if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) {
1285       oldest = conn;
1286     }
1287   }
1288 
1289   if (oldest_needing_triggered_check) {
1290     LOG(LS_INFO) << "Selecting connection for triggered check: " <<
1291         oldest_needing_triggered_check->ToString();
1292     return oldest_needing_triggered_check;
1293   }
1294   return oldest;
1295 }
1296 
1297 // Apart from sending ping from |conn| this method also updates
1298 // |use_candidate_attr| flag. The criteria to update this flag is
1299 // explained below.
1300 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND
1301 //    a) Channel is in FULL ICE AND
1302 //      a.1) |conn| is the best connection OR
1303 //      a.2) there is no best connection OR
1304 //      a.3) the best connection is unwritable OR
1305 //      a.4) |conn| has higher priority than best_connection.
1306 //    b) we're doing LITE ICE AND
1307 //      b.1) |conn| is the best_connection AND
1308 //      b.2) |conn| is writable.
PingConnection(Connection * conn)1309 void P2PTransportChannel::PingConnection(Connection* conn) {
1310   bool use_candidate = false;
1311   if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1312     use_candidate = (conn == best_connection_) || (best_connection_ == NULL) ||
1313                     (!best_connection_->writable()) ||
1314                     (conn->priority() > best_connection_->priority());
1315   } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) {
1316     use_candidate = best_connection_->writable();
1317   }
1318   conn->set_use_candidate_attr(use_candidate);
1319   last_ping_sent_ms_ = rtc::Time();
1320   conn->Ping(last_ping_sent_ms_);
1321 }
1322 
1323 // When a connection's state changes, we need to figure out who to use as
1324 // the best connection again.  It could have become usable, or become unusable.
OnConnectionStateChange(Connection * connection)1325 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1326   ASSERT(worker_thread_ == rtc::Thread::Current());
1327 
1328   // Update the best connection if the state change is from pending best
1329   // connection and role is controlled.
1330   if (ice_role_ == ICEROLE_CONTROLLED) {
1331     if (connection == pending_best_connection_ && connection->writable()) {
1332       pending_best_connection_ = NULL;
1333       LOG(LS_INFO) << "Switching best connection on controlled side"
1334                    << " because it's now writable: " << connection->ToString();
1335       SwitchBestConnectionTo(connection);
1336     }
1337   }
1338 
1339   // May stop the allocator session when at least one connection becomes
1340   // strongly connected after starting to get ports. It is not enough to check
1341   // that the connection becomes weakly connected because the connection may be
1342   // changing from (writable, receiving) to (writable, not receiving).
1343   if (!connection->weak()) {
1344     MaybeStopPortAllocatorSessions();
1345   }
1346 
1347   // We have to unroll the stack before doing this because we may be changing
1348   // the state of connections while sorting.
1349   RequestSort();
1350 }
1351 
1352 // When a connection is removed, edit it out, and then update our best
1353 // connection.
OnConnectionDestroyed(Connection * connection)1354 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
1355   ASSERT(worker_thread_ == rtc::Thread::Current());
1356 
1357   // Note: the previous best_connection_ may be destroyed by now, so don't
1358   // use it.
1359 
1360   // Remove this connection from the list.
1361   std::vector<Connection*>::iterator iter =
1362       std::find(connections_.begin(), connections_.end(), connection);
1363   ASSERT(iter != connections_.end());
1364   connections_.erase(iter);
1365 
1366   LOG_J(LS_INFO, this) << "Removed connection ("
1367     << static_cast<int>(connections_.size()) << " remaining)";
1368 
1369   if (pending_best_connection_ == connection) {
1370     pending_best_connection_ = NULL;
1371   }
1372 
1373   // If this is currently the best connection, then we need to pick a new one.
1374   // The call to SortConnections will pick a new one.  It looks at the current
1375   // best connection in order to avoid switching between fairly similar ones.
1376   // Since this connection is no longer an option, we can just set best to NULL
1377   // and re-choose a best assuming that there was no best connection.
1378   if (best_connection_ == connection) {
1379     LOG(LS_INFO) << "Best connection destroyed.  Will choose a new one.";
1380     SwitchBestConnectionTo(NULL);
1381     RequestSort();
1382   }
1383 
1384   UpdateState();
1385   // SignalConnectionRemoved should be called after the channel state is
1386   // updated because the receiver of the event may access the channel state.
1387   SignalConnectionRemoved(this);
1388 }
1389 
1390 // When a port is destroyed remove it from our list of ports to use for
1391 // connection attempts.
OnPortDestroyed(PortInterface * port)1392 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1393   ASSERT(worker_thread_ == rtc::Thread::Current());
1394 
1395   // Remove this port from the list (if we didn't drop it already).
1396   std::vector<PortInterface*>::iterator iter =
1397       std::find(ports_.begin(), ports_.end(), port);
1398   if (iter != ports_.end())
1399     ports_.erase(iter);
1400 
1401   LOG(INFO) << "Removed port from p2p socket: "
1402             << static_cast<int>(ports_.size()) << " remaining";
1403 }
1404 
1405 // We data is available, let listeners know
OnReadPacket(Connection * connection,const char * data,size_t len,const rtc::PacketTime & packet_time)1406 void P2PTransportChannel::OnReadPacket(Connection* connection,
1407                                        const char* data,
1408                                        size_t len,
1409                                        const rtc::PacketTime& packet_time) {
1410   ASSERT(worker_thread_ == rtc::Thread::Current());
1411 
1412   // Do not deliver, if packet doesn't belong to the correct transport channel.
1413   if (!FindConnection(connection))
1414     return;
1415 
1416   // Let the client know of an incoming packet
1417   SignalReadPacket(this, data, len, packet_time, 0);
1418 
1419   // May need to switch the sending connection based on the receiving media path
1420   // if this is the controlled side.
1421   if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() &&
1422       connection->writable() && best_connection_ != connection) {
1423     SwitchBestConnectionTo(connection);
1424   }
1425 }
1426 
OnSentPacket(const rtc::SentPacket & sent_packet)1427 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
1428   ASSERT(worker_thread_ == rtc::Thread::Current());
1429 
1430   SignalSentPacket(this, sent_packet);
1431 }
1432 
OnReadyToSend(Connection * connection)1433 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1434   if (connection == best_connection_ && writable()) {
1435     SignalReadyToSend(this);
1436   }
1437 }
1438 
1439 }  // namespace cricket
1440