| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 connections_.push_back(connection); | 222 connections_.push_back(connection); |
| 223 connection->set_remote_ice_mode(remote_ice_mode_); | 223 connection->set_remote_ice_mode(remote_ice_mode_); |
| 224 connection->SignalReadPacket.connect( | 224 connection->SignalReadPacket.connect( |
| 225 this, &P2PTransportChannel::OnReadPacket); | 225 this, &P2PTransportChannel::OnReadPacket); |
| 226 connection->SignalReadyToSend.connect( | 226 connection->SignalReadyToSend.connect( |
| 227 this, &P2PTransportChannel::OnReadyToSend); | 227 this, &P2PTransportChannel::OnReadyToSend); |
| 228 connection->SignalStateChange.connect( | 228 connection->SignalStateChange.connect( |
| 229 this, &P2PTransportChannel::OnConnectionStateChange); | 229 this, &P2PTransportChannel::OnConnectionStateChange); |
| 230 connection->SignalDestroyed.connect( | 230 connection->SignalDestroyed.connect( |
| 231 this, &P2PTransportChannel::OnConnectionDestroyed); | 231 this, &P2PTransportChannel::OnConnectionDestroyed); |
| 232 connection->SignalUseCandidate.connect( | 232 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); |
| 233 this, &P2PTransportChannel::OnUseCandidate); | |
| 234 } | 233 } |
| 235 | 234 |
| 236 void P2PTransportChannel::SetIceRole(IceRole ice_role) { | 235 void P2PTransportChannel::SetIceRole(IceRole ice_role) { |
| 237 ASSERT(worker_thread_ == rtc::Thread::Current()); | 236 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 238 if (ice_role_ != ice_role) { | 237 if (ice_role_ != ice_role) { |
| 239 ice_role_ = ice_role; | 238 ice_role_ = ice_role; |
| 240 for (std::vector<PortInterface *>::iterator it = ports_.begin(); | 239 for (std::vector<PortInterface *>::iterator it = ports_.begin(); |
| 241 it != ports_.end(); ++it) { | 240 it != ports_.end(); ++it) { |
| 242 (*it)->SetIceRole(ice_role); | 241 (*it)->SetIceRole(ice_role); |
| 243 } | 242 } |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 } | 514 } |
| 516 | 515 |
| 517 // RFC5245, the agent constructs a pair whose local candidate is equal to | 516 // RFC5245, the agent constructs a pair whose local candidate is equal to |
| 518 // the transport address on which the STUN request was received, and a | 517 // the transport address on which the STUN request was received, and a |
| 519 // remote candidate equal to the source transport address where the | 518 // remote candidate equal to the source transport address where the |
| 520 // request came from. | 519 // request came from. |
| 521 | 520 |
| 522 // There shouldn't be an existing connection with this remote address. | 521 // There shouldn't be an existing connection with this remote address. |
| 523 // When ports are muxed, this channel might get multiple unknown address | 522 // When ports are muxed, this channel might get multiple unknown address |
| 524 // signals. In that case if the connection is already exists, we should | 523 // signals. In that case if the connection is already exists, we should |
| 525 // simply ignore the signal othewise send server error. | 524 // simply ignore the signal otherwise send server error. |
| 526 if (port->GetConnection(remote_candidate.address())) { | 525 if (port->GetConnection(remote_candidate.address())) { |
| 527 if (port_muxed) { | 526 if (port_muxed) { |
| 528 LOG(LS_INFO) << "Connection already exists for peer reflexive " | 527 LOG(LS_INFO) << "Connection already exists for peer reflexive " |
| 529 << "candidate: " << remote_candidate.ToString(); | 528 << "candidate: " << remote_candidate.ToString(); |
| 530 return; | 529 return; |
| 531 } else { | 530 } else { |
| 532 ASSERT(false); | 531 ASSERT(false); |
| 533 port->SendBindingErrorResponse(stun_msg, address, | 532 port->SendBindingErrorResponse(stun_msg, address, |
| 534 STUN_ERROR_SERVER_ERROR, | 533 STUN_ERROR_SERVER_ERROR, |
| 535 STUN_ERROR_REASON_SERVER_ERROR); | 534 STUN_ERROR_REASON_SERVER_ERROR); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 546 STUN_ERROR_REASON_SERVER_ERROR); | 545 STUN_ERROR_REASON_SERVER_ERROR); |
| 547 return; | 546 return; |
| 548 } | 547 } |
| 549 | 548 |
| 550 LOG(LS_INFO) << "Adding connection from " | 549 LOG(LS_INFO) << "Adding connection from " |
| 551 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") | 550 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
| 552 << " candidate: " << remote_candidate.ToString(); | 551 << " candidate: " << remote_candidate.ToString(); |
| 553 AddConnection(connection); | 552 AddConnection(connection); |
| 554 connection->ReceivedPing(); | 553 connection->ReceivedPing(); |
| 555 | 554 |
| 555 bool received_use_candidate = |
| 556 stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr; |
| 557 if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED) { |
| 558 connection->set_nominated(true); |
| 559 OnNominated(connection); |
| 560 } |
| 561 |
| 556 // Update the list of connections since we just added another. We do this | 562 // Update the list of connections since we just added another. We do this |
| 557 // after sending the response since it could (in principle) delete the | 563 // after sending the response since it could (in principle) delete the |
| 558 // connection in question. | 564 // connection in question. |
| 559 SortConnections(); | 565 SortConnections(); |
| 560 } | 566 } |
| 561 | 567 |
| 562 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { | 568 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { |
| 563 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called | 569 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called |
| 564 // from Transport. | 570 // from Transport. |
| 565 } | 571 } |
| 566 | 572 |
| 567 // When the signalling channel is ready, we can really kick off the allocator | 573 // When the signalling channel is ready, we can really kick off the allocator |
| 568 void P2PTransportChannel::OnSignalingReady() { | 574 void P2PTransportChannel::OnSignalingReady() { |
| 569 ASSERT(worker_thread_ == rtc::Thread::Current()); | 575 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 570 if (waiting_for_signaling_) { | 576 if (waiting_for_signaling_) { |
| 571 waiting_for_signaling_ = false; | 577 waiting_for_signaling_ = false; |
| 572 AddAllocatorSession(allocator_->CreateSession( | 578 AddAllocatorSession(allocator_->CreateSession( |
| 573 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); | 579 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); |
| 574 } | 580 } |
| 575 } | 581 } |
| 576 | 582 |
| 577 void P2PTransportChannel::OnUseCandidate(Connection* conn) { | 583 void P2PTransportChannel::OnNominated(Connection* conn) { |
| 578 ASSERT(worker_thread_ == rtc::Thread::Current()); | 584 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 579 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 585 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
| 580 | 586 |
| 581 if (conn->write_state() == Connection::STATE_WRITABLE) { | 587 if (conn->write_state() == Connection::STATE_WRITABLE) { |
| 582 if (best_connection_ != conn) { | 588 if (best_connection_ != conn) { |
| 583 pending_best_connection_ = NULL; | 589 pending_best_connection_ = NULL; |
| 584 LOG(LS_INFO) << "Switching best connection on controlled side: " | 590 LOG(LS_INFO) << "Switching best connection on controlled side: " |
| 585 << conn->ToString(); | 591 << conn->ToString(); |
| 586 SwitchBestConnectionTo(conn); | 592 SwitchBestConnectionTo(conn); |
| 587 // Now we have selected the best connection, time to prune other existing | 593 // Now we have selected the best connection, time to prune other existing |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 void P2PTransportChannel::SortConnections() { | 916 void P2PTransportChannel::SortConnections() { |
| 911 ASSERT(worker_thread_ == rtc::Thread::Current()); | 917 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 912 | 918 |
| 913 // Make sure the connection states are up-to-date since this affects how they | 919 // Make sure the connection states are up-to-date since this affects how they |
| 914 // will be sorted. | 920 // will be sorted. |
| 915 UpdateConnectionStates(); | 921 UpdateConnectionStates(); |
| 916 | 922 |
| 917 // Any changes after this point will require a re-sort. | 923 // Any changes after this point will require a re-sort. |
| 918 sort_dirty_ = false; | 924 sort_dirty_ = false; |
| 919 | 925 |
| 920 // Get a list of the networks that we are using. | |
| 921 std::set<rtc::Network*> networks; | |
| 922 for (uint32 i = 0; i < connections_.size(); ++i) | |
| 923 networks.insert(connections_[i]->port()->Network()); | |
| 924 | |
| 925 // Find the best alternative connection by sorting. It is important to note | 926 // Find the best alternative connection by sorting. It is important to note |
| 926 // that amongst equal preference, writable connections, this will choose the | 927 // that amongst equal preference, writable connections, this will choose the |
| 927 // one whose estimated latency is lowest. So it is the only one that we | 928 // one whose estimated latency is lowest. So it is the only one that we |
| 928 // need to consider switching to. | 929 // need to consider switching to. |
| 929 | |
| 930 ConnectionCompare cmp; | 930 ConnectionCompare cmp; |
| 931 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 931 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
| 932 LOG(LS_VERBOSE) << "Sorting available connections:"; | 932 LOG(LS_VERBOSE) << "Sorting available connections:"; |
| 933 for (uint32 i = 0; i < connections_.size(); ++i) { | 933 for (uint32 i = 0; i < connections_.size(); ++i) { |
| 934 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 934 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
| 935 } | 935 } |
| 936 | 936 |
| 937 Connection* top_connection = NULL; | 937 Connection* top_connection = |
| 938 if (connections_.size() > 0) | 938 (connections_.size() > 0) ? connections_[0] : nullptr; |
| 939 top_connection = connections_[0]; | |
| 940 | |
| 941 // We don't want to pick the best connections if channel is | |
| 942 // CONTROLLED, as connections will be selected by the CONTROLLING | |
| 943 // agent. | |
| 944 | 939 |
| 945 // If necessary, switch to the new choice. | 940 // If necessary, switch to the new choice. |
| 946 if (ice_role_ == ICEROLE_CONTROLLING) { | 941 // Note that |top_connection| doesn't have to be writable to become the best |
| 947 if (ShouldSwitch(best_connection_, top_connection)) { | 942 // connection although it will have higher priority if it is writable. |
| 948 LOG(LS_INFO) << "Switching best connection on controlling side: " | 943 // The controlled side can switch the best connection only if the current |
| 949 << top_connection->ToString(); | 944 // |best connection_| has not been nominated by the controlling side yet. |
| 950 SwitchBestConnectionTo(top_connection); | 945 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) && |
| 951 } | 946 ShouldSwitch(best_connection_, top_connection)) { |
| 947 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); |
| 948 SwitchBestConnectionTo(top_connection); |
| 952 } | 949 } |
| 953 | 950 |
| 954 // We can prune any connection for which there is a connected, writable | 951 // Controlled side can prune only if the best connection has been nominated. |
| 955 // connection on the same network with better or equal priority. We leave | 952 // because otherwise it may delete the connection that will be selected by |
| 956 // those with better priority just in case they become writable later (at | 953 // the controlling side. |
| 957 // which point, we would prune out the current best connection). We leave | 954 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { |
| 958 // connections on other networks because they may not be using the same | 955 PruneConnections(); |
| 959 // resources and they may represent very distinct paths over which we can | |
| 960 // switch. If the |primier| connection is not connected, we may be | |
| 961 // reconnecting a TCP connection and temporarily do not prune connections in | |
| 962 // this network. See the big comment in CompareConnections. | |
| 963 std::set<rtc::Network*>::iterator network; | |
| 964 for (network = networks.begin(); network != networks.end(); ++network) { | |
| 965 Connection* primier = GetBestConnectionOnNetwork(*network); | |
| 966 if (!primier || (primier->write_state() != Connection::STATE_WRITABLE) || | |
| 967 !primier->connected()) | |
| 968 continue; | |
| 969 | |
| 970 for (uint32 i = 0; i < connections_.size(); ++i) { | |
| 971 if ((connections_[i] != primier) && | |
| 972 (connections_[i]->port()->Network() == *network) && | |
| 973 (CompareConnectionCandidates(primier, connections_[i]) >= 0)) { | |
| 974 connections_[i]->Prune(); | |
| 975 } | |
| 976 } | |
| 977 } | 956 } |
| 978 | 957 |
| 979 // Check if all connections are timedout. | 958 // Check if all connections are timedout. |
| 980 bool all_connections_timedout = true; | 959 bool all_connections_timedout = true; |
| 981 for (uint32 i = 0; i < connections_.size(); ++i) { | 960 for (uint32 i = 0; i < connections_.size(); ++i) { |
| 982 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { | 961 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { |
| 983 all_connections_timedout = false; | 962 all_connections_timedout = false; |
| 984 break; | 963 break; |
| 985 } | 964 } |
| 986 } | 965 } |
| 987 | 966 |
| 988 // Now update the writable state of the channel with the information we have | 967 // Now update the writable state of the channel with the information we have |
| 989 // so far. | 968 // so far. |
| 990 if (best_connection_ && best_connection_->writable()) { | 969 if (best_connection_ && best_connection_->writable()) { |
| 991 HandleWritable(); | 970 HandleWritable(); |
| 992 } else if (all_connections_timedout) { | 971 } else if (all_connections_timedout) { |
| 993 HandleAllTimedOut(); | 972 HandleAllTimedOut(); |
| 994 } else { | 973 } else { |
| 995 HandleNotWritable(); | 974 HandleNotWritable(); |
| 996 } | 975 } |
| 997 | 976 |
| 998 // Update the state of this channel. This method is called whenever the | 977 // Update the state of this channel. This method is called whenever the |
| 999 // state of any connection changes, so this is a good place to do this. | 978 // state of any connection changes, so this is a good place to do this. |
| 1000 UpdateChannelState(); | 979 UpdateChannelState(); |
| 1001 } | 980 } |
| 1002 | 981 |
| 982 Connection* P2PTransportChannel::best_nominated_connection() const { |
| 983 return (best_connection_ && best_connection_->nominated()) ? best_connection_ |
| 984 : nullptr; |
| 985 } |
| 986 |
| 987 void P2PTransportChannel::PruneConnections() { |
| 988 // We can prune any connection for which there is a connected, writable |
| 989 // connection on the same network with better or equal priority. We leave |
| 990 // those with better priority just in case they become writable later (at |
| 991 // which point, we would prune out the current best connection). We leave |
| 992 // connections on other networks because they may not be using the same |
| 993 // resources and they may represent very distinct paths over which we can |
| 994 // switch. If the |primier| connection is not connected, we may be |
| 995 // reconnecting a TCP connection and temporarily do not prune connections in |
| 996 // this network. See the big comment in CompareConnections. |
| 997 |
| 998 // Get a list of the networks that we are using. |
| 999 std::set<rtc::Network*> networks; |
| 1000 for (const Connection* conn : connections_) { |
| 1001 networks.insert(conn->port()->Network()); |
| 1002 } |
| 1003 for (rtc::Network* network : networks) { |
| 1004 Connection* primier = GetBestConnectionOnNetwork(network); |
| 1005 if (!(primier && primier->writable() && primier->connected())) { |
| 1006 continue; |
| 1007 } |
| 1008 |
| 1009 for (Connection* conn : connections_) { |
| 1010 if ((conn != primier) && (conn->port()->Network() == network) && |
| 1011 (CompareConnectionCandidates(primier, conn) >= 0)) { |
| 1012 conn->Prune(); |
| 1013 } |
| 1014 } |
| 1015 } |
| 1016 } |
| 1003 | 1017 |
| 1004 // Track the best connection, and let listeners know | 1018 // Track the best connection, and let listeners know |
| 1005 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { | 1019 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { |
| 1006 // Note: if conn is NULL, the previous best_connection_ has been destroyed, | 1020 // Note: if conn is NULL, the previous best_connection_ has been destroyed, |
| 1007 // so don't use it. | 1021 // so don't use it. |
| 1008 Connection* old_best_connection = best_connection_; | 1022 Connection* old_best_connection = best_connection_; |
| 1009 best_connection_ = conn; | 1023 best_connection_ = conn; |
| 1010 if (best_connection_) { | 1024 if (best_connection_) { |
| 1011 if (old_best_connection) { | 1025 if (old_best_connection) { |
| 1012 LOG_J(LS_INFO, this) << "Previous best connection: " | 1026 LOG_J(LS_INFO, this) << "Previous best connection: " |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 Connection *connection, const char *data, size_t len, | 1339 Connection *connection, const char *data, size_t len, |
| 1326 const rtc::PacketTime& packet_time) { | 1340 const rtc::PacketTime& packet_time) { |
| 1327 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1341 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1328 | 1342 |
| 1329 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1343 // Do not deliver, if packet doesn't belong to the correct transport channel. |
| 1330 if (!FindConnection(connection)) | 1344 if (!FindConnection(connection)) |
| 1331 return; | 1345 return; |
| 1332 | 1346 |
| 1333 // Let the client know of an incoming packet | 1347 // Let the client know of an incoming packet |
| 1334 SignalReadPacket(this, data, len, packet_time, 0); | 1348 SignalReadPacket(this, data, len, packet_time, 0); |
| 1349 |
| 1350 // May need to switch the sending connection based on the receiving media path |
| 1351 // if this is the controlled side. |
| 1352 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && |
| 1353 connection->writable() && best_connection_ != connection) { |
| 1354 SwitchBestConnectionTo(connection); |
| 1355 } |
| 1335 } | 1356 } |
| 1336 | 1357 |
| 1337 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1358 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
| 1338 if (connection == best_connection_ && writable()) { | 1359 if (connection == best_connection_ && writable()) { |
| 1339 SignalReadyToSend(this); | 1360 SignalReadyToSend(this); |
| 1340 } | 1361 } |
| 1341 } | 1362 } |
| 1342 | 1363 |
| 1343 } // namespace cricket | 1364 } // namespace cricket |
| OLD | NEW |