From 7f3c1b35b54a7af060b3db6185d4d22201efb54f Mon Sep 17 00:00:00 2001
From: Ming Rui Zhang <mingrui.zhang@savoirfairelinux.com>
Date: Tue, 30 Mar 2021 14:53:40 -0400
Subject: [PATCH] sip: refinement for dealing with re-INVITE

Use on_rx_reinvite to send re-INVITE response manually

Gitlab: #499

Change-Id: Ia6127f84933708786441f08e26ae4038f41026bc
---
 src/sip/sipcall.cpp     | 45 ++++++++++++++++++++++++++++++++++++-----
 src/sip/sipcall.h       |  3 ++-
 src/sip/sipvoiplink.cpp | 18 ++++++++++-------
 3 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index f294671524..ab3ad8e823 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -41,6 +41,7 @@
 #include "dring/media_const.h"
 #include "client/ring_signal.h"
 #include "ice_transport.h"
+#include "pjsip-ua/sip_inv.h"
 
 #ifdef ENABLE_PLUGIN
 #include "plugin/jamipluginmanager.h"
@@ -1485,17 +1486,18 @@ SIPCall::onIceNegoSucceed()
     startAllMedia();
 }
 
-void
-SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer)
+int
+SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* rdata)
 {
     if (!sdp_)
-        return;
+        return !PJ_SUCCESS;
     sdp_->clearIce();
     auto acc = getSIPAccount();
     if (!acc) {
         JAMI_ERR("No account detected");
-        return;
+        return !PJ_SUCCESS;
     }
+
     sdp_->receiveOffer(offer,
                        acc->getActiveAccountCodecInfoList(MEDIA_AUDIO),
                        acc->getActiveAccountCodecInfoList(acc->isVideoEnabled() ? MEDIA_VIDEO
@@ -1504,8 +1506,41 @@ SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer)
                        getState() == CallState::HOLD);
     setRemoteSdp(offer);
     sdp_->startNegotiation();
-    pjsip_inv_set_sdp_answer(inviteSession_.get(), sdp_->getLocalSdpSession());
+
+    pjsip_tx_data* tdata = nullptr;
+
+    if (pjsip_inv_initial_answer(inviteSession_.get(),
+                                 const_cast<pjsip_rx_data*>(rdata),
+                                 PJSIP_SC_OK,
+                                 NULL,
+                                 NULL,
+                                 &tdata)
+        != PJ_SUCCESS) {
+        JAMI_ERR("Could not create initial answer OK");
+        return !PJ_SUCCESS;
+    }
+
+    // Add user-agent header
+    sip_utils::addUserAgentHeader(getSIPAccount()->getUserAgentName(), tdata);
+
+    if (pjsip_inv_answer(inviteSession_.get(), PJSIP_SC_OK, NULL, sdp_->getLocalSdpSession(), &tdata)
+        != PJ_SUCCESS) {
+        JAMI_ERR("Could not create answer OK");
+        return !PJ_SUCCESS;
+    }
+
+    // ContactStr must stay in scope as long as tdata
+    const pj_str_t contactStr(getSIPAccount()->getContactHeader(getTransport()->get()));
+    sip_utils::addContactHeader(&contactStr, tdata);
+
+    if (pjsip_inv_send_msg(inviteSession_.get(), tdata) != PJ_SUCCESS) {
+        JAMI_ERR("Could not send msg OK");
+        return !PJ_SUCCESS;
+    }
+
     openPortsUPnP();
+
+    return PJ_SUCCESS;
 }
 
 void
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index d41676304e..f71ceb1a97 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -51,6 +51,7 @@ struct pjsip_evsub;
 struct pjsip_inv_session;
 struct pjmedia_sdp_session;
 struct pj_ice_sess_cand;
+struct pjsip_rx_data;
 }
 
 namespace jami {
@@ -167,7 +168,7 @@ public:
      */
     void onClosed();
 
-    void onReceiveOffer(const pjmedia_sdp_session* offer);
+    int onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* rdata);
 
     void onMediaUpdate();
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index f3fd9f6092..a5ef89708a 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -75,8 +75,10 @@ static pjsip_endpoint* endpt_;
 static pjsip_module mod_ua_;
 
 static void sdp_media_update_cb(pjsip_inv_session* inv, pj_status_t status);
-static void sdp_request_offer_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer);
 static void sdp_create_offer_cb(pjsip_inv_session* inv, pjmedia_sdp_session** p_offer);
+static pj_status_t reinvite_received_cb(pjsip_inv_session* inv,
+                                        const pjmedia_sdp_session* offer,
+                                        pjsip_rx_data* rdata);
 static void invite_session_state_changed_cb(pjsip_inv_session* inv, pjsip_event* e);
 static void outgoing_request_forked_cb(pjsip_inv_session* inv, pjsip_event* e);
 static void transaction_state_changed_cb(pjsip_inv_session* inv,
@@ -665,12 +667,12 @@ SIPVoIPLink::SIPVoIPLink()
         = { invite_session_state_changed_cb,
             outgoing_request_forked_cb,
             transaction_state_changed_cb,
-            sdp_request_offer_cb,
+            nullptr /* on_rx_offer */,
 #if PJ_VERSION_NUM >= (2 << 24 | 7 << 16)
             nullptr /* on_rx_offer2 */,
 #endif
 #if PJ_VERSION_NUM > (2 << 24 | 1 << 16)
-            nullptr /* on_rx_reinvite */,
+            reinvite_received_cb,
 #endif
             sdp_create_offer_cb,
             sdp_media_update_cb,
@@ -921,11 +923,13 @@ invite_session_state_changed_cb(pjsip_inv_session* inv, pjsip_event* ev)
     }
 }
 
-static void
-sdp_request_offer_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer)
+static pj_status_t
+reinvite_received_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer, pjsip_rx_data* rdata)
 {
-    if (auto call = getCallFromInvite(inv))
-        call->onReceiveOffer(offer);
+    if (auto call = getCallFromInvite(inv)) {
+        return call->onReceiveOffer(offer, rdata);
+    }
+    return !PJ_SUCCESS;
 }
 
 static void
-- 
GitLab