| Index: webrtc/p2p/base/turnport.cc
|
| diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc
|
| index 32f63bed2a1064c5609a9664fe4640d784ad98ed..5e88365a83d615bdbc2e19ffe62694444ee20039 100644
|
| --- a/webrtc/p2p/base/turnport.cc
|
| +++ b/webrtc/p2p/base/turnport.cc
|
| @@ -140,6 +140,11 @@ class TurnEntry : public sigslot::has_slots<> {
|
| const rtc::SocketAddress& address() const { return ext_addr_; }
|
| BindState state() const { return state_; }
|
|
|
| + uint32_t destruction_timestamp() { return destruction_timestamp_; }
|
| + void set_destruction_timestamp(uint32_t destruction_timestamp) {
|
| + destruction_timestamp_ = destruction_timestamp;
|
| + }
|
| +
|
| // Helper methods to send permission and channel bind requests.
|
| void SendCreatePermissionRequest(int delay);
|
| void SendChannelBindRequest(int delay);
|
| @@ -160,6 +165,11 @@ class TurnEntry : public sigslot::has_slots<> {
|
| int channel_id_;
|
| rtc::SocketAddress ext_addr_;
|
| BindState state_;
|
| + // A non-zero value indicates that this entry is scheduled to be destroyed.
|
| + // It is also used as an ID of the event scheduling. When the destruction
|
| + // event actually fires, the TurnEntry will be destroyed only if the
|
| + // timestamp here matches the one in the firing event.
|
| + uint32_t destruction_timestamp_ = 0;
|
| };
|
|
|
| TurnPort::TurnPort(rtc::Thread* thread,
|
| @@ -239,7 +249,7 @@ TurnPort::~TurnPort() {
|
| }
|
|
|
| while (!entries_.empty()) {
|
| - DestroyEntry(entries_.front()->address());
|
| + DestroyEntry(entries_.front());
|
| }
|
| if (resolver_) {
|
| resolver_->Destroy(false);
|
| @@ -438,7 +448,7 @@ Connection* TurnPort::CreateConnection(const Candidate& address,
|
| }
|
|
|
| // Create an entry, if needed, so we can get our permissions set up correctly.
|
| - CreateEntry(address.address());
|
| + CreateOrRefreshEntry(address.address());
|
|
|
| // A TURN port will have two candiates, STUN and TURN. STUN may not
|
| // present in all cases. If present stun candidate will be added first
|
| @@ -713,7 +723,6 @@ void TurnPort::OnMessage(rtc::Message* message) {
|
| }
|
| return;
|
| }
|
| -
|
| Port::OnMessage(message);
|
| }
|
|
|
| @@ -898,24 +907,55 @@ TurnEntry* TurnPort::FindEntry(int channel_id) const {
|
| return (it != entries_.end()) ? *it : NULL;
|
| }
|
|
|
| -TurnEntry* TurnPort::CreateEntry(const rtc::SocketAddress& addr) {
|
| - ASSERT(FindEntry(addr) == NULL);
|
| - TurnEntry* entry = new TurnEntry(this, next_channel_number_++, addr);
|
| - entries_.push_back(entry);
|
| - return entry;
|
| +void TurnPort::CreateOrRefreshEntry(const rtc::SocketAddress& addr) {
|
| + TurnEntry* entry = FindEntry(addr);
|
| + if (entry == nullptr) {
|
| + entry = new TurnEntry(this, next_channel_number_++, addr);
|
| + entries_.push_back(entry);
|
| + } else {
|
| + // The channel binding request for the entry will be refreshed automatically
|
| + // until the entry is destroyed.
|
| + CancelEntryDestruction(entry);
|
| + }
|
| }
|
|
|
| -void TurnPort::DestroyEntry(const rtc::SocketAddress& addr) {
|
| - TurnEntry* entry = FindEntry(addr);
|
| +void TurnPort::DestroyEntry(TurnEntry* entry) {
|
| ASSERT(entry != NULL);
|
| entry->SignalDestroyed(entry);
|
| entries_.remove(entry);
|
| delete entry;
|
| }
|
|
|
| +void TurnPort::DestroyEntryIfNotCancelled(TurnEntry* entry,
|
| + uint32_t timestamp) {
|
| + bool cancelled = timestamp != entry->destruction_timestamp();
|
| + if (!cancelled) {
|
| + DestroyEntry(entry);
|
| + }
|
| +}
|
| +
|
| void TurnPort::OnConnectionDestroyed(Connection* conn) {
|
| - // Destroying TurnEntry for the connection, which is already destroyed.
|
| - DestroyEntry(conn->remote_candidate().address());
|
| + // Schedule an event to destroy TurnEntry for the connection, which is
|
| + // already destroyed.
|
| + const rtc::SocketAddress& remote_address = conn->remote_candidate().address();
|
| + TurnEntry* entry = FindEntry(remote_address);
|
| + ASSERT(entry != NULL);
|
| + ScheduleEntryDestruction(entry);
|
| +}
|
| +
|
| +void TurnPort::ScheduleEntryDestruction(TurnEntry* entry) {
|
| + ASSERT(entry->destruction_timestamp() == 0);
|
| + uint32_t timestamp = rtc::Time();
|
| + entry->set_destruction_timestamp(timestamp);
|
| + invoker_.AsyncInvokeDelayed<void>(
|
| + thread(),
|
| + rtc::Bind(&TurnPort::DestroyEntryIfNotCancelled, this, entry, timestamp),
|
| + TURN_PERMISSION_TIMEOUT);
|
| +}
|
| +
|
| +void TurnPort::CancelEntryDestruction(TurnEntry* entry) {
|
| + ASSERT(entry->destruction_timestamp() != 0);
|
| + entry->set_destruction_timestamp(0);
|
| }
|
|
|
| TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
|
|
|