release the turn allocation by sending a refresh request with lifetime 0
BUG=406578
Patch originally from philipp.hancke@googlemail.com
R=juberti@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/41449004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8087 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/p2p/base/stunrequest.cc b/webrtc/p2p/base/stunrequest.cc
index a6f4c15..32b4694 100644
--- a/webrtc/p2p/base/stunrequest.cc
+++ b/webrtc/p2p/base/stunrequest.cc
@@ -44,7 +44,11 @@
request->set_origin(origin_);
request->Construct();
requests_[request->id()] = request;
- thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL);
+ if (delay > 0) {
+ thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL);
+ } else {
+ thread_->Send(request, MSG_STUN_SEND, NULL);
+ }
}
void StunRequestManager::Remove(StunRequest* request) {
diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc
index 37f0c11..a3e355e 100644
--- a/webrtc/p2p/base/turnport.cc
+++ b/webrtc/p2p/base/turnport.cc
@@ -78,9 +78,11 @@
virtual void OnResponse(StunMessage* response);
virtual void OnErrorResponse(StunMessage* response);
virtual void OnTimeout();
+ void set_lifetime(int lifetime) { lifetime_ = lifetime; }
private:
TurnPort* port_;
+ int lifetime_;
};
class TurnCreatePermissionRequest : public StunRequest,
@@ -212,6 +214,15 @@
TurnPort::~TurnPort() {
// TODO(juberti): Should this even be necessary?
+
+ // release the allocation by sending a refresh with
+ // lifetime 0.
+ if (connected_) {
+ TurnRefreshRequest bye(this);
+ bye.set_lifetime(0);
+ SendRequest(&bye, 0);
+ }
+
while (!entries_.empty()) {
DestroyEntry(entries_.front()->address());
}
@@ -352,6 +363,7 @@
if (!connected_) {
OnAllocateError();
}
+ connected_ = false;
}
void TurnPort::OnAllocateMismatch() {
@@ -1020,13 +1032,19 @@
TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
: StunRequest(new TurnMessage()),
- port_(port) {
+ port_(port),
+ lifetime_(-1) {
}
void TurnRefreshRequest::Prepare(StunMessage* request) {
// Create the request as indicated in RFC 5766, Section 7.1.
// No attributes need to be included.
request->SetType(TURN_REFRESH_REQUEST);
+ if (lifetime_ > -1) {
+ VERIFY(request->AddAttribute(new StunUInt32Attribute(
+ STUN_ATTR_LIFETIME, lifetime_)));
+ }
+
port_->AddRequestAuthInfo(request);
}
diff --git a/webrtc/p2p/base/turnport_unittest.cc b/webrtc/p2p/base/turnport_unittest.cc
index f84d106..da2c6b9 100644
--- a/webrtc/p2p/base/turnport_unittest.cc
+++ b/webrtc/p2p/base/turnport_unittest.cc
@@ -550,6 +550,10 @@
EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+ // Clear connected_ flag on turnport to suppress the release of
+ // the allocation.
+ turn_port_->OnSocketClose(turn_port_->socket(), 0);
+
// Forces the socket server to assign the same port.
ss_->SetNextPortForTesting(first_addr.port());
@@ -575,6 +579,10 @@
EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+ // Clear connected_ flag on turnport to suppress the release of
+ // the allocation.
+ turn_port_->OnSocketClose(turn_port_->socket(), 0);
+
turn_ready_ = false;
CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
@@ -599,6 +607,10 @@
EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+ // Clear connected_ flag on turnport to suppress the release of
+ // the allocation.
+ turn_port_->OnSocketClose(turn_port_->socket(), 0);
+
// Forces the socket server to assign the same port.
ss_->SetNextPortForTesting(first_addr.port());
@@ -747,6 +759,29 @@
EXPECT_EQ(kTestOrigin, turn_server_.FindAllocation(local_address)->origin());
}
+// Test that a TURN allocation is released when the port is closed.
+TEST_F(TurnPortTest, TestTurnReleaseAllocation) {
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ ASSERT_GT(turn_server_.server()->allocations().size(), 0U);
+ turn_port_.reset();
+ EXPECT_EQ_WAIT(0U, turn_server_.server()->allocations().size(), kTimeout);
+}
+
+// Test that a TURN TCP allocation is released when the port is closed.
+TEST_F(TurnPortTest, DISABLED_TestTurnTCPReleaseAllocation) {
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ ASSERT_GT(turn_server_.server()->allocations().size(), 0U);
+ turn_port_.reset();
+ EXPECT_EQ_WAIT(0U, turn_server_.server()->allocations().size(), kTimeout);
+}
+
// This test verifies any FD's are not leaked after TurnPort is destroyed.
// https://code.google.com/p/webrtc/issues/detail?id=2651
#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)