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 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. 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. 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: 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. 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 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 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. 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 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 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 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 240 bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const { 241 *type = protocol_type_; 242 return true; 243 } 244 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 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 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 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 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 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 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 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 401 void P2PTransportChannel::OnCandidatesAllocationDone( 402 PortAllocatorSession* session) { 403 ASSERT(worker_thread_ == rtc::Thread::Current()); 404 SignalCandidatesAllocationDone(this); 405 } 406 407 // Handle stun packets 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 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 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 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 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. 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. 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 737 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 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. 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. 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. 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. 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 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 873 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) 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. 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. 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. 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 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 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. 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. 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 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). 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 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 1107 void P2PTransportChannel::OnSort() { 1108 // Resort the connections based on the new statistics. 1109 SortConnections(); 1110 } 1111 1112 // Handle queued up ping request 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? 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. 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. 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. 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. 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. 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 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 1285 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1286 if (connection == best_connection_ && writable()) { 1287 SignalReadyToSend(this); 1288 } 1289 } 1290 1291 } // namespace cricket 1292