diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index bc3163de2ee28dc57a8f81a38f41916b97c5327e..05ec6a4d2bcffbfcc5a92de22e77c6d41ee055df 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -371,7 +371,6 @@ JamiAccount::newIncomingCall(const std::string& from, std::weak_ptr<SIPCall> wcall = call; call->setPeerUri(RING_URI_PREFIX + from); call->setPeerNumber(from); - call->updateDetails(details); return call; } @@ -568,8 +567,7 @@ JamiAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std:: requestSIPConnection(toUri, deviceId); }; - for (auto it = sipConns_.begin(); it != sipConns_.end(); ++it) { - auto& [key, value] = *it; + for (auto& [key, value] : sipConns_) { if (key.first != toUri) continue; if (value.empty()) @@ -1729,6 +1727,7 @@ JamiAccount::handlePendingCall(PendingCall& pc, bool incoming) if (!transport) throw std::runtime_error("transport creation failed"); + transport->setAccount(shared()); call->setTransport(transport); if (incoming) { @@ -3735,9 +3734,9 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket, SipConnectionKey key(peerId, deviceId); auto it = sipConns_.find(key); if (it == sipConns_.end()) - it = sipConns_.insert(it, std::make_pair(key, std::vector<SipConnection> {})); + it = sipConns_.emplace(key, std::vector<SipConnection> {}).first; auto& connections = it->second; - auto conn = std::find_if(connections.begin(), connections.end(), [socket](auto v) { + auto conn = std::find_if(connections.begin(), connections.end(), [&](auto v) { return v.channel == socket; }); if (conn != connections.end()) { @@ -3773,6 +3772,7 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket, shared->callConnectionClosed(key.second, false); }; auto sip_tr = link_.sipTransportBroker->getChanneledTransport(socket, std::move(onShutdown)); + sip_tr->setAccount(shared()); // Store the connection connections.emplace_back(SipConnection {sip_tr, socket}); JAMI_WARN("New SIP channel opened with %s", deviceId.to_c_str()); diff --git a/src/sip/siptransport.h b/src/sip/siptransport.h index 9ccd4e51b31c9b43c4bd6c8a7a4872823c303f87..2472a8f3e627a6c9a192450060d2a7a8c2afa576 100644 --- a/src/sip/siptransport.h +++ b/src/sip/siptransport.h @@ -19,8 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef SIPTRANSPORT_H_ -#define SIPTRANSPORT_H_ +#pragma once #ifdef HAVE_CONFIG_H #include "config.h" @@ -53,6 +52,7 @@ struct Certificate; namespace jami { class ChannelSocket; +class SIPAccountBase; using onShutdownCb = std::function<void(void)>; struct TlsListener @@ -115,6 +115,12 @@ public: void setIsIceTransport() { isIceTransport_ = true; } void setIsChanneledTransport() { isChanneledTransport_ = true; } + inline void setAccount(const std::shared_ptr<SIPAccountBase>& account) { + account_ = account; + } + inline const std::weak_ptr<SIPAccountBase>& getAccount() const { + return account_; + } uint16_t getTlsMtu(); @@ -125,8 +131,9 @@ private: std::unique_ptr<pjsip_transport, decltype(deleteTransport)&> transport_; std::shared_ptr<TlsListener> tlsListener_; - std::map<uintptr_t, SipTransportStateCallback> stateListeners_; std::mutex stateListenersMutex_; + std::map<uintptr_t, SipTransportStateCallback> stateListeners_; + std::weak_ptr<SIPAccountBase> account_ {}; bool connected_ {false}; bool isIceTransport_ {false}; @@ -202,5 +209,3 @@ private: }; } // namespace jami - -#endif // SIPTRANSPORT_H_ diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp index d4010ce66d03c95bf36c57db37faa507348fca21..0ef2be8782a38b0a461cd6da3a209fe02f00f4de 100644 --- a/src/sip/sipvoiplink.cpp +++ b/src/sip/sipvoiplink.cpp @@ -165,6 +165,12 @@ try_respond_stateless(pjsip_endpoint* endpt, return !PJ_SUCCESS; } +template <typename T> +bool is_uninitialized(std::weak_ptr<T> const& weak) { + using wt = std::weak_ptr<T>; + return !weak.owner_before(wt{}) && !wt{}.owner_before(weak); +} + static pj_bool_t transaction_request_cb(pjsip_rx_data* rdata) { @@ -213,19 +219,32 @@ transaction_request_cb(pjsip_rx_data* rdata) peerNumber = sip_utils::stripSipUriPrefix(std::string_view(tmp, length)); } - auto account( - Manager::instance().sipVoIPLink().guessAccount(toUsername, viaHostname, remote_hostname)); - if (!account) { - JAMI_ERR("NULL account"); + auto transport = Manager::instance().sipVoIPLink().sipTransportBroker->addTransport( + rdata->tp_info.transport); + + std::shared_ptr<SIPAccountBase> account; + // If transport account is default-constructed, guessing account is allowed + const auto& waccount = transport ? transport->getAccount() : std::weak_ptr<SIPAccountBase>{}; + if (is_uninitialized(waccount)) { + account = Manager::instance().sipVoIPLink().guessAccount(toUsername, viaHostname, remote_hostname); + if (not account) + return PJ_FALSE; + if (not transport and not ::strcmp(account->getAccountType(), SIPAccount::ACCOUNT_TYPE)) { + if (not (transport = std::static_pointer_cast<SIPAccount>(account)->getTransport())) { + JAMI_ERR("No suitable transport to answer this call."); + return PJ_FALSE; + } + JAMI_WARN("Using transport from account."); + } + } else if (!(account = waccount.lock())) { + JAMI_ERR("Dropping SIP request: account is expired."); return PJ_FALSE; } - const auto& account_id = account->getAccountID(); pjsip_msg_body* body = rdata->msg_info.msg->body; if (method->id == PJSIP_OTHER_METHOD) { - pj_str_t* str = &method->name; - std::string_view request(str->ptr, str->slen); + std::string_view request = sip_utils::as_view(method->name); if (request.find("NOTIFY") != std::string_view::npos) { if (body and body->data) { @@ -245,7 +264,7 @@ transaction_request_cb(pjsip_rx_data* rdata) // According to rfc3842 // urgent messages are optional if (ret >= 2) - emitSignal<DRing::CallSignal::VoiceMailNotify>(account_id, + emitSignal<DRing::CallSignal::VoiceMailNotify>(account->getAccountID(), newCount, oldCount, urgentCount); @@ -334,36 +353,21 @@ transaction_request_cb(pjsip_rx_data* rdata) } } - auto transport = Manager::instance().sipVoIPLink().sipTransportBroker->addTransport( - rdata->tp_info.transport); auto call = account->newIncomingCall(std::string(remote_user), {{"AUDIO_ONLY", (hasVideo ? "false" : "true")}}, transport); if (!call) { return PJ_FALSE; } + call->setTransport(transport); // JAMI_DBG("transaction_request_cb viaHostname %s toUsername %s addrToUse %s addrSdp %s // peerNumber: %s" , viaHostname.c_str(), toUsername.c_str(), addrToUse.toString().c_str(), // addrSdp.toString().c_str(), peerNumber.c_str()); - // Append PJSIP transport to the broker's SipTransport list - if (!transport) { - if (not ::strcmp(account->getAccountType(), SIPAccount::ACCOUNT_TYPE)) { - JAMI_WARN("Using transport from account."); - transport = std::static_pointer_cast<SIPAccount>(account)->getTransport(); - } - if (!transport) { - JAMI_ERR("No suitable transport to answer this call."); - return PJ_FALSE; - } - } - call->setTransport(transport); - // FIXME : for now, use the same address family as the SIP transport auto family = pjsip_transport_type_get_af( pjsip_transport_get_type_from_flag(transport->get()->flag)); - IpAddr addrToUse = ip_utils::getInterfaceAddr(account->getLocalInterface(), family); IpAddr addrSdp; if (account->getUPnPActive()) { @@ -373,12 +377,12 @@ transaction_request_cb(pjsip_rx_data* rdata) } else { addrSdp = account->isStunEnabled() or (not account->getPublishedSameasLocal()) ? account->getPublishedIpAddress() - : addrToUse; + : ip_utils::getInterfaceAddr(account->getLocalInterface(), family); } /* fallback on local address */ if (not addrSdp) - addrSdp = addrToUse; + addrSdp = ip_utils::getInterfaceAddr(account->getLocalInterface(), family); // Try to obtain display name from From: header first, fallback on Contact: auto peerDisplayName = sip_utils::parseDisplayName(rdata->msg_info.from); @@ -506,7 +510,7 @@ transaction_request_cb(pjsip_rx_data* rdata) call->setState(Call::ConnectionState::RINGING); - Manager::instance().incomingCall(*call, account_id); + Manager::instance().incomingCall(*call, account->getAccountID()); if (replaced_dlg) { // Get the INVITE session associated with the replaced dialog. @@ -737,25 +741,8 @@ SIPVoIPLink::guessAccount(std::string_view userName, std::shared_ptr<SIPAccountBase> IP2IPAccount; MatchRank best = MatchRank::NONE; - // DHT accounts - for (const auto& account : Manager::instance().getAllAccounts<JamiAccount>()) { - if (!account) - continue; - const MatchRank match(account->matches(userName, server)); - - // return right away if this is a full match - if (match == MatchRank::FULL) { - return account; - } else if (match > best) { - best = match; - result = account; - } - } - // SIP accounts for (const auto& account : Manager::instance().getAllAccounts<SIPAccount>()) { - if (!account) - continue; const MatchRank match(account->matches(userName, server)); // return right away if this is a full match