• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004--2005, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/p2p/base/p2ptransportchannel.h"
29 
30 #include <set>
31 #include "talk/p2p/base/common.h"
32 #include "talk/p2p/base/relayport.h"  // For RELAY_PORT_TYPE.
33 #include "talk/p2p/base/stunport.h"  // For STUN_PORT_TYPE.
34 #include "webrtc/base/common.h"
35 #include "webrtc/base/crc32.h"
36 #include "webrtc/base/logging.h"
37 #include "webrtc/base/stringencode.h"
38 
39 namespace {
40 
41 // messages for queuing up work for ourselves
42 enum {
43   MSG_SORT = 1,
44   MSG_PING,
45 };
46 
47 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
48 // for pinging.  When the socket is writable, we will use only 1 Kbps because
49 // we don't want to degrade the quality on a modem.  These numbers should work
50 // well on a 28.8K modem, which is the slowest connection on which the voice
51 // quality is reasonable at all.
52 static const uint32 PING_PACKET_SIZE = 60 * 8;
53 static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000;  // 480ms
54 static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000;  // 50ms
55 
56 // If there is a current writable connection, then we will also try hard to
57 // make sure it is pinged at this rate.
58 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900;  // 2*WRITABLE_DELAY - bit
59 
60 // The minimum improvement in RTT that justifies a switch.
61 static const double kMinImprovement = 10;
62 
GetOrigin(cricket::PortInterface * port,cricket::PortInterface * origin_port)63 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port,
64                                          cricket::PortInterface* origin_port) {
65   if (!origin_port)
66     return cricket::PortInterface::ORIGIN_MESSAGE;
67   else if (port == origin_port)
68     return cricket::PortInterface::ORIGIN_THIS_PORT;
69   else
70     return cricket::PortInterface::ORIGIN_OTHER_PORT;
71 }
72 
73 // Compares two connections based only on static information about them.
CompareConnectionCandidates(cricket::Connection * a,cricket::Connection * b)74 int CompareConnectionCandidates(cricket::Connection* a,
75                                 cricket::Connection* b) {
76   // Compare connection priority. Lower values get sorted last.
77   if (a->priority() > b->priority())
78     return 1;
79   if (a->priority() < b->priority())
80     return -1;
81 
82   // If we're still tied at this point, prefer a younger generation.
83   return (a->remote_candidate().generation() + a->port()->generation()) -
84          (b->remote_candidate().generation() + b->port()->generation());
85 }
86 
87 // Compare two connections based on their writability and static preferences.
CompareConnections(cricket::Connection * a,cricket::Connection * b)88 int CompareConnections(cricket::Connection *a, cricket::Connection *b) {
89   // Sort based on write-state.  Better states have lower values.
90   if (a->write_state() < b->write_state())
91     return 1;
92   if (a->write_state() > b->write_state())
93     return -1;
94 
95   // Compare the candidate information.
96   return CompareConnectionCandidates(a, b);
97 }
98 
99 // Wraps the comparison connection into a less than operator that puts higher
100 // priority writable connections first.
101 class ConnectionCompare {
102  public:
operator ()(const cricket::Connection * ca,const cricket::Connection * cb)103   bool operator()(const cricket::Connection *ca,
104                   const cricket::Connection *cb) {
105     cricket::Connection* a = const_cast<cricket::Connection*>(ca);
106     cricket::Connection* b = const_cast<cricket::Connection*>(cb);
107 
108     ASSERT(a->port()->IceProtocol() == b->port()->IceProtocol());
109 
110     // Compare first on writability and static preferences.
111     int cmp = CompareConnections(a, b);
112     if (cmp > 0)
113       return true;
114     if (cmp < 0)
115       return false;
116 
117     // Otherwise, sort based on latency estimate.
118     return a->rtt() < b->rtt();
119 
120     // Should we bother checking for the last connection that last received
121     // data? It would help rendezvous on the connection that is also receiving
122     // packets.
123     //
124     // TODO: Yes we should definitely do this.  The TCP protocol gains
125     // efficiency by being used bidirectionally, as opposed to two separate
126     // unidirectional streams.  This test should probably occur before
127     // comparison of local prefs (assuming combined prefs are the same).  We
128     // need to be careful though, not to bounce back and forth with both sides
129     // trying to rendevous with the other.
130   }
131 };
132 
133 // Determines whether we should switch between two connections, based first on
134 // static preferences and then (if those are equal) on latency estimates.
ShouldSwitch(cricket::Connection * a_conn,cricket::Connection * b_conn)135 bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) {
136   if (a_conn == b_conn)
137     return false;
138 
139   if (!a_conn || !b_conn)  // don't think the latter should happen
140     return true;
141 
142   int prefs_cmp = CompareConnections(a_conn, b_conn);
143   if (prefs_cmp < 0)
144     return true;
145   if (prefs_cmp > 0)
146     return false;
147 
148   return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
149 }
150 
151 }  // unnamed namespace
152 
153 namespace cricket {
154 
P2PTransportChannel(const std::string & content_name,int component,P2PTransport * transport,PortAllocator * allocator)155 P2PTransportChannel::P2PTransportChannel(const std::string& content_name,
156                                          int component,
157                                          P2PTransport* transport,
158                                          PortAllocator *allocator) :
159     TransportChannelImpl(content_name, component),
160     transport_(transport),
161     allocator_(allocator),
162     worker_thread_(rtc::Thread::Current()),
163     incoming_only_(false),
164     waiting_for_signaling_(false),
165     error_(0),
166     best_connection_(NULL),
167     pending_best_connection_(NULL),
168     sort_dirty_(false),
169     was_writable_(false),
170     protocol_type_(ICEPROTO_HYBRID),
171     remote_ice_mode_(ICEMODE_FULL),
172     ice_role_(ICEROLE_UNKNOWN),
173     tiebreaker_(0),
174     remote_candidate_generation_(0) {
175 }
176 
~P2PTransportChannel()177 P2PTransportChannel::~P2PTransportChannel() {
178   ASSERT(worker_thread_ == rtc::Thread::Current());
179 
180   for (uint32 i = 0; i < allocator_sessions_.size(); ++i)
181     delete allocator_sessions_[i];
182 }
183 
184 // Add the allocator session to our list so that we know which sessions
185 // are still active.
AddAllocatorSession(PortAllocatorSession * session)186 void P2PTransportChannel::AddAllocatorSession(PortAllocatorSession* session) {
187   session->set_generation(static_cast<uint32>(allocator_sessions_.size()));
188   allocator_sessions_.push_back(session);
189 
190   // We now only want to apply new candidates that we receive to the ports
191   // created by this new session because these are replacing those of the
192   // previous sessions.
193   ports_.clear();
194 
195   session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady);
196   session->SignalCandidatesReady.connect(
197       this, &P2PTransportChannel::OnCandidatesReady);
198   session->SignalCandidatesAllocationDone.connect(
199       this, &P2PTransportChannel::OnCandidatesAllocationDone);
200   session->StartGettingPorts();
201 }
202 
AddConnection(Connection * connection)203 void P2PTransportChannel::AddConnection(Connection* connection) {
204   connections_.push_back(connection);
205   connection->set_remote_ice_mode(remote_ice_mode_);
206   connection->SignalReadPacket.connect(
207       this, &P2PTransportChannel::OnReadPacket);
208   connection->SignalReadyToSend.connect(
209       this, &P2PTransportChannel::OnReadyToSend);
210   connection->SignalStateChange.connect(
211       this, &P2PTransportChannel::OnConnectionStateChange);
212   connection->SignalDestroyed.connect(
213       this, &P2PTransportChannel::OnConnectionDestroyed);
214   connection->SignalUseCandidate.connect(
215       this, &P2PTransportChannel::OnUseCandidate);
216 }
217 
SetIceRole(IceRole ice_role)218 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
219   ASSERT(worker_thread_ == rtc::Thread::Current());
220   if (ice_role_ != ice_role) {
221     ice_role_ = ice_role;
222     for (std::vector<PortInterface *>::iterator it = ports_.begin();
223          it != ports_.end(); ++it) {
224       (*it)->SetIceRole(ice_role);
225     }
226   }
227 }
228 
SetIceTiebreaker(uint64 tiebreaker)229 void P2PTransportChannel::SetIceTiebreaker(uint64 tiebreaker) {
230   ASSERT(worker_thread_ == rtc::Thread::Current());
231   if (!ports_.empty()) {
232     LOG(LS_ERROR)
233         << "Attempt to change tiebreaker after Port has been allocated.";
234     return;
235   }
236 
237   tiebreaker_ = tiebreaker;
238 }
239 
GetIceProtocolType(IceProtocolType * type) const240 bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const {
241   *type = protocol_type_;
242   return true;
243 }
244 
SetIceProtocolType(IceProtocolType type)245 void P2PTransportChannel::SetIceProtocolType(IceProtocolType type) {
246   ASSERT(worker_thread_ == rtc::Thread::Current());
247 
248   protocol_type_ = type;
249   for (std::vector<PortInterface *>::iterator it = ports_.begin();
250        it != ports_.end(); ++it) {
251     (*it)->SetIceProtocolType(protocol_type_);
252   }
253 }
254 
SetIceCredentials(const std::string & ice_ufrag,const std::string & ice_pwd)255 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag,
256                                             const std::string& ice_pwd) {
257   ASSERT(worker_thread_ == rtc::Thread::Current());
258   bool ice_restart = false;
259   if (!ice_ufrag_.empty() && !ice_pwd_.empty()) {
260     // Restart candidate allocation if there is any change in either
261     // ice ufrag or password.
262     ice_restart =
263         IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd);
264   }
265 
266   ice_ufrag_ = ice_ufrag;
267   ice_pwd_ = ice_pwd;
268 
269   if (ice_restart) {
270     // Restart candidate gathering.
271     Allocate();
272   }
273 }
274 
SetRemoteIceCredentials(const std::string & ice_ufrag,const std::string & ice_pwd)275 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag,
276                                                   const std::string& ice_pwd) {
277   ASSERT(worker_thread_ == rtc::Thread::Current());
278   bool ice_restart = false;
279   if (!remote_ice_ufrag_.empty() && !remote_ice_pwd_.empty()) {
280     ice_restart = (remote_ice_ufrag_ != ice_ufrag) ||
281                   (remote_ice_pwd_!= ice_pwd);
282   }
283 
284   remote_ice_ufrag_ = ice_ufrag;
285   remote_ice_pwd_ = ice_pwd;
286 
287   if (ice_restart) {
288     // |candidate.generation()| is not signaled in ICEPROTO_RFC5245.
289     // Therefore we need to keep track of the remote ice restart so
290     // newer connections are prioritized over the older.
291     ++remote_candidate_generation_;
292   }
293 }
294 
SetRemoteIceMode(IceMode mode)295 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) {
296   remote_ice_mode_ = mode;
297 }
298 
299 // Go into the state of processing candidates, and running in general
Connect()300 void P2PTransportChannel::Connect() {
301   ASSERT(worker_thread_ == rtc::Thread::Current());
302   if (ice_ufrag_.empty() || ice_pwd_.empty()) {
303     ASSERT(false);
304     LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
305                   << "ice_pwd_ are not set.";
306     return;
307   }
308 
309   // Kick off an allocator session
310   Allocate();
311 
312   // Start pinging as the ports come in.
313   thread()->Post(this, MSG_PING);
314 }
315 
316 // Reset the socket, clear up any previous allocations and start over
Reset()317 void P2PTransportChannel::Reset() {
318   ASSERT(worker_thread_ == rtc::Thread::Current());
319 
320   // Get rid of all the old allocators.  This should clean up everything.
321   for (uint32 i = 0; i < allocator_sessions_.size(); ++i)
322     delete allocator_sessions_[i];
323 
324   allocator_sessions_.clear();
325   ports_.clear();
326   connections_.clear();
327   best_connection_ = NULL;
328 
329   // Forget about all of the candidates we got before.
330   remote_candidates_.clear();
331 
332   // Revert to the initial state.
333   set_readable(false);
334   set_writable(false);
335 
336   // Reinitialize the rest of our state.
337   waiting_for_signaling_ = false;
338   sort_dirty_ = false;
339 
340   // If we allocated before, start a new one now.
341   if (transport_->connect_requested())
342     Allocate();
343 
344   // Start pinging as the ports come in.
345   thread()->Clear(this);
346   thread()->Post(this, MSG_PING);
347 }
348 
349 // A new port is available, attempt to make connections for it
OnPortReady(PortAllocatorSession * session,PortInterface * port)350 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
351                                       PortInterface* port) {
352   ASSERT(worker_thread_ == rtc::Thread::Current());
353 
354   // Set in-effect options on the new port
355   for (OptionMap::const_iterator it = options_.begin();
356        it != options_.end();
357        ++it) {
358     int val = port->SetOption(it->first, it->second);
359     if (val < 0) {
360       LOG_J(LS_WARNING, port) << "SetOption(" << it->first
361                               << ", " << it->second
362                               << ") failed: " << port->GetError();
363     }
364   }
365 
366   // Remember the ports and candidates, and signal that candidates are ready.
367   // The session will handle this, and send an initiate/accept/modify message
368   // if one is pending.
369 
370   port->SetIceProtocolType(protocol_type_);
371   port->SetIceRole(ice_role_);
372   port->SetIceTiebreaker(tiebreaker_);
373   ports_.push_back(port);
374   port->SignalUnknownAddress.connect(
375       this, &P2PTransportChannel::OnUnknownAddress);
376   port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed);
377   port->SignalRoleConflict.connect(
378       this, &P2PTransportChannel::OnRoleConflict);
379 
380   // Attempt to create a connection from this new port to all of the remote
381   // candidates that we were given so far.
382 
383   std::vector<RemoteCandidate>::iterator iter;
384   for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
385        ++iter) {
386     CreateConnection(port, *iter, iter->origin_port(), false);
387   }
388 
389   SortConnections();
390 }
391 
392 // A new candidate is available, let listeners know
OnCandidatesReady(PortAllocatorSession * session,const std::vector<Candidate> & candidates)393 void P2PTransportChannel::OnCandidatesReady(
394     PortAllocatorSession *session, const std::vector<Candidate>& candidates) {
395   ASSERT(worker_thread_ == rtc::Thread::Current());
396   for (size_t i = 0; i < candidates.size(); ++i) {
397     SignalCandidateReady(this, candidates[i]);
398   }
399 }
400 
OnCandidatesAllocationDone(PortAllocatorSession * session)401 void P2PTransportChannel::OnCandidatesAllocationDone(
402     PortAllocatorSession* session) {
403   ASSERT(worker_thread_ == rtc::Thread::Current());
404   SignalCandidatesAllocationDone(this);
405 }
406 
407 // Handle stun packets
OnUnknownAddress(PortInterface * port,const rtc::SocketAddress & address,ProtocolType proto,IceMessage * stun_msg,const std::string & remote_username,bool port_muxed)408 void P2PTransportChannel::OnUnknownAddress(
409     PortInterface* port,
410     const rtc::SocketAddress& address, ProtocolType proto,
411     IceMessage* stun_msg, const std::string &remote_username,
412     bool port_muxed) {
413   ASSERT(worker_thread_ == rtc::Thread::Current());
414 
415   // Port has received a valid stun packet from an address that no Connection
416   // is currently available for. See if we already have a candidate with the
417   // address. If it isn't we need to create new candidate for it.
418 
419   // Determine if the remote candidates use shared ufrag.
420   bool ufrag_per_port = false;
421   std::vector<RemoteCandidate>::iterator it;
422   if (remote_candidates_.size() > 0) {
423     it = remote_candidates_.begin();
424     std::string username = it->username();
425     for (; it != remote_candidates_.end(); ++it) {
426       if (it->username() != username) {
427         ufrag_per_port = true;
428         break;
429       }
430     }
431   }
432 
433   const Candidate* candidate = NULL;
434   bool known_username = false;
435   std::string remote_password;
436   for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) {
437     if (it->username() == remote_username) {
438       remote_password = it->password();
439       known_username = true;
440       if (ufrag_per_port ||
441           (it->address() == address &&
442            it->protocol() == ProtoToString(proto))) {
443         candidate = &(*it);
444         break;
445       }
446       // We don't want to break here because we may find a match of the address
447       // later.
448     }
449   }
450 
451   if (!known_username) {
452     if (port_muxed) {
453       // When Ports are muxed, SignalUnknownAddress is delivered to all
454       // P2PTransportChannel belong to a session. Return from here will
455       // save us from sending stun binding error message from incorrect channel.
456       return;
457     }
458     // Don't know about this username, the request is bogus
459     // This sometimes happens if a binding response comes in before the ACCEPT
460     // message.  It is totally valid; the retry state machine will try again.
461     port->SendBindingErrorResponse(stun_msg, address,
462         STUN_ERROR_STALE_CREDENTIALS, STUN_ERROR_REASON_STALE_CREDENTIALS);
463     return;
464   }
465 
466   Candidate new_remote_candidate;
467   if (candidate != NULL) {
468     new_remote_candidate = *candidate;
469     if (ufrag_per_port) {
470       new_remote_candidate.set_address(address);
471     }
472   } else {
473     // Create a new candidate with this address.
474     std::string type;
475     if (port->IceProtocol() == ICEPROTO_RFC5245) {
476       type = PRFLX_PORT_TYPE;
477     } else {
478       // G-ICE doesn't support prflx candidate.
479       // We set candidate type to STUN_PORT_TYPE if the binding request comes
480       // from a relay port or the shared socket is used. Otherwise we use the
481       // port's type as the candidate type.
482       if (port->Type() == RELAY_PORT_TYPE || port->SharedSocket()) {
483         type = STUN_PORT_TYPE;
484       } else {
485         type = port->Type();
486       }
487     }
488 
489     std::string id = rtc::CreateRandomString(8);
490     new_remote_candidate = Candidate(
491         id, component(), ProtoToString(proto), address,
492         0, remote_username, remote_password, type,
493         port->Network()->name(), 0U,
494         rtc::ToString<uint32>(rtc::ComputeCrc32(id)));
495     new_remote_candidate.set_priority(
496         new_remote_candidate.GetPriority(ICE_TYPE_PREFERENCE_SRFLX,
497                                          port->Network()->preference(), 0));
498   }
499 
500   if (port->IceProtocol() == ICEPROTO_RFC5245) {
501     // RFC 5245
502     // If the source transport address of the request does not match any
503     // existing remote candidates, it represents a new peer reflexive remote
504     // candidate.
505 
506     // The priority of the candidate is set to the PRIORITY attribute
507     // from the request.
508     const StunUInt32Attribute* priority_attr =
509         stun_msg->GetUInt32(STUN_ATTR_PRIORITY);
510     if (!priority_attr) {
511       LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - "
512                       << "No STUN_ATTR_PRIORITY found in the "
513                       << "stun request message";
514       port->SendBindingErrorResponse(stun_msg, address,
515                                      STUN_ERROR_BAD_REQUEST,
516                                      STUN_ERROR_REASON_BAD_REQUEST);
517       return;
518     }
519     new_remote_candidate.set_priority(priority_attr->value());
520 
521     // RFC5245, the agent constructs a pair whose local candidate is equal to
522     // the transport address on which the STUN request was received, and a
523     // remote candidate equal to the source transport address where the
524     // request came from.
525 
526     // There shouldn't be an existing connection with this remote address.
527     // When ports are muxed, this channel might get multiple unknown address
528     // signals. In that case if the connection is already exists, we should
529     // simply ignore the signal othewise send server error.
530     if (port->GetConnection(new_remote_candidate.address())) {
531       if (port_muxed) {
532         LOG(LS_INFO) << "Connection already exists for peer reflexive "
533                      << "candidate: " << new_remote_candidate.ToString();
534         return;
535       } else {
536         ASSERT(false);
537         port->SendBindingErrorResponse(stun_msg, address,
538                                        STUN_ERROR_SERVER_ERROR,
539                                        STUN_ERROR_REASON_SERVER_ERROR);
540         return;
541       }
542     }
543 
544     Connection* connection = port->CreateConnection(
545         new_remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT);
546     if (!connection) {
547       ASSERT(false);
548       port->SendBindingErrorResponse(stun_msg, address,
549                                      STUN_ERROR_SERVER_ERROR,
550                                      STUN_ERROR_REASON_SERVER_ERROR);
551       return;
552     }
553 
554     AddConnection(connection);
555     connection->ReceivedPing();
556 
557     // Send the pinger a successful stun response.
558     port->SendBindingResponse(stun_msg, address);
559 
560     // Update the list of connections since we just added another.  We do this
561     // after sending the response since it could (in principle) delete the
562     // connection in question.
563     SortConnections();
564   } else {
565     // Check for connectivity to this address. Create connections
566     // to this address across all local ports. First, add this as a new remote
567     // address
568     if (!CreateConnections(new_remote_candidate, port, true)) {
569       // Hopefully this won't occur, because changing a destination address
570       // shouldn't cause a new connection to fail
571       ASSERT(false);
572       port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR,
573           STUN_ERROR_REASON_SERVER_ERROR);
574       return;
575     }
576 
577     // Send the pinger a successful stun response.
578     port->SendBindingResponse(stun_msg, address);
579 
580     // Update the list of connections since we just added another.  We do this
581     // after sending the response since it could (in principle) delete the
582     // connection in question.
583     SortConnections();
584   }
585 }
586 
OnRoleConflict(PortInterface * port)587 void P2PTransportChannel::OnRoleConflict(PortInterface* port) {
588   SignalRoleConflict(this);  // STUN ping will be sent when SetRole is called
589                              // from Transport.
590 }
591 
592 // When the signalling channel is ready, we can really kick off the allocator
OnSignalingReady()593 void P2PTransportChannel::OnSignalingReady() {
594   ASSERT(worker_thread_ == rtc::Thread::Current());
595   if (waiting_for_signaling_) {
596     waiting_for_signaling_ = false;
597     AddAllocatorSession(allocator_->CreateSession(
598         SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_));
599   }
600 }
601 
OnUseCandidate(Connection * conn)602 void P2PTransportChannel::OnUseCandidate(Connection* conn) {
603   ASSERT(worker_thread_ == rtc::Thread::Current());
604   ASSERT(ice_role_ == ICEROLE_CONTROLLED);
605   ASSERT(protocol_type_ == ICEPROTO_RFC5245);
606   if (conn->write_state() == Connection::STATE_WRITABLE) {
607     if (best_connection_ != conn) {
608       pending_best_connection_ = NULL;
609       SwitchBestConnectionTo(conn);
610       // Now we have selected the best connection, time to prune other existing
611       // connections and update the read/write state of the channel.
612       RequestSort();
613     }
614   } else {
615     pending_best_connection_ = conn;
616   }
617 }
618 
OnCandidate(const Candidate & candidate)619 void P2PTransportChannel::OnCandidate(const Candidate& candidate) {
620   ASSERT(worker_thread_ == rtc::Thread::Current());
621 
622   // Create connections to this remote candidate.
623   CreateConnections(candidate, NULL, false);
624 
625   // Resort the connections list, which may have new elements.
626   SortConnections();
627 }
628 
629 // Creates connections from all of the ports that we care about to the given
630 // remote candidate.  The return value is true if we created a connection from
631 // the origin port.
CreateConnections(const Candidate & remote_candidate,PortInterface * origin_port,bool readable)632 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate,
633                                             PortInterface* origin_port,
634                                             bool readable) {
635   ASSERT(worker_thread_ == rtc::Thread::Current());
636 
637   Candidate new_remote_candidate(remote_candidate);
638   new_remote_candidate.set_generation(
639       GetRemoteCandidateGeneration(remote_candidate));
640   // ICE candidates don't need to have username and password set, but
641   // the code below this (specifically, ConnectionRequest::Prepare in
642   // port.cc) uses the remote candidates's username.  So, we set it
643   // here.
644   if (remote_candidate.username().empty()) {
645     new_remote_candidate.set_username(remote_ice_ufrag_);
646   }
647   if (remote_candidate.password().empty()) {
648     new_remote_candidate.set_password(remote_ice_pwd_);
649   }
650 
651   // If we've already seen the new remote candidate (in the current candidate
652   // generation), then we shouldn't try creating connections for it.
653   // We either already have a connection for it, or we previously created one
654   // and then later pruned it. If we don't return, the channel will again
655   // re-create any connections that were previously pruned, which will then
656   // immediately be re-pruned, churning the network for no purpose.
657   // This only applies to candidates received over signaling (i.e. origin_port
658   // is NULL).
659   if (!origin_port && IsDuplicateRemoteCandidate(new_remote_candidate)) {
660     // return true to indicate success, without creating any new connections.
661     return true;
662   }
663 
664   // Add a new connection for this candidate to every port that allows such a
665   // connection (i.e., if they have compatible protocols) and that does not
666   // already have a connection to an equivalent candidate.  We must be careful
667   // to make sure that the origin port is included, even if it was pruned,
668   // since that may be the only port that can create this connection.
669   bool created = false;
670   std::vector<PortInterface *>::reverse_iterator it;
671   for (it = ports_.rbegin(); it != ports_.rend(); ++it) {
672     if (CreateConnection(*it, new_remote_candidate, origin_port, readable)) {
673       if (*it == origin_port)
674         created = true;
675     }
676   }
677 
678   if ((origin_port != NULL) &&
679       std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
680     if (CreateConnection(
681         origin_port, new_remote_candidate, origin_port, readable))
682       created = true;
683   }
684 
685   // Remember this remote candidate so that we can add it to future ports.
686   RememberRemoteCandidate(new_remote_candidate, origin_port);
687 
688   return created;
689 }
690 
691 // Setup a connection object for the local and remote candidate combination.
692 // And then listen to connection object for changes.
CreateConnection(PortInterface * port,const Candidate & remote_candidate,PortInterface * origin_port,bool readable)693 bool P2PTransportChannel::CreateConnection(PortInterface* port,
694                                            const Candidate& remote_candidate,
695                                            PortInterface* origin_port,
696                                            bool readable) {
697   // Look for an existing connection with this remote address.  If one is not
698   // found, then we can create a new connection for this address.
699   Connection* connection = port->GetConnection(remote_candidate.address());
700   if (connection != NULL) {
701     // It is not legal to try to change any of the parameters of an existing
702     // connection; however, the other side can send a duplicate candidate.
703     if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
704       LOG(INFO) << "Attempt to change a remote candidate."
705                 << " Existing remote candidate: "
706                 << connection->remote_candidate().ToString()
707                 << "New remote candidate: "
708                 << remote_candidate.ToString();
709       return false;
710     }
711   } else {
712     PortInterface::CandidateOrigin origin = GetOrigin(port, origin_port);
713 
714     // Don't create connection if this is a candidate we received in a
715     // message and we are not allowed to make outgoing connections.
716     if (origin == cricket::PortInterface::ORIGIN_MESSAGE && incoming_only_)
717       return false;
718 
719     connection = port->CreateConnection(remote_candidate, origin);
720     if (!connection)
721       return false;
722 
723     AddConnection(connection);
724 
725     LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", ("
726                          << connections_.size() << " total)";
727   }
728 
729   // If we are readable, it is because we are creating this in response to a
730   // ping from the other side.  This will cause the state to become readable.
731   if (readable)
732     connection->ReceivedPing();
733 
734   return true;
735 }
736 
FindConnection(cricket::Connection * connection) const737 bool P2PTransportChannel::FindConnection(
738     cricket::Connection* connection) const {
739   std::vector<Connection*>::const_iterator citer =
740       std::find(connections_.begin(), connections_.end(), connection);
741   return citer != connections_.end();
742 }
743 
GetRemoteCandidateGeneration(const Candidate & candidate)744 uint32 P2PTransportChannel::GetRemoteCandidateGeneration(
745     const Candidate& candidate) {
746   if (protocol_type_ == ICEPROTO_GOOGLE) {
747     // The Candidate.generation() can be trusted. Nothing needs to be done.
748     return candidate.generation();
749   }
750   // |candidate.generation()| is not signaled in ICEPROTO_RFC5245.
751   // Therefore we need to keep track of the remote ice restart so
752   // newer connections are prioritized over the older.
753   ASSERT(candidate.generation() == 0 ||
754          candidate.generation() == remote_candidate_generation_);
755   return remote_candidate_generation_;
756 }
757 
758 // Check if remote candidate is already cached.
IsDuplicateRemoteCandidate(const Candidate & candidate)759 bool P2PTransportChannel::IsDuplicateRemoteCandidate(
760     const Candidate& candidate) {
761   for (uint32 i = 0; i < remote_candidates_.size(); ++i) {
762     if (remote_candidates_[i].IsEquivalent(candidate)) {
763       return true;
764     }
765   }
766   return false;
767 }
768 
769 // Maintain our remote candidate list, adding this new remote one.
RememberRemoteCandidate(const Candidate & remote_candidate,PortInterface * origin_port)770 void P2PTransportChannel::RememberRemoteCandidate(
771     const Candidate& remote_candidate, PortInterface* origin_port) {
772   // Remove any candidates whose generation is older than this one.  The
773   // presence of a new generation indicates that the old ones are not useful.
774   uint32 i = 0;
775   while (i < remote_candidates_.size()) {
776     if (remote_candidates_[i].generation() < remote_candidate.generation()) {
777       LOG(INFO) << "Pruning candidate from old generation: "
778                 << remote_candidates_[i].address().ToSensitiveString();
779       remote_candidates_.erase(remote_candidates_.begin() + i);
780     } else {
781       i += 1;
782     }
783   }
784 
785   // Make sure this candidate is not a duplicate.
786   if (IsDuplicateRemoteCandidate(remote_candidate)) {
787     LOG(INFO) << "Duplicate candidate: " << remote_candidate.ToString();
788     return;
789   }
790 
791   // Try this candidate for all future ports.
792   remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port));
793 }
794 
795 // Set options on ourselves is simply setting options on all of our available
796 // port objects.
SetOption(rtc::Socket::Option opt,int value)797 int P2PTransportChannel::SetOption(rtc::Socket::Option opt, int value) {
798   OptionMap::iterator it = options_.find(opt);
799   if (it == options_.end()) {
800     options_.insert(std::make_pair(opt, value));
801   } else if (it->second == value) {
802     return 0;
803   } else {
804     it->second = value;
805   }
806 
807   for (uint32 i = 0; i < ports_.size(); ++i) {
808     int val = ports_[i]->SetOption(opt, value);
809     if (val < 0) {
810       // Because this also occurs deferred, probably no point in reporting an
811       // error
812       LOG(WARNING) << "SetOption(" << opt << ", " << value << ") failed: "
813                    << ports_[i]->GetError();
814     }
815   }
816   return 0;
817 }
818 
819 // Send data to the other side, using our best connection.
SendPacket(const char * data,size_t len,const rtc::PacketOptions & options,int flags)820 int P2PTransportChannel::SendPacket(const char *data, size_t len,
821                                     const rtc::PacketOptions& options,
822                                     int flags) {
823   ASSERT(worker_thread_ == rtc::Thread::Current());
824   if (flags != 0) {
825     error_ = EINVAL;
826     return -1;
827   }
828   if (best_connection_ == NULL) {
829     error_ = EWOULDBLOCK;
830     return -1;
831   }
832 
833   int sent = best_connection_->Send(data, len, options);
834   if (sent <= 0) {
835     ASSERT(sent < 0);
836     error_ = best_connection_->GetError();
837   }
838   return sent;
839 }
840 
GetStats(ConnectionInfos * infos)841 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
842   ASSERT(worker_thread_ == rtc::Thread::Current());
843   // Gather connection infos.
844   infos->clear();
845 
846   std::vector<Connection *>::const_iterator it;
847   for (it = connections_.begin(); it != connections_.end(); ++it) {
848     Connection *connection = *it;
849     ConnectionInfo info;
850     info.best_connection = (best_connection_ == connection);
851     info.readable =
852         (connection->read_state() == Connection::STATE_READABLE);
853     info.writable =
854         (connection->write_state() == Connection::STATE_WRITABLE);
855     info.timeout =
856         (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
857     info.new_connection = !connection->reported();
858     connection->set_reported(true);
859     info.rtt = connection->rtt();
860     info.sent_total_bytes = connection->sent_total_bytes();
861     info.sent_bytes_second = connection->sent_bytes_second();
862     info.recv_total_bytes = connection->recv_total_bytes();
863     info.recv_bytes_second = connection->recv_bytes_second();
864     info.local_candidate = connection->local_candidate();
865     info.remote_candidate = connection->remote_candidate();
866     info.key = connection;
867     infos->push_back(info);
868   }
869 
870   return true;
871 }
872 
DefaultDscpValue() const873 rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const {
874   OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP);
875   if (it == options_.end()) {
876     return rtc::DSCP_NO_CHANGE;
877   }
878   return static_cast<rtc::DiffServCodePoint> (it->second);
879 }
880 
881 // Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending)
Allocate()882 void P2PTransportChannel::Allocate() {
883   // Time for a new allocator, lets make sure we have a signalling channel
884   // to communicate candidates through first.
885   waiting_for_signaling_ = true;
886   SignalRequestSignaling(this);
887 }
888 
889 // Monitor connection states.
UpdateConnectionStates()890 void P2PTransportChannel::UpdateConnectionStates() {
891   uint32 now = rtc::Time();
892 
893   // We need to copy the list of connections since some may delete themselves
894   // when we call UpdateState.
895   for (uint32 i = 0; i < connections_.size(); ++i)
896     connections_[i]->UpdateState(now);
897 }
898 
899 // Prepare for best candidate sorting.
RequestSort()900 void P2PTransportChannel::RequestSort() {
901   if (!sort_dirty_) {
902     worker_thread_->Post(this, MSG_SORT);
903     sort_dirty_ = true;
904   }
905 }
906 
907 // Sort the available connections to find the best one.  We also monitor
908 // the number of available connections and the current state.
SortConnections()909 void P2PTransportChannel::SortConnections() {
910   ASSERT(worker_thread_ == rtc::Thread::Current());
911 
912   // Make sure the connection states are up-to-date since this affects how they
913   // will be sorted.
914   UpdateConnectionStates();
915 
916   if (protocol_type_ == ICEPROTO_HYBRID) {
917     // If we are in hybrid mode, we are not sending any ping requests, so there
918     // is no point in sorting the connections. In hybrid state, ports can have
919     // different protocol than hybrid and protocol may differ from one another.
920     // Instead just update the state of this channel
921     UpdateChannelState();
922     return;
923   }
924 
925   // Any changes after this point will require a re-sort.
926   sort_dirty_ = false;
927 
928   // Get a list of the networks that we are using.
929   std::set<rtc::Network*> networks;
930   for (uint32 i = 0; i < connections_.size(); ++i)
931     networks.insert(connections_[i]->port()->Network());
932 
933   // Find the best alternative connection by sorting.  It is important to note
934   // that amongst equal preference, writable connections, this will choose the
935   // one whose estimated latency is lowest.  So it is the only one that we
936   // need to consider switching to.
937 
938   ConnectionCompare cmp;
939   std::stable_sort(connections_.begin(), connections_.end(), cmp);
940   LOG(LS_VERBOSE) << "Sorting available connections:";
941   for (uint32 i = 0; i < connections_.size(); ++i) {
942     LOG(LS_VERBOSE) << connections_[i]->ToString();
943   }
944 
945   Connection* top_connection = NULL;
946   if (connections_.size() > 0)
947     top_connection = connections_[0];
948 
949   // We don't want to pick the best connections if channel is using RFC5245
950   // and it's mode is CONTROLLED, as connections will be selected by the
951   // CONTROLLING agent.
952 
953   // If necessary, switch to the new choice.
954   if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING) {
955     if (ShouldSwitch(best_connection_, top_connection))
956       SwitchBestConnectionTo(top_connection);
957   }
958 
959   // We can prune any connection for which there is a writable connection on
960   // the same network with better or equal priority.  We leave those with
961   // better priority just in case they become writable later (at which point,
962   // we would prune out the current best connection).  We leave connections on
963   // other networks because they may not be using the same resources and they
964   // may represent very distinct paths over which we can switch.
965   std::set<rtc::Network*>::iterator network;
966   for (network = networks.begin(); network != networks.end(); ++network) {
967     Connection* primier = GetBestConnectionOnNetwork(*network);
968     if (!primier || (primier->write_state() != Connection::STATE_WRITABLE))
969       continue;
970 
971     for (uint32 i = 0; i < connections_.size(); ++i) {
972       if ((connections_[i] != primier) &&
973           (connections_[i]->port()->Network() == *network) &&
974           (CompareConnectionCandidates(primier, connections_[i]) >= 0)) {
975         connections_[i]->Prune();
976       }
977     }
978   }
979 
980   // Check if all connections are timedout.
981   bool all_connections_timedout = true;
982   for (uint32 i = 0; i < connections_.size(); ++i) {
983     if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
984       all_connections_timedout = false;
985       break;
986     }
987   }
988 
989   // Now update the writable state of the channel with the information we have
990   // so far.
991   if (best_connection_ && best_connection_->writable()) {
992     HandleWritable();
993   } else if (all_connections_timedout) {
994     HandleAllTimedOut();
995   } else {
996     HandleNotWritable();
997   }
998 
999   // Update the state of this channel.  This method is called whenever the
1000   // state of any connection changes, so this is a good place to do this.
1001   UpdateChannelState();
1002 }
1003 
1004 
1005 // Track the best connection, and let listeners know
SwitchBestConnectionTo(Connection * conn)1006 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1007   // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1008   // so don't use it.
1009   Connection* old_best_connection = best_connection_;
1010   best_connection_ = conn;
1011   if (best_connection_) {
1012     if (old_best_connection) {
1013       LOG_J(LS_INFO, this) << "Previous best connection: "
1014                            << old_best_connection->ToString();
1015     }
1016     LOG_J(LS_INFO, this) << "New best connection: "
1017                          << best_connection_->ToString();
1018     SignalRouteChange(this, best_connection_->remote_candidate());
1019   } else {
1020     LOG_J(LS_INFO, this) << "No best connection";
1021   }
1022 }
1023 
UpdateChannelState()1024 void P2PTransportChannel::UpdateChannelState() {
1025   // The Handle* functions already set the writable state.  We'll just double-
1026   // check it here.
1027   bool writable = ((best_connection_ != NULL)  &&
1028       (best_connection_->write_state() ==
1029       Connection::STATE_WRITABLE));
1030   ASSERT(writable == this->writable());
1031   if (writable != this->writable())
1032     LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch";
1033 
1034   bool readable = false;
1035   for (uint32 i = 0; i < connections_.size(); ++i) {
1036     if (connections_[i]->read_state() == Connection::STATE_READABLE) {
1037       readable = true;
1038       break;
1039     }
1040   }
1041   set_readable(readable);
1042 }
1043 
1044 // We checked the status of our connections and we had at least one that
1045 // was writable, go into the writable state.
HandleWritable()1046 void P2PTransportChannel::HandleWritable() {
1047   ASSERT(worker_thread_ == rtc::Thread::Current());
1048   if (!writable()) {
1049     for (uint32 i = 0; i < allocator_sessions_.size(); ++i) {
1050       if (allocator_sessions_[i]->IsGettingPorts()) {
1051         allocator_sessions_[i]->StopGettingPorts();
1052       }
1053     }
1054   }
1055 
1056   was_writable_ = true;
1057   set_writable(true);
1058 }
1059 
1060 // Notify upper layer about channel not writable state, if it was before.
HandleNotWritable()1061 void P2PTransportChannel::HandleNotWritable() {
1062   ASSERT(worker_thread_ == rtc::Thread::Current());
1063   if (was_writable_) {
1064     was_writable_ = false;
1065     set_writable(false);
1066   }
1067 }
1068 
HandleAllTimedOut()1069 void P2PTransportChannel::HandleAllTimedOut() {
1070   // Currently we are treating this as channel not writable.
1071   HandleNotWritable();
1072 }
1073 
1074 // If we have a best connection, return it, otherwise return top one in the
1075 // list (later we will mark it best).
GetBestConnectionOnNetwork(rtc::Network * network)1076 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1077     rtc::Network* network) {
1078   // If the best connection is on this network, then it wins.
1079   if (best_connection_ && (best_connection_->port()->Network() == network))
1080     return best_connection_;
1081 
1082   // Otherwise, we return the top-most in sorted order.
1083   for (uint32 i = 0; i < connections_.size(); ++i) {
1084     if (connections_[i]->port()->Network() == network)
1085       return connections_[i];
1086   }
1087 
1088   return NULL;
1089 }
1090 
1091 // Handle any queued up requests
OnMessage(rtc::Message * pmsg)1092 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1093   switch (pmsg->message_id) {
1094     case MSG_SORT:
1095       OnSort();
1096       break;
1097     case MSG_PING:
1098       OnPing();
1099       break;
1100     default:
1101       ASSERT(false);
1102       break;
1103   }
1104 }
1105 
1106 // Handle queued up sort request
OnSort()1107 void P2PTransportChannel::OnSort() {
1108   // Resort the connections based on the new statistics.
1109   SortConnections();
1110 }
1111 
1112 // Handle queued up ping request
OnPing()1113 void P2PTransportChannel::OnPing() {
1114   // Make sure the states of the connections are up-to-date (since this affects
1115   // which ones are pingable).
1116   UpdateConnectionStates();
1117 
1118   // Find the oldest pingable connection and have it do a ping.
1119   Connection* conn = FindNextPingableConnection();
1120   if (conn)
1121     PingConnection(conn);
1122 
1123   // Post ourselves a message to perform the next ping.
1124   uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY;
1125   thread()->PostDelayed(delay, this, MSG_PING);
1126 }
1127 
1128 // Is the connection in a state for us to even consider pinging the other side?
IsPingable(Connection * conn)1129 bool P2PTransportChannel::IsPingable(Connection* conn) {
1130   // An unconnected connection cannot be written to at all, so pinging is out
1131   // of the question.
1132   if (!conn->connected())
1133     return false;
1134 
1135   if (writable()) {
1136     // If we are writable, then we only want to ping connections that could be
1137     // better than this one, i.e., the ones that were not pruned.
1138     return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT);
1139   } else {
1140     // If we are not writable, then we need to try everything that might work.
1141     // This includes both connections that do not have write timeout as well as
1142     // ones that do not have read timeout.  A connection could be readable but
1143     // be in write-timeout if we pruned it before.  Since the other side is
1144     // still pinging it, it very well might still work.
1145     return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) ||
1146            (conn->read_state() != Connection::STATE_READ_TIMEOUT);
1147   }
1148 }
1149 
1150 // Returns the next pingable connection to ping.  This will be the oldest
1151 // pingable connection unless we have a writable connection that is past the
1152 // maximum acceptable ping delay.
FindNextPingableConnection()1153 Connection* P2PTransportChannel::FindNextPingableConnection() {
1154   uint32 now = rtc::Time();
1155   if (best_connection_ &&
1156       (best_connection_->write_state() == Connection::STATE_WRITABLE) &&
1157       (best_connection_->last_ping_sent()
1158        + MAX_CURRENT_WRITABLE_DELAY <= now)) {
1159     return best_connection_;
1160   }
1161 
1162   Connection* oldest_conn = NULL;
1163   uint32 oldest_time = 0xFFFFFFFF;
1164   for (uint32 i = 0; i < connections_.size(); ++i) {
1165     if (IsPingable(connections_[i])) {
1166       if (connections_[i]->last_ping_sent() < oldest_time) {
1167         oldest_time = connections_[i]->last_ping_sent();
1168         oldest_conn = connections_[i];
1169       }
1170     }
1171   }
1172   return oldest_conn;
1173 }
1174 
1175 // Apart from sending ping from |conn| this method also updates
1176 // |use_candidate_attr| flag. The criteria to update this flag is
1177 // explained below.
1178 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND
1179 //    a) Channel is in FULL ICE AND
1180 //      a.1) |conn| is the best connection OR
1181 //      a.2) there is no best connection OR
1182 //      a.3) the best connection is unwritable OR
1183 //      a.4) |conn| has higher priority than best_connection.
1184 //    b) we're doing LITE ICE AND
1185 //      b.1) |conn| is the best_connection AND
1186 //      b.2) |conn| is writable.
PingConnection(Connection * conn)1187 void P2PTransportChannel::PingConnection(Connection* conn) {
1188   bool use_candidate = false;
1189   if (protocol_type_ == ICEPROTO_RFC5245) {
1190     if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1191       use_candidate = (conn == best_connection_) ||
1192                       (best_connection_ == NULL) ||
1193                       (!best_connection_->writable()) ||
1194                       (conn->priority() > best_connection_->priority());
1195     } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) {
1196       use_candidate = best_connection_->writable();
1197     }
1198   }
1199   conn->set_use_candidate_attr(use_candidate);
1200   conn->Ping(rtc::Time());
1201 }
1202 
1203 // When a connection's state changes, we need to figure out who to use as
1204 // the best connection again.  It could have become usable, or become unusable.
OnConnectionStateChange(Connection * connection)1205 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1206   ASSERT(worker_thread_ == rtc::Thread::Current());
1207 
1208   // Update the best connection if the state change is from pending best
1209   // connection and role is controlled.
1210   if (protocol_type_ == ICEPROTO_RFC5245 && ice_role_ == ICEROLE_CONTROLLED) {
1211     if (connection == pending_best_connection_ && connection->writable()) {
1212       pending_best_connection_ = NULL;
1213       SwitchBestConnectionTo(connection);
1214     }
1215   }
1216 
1217   // We have to unroll the stack before doing this because we may be changing
1218   // the state of connections while sorting.
1219   RequestSort();
1220 }
1221 
1222 // When a connection is removed, edit it out, and then update our best
1223 // connection.
OnConnectionDestroyed(Connection * connection)1224 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
1225   ASSERT(worker_thread_ == rtc::Thread::Current());
1226 
1227   // Note: the previous best_connection_ may be destroyed by now, so don't
1228   // use it.
1229 
1230   // Remove this connection from the list.
1231   std::vector<Connection*>::iterator iter =
1232       std::find(connections_.begin(), connections_.end(), connection);
1233   ASSERT(iter != connections_.end());
1234   connections_.erase(iter);
1235 
1236   LOG_J(LS_INFO, this) << "Removed connection ("
1237     << static_cast<int>(connections_.size()) << " remaining)";
1238 
1239   if (pending_best_connection_ == connection) {
1240     pending_best_connection_ = NULL;
1241   }
1242 
1243   // If this is currently the best connection, then we need to pick a new one.
1244   // The call to SortConnections will pick a new one.  It looks at the current
1245   // best connection in order to avoid switching between fairly similar ones.
1246   // Since this connection is no longer an option, we can just set best to NULL
1247   // and re-choose a best assuming that there was no best connection.
1248   if (best_connection_ == connection) {
1249     SwitchBestConnectionTo(NULL);
1250     RequestSort();
1251   }
1252 
1253   SignalConnectionRemoved(this);
1254 }
1255 
1256 // When a port is destroyed remove it from our list of ports to use for
1257 // connection attempts.
OnPortDestroyed(PortInterface * port)1258 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1259   ASSERT(worker_thread_ == rtc::Thread::Current());
1260 
1261   // Remove this port from the list (if we didn't drop it already).
1262   std::vector<PortInterface*>::iterator iter =
1263       std::find(ports_.begin(), ports_.end(), port);
1264   if (iter != ports_.end())
1265     ports_.erase(iter);
1266 
1267   LOG(INFO) << "Removed port from p2p socket: "
1268             << static_cast<int>(ports_.size()) << " remaining";
1269 }
1270 
1271 // We data is available, let listeners know
OnReadPacket(Connection * connection,const char * data,size_t len,const rtc::PacketTime & packet_time)1272 void P2PTransportChannel::OnReadPacket(
1273     Connection *connection, const char *data, size_t len,
1274     const rtc::PacketTime& packet_time) {
1275   ASSERT(worker_thread_ == rtc::Thread::Current());
1276 
1277   // Do not deliver, if packet doesn't belong to the correct transport channel.
1278   if (!FindConnection(connection))
1279     return;
1280 
1281   // Let the client know of an incoming packet
1282   SignalReadPacket(this, data, len, packet_time, 0);
1283 }
1284 
OnReadyToSend(Connection * connection)1285 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1286   if (connection == best_connection_ && writable()) {
1287     SignalReadyToSend(this);
1288   }
1289 }
1290 
1291 }  // namespace cricket
1292