Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Unified Diff: webrtc/p2p/base/p2ptransportchannel.cc

Issue 1311433009: A few updates on connection states (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Merge with the head Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/p2p/base/p2ptransportchannel.cc
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc
index e7f5c941c403825362799f9fe82bcc44ecf1a196..cd1af82c8d59365a47af2647869680ae6c98c20c 100644
--- a/webrtc/p2p/base/p2ptransportchannel.cc
+++ b/webrtc/p2p/base/p2ptransportchannel.cc
@@ -10,8 +10,8 @@
#include "webrtc/p2p/base/p2ptransportchannel.h"
-#include <set>
#include <algorithm>
+#include <set>
#include "webrtc/p2p/base/common.h"
#include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE.
#include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE.
@@ -23,11 +23,7 @@
namespace {
// messages for queuing up work for ourselves
-enum {
- MSG_SORT = 1,
- MSG_PING,
- MSG_CHECK_RECEIVING
-};
+enum { MSG_SORT = 1, MSG_CHECK_AND_PING };
// When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
// for pinging. When the socket is writable, we will use only 1 Kbps because
@@ -35,12 +31,17 @@ enum {
// well on a 28.8K modem, which is the slowest connection on which the voice
// quality is reasonable at all.
static const uint32 PING_PACKET_SIZE = 60 * 8;
-static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms
-static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms
-
-// If there is a current writable connection, then we will also try hard to
-// make sure it is pinged at this rate.
-static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit
+// STRONG_PING_DELAY (480ms) is applied when the best connection is both
+// writable and receiving.
+static const uint32 STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000;
+// WEAK_PING_DELAY (48ms) is applied when the best connection is either not
+// writable or not receiving.
+static const uint32 WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000;
+
+// If the current best connection is both writable and receiving, then we will
+// also try hard to make sure it is pinged at this rate (a little less than
+// 2 * STRONG_PING_DELAY).
+static const uint32 MAX_CURRENT_STRONG_DELAY = 900;
static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms
@@ -71,15 +72,23 @@ int CompareConnectionCandidates(cricket::Connection* a,
(b->remote_candidate().generation() + b->port()->generation());
}
-// Compare two connections based on their connected state, writability and
-// static preferences.
-int CompareConnections(cricket::Connection *a, cricket::Connection *b) {
+// Compare two connections based on their writing, receiving, and connected
+// states.
+int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) {
// Sort based on write-state. Better states have lower values.
if (a->write_state() < b->write_state())
return 1;
if (a->write_state() > b->write_state())
return -1;
+ // We prefer a receiving connection to a non-receiving, higher-priority
+ // connection when sorting connections and choosing which connection to
+ // switch to.
+ if (a->receiving() && !b->receiving())
+ return 1;
+ if (!a->receiving() && b->receiving())
+ return -1;
+
// WARNING: Some complexity here about TCP reconnecting.
// When a TCP connection fails because of a TCP socket disconnecting, the
// active side of the connection will attempt to reconnect for 5 seconds while
@@ -111,7 +120,14 @@ int CompareConnections(cricket::Connection *a, cricket::Connection *b) {
return -1;
}
}
+ return 0;
+}
+int CompareConnections(cricket::Connection* a, cricket::Connection* b) {
+ int state_cmp = CompareConnectionStates(a, b);
+ if (state_cmp != 0) {
+ return state_cmp;
+ }
// Compare the candidate information.
return CompareConnectionCandidates(a, b);
}
@@ -149,19 +165,33 @@ class ConnectionCompare {
};
// Determines whether we should switch between two connections, based first on
-// static preferences and then (if those are equal) on latency estimates.
-bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) {
+// connection states, static preferences, and then (if those are equal) on
+// latency estimates.
+bool ShouldSwitch(cricket::Connection* a_conn,
+ cricket::Connection* b_conn,
+ cricket::IceRole ice_role) {
if (a_conn == b_conn)
return false;
if (!a_conn || !b_conn) // don't think the latter should happen
return true;
- int prefs_cmp = CompareConnections(a_conn, b_conn);
- if (prefs_cmp < 0)
- return true;
- if (prefs_cmp > 0)
+ // We prefer to switch to a writable and receiving connection over a
+ // non-writable or non-receiving connection, even if the latter has
+ // been nominated by the controlling side.
+ int state_cmp = CompareConnectionStates(a_conn, b_conn);
+ if (state_cmp != 0) {
+ return state_cmp < 0;
+ }
+ if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) {
+ LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status";
return false;
+ }
+
+ int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn);
+ if (prefs_cmp != 0) {
+ return prefs_cmp < 0;
+ }
return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
}
@@ -350,11 +380,8 @@ void P2PTransportChannel::Connect() {
return;
}
- // Start pinging as the ports come in.
- thread()->Post(this, MSG_PING);
-
- thread()->PostDelayed(
- check_receiving_delay_, this, MSG_CHECK_RECEIVING);
+ // Start checking and pinging as the ports come in.
+ thread()->Post(this, MSG_CHECK_AND_PING);
}
void P2PTransportChannel::MaybeStartGathering() {
@@ -913,7 +940,8 @@ void P2PTransportChannel::SortConnections() {
// need to consider switching to.
ConnectionCompare cmp;
std::stable_sort(connections_.begin(), connections_.end(), cmp);
- LOG(LS_VERBOSE) << "Sorting available connections:";
+ LOG(LS_VERBOSE) << "Sorting " << connections_.size()
+ << " available connections:";
for (uint32 i = 0; i < connections_.size(); ++i) {
LOG(LS_VERBOSE) << connections_[i]->ToString();
}
@@ -924,10 +952,7 @@ void P2PTransportChannel::SortConnections() {
// If necessary, switch to the new choice.
// Note that |top_connection| doesn't have to be writable to become the best
// connection although it will have higher priority if it is writable.
- // The controlled side can switch the best connection only if the current
- // |best connection_| has not been nominated by the controlling side yet.
- if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) &&
- ShouldSwitch(best_connection_, top_connection)) {
+ if (ShouldSwitch(best_connection_, top_connection, ice_role_)) {
LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
SwitchBestConnectionTo(top_connection);
}
@@ -1013,7 +1038,6 @@ void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
LOG_J(LS_INFO, this) << "New best connection: "
<< best_connection_->ToString();
SignalRouteChange(this, best_connection_->remote_candidate());
- set_receiving(best_connection_->receiving());
} else {
LOG_J(LS_INFO, this) << "No best connection";
}
@@ -1022,15 +1046,19 @@ void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
void P2PTransportChannel::UpdateChannelState() {
// The Handle* functions already set the writable state. We'll just double-
// check it here.
- bool writable = ((best_connection_ != NULL) &&
- (best_connection_->write_state() ==
- Connection::STATE_WRITABLE));
+ bool writable = best_connection_ && best_connection_->writable();
ASSERT(writable == this->writable());
if (writable != this->writable())
LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch";
- // TODO(honghaiz): The channel receiving state is set in OnCheckReceiving.
- // Will revisit in a subsequent code change.
+ bool receiving = false;
+ for (const Connection* connection : connections_) {
+ if (connection->receiving()) {
+ receiving = true;
+ break;
+ }
+ }
+ set_receiving(receiving);
}
// We checked the status of our connections and we had at least one that
@@ -1063,6 +1091,11 @@ void P2PTransportChannel::HandleAllTimedOut() {
HandleNotWritable();
}
+bool P2PTransportChannel::Weak() const {
+ return !(best_connection_ && best_connection_->receiving() &&
+ best_connection_->writable());
+}
+
// If we have a best connection, return it, otherwise return top one in the
// list (later we will mark it best).
Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
@@ -1086,11 +1119,8 @@ void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
case MSG_SORT:
OnSort();
break;
- case MSG_PING:
- OnPing();
- break;
- case MSG_CHECK_RECEIVING:
- OnCheckReceiving();
+ case MSG_CHECK_AND_PING:
+ OnCheckAndPing();
break;
default:
ASSERT(false);
@@ -1104,30 +1134,22 @@ void P2PTransportChannel::OnSort() {
SortConnections();
}
-// Handle queued up ping request
-void P2PTransportChannel::OnPing() {
+// Handle queued up check-and-ping request
+void P2PTransportChannel::OnCheckAndPing() {
// Make sure the states of the connections are up-to-date (since this affects
// which ones are pingable).
UpdateConnectionStates();
-
- // Find the oldest pingable connection and have it do a ping.
- Connection* conn = FindNextPingableConnection();
- if (conn)
- PingConnection(conn);
-
- // Post ourselves a message to perform the next ping.
- uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY;
- thread()->PostDelayed(delay, this, MSG_PING);
-}
-
-void P2PTransportChannel::OnCheckReceiving() {
- if (best_connection_) {
- bool receiving = rtc::Time() <=
- best_connection_->last_received() + receiving_timeout_;
- set_receiving(receiving);
+ // When the best connection is either not receiving or not writable,
+ // switch to weak ping delay.
+ int ping_delay = Weak() ? WEAK_PING_DELAY : STRONG_PING_DELAY;
+ if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) {
+ Connection* conn = FindNextPingableConnection();
+ if (conn) {
+ PingConnection(conn);
+ }
}
-
- thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING);
+ int check_delay = std::min(ping_delay, check_receiving_delay_);
+ thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
}
// Is the connection in a state for us to even consider pinging the other side?
@@ -1149,9 +1171,9 @@ bool P2PTransportChannel::IsPingable(Connection* conn) {
return false;
}
- // If the channel is not writable, ping all candidates. Otherwise, we only
+ // If the channel is weak, ping all candidates. Otherwise, we only
// want to ping connections that have not timed out on writing.
- return !writable() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT;
+ return Weak() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT;
}
// Returns the next pingable connection to ping. This will be the oldest
@@ -1163,9 +1185,8 @@ bool P2PTransportChannel::IsPingable(Connection* conn) {
Connection* P2PTransportChannel::FindNextPingableConnection() {
uint32 now = rtc::Time();
if (best_connection_ && best_connection_->connected() &&
- (best_connection_->write_state() == Connection::STATE_WRITABLE) &&
- (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <=
- now)) {
+ best_connection_->writable() &&
+ (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) {
return best_connection_;
}
@@ -1223,7 +1244,8 @@ void P2PTransportChannel::PingConnection(Connection* conn) {
use_candidate = best_connection_->writable();
}
conn->set_use_candidate_attr(use_candidate);
- conn->Ping(rtc::Time());
+ last_ping_sent_ms_ = rtc::Time();
+ conn->Ping(last_ping_sent_ms_);
}
// When a connection's state changes, we need to figure out who to use as
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698