From 39c084ffb7cff4e33256a0c843461b4300c5e816 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Date: Wed, 20 Apr 2011 18:33:34 -0400
Subject: [PATCH] [#5571] Move attribute handling for onhold/offhold actions in
 SDP session

---
 .../src/audio/audiortp/AudioRtpFactory.cpp    |   4 +-
 sflphone-common/src/sip/sdp.cpp               |  15 ++
 sflphone-common/src/sip/sdp.h                 |  44 +++--
 sflphone-common/src/sip/sipvoiplink.cpp       | 175 +++++++++---------
 sflphone-common/src/sip/sipvoiplink.h         |   8 +-
 5 files changed, 139 insertions(+), 107 deletions(-)

diff --git a/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp b/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp
index cc52b96c63..8c8d54d1db 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp
+++ b/sflphone-common/src/audio/audiortp/AudioRtpFactory.cpp
@@ -127,7 +127,7 @@ void AudioRtpFactory::initAudioRtpSession (SIPCall * ca)
                 if (_helloHashEnabled) {
                     // TODO: be careful with that. The hello hash is computed asynchronously. Maybe it's
                     // not even available at that point.
-                    ca->getLocalSDP()->set_zrtp_hash (static_cast<AudioZrtpSession *> (_rtpSession)->getHelloHash());
+                    ca->getLocalSDP()->setZrtpHash (static_cast<AudioZrtpSession *> (_rtpSession)->getHelloHash());
                     _debug ("AudioRtpFactory: Zrtp hello hash fed to SDP");
                 }
 
@@ -320,7 +320,7 @@ void sfl::AudioRtpFactory::initLocalCryptoInfo (SIPCall * ca)
     if (_rtpSession && _rtpSessionType && (_rtpSessionType == Sdes)) {
         static_cast<AudioSrtpSession *> (_rtpSession)->initLocalCryptoInfo ();
 
-        ca->getLocalSDP()->set_srtp_crypto (static_cast<AudioSrtpSession *> (_rtpSession)->getLocalCryptoInfo());
+        ca->getLocalSDP()->setLocalSdpCrypto (static_cast<AudioSrtpSession *> (_rtpSession)->getLocalCryptoInfo());
     }
 }
 
diff --git a/sflphone-common/src/sip/sdp.cpp b/sflphone-common/src/sip/sdp.cpp
index b921c47e2d..5a5d62532b 100644
--- a/sflphone-common/src/sip/sdp.cpp
+++ b/sflphone-common/src/sip/sdp.cpp
@@ -717,6 +717,21 @@ void Sdp::setPortToAllMedia (int port)
     }
 }
 
+void Sdp::addAttributeToLocalAudioMedia(std::string attr)
+{
+    pjmedia_sdp_attr *attribute;
+
+    attribute = pjmedia_sdp_attr_create (memPool, attr.c_str(), NULL);
+
+	pjmedia_sdp_media_add_attr (getLocalSdpSession()->media[0], attribute);
+}
+
+void Sdp::removeAttributeFromLocalAudioMedia(std::string attr)
+{
+	pjmedia_sdp_media_remove_all_attr (getLocalSdpSession()->media[0], attr.c_str());
+
+}
+
 std::string Sdp::convertIntToString (int value)
 {
     std::ostringstream result;
diff --git a/sflphone-common/src/sip/sdp.h b/sflphone-common/src/sip/sdp.h
index e44fcf5fa3..73ccecb185 100644
--- a/sflphone-common/src/sip/sdp.h
+++ b/sflphone-common/src/sip/sdp.h
@@ -282,30 +282,52 @@ class Sdp
             return remoteAudioPort;
         }
 
-        std::vector<sdpMedia*> getSessionMediaList (void) {
+        /**
+         * Get media list for this session
+         */
+        SdpMediaList getSessionMediaList (void) {
             return sessionAudioMedia;
         }
 
+        /**
+         *
+         */
+        void addAttributeToLocalAudioMedia(std::string);
+
+        /**
+         *
+         */
+        void removeAttributeFromLocalAudioMedia(std::string);
+
+
+        /**
+         * Get SRTP master key
+         * @param remote sdp session
+         * @param crypto offer
+         */
         void getRemoteSdpCryptoFromOffer (const pjmedia_sdp_session* remote_sdp, CryptoOffer& crypto_offer);
 
+        /**
+         * Set the SRTP master_key
+         * @param mk The Master Key of a srtp session.
+         */
+        inline void setLocalSdpCrypto (const std::vector<std::string> lc) {
+            srtpCrypto = lc;
+        }
 
-        /* Set the zrtp hash that was previously calculated from the hello message in the zrtp layer.
+        /**
+         * Set the zrtp hash that was previously calculated from the hello message in the zrtp layer.
          * This hash value is unique at the media level. Therefore, if video support is added, one would
          * have to set the correct zrtp-hash value in the corresponding media section.
          * @param hash The hello hash of a rtp session. (Only audio at the moment)
          */
-        inline void set_zrtp_hash (const std::string& hash) {
+        inline void setZrtpHash (const std::string& hash) {
             zrtpHelloHash = hash;
-            _debug ("Zrtp hash set with %s\n", hash.c_str());
-        }
-
-        /* Set the srtp _master_key
-             * @param mk The Master Key of a srtp session.
-             */
-        inline void set_srtp_crypto (const std::vector<std::string> lc) {
-            srtpCrypto = lc;
         }
 
+        /**
+         * Print internal state info
+         */
         void toString (void);
 
 
diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp
index 87a501d4b8..9302e9c9ef 100644
--- a/sflphone-common/src/sip/sipvoiplink.cpp
+++ b/sflphone-common/src/sip/sipvoiplink.cpp
@@ -897,35 +897,109 @@ SIPVoIPLink::cancel (const CallID& id)
     return true;
 }
 
+
 bool
 SIPVoIPLink::onhold (const CallID& id)
 {
-
+	Sdp *sdpSession;
     pj_status_t status;
     SIPCall* call;
 
     call = getSIPCall (id);
 
-    if (call==0) {
-        _debug ("! SIP Error: call doesn't exist");
+    if (call == NULL) {
+        _debug ("UserAgent: Error: call doesn't exist in onhold action");
         return false;
     }
 
-
     // Stop sound
     call->setAudioStart (false);
-
     call->setState (Call::Hold);
+    call->getAudioRtp()->stop();
 
-    _debug ("* SIP Info: Stopping AudioRTP for onhold action");
+    _debug ("UserAgent: Stopping RTP session for on hold action");
 
-    call->getAudioRtp()->stop();
+    if ( (sdpSession = call->getLocalSDP()) == NULL) {
+        _debug ("UserAgent: Error: Unable to find local sdp");
+        return false;
+    }
+
+    sdpSession->removeAttributeFromLocalAudioMedia("sendrecv");
+    sdpSession->removeAttributeFromLocalAudioMedia("sendonly");
+
+    sdpSession->addAttributeToLocalAudioMedia("sendonly");
+
+    // Create re-INVITE with new offer
+    status = SIPSessionReinvite (call);
+
+    if (status != PJ_SUCCESS) {
+        return false;
+    }
+
+    return true;
+}
+
+bool
+SIPVoIPLink::offhold (const CallID& id)
+{
+	Sdp *sdpSession;
+    pj_status_t status;
+    SIPCall *call;
+
+    _debug ("UserAgent: retrive call from hold status");
+
+    call = getSIPCall (id);
+
+    if (call==0) {
+        _debug ("! SIP Error: Call doesn't exist");
+        return false;
+    }
+
+    if ( (sdpSession = call->getLocalSDP()) == NULL) {
+        _debug ("UserAgent: Error: Unable to find local sdp");
+        return false;
+    }
+
+    // Retreive previously selected codec
+    sfl::Codec *sessionMedia = sdpSession->getSessionMedia();
+
+    if (!sessionMedia) {
+        return false;
+    }
+
+    // Get PayloadType for this codec
+    AudioCodecType pl = (AudioCodecType) sessionMedia->getPayloadType();
+
+    _debug ("UserAgent: Payload from session media %d", pl);
+
+    try {
+        // Create a new instance for this codec
+        sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl);
+
+        if (audiocodec == NULL)
+            _error ("UserAgent: No audiocodec found");
+
+        call->getAudioRtp()->initAudioRtpConfig (call);
+        call->getAudioRtp()->initAudioRtpSession (call);
+        call->getAudioRtp()->start (static_cast<AudioCodec *>(audiocodec));
+
+    } catch (...) {
+        _debug ("! SIP Failure: Unable to create RTP Session (%s:%d)", __FILE__, __LINE__);
+    }
+
+    sdpSession->removeAttributeFromLocalAudioMedia("sendrecv");
+    sdpSession->removeAttributeFromLocalAudioMedia("sendonly");
+
+    sdpSession->addAttributeToLocalAudioMedia("sendrecv");
 
     /* Create re-INVITE with new offer */
-    status = SIPInvSessionReinvite (call, "sendonly");
+    status = SIPSessionReinvite (call);
 
-    if (status != PJ_SUCCESS)
+    if (status != PJ_SUCCESS) {
         return false;
+    }
+
+    call->setState (Call::Active);
 
     return true;
 }
@@ -968,14 +1042,12 @@ SIPVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string&
     return status;
 }
 
-int SIPVoIPLink::SIPInvSessionReinvite (SIPCall *call, std::string direction)
+int SIPVoIPLink::SIPSessionReinvite (SIPCall *call)
 {
 
     pj_status_t status;
     pjsip_tx_data *tdata;
     pjmedia_sdp_session *local_sdp;
-    pjmedia_sdp_attr *attr;
-    pj_pool_t *call_memory_pool;
 
     if (call == NULL) {
         _error ("UserAgent: Error: Call is NULL in session reinvite");
@@ -987,32 +1059,8 @@ int SIPVoIPLink::SIPInvSessionReinvite (SIPCall *call, std::string direction)
         return !PJ_SUCCESS;
     }
 
-    if ( (call_memory_pool = call->getLocalSDP()->getMemoryPool()) == NULL) {
-        _debug ("UserAgent: Error: Unable to find call memory pool");
-        return !PJ_SUCCESS;
-    }
-
-    // Reinvite only if connected
-    // Build the local SDP offer
-    // TODO Restore Re-Invite
-    // status = call->getLocalSDP()->create_initial_offer();
-
-    // if (status != PJ_SUCCESS)
-    // return 1;   // !PJ_SUCCESS
-
-
-    pjmedia_sdp_media_remove_all_attr (local_sdp->media[0], "sendrecv");
-    pjmedia_sdp_media_remove_all_attr (local_sdp->media[0], "sendonly");
-
-    attr = pjmedia_sdp_attr_create (call_memory_pool, direction.c_str(), NULL);
-
-    pjmedia_sdp_media_add_attr (local_sdp->media[0], attr);
-
-    // pjmedia_sdp_neg_modify_local_offer (_pool, call->getLocalSDP()->_negociator, local_sdp);
-
     // Build the reinvite request
-    status = pjsip_inv_reinvite (call->getInvSession(), NULL,
-                                 local_sdp, &tdata);
+    status = pjsip_inv_reinvite (call->getInvSession(), NULL, local_sdp, &tdata);
 
     if (status != PJ_SUCCESS)
         return 1;   // !PJ_SUCCESS
@@ -1026,59 +1074,6 @@ int SIPVoIPLink::SIPInvSessionReinvite (SIPCall *call, std::string direction)
     return PJ_SUCCESS;
 }
 
-
-bool
-SIPVoIPLink::offhold (const CallID& id)
-{
-    SIPCall *call;
-    pj_status_t status;
-
-    _debug ("UserAgent: retrive call from hold status");
-
-    call = getSIPCall (id);
-
-    if (call==0) {
-        _debug ("! SIP Error: Call doesn't exist");
-        return false;
-    }
-
-    // Retreive previously selected codec
-    sfl::Codec *sessionMedia = call->getLocalSDP()->getSessionMedia();
-
-    if (!sessionMedia)
-        return false;
-
-    // Get PayloadType for this codec
-    AudioCodecType pl = (AudioCodecType) sessionMedia->getPayloadType();
-
-    _debug ("UserAgent: Payload from session media %d", pl);
-
-    try {
-        // Create a new instance for this codec
-        sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl);
-
-        if (audiocodec == NULL)
-            _error ("UserAgent: No audiocodec found");
-
-        call->getAudioRtp()->initAudioRtpConfig (call);
-        call->getAudioRtp()->initAudioRtpSession (call);
-        call->getAudioRtp()->start (static_cast<AudioCodec *>(audiocodec));
-
-    } catch (...) {
-        _debug ("! SIP Failure: Unable to create RTP Session (%s:%d)", __FILE__, __LINE__);
-    }
-
-    /* Create re-INVITE with new offer */
-    status = SIPInvSessionReinvite (call, "sendrecv");
-
-    if (status != PJ_SUCCESS)
-        return false;
-
-    call->setState (Call::Active);
-
-    return true;
-}
-
 bool
 SIPVoIPLink::transfer (const CallID& id, const std::string& to)
 {
diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h
index 76fc825538..abcd552abb 100644
--- a/sflphone-common/src/sip/sipvoiplink.h
+++ b/sflphone-common/src/sip/sipvoiplink.h
@@ -300,18 +300,18 @@ class SIPVoIPLink : public VoIPLink
         /**
          * Handle a re-invite request by the remote peer.
          * A re-invite is an invite request inside a dialog.
-         * When receiving a re-invite, we close the current rtp session and create
-         * a new one with the updated information
+         * When receiving a re-invite, we updated information
+         * concerning medias
          * @param sip call
          */
         void SIPHandleReinvite (SIPCall *call);
 
         /**
          * Send a reINVITE inside an active dialog to modify its state
+         * Local SDP session should be modified before calling this method
          * @param sip call
-         * @param the direction, "sendrecv" or "sendonly"
          */
-        int SIPInvSessionReinvite (SIPCall *call, std::string direction="");
+        int SIPSessionReinvite (SIPCall *call);
 
         pj_caching_pool *getMemoryPoolFactory();
 
-- 
GitLab