Index: webrtc/p2p/base/stunport.cc |
diff --git a/webrtc/p2p/base/stunport.cc b/webrtc/p2p/base/stunport.cc |
index 8f37dd5218bb745b5e06ab6d8b2574faefc9aa44..e871a6c0cc6c042f544f0f6543d52726db464e00 100644 |
--- a/webrtc/p2p/base/stunport.cc |
+++ b/webrtc/p2p/base/stunport.cc |
@@ -24,21 +24,23 @@ namespace cricket { |
// TODO: Move these to a common place (used in relayport too) |
const int KEEPALIVE_DELAY = 10 * 1000; // 10 seconds - sort timeouts |
-const int RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs |
-// Stop sending STUN binding requests after this amount of time |
-// (in milliseconds) because the connection binding requests should keep |
-// the NAT binding alive. |
-const int KEEP_ALIVE_TIMEOUT = 2 * 60 * 1000; // 2 minutes |
+const int RETRY_TIMEOUT = 50 * 1000; // 50 seconds |
+// Lifetime chosen for STUN ports on low-cost networks. |
+const int INFINITE_LIFETIME = -1; |
+// Lifetime for STUN ports on high-cost networks: 2 minutes |
+const int HIGH_COST_PORT_KEEPALIVE_LIFETIME = 2 * 60 * 1000; |
// Handles a binding request sent to the STUN server. |
class StunBindingRequest : public StunRequest { |
public: |
StunBindingRequest(UDPPort* port, |
const rtc::SocketAddress& addr, |
- uint32_t deadline) |
- : port_(port), server_addr_(addr), deadline_(deadline) { |
- start_time_ = rtc::Time(); |
- } |
+ uint32_t start_time, |
+ int lifetime) |
+ : port_(port), |
+ server_addr_(addr), |
+ start_time_(start_time), |
+ lifetime_(lifetime) {} |
virtual ~StunBindingRequest() { |
} |
@@ -62,11 +64,10 @@ class StunBindingRequest : public StunRequest { |
port_->OnStunBindingRequestSucceeded(server_addr_, addr); |
} |
- // We will do a keep-alive regardless of whether this request succeeds. |
- // It will be stopped after |deadline_| mostly to conserve the battery life. |
- if (rtc::Time() <= deadline_) { |
+ // The keep-alive requests will be stopped after its lifetime has passed. |
+ if (WithinLifetime(rtc::Time())) { |
port_->requests_.SendDelayed( |
- new StunBindingRequest(port_, server_addr_, deadline_), |
+ new StunBindingRequest(port_, server_addr_, start_time_, lifetime_), |
port_->stun_keepalive_delay()); |
} |
} |
@@ -77,34 +78,41 @@ class StunBindingRequest : public StunRequest { |
LOG(LS_ERROR) << "Bad allocate response error code"; |
} else { |
LOG(LS_ERROR) << "Binding error response:" |
- << " class=" << attr->eclass() |
- << " number=" << attr->number() |
- << " reason='" << attr->reason() << "'"; |
+ << " class=" << attr->eclass() |
+ << " number=" << attr->number() << " reason='" |
+ << attr->reason() << "'"; |
} |
port_->OnStunBindingOrResolveRequestFailed(server_addr_); |
uint32_t now = rtc::Time(); |
- if (now <= deadline_ && rtc::TimeDiff(now, start_time_) <= RETRY_TIMEOUT) { |
+ if (WithinLifetime(now) && |
+ rtc::TimeDiff(now, start_time_) < RETRY_TIMEOUT) { |
port_->requests_.SendDelayed( |
- new StunBindingRequest(port_, server_addr_, deadline_), |
+ new StunBindingRequest(port_, server_addr_, start_time_, lifetime_), |
port_->stun_keepalive_delay()); |
} |
} |
- |
virtual void OnTimeout() override { |
LOG(LS_ERROR) << "Binding request timed out from " |
- << port_->GetLocalAddress().ToSensitiveString() |
- << " (" << port_->Network()->name() << ")"; |
+ << port_->GetLocalAddress().ToSensitiveString() << " (" |
+ << port_->Network()->name() << ")"; |
port_->OnStunBindingOrResolveRequestFailed(server_addr_); |
} |
private: |
+ // Returns true if |now| is within the lifetime of the request (a negative |
+ // lifetime means infinite). |
+ bool WithinLifetime(uint32_t now) const { |
+ return lifetime_ < 0 || rtc::TimeDiff(now, start_time_) <= lifetime_; |
+ } |
UDPPort* port_; |
const rtc::SocketAddress server_addr_; |
+ |
uint32_t start_time_; |
- uint32_t deadline_; |
+ // The time duration for which this request will be rescheduled. |
+ int lifetime_; |
}; |
UDPPort::AddressResolver::AddressResolver( |
@@ -212,6 +220,12 @@ UDPPort::UDPPort(rtc::Thread* thread, |
} |
bool UDPPort::Init() { |
+ // If this is a zero-cost network, it will keep on sending STUN binding |
+ // requests indefinitely to keep the NAT binding alive. Otherwise, stop |
+ // sending STUN binding requests after HIGH_COST_PORT_KEEPALIVE_LIFETIME. |
+ stun_keepalive_lifetime_ = (network_cost() == 0) |
+ ? INFINITE_LIFETIME |
+ : HIGH_COST_PORT_KEEPALIVE_LIFETIME; |
if (!SharedSocket()) { |
ASSERT(socket_ == NULL); |
socket_ = socket_factory()->CreateUdpSocket( |
@@ -397,8 +411,8 @@ void UDPPort::SendStunBindingRequest(const rtc::SocketAddress& stun_addr) { |
} else if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) { |
// Check if |server_addr_| is compatible with the port's ip. |
if (IsCompatibleAddress(stun_addr)) { |
- requests_.Send(new StunBindingRequest(this, stun_addr, |
- rtc::Time() + KEEP_ALIVE_TIMEOUT)); |
+ requests_.Send(new StunBindingRequest(this, stun_addr, rtc::Time(), |
+ stun_keepalive_lifetime_)); |
} else { |
// Since we can't send stun messages to the server, we should mark this |
// port ready. |