diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp index f36de9ec2eb8e1288084314a8fdece9d3d7e976c..6ac9f60808d7da7cef7a77f65bbfc3fe78440920 100644 --- a/src/ringdht/ringaccount.cpp +++ b/src/ringdht/ringaccount.cpp @@ -592,30 +592,13 @@ RingAccount::SIPStartCall(const std::shared_ptr<SIPCall>& call, IpAddr target) (int)pjContact.slen, pjContact.ptr, from.c_str(), toUri.c_str(), (int)pjTarget.slen, pjTarget.ptr); - pjsip_dialog *dialog = NULL; - if (pjsip_dlg_create_uac(pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, &pjTarget, &dialog) != PJ_SUCCESS) { - RING_ERR("Unable to create SIP dialogs for user agent client when " - "calling %s", toUri.c_str()); - return false; - } - - pj_str_t subj_hdr_name = CONST_PJ_STR("Subject"); - pjsip_hdr* subj_hdr = (pjsip_hdr*) pjsip_parse_hdr(dialog->pool, &subj_hdr_name, (char *) "Phone call", 10, NULL); - - pj_list_push_back(&dialog->inv_hdr, subj_hdr); - pjsip_inv_session* inv = nullptr; - if (pjsip_inv_create_uac(dialog, call->getSDP().getLocalSdpSession(), 0, &inv) != PJ_SUCCESS) { - RING_ERR("Unable to create invite session for user agent client"); + auto local_sdp = call->getSDP().getLocalSdpSession(); + pjsip_dialog* dialog {nullptr}; + pjsip_inv_session* inv {nullptr}; + if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo, &pjTarget, local_sdp, &dialog, &inv)) return false; - } - - if (!inv) { - RING_ERR("Call invite is not initialized"); - return PJ_FALSE; - } - pjsip_dlg_inc_lock(inv->dlg); inv->mod_data[link_->getModId()] = call.get(); call->inv.reset(inv); diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp index 06a5477f56a7906c309495d530504a908c0d48e5..da6a6fa4e331195b6962ea0a0444d7d9fadb3a08 100644 --- a/src/sip/sipaccount.cpp +++ b/src/sip/sipaccount.cpp @@ -339,31 +339,12 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call) RING_DBG("contact header: %.*s / %s -> %s", (int)pjContact.slen, pjContact.ptr, from.c_str(), toUri.c_str()); - pjsip_dialog *dialog = NULL; - - if (pjsip_dlg_create_uac(pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, NULL, &dialog) != PJ_SUCCESS) { - RING_ERR("Unable to create SIP dialogs for user agent client when " - "calling %s", toUri.c_str()); + auto local_sdp = call->getSDP().getLocalSdpSession(); + pjsip_dialog* dialog {nullptr}; + pjsip_inv_session* inv {nullptr}; + if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo, nullptr, local_sdp, &dialog, &inv)) return false; - } - - auto subj_hdr_name = CONST_PJ_STR("Subject"); - pjsip_hdr* subj_hdr = (pjsip_hdr*) pjsip_parse_hdr(dialog->pool, &subj_hdr_name, (char *) "Phone call", 10, NULL); - - pj_list_push_back(&dialog->inv_hdr, subj_hdr); - - pjsip_inv_session* inv = nullptr; - if (pjsip_inv_create_uac(dialog, call->getSDP().getLocalSdpSession(), 0, &inv) != PJ_SUCCESS) { - RING_ERR("Unable to create invite session for user agent client"); - return false; - } - - if (!inv) { - RING_ERR("Call invite is not initialized"); - return PJ_FALSE; - } - pjsip_dlg_inc_lock(inv->dlg); inv->mod_data[link_->getModId()] = call.get(); call->inv.reset(inv); diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp index 5b516a20145e7fdc2eec2dfe6fa004ace1ea00c4..098995d53fbc39762254ffa14d8bcff05e446e61 100644 --- a/src/sip/sipaccountbase.cpp +++ b/src/sip/sipaccountbase.cpp @@ -40,6 +40,7 @@ #include "client/ring_signal.h" #include "string_utils.h" #include "fileutils.h" +#include "sip_utils.h" #include <type_traits> @@ -53,6 +54,43 @@ SIPAccountBase::SIPAccountBase(const std::string& accountID) SIPAccountBase::~SIPAccountBase() {} +bool +SIPAccountBase::CreateClientDialogAndInvite(const pj_str_t* from, + const pj_str_t* contact, + const pj_str_t* to, + const pj_str_t* target, + const pjmedia_sdp_session* local_sdp, + pjsip_dialog** dlg, + pjsip_inv_session** inv) +{ + if (pjsip_dlg_create_uac(pjsip_ua_instance(), from, contact, to, target, dlg) != PJ_SUCCESS) { + RING_ERR("Unable to create SIP dialogs for user agent client when calling %s", to->ptr); + return false; + } + + auto dialog = *dlg; + + { + // lock dialog until invite session creation; this one will own the dialog after + sip_utils::PJDialogLock dlg_lock {dialog}; + + // Append "Subject: Phone Call" header + auto subj_hdr_name = sip_utils::CONST_PJ_STR("Subject"); + auto subj_hdr = reinterpret_cast<pjsip_hdr*>(pjsip_parse_hdr(dialog->pool, + &subj_hdr_name, + const_cast<char *>("Phone call"), + 10, nullptr)); + pj_list_push_back(&dialog->inv_hdr, subj_hdr); + + if (pjsip_inv_create_uac(dialog, local_sdp, 0, inv) != PJ_SUCCESS) { + RING_ERR("Unable to create invite session for user agent client"); + return false; + } + } + + return true; +} + void SIPAccountBase::flush() { diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h index c6e04c0316e055fa4606d5ac3d6633a42bf9524a..01e538b8630759a15a8dededf4d63f33fbaa8860 100644 --- a/src/sip/sipaccountbase.h +++ b/src/sip/sipaccountbase.h @@ -41,6 +41,10 @@ #include <map> #include <memory> +struct pjsip_dialog; +struct pjsip_inv_session; +struct pjmedia_sdp_session; + namespace ring { namespace Conf { @@ -145,6 +149,19 @@ public: return false; } + /** + * Create UAC attached dialog and invite session + * @return true if success. false if failure and dlg and inv pointers + * should not be considered as valid. + */ + bool CreateClientDialogAndInvite(const pj_str_t* from, + const pj_str_t* contact, + const pj_str_t* to, + const pj_str_t* target, + const pjmedia_sdp_session* local_sdp, + pjsip_dialog** dlg, + pjsip_inv_session** inv); + /** * Get the local interface name on which this account is bound. */ diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index e1b7c94f26deba8e87fa16b41a92e44b3efff4ca..b81b9fb3b5f8edead082d23c75f51f6b0419aff6 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -1101,7 +1101,6 @@ SIPCall::InvSessionDeleter::operator ()(pjsip_inv_session* inv) const noexcept // prevent this from getting accessed in callbacks // RING_WARN: this is not thread-safe! inv->mod_data[getSIPVoIPLink()->getModId()] = nullptr; - pjsip_dlg_dec_lock(inv->dlg); } bool