diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp index f11e08d33676b25b36cb05dea314c1fc4fe5f7fe..f66fcde9e7f87488e9864fec22ce1a644e211621 100644 --- a/daemon/src/sip/siptransport.cpp +++ b/daemon/src/sip/siptransport.cpp @@ -72,24 +72,42 @@ SipTransportDescr::toString() const return ss.str(); } -SipTransport::SipTransport(pjsip_transport* t, const std::shared_ptr<TlsListener>& l) : -transport(t), tlsListener(l) +void +SipTransport::deleteTransport(pjsip_transport* t) +{ + pjsip_transport_shutdown(t); + pjsip_transport_dec_ref(t); +} + +SipTransport::SipTransport(pjsip_transport* t) + : transport_(nullptr, deleteTransport) +{ + if (not t or pjsip_transport_add_ref(t) != PJ_SUCCESS) + throw std::runtime_error("invalid transport"); + + // Set pointer here, right after the successful pjsip_transport_add_ref + transport_.reset(t); + + RING_DBG("SipTransport@%p {tr=%p {rc=%u}}", + this, transport_.get(), pj_atomic_get(transport_->ref_cnt)); +} + +SipTransport::SipTransport(pjsip_transport* t, + const std::shared_ptr<TlsListener>& l) + : SipTransport(t) { - pjsip_transport_add_ref(transport); + tlsListener_ = l; } SipTransport::~SipTransport() { - if (transport) { - pjsip_transport_shutdown(transport); - pjsip_transport_dec_ref(transport); // ?? - RING_DBG("Destroying transport (refcount: %u)", pj_atomic_get(transport->ref_cnt)); - transport = nullptr; - } + RING_DBG("~SipTransport@%p {tr=%p {rc=%u}}", + this, transport_.get(), pj_atomic_get(transport_->ref_cnt)); } bool -SipTransport::isAlive(UNUSED const std::shared_ptr<SipTransport>& t, pjsip_transport_state state) +SipTransport::isAlive(UNUSED const std::shared_ptr<SipTransport>& t, + pjsip_transport_state state) { return state != PJSIP_TP_STATE_DISCONNECTED #if PJ_VERSION_NUM > (2 << 24 | 1 << 16) @@ -110,13 +128,14 @@ SipTransport::stateToStr(pjsip_transport_state state) } void -SipTransport::stateCallback(pjsip_transport_state state, const pjsip_transport_state_info *info) +SipTransport::stateCallback(pjsip_transport_state state, + const pjsip_transport_state_info *info) { - std::vector<SipTransportStateCallback> cbs {}; + std::vector<SipTransportStateCallback> cbs; { std::lock_guard<std::mutex> lock(stateListenersMutex_); - cbs.reserve(stateListeners.size()); - for (auto& l : stateListeners) + cbs.reserve(stateListeners_.size()); + for (auto& l : stateListeners_) cbs.push_back(l.second); } for (auto& cb : cbs) @@ -127,16 +146,18 @@ void SipTransport::addStateListener(uintptr_t lid, SipTransportStateCallback cb) { std::lock_guard<std::mutex> lock(stateListenersMutex_); - stateListeners[lid] = cb; + auto pair = stateListeners_.insert(std::make_pair(lid, cb)); + if (not pair.second) + pair.first->second = cb; } bool SipTransport::removeStateListener(uintptr_t lid) { std::lock_guard<std::mutex> lock(stateListenersMutex_); - auto it = stateListeners.find(lid); - if (it != stateListeners.end()) { - stateListeners.erase(it); + auto it = stateListeners_.find(lid); + if (it != stateListeners_.end()) { + stateListeners_.erase(it); return true; } return false; diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h index 9034a76e6704d57e2f596f7b1f9517c9be64f126..803222e1c5221ea2e3908b682bbc0cabd6b3ca6e 100644 --- a/daemon/src/sip/siptransport.h +++ b/daemon/src/sip/siptransport.h @@ -103,37 +103,41 @@ private: pjsip_tpfactory* listener {nullptr}; }; -typedef std::function<void(pjsip_transport_state, const pjsip_transport_state_info*)> SipTransportStateCallback; +using SipTransportStateCallback = std::function<void(pjsip_transport_state, const pjsip_transport_state_info*)>; /** * SIP transport wraps pjsip_transport. */ -struct SipTransport +class SipTransport { - SipTransport() {} - SipTransport(pjsip_transport*, const std::shared_ptr<TlsListener>& l = {}); + public: + SipTransport(pjsip_transport*); + SipTransport(pjsip_transport*, const std::shared_ptr<TlsListener>&); - virtual ~SipTransport(); + ~SipTransport(); - static const char* stateToStr(pjsip_transport_state state); + static const char* stateToStr(pjsip_transport_state state); - void stateCallback(pjsip_transport_state state, const pjsip_transport_state_info *info); + void stateCallback(pjsip_transport_state state, const pjsip_transport_state_info *info); - pjsip_transport* get() { - return transport; - } + pjsip_transport* get() { + return transport_.get(); + } - void addStateListener(uintptr_t lid, SipTransportStateCallback cb); - bool removeStateListener(uintptr_t lid); + void addStateListener(uintptr_t lid, SipTransportStateCallback cb); + bool removeStateListener(uintptr_t lid); - static bool isAlive(const std::shared_ptr<SipTransport>&, pjsip_transport_state state); + static bool isAlive(const std::shared_ptr<SipTransport>&, pjsip_transport_state state); -private: - NON_COPYABLE(SipTransport); - pjsip_transport* transport {nullptr}; - std::shared_ptr<TlsListener> tlsListener {}; - std::map<uintptr_t, SipTransportStateCallback> stateListeners {}; - std::mutex stateListenersMutex_ {}; + private: + NON_COPYABLE(SipTransport); + + static void deleteTransport(pjsip_transport* t); + + std::unique_ptr<pjsip_transport, decltype(deleteTransport)&> transport_; + std::shared_ptr<TlsListener> tlsListener_; + std::map<uintptr_t, SipTransportStateCallback> stateListeners_; + std::mutex stateListenersMutex_; }; class IpAddr;