Schedule a CreatePermissionRequest after the success of a previous request

unless a channel binding request is already scheduled.

BUG=5178
R=pthatcher@webrtc.org

Review URL: https://codereview.webrtc.org/1434603002 .

Cr-Commit-Position: refs/heads/master@{#10625}
This commit is contained in:
Honghai Zhang 2015-11-12 11:07:12 -08:00
parent 68876f990e
commit 8597543ae8
5 changed files with 52 additions and 6 deletions

View File

@ -53,6 +53,14 @@ void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
}
}
void StunRequestManager::Flush() {
for (const auto kv : requests_) {
StunRequest* request = kv.second;
thread_->Clear(request, MSG_STUN_SEND);
thread_->Send(request, MSG_STUN_SEND, NULL);
}
}
void StunRequestManager::Remove(StunRequest* request) {
ASSERT(request->manager() == this);
RequestMap::iterator iter = requests_.find(request->id());

View File

@ -32,6 +32,9 @@ class StunRequestManager {
void Send(StunRequest* request);
void SendDelayed(StunRequest* request, int delay);
// Sends all pending requests right away. Only for testing.
void Flush();
// Removes a stun request that was added previously. This will happen
// automatically when a request succeeds, fails, or times out.
void Remove(StunRequest* request);

View File

@ -141,7 +141,7 @@ class TurnEntry : public sigslot::has_slots<> {
BindState state() const { return state_; }
// Helper methods to send permission and channel bind requests.
void SendCreatePermissionRequest();
void SendCreatePermissionRequest(int delay);
void SendChannelBindRequest(int delay);
// Sends a packet to the given destination address.
// This will wrap the packet in STUN if necessary.
@ -1289,12 +1289,12 @@ TurnEntry::TurnEntry(TurnPort* port, int channel_id,
ext_addr_(ext_addr),
state_(STATE_UNBOUND) {
// Creating permission for |ext_addr_|.
SendCreatePermissionRequest();
SendCreatePermissionRequest(0);
}
void TurnEntry::SendCreatePermissionRequest() {
port_->SendRequest(new TurnCreatePermissionRequest(
port_, this, ext_addr_), 0);
void TurnEntry::SendCreatePermissionRequest(int delay) {
port_->SendRequest(new TurnCreatePermissionRequest(port_, this, ext_addr_),
delay);
}
void TurnEntry::SendChannelBindRequest(int delay) {
@ -1337,12 +1337,23 @@ void TurnEntry::OnCreatePermissionSuccess() {
<< " succeeded";
// For success result code will be 0.
port_->SignalCreatePermissionResult(port_, ext_addr_, 0);
// If |state_| is STATE_BOUND, the permission will be refreshed
// by ChannelBindRequest.
if (state_ != STATE_BOUND) {
// Refresh the permission request about 1 minute before the permission
// times out.
int delay = TURN_PERMISSION_TIMEOUT - 60000;
SendCreatePermissionRequest(delay);
LOG_J(LS_INFO, port_) << "Scheduled create-permission-request in "
<< delay << "ms.";
}
}
void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
if (code == STUN_ERROR_STALE_NONCE) {
if (port_->UpdateNonce(response)) {
SendCreatePermissionRequest();
SendCreatePermissionRequest(0);
}
} else {
// Send signal with error code.

View File

@ -132,6 +132,8 @@ class TurnPort : public Port {
// This signal is only for testing purpose.
sigslot::signal3<TurnPort*, const rtc::SocketAddress&, int>
SignalCreatePermissionResult;
// For testing only.
void FlushRequests() { request_manager_.Flush(); }
protected:
TurnPort(rtc::Thread* thread,

View File

@ -715,6 +715,28 @@ TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
TestTurnConnection();
}
// Test that CreatePermissionRequest will be scheduled after the success
// of the first create permission request.
TEST_F(TurnPortTest, TestRefreshCreatePermissionRequest) {
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
ASSERT_TRUE(turn_port_ != NULL);
turn_port_->PrepareAddress();
ASSERT_TRUE_WAIT(turn_ready_, kTimeout);
CreateUdpPort();
udp_port_->PrepareAddress();
ASSERT_TRUE_WAIT(udp_ready_, kTimeout);
Connection* conn = turn_port_->CreateConnection(udp_port_->Candidates()[0],
Port::ORIGIN_MESSAGE);
ASSERT_TRUE(conn != NULL);
ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout);
turn_create_permission_success_ = false;
// A create-permission-request should be pending.
turn_port_->FlushRequests();
ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout);
}
// Do a TURN allocation, establish a UDP connection, and send some data.
TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
// Create ports and prepare addresses.