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
This commit is contained in:
pthatcher@webrtc.org 2015-01-17 00:58:15 +00:00
parent d7de1209ae
commit fe672e3839
3 changed files with 59 additions and 2 deletions

View File

@ -44,7 +44,11 @@ void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
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) {

View File

@ -78,9 +78,11 @@ class TurnRefreshRequest : public StunRequest {
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(rtc::Thread* thread,
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 @@ void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
if (!connected_) {
OnAllocateError();
}
connected_ = false;
}
void TurnPort::OnAllocateMismatch() {
@ -1020,13 +1032,19 @@ void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
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);
}

View File

@ -550,6 +550,10 @@ TEST_F(TurnPortTest, TestTurnAllocateMismatch) {
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 @@ TEST_F(TurnPortTest, TestSharedSocketAllocateMismatch) {
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 @@ TEST_F(TurnPortTest, TestTurnTcpAllocateMismatch) {
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 @@ TEST_F(TurnPortTest, TestOriginHeader) {
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)