From 48821f50b57c96d27bc6f56d262e9db072e12ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Wed, 28 Jan 2015 11:56:28 -0500 Subject: [PATCH] ringdht: don't prevent call destruction through shared_ptr Refs #64874 Change-Id: If74722be3790971484db74611a139f1022a7b8c1 --- daemon/src/ringdht/ringaccount.cpp | 61 +++++++++++++++++++++--------- daemon/src/ringdht/ringaccount.h | 7 +++- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/daemon/src/ringdht/ringaccount.cpp b/daemon/src/ringdht/ringaccount.cpp index cbdb671129..f52e29856d 100644 --- a/daemon/src/ringdht/ringaccount.cpp +++ b/daemon/src/ringdht/ringaccount.cpp @@ -116,16 +116,19 @@ RingAccount::newIncomingCall(const std::string& from) std::lock_guard<std::mutex> lock(callsMutex_); auto call_it = pendingSipCalls_.begin(); while (call_it != pendingSipCalls_.end()) { - if (call_it->call->getPeerNumber() == from) { - auto call = call_it->call; + auto call = call_it->call.lock(); + if (not call) { + RING_WARN("newIncomingCall: discarding deleted call"); + call_it = pendingSipCalls_.erase(call_it); + } else if (call->getPeerNumber() == from) { pendingSipCalls_.erase(call_it); - RING_WARN("Found matching call for %s", from.c_str()); + RING_DBG("newIncomingCall: found matching call for %s", from.c_str()); return call; } else { ++call_it; } } - RING_ERR("Can't find matching call for %s", from.c_str()); + RING_ERR("newIncomingCall: can't find matching call for %s", from.c_str()); return nullptr; } @@ -173,6 +176,9 @@ RingAccount::newOutgoingCall(const std::string& id, const std::string& toUrl) const dht::Value::Id callvid = std::uniform_int_distribution<dht::Value::Id>{}(rand_); const dht::Value::Id replyvid = callvid+1; + + std::weak_ptr<SIPCall> weak_call = call; + dht_.putEncrypted( callkey, toH, @@ -181,19 +187,23 @@ RingAccount::newOutgoingCall(const std::string& id, const std::string& toUrl) ice->getLocalAttributesAndCandidates(), callvid }, - [callkey, callvid, call, shared](bool ok) { + [callkey, callvid, weak_call, shared](bool ok) { auto& this_ = *std::static_pointer_cast<RingAccount>(shared).get(); if (!ok) { - call->setConnectionState(Call::DISCONNECTED); - Manager::instance().callFailure(*call); + RING_WARN("Can't put ICE descriptor on DHT"); + if (auto call = weak_call.lock()) { + call->setConnectionState(Call::DISCONNECTED); + Manager::instance().callFailure(*call); + call->removeCall(); + } } this_.dht_.cancelPut(callkey, callvid); } ); - dht_.listen( + auto lk = dht_.listen( callkey, - [shared, call, callkey, ice, toH, replyvid] (const std::vector<std::shared_ptr<dht::Value>>& vals) { + [shared, ice, toH, replyvid] (const std::vector<std::shared_ptr<dht::Value>>& vals) { auto& this_ = *std::static_pointer_cast<RingAccount>(shared).get(); RING_DBG("Outcall listen callback (%d values)", vals.size()); for (const auto& v : vals) { @@ -213,7 +223,7 @@ RingAccount::newOutgoingCall(const std::string& id, const std::string& toUrl) ); { std::lock_guard<std::mutex> lock(callsMutex_); - pendingCalls_.emplace_back(PendingCall{std::chrono::steady_clock::now(), ice, call, toH}); + pendingCalls_.emplace_back(PendingCall{std::chrono::steady_clock::now(), ice, weak_call, std::move(lk), callkey, toH}); } return call; } @@ -525,8 +535,14 @@ RingAccount::handleEvents() auto now = std::chrono::steady_clock::now(); auto c = pendingCalls_.begin(); while (c != pendingCalls_.end()) { + auto call = c->call.lock(); + if (not call) { + RING_WARN("Removing deleted call from pending calls"); + dht_.cancelListen(c->call_key, c->listen_key.get()); + c = pendingCalls_.erase(c); + continue; + } auto ice = c->ice.get(); - auto call = c->call.get(); if (ice->isRunning()) { call->setTransport(link_->sipTransport->getIceTransport(c->ice, ICE_COMP_SIP_TRANSPORT)); call->setConnectionState(Call::PROGRESSING); @@ -537,14 +553,18 @@ RingAccount::handleEvents() pendingSipCalls_.splice(pendingSipCalls_.begin(), pendingCalls_, in, c); } else { RING_WARN("ICE succeeded : removing pending outgoing call"); - createOutgoingCall(c->call, c->id.toString(), ice->getRemoteAddress(ICE_COMP_SIP_TRANSPORT)); + createOutgoingCall(call, c->id.toString(), ice->getRemoteAddress(ICE_COMP_SIP_TRANSPORT)); + dht_.cancelListen(c->call_key, c->listen_key.get()); c = pendingCalls_.erase(c); } } else if (ice->isFailed() || now - c->start > std::chrono::seconds(ICE_NEGOTIATION_TIMEOUT)) { RING_WARN("ICE timeout : removing pending outgoing call"); + if (c->id != dht::InfoHash()) + dht_.cancelListen(c->call_key, c->listen_key.get()); call->setConnectionState(Call::DISCONNECTED); Manager::instance().callFailure(*call); c = pendingCalls_.erase(c); + call->removeCall(); } else ++c; } @@ -707,6 +727,8 @@ void RingAccount::doRegister() if (ice->waitForInitialization(ICE_INIT_TIMEOUT) <= 0) throw std::runtime_error("Can't initialize ICE.."); + std::weak_ptr<SIPCall> weak_call = call; + this_.dht_.putEncrypted( listenKey, v->owner.getId(), @@ -715,14 +737,17 @@ void RingAccount::doRegister() ice->getLocalAttributesAndCandidates(), reply_vid }, - [call,ice,shared,listenKey,reply_vid](bool ok) { + [weak_call,ice,shared,listenKey,reply_vid](bool ok) { auto& this_ = *std::static_pointer_cast<RingAccount>(shared).get(); - this_.dht_.cancelPut(listenKey, reply_vid); if (!ok) { - RING_ERR("ICE exchange failed"); - call->setConnectionState(Call::DISCONNECTED); - Manager::instance().callFailure(*call); + RING_WARN("Can't put ICE descriptor on DHT"); + if (auto call = weak_call.lock()) { + call->setConnectionState(Call::DISCONNECTED); + Manager::instance().callFailure(*call); + call->removeCall(); + } } + this_.dht_.cancelPut(listenKey, reply_vid); } ); ice->start(v->data); @@ -730,7 +755,7 @@ void RingAccount::doRegister() call->initRecFilename(from); { std::lock_guard<std::mutex> lock(this_.callsMutex_); - this_.pendingCalls_.emplace_back(PendingCall{std::chrono::steady_clock::now(), ice, call, dht::InfoHash()}); + this_.pendingCalls_.emplace_back(PendingCall{std::chrono::steady_clock::now(), ice, weak_call, {}, {}, {}}); } return true; } catch (const std::exception& e) { diff --git a/daemon/src/ringdht/ringaccount.h b/daemon/src/ringdht/ringaccount.h index 8bf7117fa1..2f3b6b8bc2 100644 --- a/daemon/src/ringdht/ringaccount.h +++ b/daemon/src/ringdht/ringaccount.h @@ -299,11 +299,14 @@ class RingAccount : public SIPAccountBase { struct PendingCall { std::chrono::steady_clock::time_point start; std::shared_ptr<IceTransport> ice; - std::shared_ptr<SIPCall> call; + std::weak_ptr<SIPCall> call; + std::future<size_t> listen_key; + dht::InfoHash call_key; dht::InfoHash id; }; + /** - * DHT calls waiting for negotiation + * DHT calls waiting for ICE negotiation */ std::list<PendingCall> pendingCalls_ {}; /** -- GitLab