diff --git a/daemon/src/ringdht/ringaccount.cpp b/daemon/src/ringdht/ringaccount.cpp index df72637b99f335f0ad3cb94c5a094cd628155138..192a83da1afb4965496f1e048cf570c7121e788b 100644 --- a/daemon/src/ringdht/ringaccount.cpp +++ b/daemon/src/ringdht/ringaccount.cpp @@ -104,7 +104,6 @@ RingAccount::RingAccount(const std::string& accountID, bool /* presenceEnabled * RingAccount::~RingAccount() { Manager::instance().unregisterEventHandler((uintptr_t)this); - setTransport(); dht_.join(); gnutls_global_deinit(); } @@ -1098,18 +1097,17 @@ std::string RingAccount::getToUri(const std::string& to) const pj_str_t RingAccount::getContactHeader(pjsip_transport* t) { - if (!t && transport_) - t = transport_->get(); if (!t) { - RING_ERR("Transport not created yet"); - pj_cstr(&contact_, "<sips:>"); + RING_ERR("getContactHeader: no SIP transport provided"); + contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE, + "<sips:%s@ring.dht>", + username_.c_str()); return contact_; } // FIXME: be sure that given transport is from SipIceTransport auto tlsTr = reinterpret_cast<tls::SipsIceTransport::TransportData*>(t)->self; auto address = tlsTr->getLocalAddress(); - RING_WARN("getContactHeader %s@%s", username_.c_str(), address.toString(true).c_str()); contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE, "<sips:%s%s%s;transport=%s>", username_.c_str(), diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index 773746a78441fdef7eb665cb0f9e146116ec02ba..38f7597a4a291b32c1f46d58a230a99f4a63a37a 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -273,6 +273,64 @@ SIPAccount::newOutgoingCall(const std::string& toUrl) return call; } +void +SIPAccount::onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info) +{ + pj_status_t currentStatus = transportStatus_; + RING_DBG("Transport state changed to %s for account %s !", SipTransport::stateToStr(state), accountID_.c_str()); + if (!SipTransport::isAlive(transport_, state)) { + if (info) { + char err_msg[128]; + err_msg[0] = '\0'; + pj_str_t descr = pj_strerror(info->status, err_msg, sizeof(err_msg)); + transportStatus_ = info->status; + transportError_ = std::string(descr.ptr, descr.slen); + RING_ERR("Transport disconnected: %.*s", descr.slen, descr.ptr); + } + else { + // This is already the generic error used by pjsip. + transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE; + transportError_ = ""; + } + setRegistrationState(RegistrationState::ERROR_GENERIC); + setTransport(); + } + else { + // The status can be '0', this is the same as OK + transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK; + transportError_ = ""; + } + + // Notify the client of the new transport state + if (currentStatus != transportStatus_) + emitSignal<DRing::ConfigurationSignal::VolatileDetailsChanged>(accountID_, getVolatileAccountDetails()); +} + +void +SIPAccount::setTransport(const std::shared_ptr<SipTransport>& t) +{ + if (t == transport_) + return; + if (transport_) { + RING_DBG("Removing transport from account"); + if (regc_) + pjsip_regc_release_transport(regc_); + transport_->removeStateListener(reinterpret_cast<uintptr_t>(this)); + } + + transport_ = t; + + if (transport_) + transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccount::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2)); +} + +pjsip_tpselector +SIPAccount::getTransportSelector() { + if (!transport_) + return SIPVoIPLink::getTransportSelector(nullptr); + return SIPVoIPLink::getTransportSelector(transport_->get()); +} + std::shared_ptr<Call> SIPAccount::newOutgoingCall(const std::string& toUrl) { @@ -1589,16 +1647,6 @@ computeMd5HashFromCredential(const std::string& username, return std::string(hash, 32); } -void -SIPAccount::setTransport(const std::shared_ptr<SipTransport>& t) -{ - if (transport_ == t) - return; - if (transport_ && regc_) - pjsip_regc_release_transport(regc_); - SIPAccountBase::setTransport(t); -} - void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::string> >& creds) { // we can not authenticate without credentials diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index 30ca4ec03f3b51061b3afbaa41262ffa26bc6dfb..06dcecb5a5ed26d3044190160f17a68887bbc02a 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -437,7 +437,20 @@ class SIPAccount : public SIPAccountBase { return keepAliveEnabled_; } - virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr); + void setTransport(const std::shared_ptr<SipTransport>& = nullptr); + + virtual inline std::shared_ptr<SipTransport> getTransport() { + return transport_; + } + + inline pjsip_transport_type_e getTransportType() const { + return transportType_; + } + + /** + * Shortcut for SipTransport::getTransportSelector(account.getTransport()). + */ + pjsip_tpselector getTransportSelector(); /* Returns true if the username and/or hostname match this account */ MatchRank matches(const std::string &username, const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const; @@ -519,6 +532,12 @@ class SIPAccount : public SIPAccountBase { bool hostnameMatch(const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const; bool proxyMatch(const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const; + /** + * Callback called by the transport layer when the registration + * transport state changes. + */ + virtual void onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info); + struct { pj_bool_t active; /**< Flag of reregister status. */ pj_timer_entry timer; /**< Timer for reregistration. */ diff --git a/daemon/src/sip/sipaccountbase.cpp b/daemon/src/sip/sipaccountbase.cpp index a83978da762ea33cc983ea5917759407cae7cb1e..ae0d93548dff42f10ec30e349d052b37a59f39d0 100644 --- a/daemon/src/sip/sipaccountbase.cpp +++ b/daemon/src/sip/sipaccountbase.cpp @@ -53,9 +53,7 @@ SIPAccountBase::SIPAccountBase(const std::string& accountID) : Account(accountID), link_(getSIPVoIPLink()) {} -SIPAccountBase::~SIPAccountBase() { - setTransport(); -} +SIPAccountBase::~SIPAccountBase() {} template <typename T> static void @@ -253,55 +251,6 @@ SIPAccountBase::getVolatileAccountDetails() const return a; } -void -SIPAccountBase::onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info) -{ - pj_status_t currentStatus = transportStatus_; - RING_DBG("Transport state changed to %s for account %s !", SipTransport::stateToStr(state), accountID_.c_str()); - if (!SipTransport::isAlive(transport_, state)) { - if (info) { - char err_msg[128]; - err_msg[0] = '\0'; - pj_str_t descr = pj_strerror(info->status, err_msg, sizeof(err_msg)); - transportStatus_ = info->status; - transportError_ = std::string(descr.ptr, descr.slen); - RING_ERR("Transport disconnected: %.*s", descr.slen, descr.ptr); - } - else { - // This is already the generic error used by pjsip. - transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE; - transportError_ = ""; - } - setRegistrationState(RegistrationState::ERROR_GENERIC); - setTransport(); - } - else { - // The status can be '0', this is the same as OK - transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK; - transportError_ = ""; - } - - // Notify the client of the new transport state - if (currentStatus != transportStatus_) - emitSignal<DRing::ConfigurationSignal::VolatileDetailsChanged>(accountID_, getVolatileAccountDetails()); -} - -void -SIPAccountBase::setTransport(const std::shared_ptr<SipTransport>& t) -{ - if (t == transport_) - return; - if (transport_) { - RING_DBG("Removing transport from account"); - transport_->removeStateListener(reinterpret_cast<uintptr_t>(this)); - } - - transport_ = t; - - if (transport_) - transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccountBase::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2)); -} - auto SIPAccountBase::getPortsReservation() noexcept -> decltype(getPortsReservation()) { @@ -345,11 +294,4 @@ SIPAccountBase::generateVideoPort() const } #endif -pjsip_tpselector -SIPAccountBase::getTransportSelector() { - if (!transport_) - return SIPVoIPLink::getTransportSelector(nullptr); - return SIPVoIPLink::getTransportSelector(transport_->get()); -} - } // namespace ring diff --git a/daemon/src/sip/sipaccountbase.h b/daemon/src/sip/sipaccountbase.h index ea0ad0f76f3e8f08ab7c5f04cdceb093d48e4173..4607a6ce03742da2fde87b98c64bae3ceb6d86ee 100644 --- a/daemon/src/sip/sipaccountbase.h +++ b/daemon/src/sip/sipaccountbase.h @@ -248,23 +248,10 @@ public: virtual std::string getToUri(const std::string& username) const = 0; - virtual std::string getServerUri() const = 0; - - virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr); - - inline const std::shared_ptr<SipTransport>& getTransport() { - return transport_; - } - - inline pjsip_transport_type_e getTransportType() const { - return transportType_; + virtual inline std::shared_ptr<SipTransport> getTransport() { + return nullptr; } - /** - * Shortcut for SipTransport::getTransportSelector(account.getTransport()). - */ - pjsip_tpselector getTransportSelector(); - /** * Socket port generators for media * Note: given ports are application wide, a port cannot be given again @@ -292,12 +279,6 @@ protected: */ virtual std::map<std::string, std::string> getVolatileAccountDetails() const; - /** - * Callback called by the transport layer when the registration - * transport state changes. - */ - virtual void onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info); - /** * Voice over IP Link contains a listener thread and calls */ diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 01acb7de08b4d5be5dceee87f40aed1e6c72f29b..b80c5d3d94460dcebdb0ba591638e65193384dfc 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -889,10 +889,18 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); const auto& account = call->getSIPAccount(); - + auto family = pj_AF_INET(); // FIXME : for now, use the same address family as the SIP transport - auto family = pjsip_transport_type_get_af(account.getTransportType()); - IpAddr addrToUse = ip_utils::getInterfaceAddr(account.getLocalInterface(), family); + if (auto dlg = inv->dlg) { + if (dlg->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) { + if (auto tr = dlg->tp_sel.u.transport) + family = tr->local_addr.addr.sa_family; + } else if (dlg->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) { + if (auto tr = dlg->tp_sel.u.listener) + family = tr->local_addr.addr.sa_family; + } + } + auto ifaceAddr = ip_utils::getInterfaceAddr(account.getLocalInterface(), family); IpAddr address; if (account.getUPnPActive()) { @@ -901,11 +909,11 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) account.getUPnPIpAddress() : account.getPublishedIpAddress(); } else { address = account.getPublishedSameasLocal() ? - addrToUse : account.getPublishedIpAddress(); + ifaceAddr : account.getPublishedIpAddress(); } /* fallback on local address */ - if (not address) address = addrToUse; + if (not address) address = ifaceAddr; call->setCallMediaLocal(address);