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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
558 | 558 |
559 if (port->IceProtocol() == ICEPROTO_RFC5245) { | 559 if (port->IceProtocol() == ICEPROTO_RFC5245) { |
560 // RFC5245, the agent constructs a pair whose local candidate is equal to | 560 // RFC5245, the agent constructs a pair whose local candidate is equal to |
561 // the transport address on which the STUN request was received, and a | 561 // the transport address on which the STUN request was received, and a |
562 // remote candidate equal to the source transport address where the | 562 // remote candidate equal to the source transport address where the |
563 // request came from. | 563 // request came from. |
564 | 564 |
565 // There shouldn't be an existing connection with this remote address. | 565 // There shouldn't be an existing connection with this remote address. |
566 // When ports are muxed, this channel might get multiple unknown address | 566 // When ports are muxed, this channel might get multiple unknown address |
567 // signals. In that case if the connection is already exists, we should | 567 // signals. In that case if the connection is already exists, we should |
568 // simply ignore the signal othewise send server error. | 568 // simply ignore the signal otherwise send server error. |
569 if (port->GetConnection(remote_candidate.address())) { | 569 if (port->GetConnection(remote_candidate.address())) { |
570 if (port_muxed) { | 570 if (port_muxed) { |
571 LOG(LS_INFO) << "Connection already exists for peer reflexive " | 571 LOG(LS_INFO) << "Connection already exists for peer reflexive " |
572 << "candidate: " << remote_candidate.ToString(); | 572 << "candidate: " << remote_candidate.ToString(); |
573 return; | 573 return; |
574 } else { | 574 } else { |
575 ASSERT(false); | 575 ASSERT(false); |
576 port->SendBindingErrorResponse(stun_msg, address, | 576 port->SendBindingErrorResponse(stun_msg, address, |
577 STUN_ERROR_SERVER_ERROR, | 577 STUN_ERROR_SERVER_ERROR, |
578 STUN_ERROR_REASON_SERVER_ERROR); | 578 STUN_ERROR_REASON_SERVER_ERROR); |
(...skipping 10 matching lines...) Expand all Loading... | |
589 STUN_ERROR_REASON_SERVER_ERROR); | 589 STUN_ERROR_REASON_SERVER_ERROR); |
590 return; | 590 return; |
591 } | 591 } |
592 | 592 |
593 LOG(LS_INFO) << "Adding connection from " | 593 LOG(LS_INFO) << "Adding connection from " |
594 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") | 594 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
595 << " candidate: " << remote_candidate.ToString(); | 595 << " candidate: " << remote_candidate.ToString(); |
596 AddConnection(connection); | 596 AddConnection(connection); |
597 connection->ReceivedPing(); | 597 connection->ReceivedPing(); |
598 | 598 |
599 bool received_use_candidate = | |
600 stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr; | |
601 if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED && | |
602 protocol_type_ == ICEPROTO_RFC5245) { | |
603 // This need to be after AddConnection so that the event | |
604 // SignalUseCandidate is connected to this class. | |
605 connection->set_nominated(true); | |
606 } | |
607 | |
599 // Send the pinger a successful stun response. | 608 // Send the pinger a successful stun response. |
600 port->SendBindingResponse(stun_msg, address); | 609 port->SendBindingResponse(stun_msg, address); |
601 | 610 |
602 // Update the list of connections since we just added another. We do this | 611 // Update the list of connections since we just added another. We do this |
603 // after sending the response since it could (in principle) delete the | 612 // after sending the response since it could (in principle) delete the |
604 // connection in question. | 613 // connection in question. |
605 SortConnections(); | 614 SortConnections(); |
606 } else { | 615 } else { |
607 // Check for connectivity to this address. Create connections | 616 // Check for connectivity to this address. Create connections |
608 // to this address across all local ports. First, add this as a new remote | 617 // to this address across all local ports. First, add this as a new remote |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
992 // is no point in sorting the connections. In hybrid state, ports can have | 1001 // is no point in sorting the connections. In hybrid state, ports can have |
993 // different protocol than hybrid and protocol may differ from one another. | 1002 // different protocol than hybrid and protocol may differ from one another. |
994 // Instead just update the state of this channel | 1003 // Instead just update the state of this channel |
995 UpdateChannelState(); | 1004 UpdateChannelState(); |
996 return; | 1005 return; |
997 } | 1006 } |
998 | 1007 |
999 // Any changes after this point will require a re-sort. | 1008 // Any changes after this point will require a re-sort. |
1000 sort_dirty_ = false; | 1009 sort_dirty_ = false; |
1001 | 1010 |
1002 // Get a list of the networks that we are using. | |
1003 std::set<rtc::Network*> networks; | |
1004 for (uint32 i = 0; i < connections_.size(); ++i) | |
1005 networks.insert(connections_[i]->port()->Network()); | |
1006 | |
1007 // Find the best alternative connection by sorting. It is important to note | 1011 // Find the best alternative connection by sorting. It is important to note |
1008 // that amongst equal preference, writable connections, this will choose the | 1012 // that amongst equal preference, writable connections, this will choose the |
1009 // one whose estimated latency is lowest. So it is the only one that we | 1013 // one whose estimated latency is lowest. So it is the only one that we |
1010 // need to consider switching to. | 1014 // need to consider switching to. |
1011 | |
1012 ConnectionCompare cmp; | 1015 ConnectionCompare cmp; |
1013 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 1016 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
1014 LOG(LS_VERBOSE) << "Sorting available connections:"; | 1017 LOG(LS_VERBOSE) << "Sorting available connections:"; |
1015 for (uint32 i = 0; i < connections_.size(); ++i) { | 1018 for (uint32 i = 0; i < connections_.size(); ++i) { |
1016 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 1019 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
1017 } | 1020 } |
1018 | 1021 Connection* top_connection = |
1019 Connection* top_connection = NULL; | 1022 (connections_.size() > 0) ? connections_[0] : nullptr; |
1020 if (connections_.size() > 0) | |
1021 top_connection = connections_[0]; | |
1022 | |
1023 // We don't want to pick the best connections if channel is using RFC5245 | |
1024 // and it's mode is CONTROLLED, as connections will be selected by the | |
1025 // CONTROLLING agent. | |
1026 | 1023 |
1027 // If necessary, switch to the new choice. | 1024 // If necessary, switch to the new choice. |
1028 if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING) { | 1025 // Note that top_connection don't have to be writable to be |
juberti1
2015/08/07 01:31:19
don't ->doesn't
honghaiz3
2015/08/07 20:42:04
Done.
| |
1029 if (ShouldSwitch(best_connection_, top_connection)) { | 1026 // switched to although it will have higher priority if it is writable. |
1030 LOG(LS_INFO) << "Switching best connection on controlling side: " | 1027 // Controlled side can switch the best connection only if the best connection |
1031 << top_connection->ToString(); | 1028 // was not nominated yet. |
1032 SwitchBestConnectionTo(top_connection); | 1029 if ((protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING || |
1033 } | 1030 !best_nominated_connection()) && |
1031 ShouldSwitch(best_connection_, top_connection)) { | |
1032 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | |
1033 SwitchBestConnectionTo(top_connection); | |
1034 } | 1034 } |
1035 | 1035 |
1036 // We can prune any connection for which there is a connected, writable | 1036 // Controlled side can prune only if the best connection has been nominated. |
1037 // connection on the same network with better or equal priority. We leave | 1037 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { |
1038 // those with better priority just in case they become writable later (at | 1038 PruneConnections(); |
1039 // which point, we would prune out the current best connection). We leave | |
1040 // connections on other networks because they may not be using the same | |
1041 // resources and they may represent very distinct paths over which we can | |
1042 // switch. If the |primier| connection is not connected, we may be | |
1043 // reconnecting a TCP connection and temporarily do not prune connections in | |
1044 // this network. See the big comment in CompareConnections. | |
1045 std::set<rtc::Network*>::iterator network; | |
1046 for (network = networks.begin(); network != networks.end(); ++network) { | |
1047 Connection* primier = GetBestConnectionOnNetwork(*network); | |
1048 if (!primier || (primier->write_state() != Connection::STATE_WRITABLE) || | |
1049 !primier->connected()) | |
1050 continue; | |
1051 | |
1052 for (uint32 i = 0; i < connections_.size(); ++i) { | |
1053 if ((connections_[i] != primier) && | |
1054 (connections_[i]->port()->Network() == *network) && | |
1055 (CompareConnectionCandidates(primier, connections_[i]) >= 0)) { | |
1056 connections_[i]->Prune(); | |
1057 } | |
1058 } | |
1059 } | 1039 } |
1060 | 1040 |
1061 // Check if all connections are timedout. | 1041 // Check if all connections are timedout. |
1062 bool all_connections_timedout = true; | 1042 bool all_connections_timedout = true; |
1063 for (uint32 i = 0; i < connections_.size(); ++i) { | 1043 for (uint32 i = 0; i < connections_.size(); ++i) { |
1064 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { | 1044 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { |
1065 all_connections_timedout = false; | 1045 all_connections_timedout = false; |
1066 break; | 1046 break; |
1067 } | 1047 } |
1068 } | 1048 } |
1069 | 1049 |
1070 // Now update the writable state of the channel with the information we have | 1050 // Now update the writable state of the channel with the information we have |
1071 // so far. | 1051 // so far. |
1072 if (best_connection_ && best_connection_->writable()) { | 1052 if (best_connection_ && best_connection_->writable()) { |
1073 HandleWritable(); | 1053 HandleWritable(); |
1074 } else if (all_connections_timedout) { | 1054 } else if (all_connections_timedout) { |
1075 HandleAllTimedOut(); | 1055 HandleAllTimedOut(); |
1076 } else { | 1056 } else { |
1077 HandleNotWritable(); | 1057 HandleNotWritable(); |
1078 } | 1058 } |
1079 | 1059 |
1080 // Update the state of this channel. This method is called whenever the | 1060 // Update the state of this channel. This method is called whenever the |
1081 // state of any connection changes, so this is a good place to do this. | 1061 // state of any connection changes, so this is a good place to do this. |
1082 UpdateChannelState(); | 1062 UpdateChannelState(); |
1083 } | 1063 } |
1084 | 1064 |
1065 Connection* P2PTransportChannel::best_nominated_connection() const { | |
1066 return (best_connection_ && best_connection_->nominated()) ? best_connection_ | |
1067 : nullptr; | |
1068 } | |
1069 | |
1070 void P2PTransportChannel::PruneConnections() { | |
1071 // We can prune any connection for which there is a connected, writable | |
1072 // connection on the same network with better or equal priority. We leave | |
1073 // those with better priority just in case they become writable later (at | |
1074 // which point, we would prune out the current best connection). We leave | |
1075 // connections on other networks because they may not be using the same | |
1076 // resources and they may represent very distinct paths over which we can | |
1077 // switch. If the |primier| connection is not connected, we may be | |
1078 // reconnecting a TCP connection and temporarily do not prune connections in | |
1079 // this network. See the big comment in CompareConnections. | |
1080 // NOTE: If the ICE role is controlled and it has not received requests with | |
1081 // use_candidate yet, do not prune the connections because it may delete the | |
1082 // connection that will be selected by the controlling side. | |
1083 | |
1084 // Get a list of the networks that we are using. | |
1085 std::set<rtc::Network*> networks; | |
1086 for (uint32 i = 0; i < connections_.size(); ++i) | |
1087 networks.insert(connections_[i]->port()->Network()); | |
1088 for (auto network : networks) { | |
1089 Connection* primier = GetBestConnectionOnNetwork(network); | |
1090 if (!(primier && primier->writable() && primier->connected())) | |
1091 continue; | |
1092 | |
1093 for (auto connection : connections_) { | |
1094 if ((connection != primier) && | |
1095 (connection->port()->Network() == network) && | |
1096 (CompareConnectionCandidates(primier, connection) >= 0)) { | |
1097 connection->Prune(); | |
1098 } | |
1099 } | |
1100 } | |
1101 } | |
1085 | 1102 |
1086 // Track the best connection, and let listeners know | 1103 // Track the best connection, and let listeners know |
1087 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { | 1104 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { |
1088 // Note: if conn is NULL, the previous best_connection_ has been destroyed, | 1105 // Note: if conn is NULL, the previous best_connection_ has been destroyed, |
1089 // so don't use it. | 1106 // so don't use it. |
1090 Connection* old_best_connection = best_connection_; | 1107 Connection* old_best_connection = best_connection_; |
1091 best_connection_ = conn; | 1108 best_connection_ = conn; |
1092 if (best_connection_) { | 1109 if (best_connection_) { |
1093 if (old_best_connection) { | 1110 if (old_best_connection) { |
1094 LOG_J(LS_INFO, this) << "Previous best connection: " | 1111 LOG_J(LS_INFO, this) << "Previous best connection: " |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1410 Connection *connection, const char *data, size_t len, | 1427 Connection *connection, const char *data, size_t len, |
1411 const rtc::PacketTime& packet_time) { | 1428 const rtc::PacketTime& packet_time) { |
1412 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1429 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1413 | 1430 |
1414 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1431 // Do not deliver, if packet doesn't belong to the correct transport channel. |
1415 if (!FindConnection(connection)) | 1432 if (!FindConnection(connection)) |
1416 return; | 1433 return; |
1417 | 1434 |
1418 // Let the client know of an incoming packet | 1435 // Let the client know of an incoming packet |
1419 SignalReadPacket(this, data, len, packet_time, 0); | 1436 SignalReadPacket(this, data, len, packet_time, 0); |
1437 | |
1438 // May need to switch the sending connection based on the receiving media path | |
1439 // if this is the controlled side. | |
1440 if (best_connection_ != connection && ice_role_ == ICEROLE_CONTROLLED && | |
1441 !best_nominated_connection() && connection->writable()) { | |
1442 SwitchBestConnectionTo(connection); | |
1443 } | |
1420 } | 1444 } |
1421 | 1445 |
1422 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1446 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1423 if (connection == best_connection_ && writable()) { | 1447 if (connection == best_connection_ && writable()) { |
1424 SignalReadyToSend(this); | 1448 SignalReadyToSend(this); |
1425 } | 1449 } |
1426 } | 1450 } |
1427 | 1451 |
1428 } // namespace cricket | 1452 } // namespace cricket |
OLD | NEW |