From 5cc1aeb9c4586e7377882bdf7f90d6b1a70251b5 Mon Sep 17 00:00:00 2001 From: Tristan Matthews <tristan.matthews@savoirfairelinux.com> Date: Wed, 19 Sep 2012 14:30:51 -0400 Subject: [PATCH] * #15545: respond to INVITE that has no SDP with an OK that has an SDP --- daemon/src/call.h | 2 -- daemon/src/iax/iaxcall.h | 3 ++- daemon/src/iax/iaxvoiplink.cpp | 2 +- daemon/src/sip/sdp.cpp | 11 ++++++----- daemon/src/sip/sipcall.cpp | 4 ++-- daemon/src/sip/sipcall.h | 6 ++++-- daemon/src/sip/sipvoiplink.cpp | 21 +++++++++++++++++++-- 7 files changed, 34 insertions(+), 15 deletions(-) diff --git a/daemon/src/call.h b/daemon/src/call.h index 281f896724..2a4b8da43b 100644 --- a/daemon/src/call.h +++ b/daemon/src/call.h @@ -173,8 +173,6 @@ class Call : public Recordable { isIPToIP_ = IPToIP; } - virtual void answer() = 0; - /** * Set my IP [not protected] * @param ip The local IP address diff --git a/daemon/src/iax/iaxcall.h b/daemon/src/iax/iaxcall.h index 1cf5233cea..d9dfde7700 100644 --- a/daemon/src/iax/iaxcall.h +++ b/daemon/src/iax/iaxcall.h @@ -71,10 +71,11 @@ class IAXCall : public Call { int getAudioCodec() const; + void answer(); + int format; iax_session* session; private: - virtual void answer(); NON_COPYABLE(IAXCall); }; diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index aaf1333cf2..0518937d6e 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -278,7 +278,7 @@ IAXVoIPLink::answer(Call *call) Manager::instance().addStream(call->getCallId()); mutexIAX_.enter(); - call->answer(); + static_cast<IAXCall*>(call)->answer(); mutexIAX_.leave(); call->setState(Call::ACTIVE); diff --git a/daemon/src/sip/sdp.cpp b/daemon/src/sip/sdp.cpp index 0f54dd6621..1c9a547dba 100644 --- a/daemon/src/sip/sdp.cpp +++ b/daemon/src/sip/sdp.cpp @@ -386,15 +386,16 @@ bool Sdp::createOffer(const vector<int> &selectedCodecs, const vector<map<string, string> > &videoCodecs) { - bool result = true; if (createLocalSession(selectedCodecs, videoCodecs) != PJ_SUCCESS) { ERROR("Failed to create initial offer"); - result = false; - } else if (pjmedia_sdp_neg_create_w_local_offer(memPool_, localSession_, &negotiator_) != PJ_SUCCESS) { + return false; + } + + if (pjmedia_sdp_neg_create_w_local_offer(memPool_, localSession_, &negotiator_) != PJ_SUCCESS) { ERROR("Failed to create an initial SDP negotiator"); - result = false; + return false; } - return result; + return true; } void Sdp::receiveOffer(const pjmedia_sdp_session* remote, diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp index f91a00af42..8359bf2fe3 100644 --- a/daemon/src/sip/sipcall.cpp +++ b/daemon/src/sip/sipcall.cpp @@ -62,10 +62,10 @@ SIPCall::~SIPCall() pj_pool_release(pool_); } -void SIPCall::answer() +void SIPCall::answer(bool needsSdp) { pjsip_tx_data *tdata; - if (pjsip_inv_answer(inv, PJSIP_SC_OK, NULL, NULL, &tdata) != PJ_SUCCESS) + if (pjsip_inv_answer(inv, PJSIP_SC_OK, NULL, needsSdp ? local_sdp_->getLocalSdpSession() : NULL, &tdata) != PJ_SUCCESS) throw std::runtime_error("Could not init invite request answer (200 OK)"); if (pjsip_inv_send_msg(inv, tdata) != PJ_SUCCESS) diff --git a/daemon/src/sip/sipcall.h b/daemon/src/sip/sipcall.h index ba7e5e2878..edd56b6afe 100644 --- a/daemon/src/sip/sipcall.h +++ b/daemon/src/sip/sipcall.h @@ -100,6 +100,10 @@ class SIPCall : public Call { return pool_; } + // @param needsSdp: true if the invite was received without an SDP + // and thus one must been added, false otherwise + void answer(bool needsSdp); + /** * The invite session to be reused in case of transfer */ @@ -114,8 +118,6 @@ class SIPCall : public Call { std::map<std::string, std::string> createHistoryEntry() const; - virtual void answer(); - NON_COPYABLE(SIPCall); /** diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 2c1182b213..6967efe2a4 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -902,7 +902,17 @@ SIPVoIPLink::answer(Call *call) { if (!call) return; - call->answer(); + + SIPCall *sipCall = static_cast<SIPCall*>(call); + bool needsSdp = false; + if (!sipCall->inv->neg) { + WARN("Negotiator is NULL, we've received an INVITE without an SDP"); + pjmedia_sdp_session *dummy; + sdp_create_offer_cb(sipCall->inv, &dummy); + needsSdp = true; + } + + sipCall->answer(needsSdp); } namespace { @@ -946,8 +956,15 @@ SIPVoIPLink::hangup(const std::string& id) pjsip_tx_data *tdata = NULL; + const int status = + inv->state <= PJSIP_INV_STATE_EARLY and inv->role != PJSIP_ROLE_UAC ? + PJSIP_SC_CALL_TSX_DOES_NOT_EXIST : + inv->state >= PJSIP_INV_STATE_DISCONNECTED ? PJSIP_SC_DECLINE : + 0; + + // User hangup current call. Notify peer - if (pjsip_inv_end_session(inv, 0, NULL, &tdata) != PJ_SUCCESS || !tdata) + if (pjsip_inv_end_session(inv, status, NULL, &tdata) != PJ_SUCCESS || !tdata) return; // add contact header -- GitLab