From b61c3339cd3c926091cfb34fdbbe07bf994b7dc0 Mon Sep 17 00:00:00 2001
From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
Date: Thu, 5 Mar 2009 11:34:32 -0500
Subject: [PATCH] Fix media port problem; set the session media resulting of
 the sdp negociated

---
 src/audio/audiortp.cpp |  7 ++--
 src/sdp.cpp            | 59 +++++++++++++++++++++-----------
 src/sdp.h              | 25 ++++++--------
 src/sipvoiplink.cpp    | 78 +++++++++++++++++++++++-------------------
 4 files changed, 96 insertions(+), 73 deletions(-)

diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index 7810bc9c5c..c6666e36b0 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -190,10 +190,13 @@ AudioRtpRTX::initAudioRtpSession (void)
 
     try {
         if (_ca == 0) { return; }
-        _audiocodec = Manager::instance().getCodecDescriptorMap().getCodec( _ca->getLocalSDP()->getAudioCodec() );
+        _audiocodec = _ca->getLocalSDP()->get_session_media ();
+
+        if(_audiocodec == 0) { return; }
+
         _codecSampleRate = _audiocodec->getClockRate();	
 
-        remoteIP = _ca->getLocalSDP()->getRemoteIp();
+        remoteIP = _ca->getRemoteIp();
         _debug("Init audio RTP session - remote IP = %s\n", remoteIP.c_str());
         ost::InetHostAddress remote_ip(remoteIP.c_str());
         if (!remote_ip) {
diff --git a/src/sdp.cpp b/src/sdp.cpp
index 6eea13899f..b4b813ada4 100644
--- a/src/sdp.cpp
+++ b/src/sdp.cpp
@@ -32,7 +32,7 @@ static const pj_str_t STR_RTP_AVP = { (char*)"RTP/AVP", 7 };
 static const pj_str_t STR_SDP_NAME = { (char*)"sflphone", 7 };
 static const pj_str_t STR_SENDRECV = { (char*)"sendrecv", 8 };
 
-    Sdp::Sdp( pj_pool_t *pool, int port ) 
+    Sdp::Sdp( pj_pool_t *pool ) 
         : _local_media_cap(), _session_media(0),  _ip_addr( "" ), _local_offer( NULL ), _negociated_offer(NULL), _negociator(NULL), _pool(NULL) 
 {
     _pool = pool;
@@ -55,7 +55,7 @@ void Sdp::set_media_descriptor_line( sdpMedia *media,
     pjmedia_sdp_attr *attr;
     AudioCodec *codec;
     int count, i;
-    std::ostringstream tmp;
+    std::string tmp;
 
     med = PJ_POOL_ZALLOC_T( _pool, pjmedia_sdp_media );
 
@@ -63,7 +63,7 @@ void Sdp::set_media_descriptor_line( sdpMedia *media,
     pj_strdup(_pool, &med->desc.media,
               ( media->get_media_type() == MIME_TYPE_AUDIO ) ? &STR_AUDIO : &STR_VIDEO );
     med->desc.port_count = 1;
-    med->desc.port = 65555; //media->get_port();
+    med->desc.port = media->get_port();
     pj_strdup (_pool, &med->desc.transport, &STR_RTP_AVP);
 
     // Media format ( RTP payload )
@@ -73,8 +73,9 @@ void Sdp::set_media_descriptor_line( sdpMedia *media,
     // add the payload list
     for(i=0; i<count; i++){
         codec = media->get_media_codec_list()[i];
-        tmp << codec->getPayload (); 
-        pj_strdup2( _pool, &med->desc.fmt[i], tmp.str().c_str());
+        tmp = this->convert_int_to_string (codec->getPayload ()); 
+        _debug ("%s\n", tmp.c_str());
+        pj_strdup2( _pool, &med->desc.fmt[i], tmp.c_str());
 
         // Add a rtpmap field for each codec
         // We could add one only for dynamic payloads because the codecs with static RTP payloads
@@ -122,7 +123,6 @@ int Sdp::create_local_offer (){
     //sdp_addAttributes( _pool );
     sdp_add_media_description( );
 
-    _debug ("local port = %i\n", _localAudioPort);
     toString ();
 
     // Validate the sdp session
@@ -192,9 +192,6 @@ void Sdp::sdp_add_origin( void ){
     this->_local_offer->origin.addr = pj_str( (char*)_ip_addr.c_str() );
 }
 
-
-
-
 void Sdp::sdp_add_session_name( void ){
     this->_local_offer->name = STR_SDP_NAME;
 }
@@ -306,6 +303,7 @@ AudioCodec* Sdp::get_session_media( void ){
 void Sdp::toString (void) {
 
     std::ostringstream sdp;
+    int count, i;
 
     sdp <<  "origin= " <<  _local_offer->origin.user.ptr << "\n";
     sdp << "origin.id= " << _local_offer->origin.id << "\n";
@@ -324,11 +322,14 @@ void Sdp::toString (void) {
 
     sdp << "attr_count=" << _local_offer->attr_count << "\n";
     sdp << "media_count=" << _local_offer->media_count << "\n";
-    sdp << "m=" << _local_offer->media[0]->desc.media.ptr << "\n";
-    sdp << "port=" << _local_offer->media[0]->desc.port << "\n";
-    sdp << "transport=" << _local_offer->media[0]->desc.transport.ptr << "\n";
-    sdp << "fmt_count=" << _local_offer->media[0]->desc.fmt_count << "\n";
-    sdp << "fmt=" << _local_offer->media[0]->desc.fmt[0].ptr << "\n";
+    sdp << "m=" << _local_offer->media[0]->desc.media.ptr << " ";
+    sdp << _local_offer->media[0]->desc.port << " ";
+    sdp << _local_offer->media[0]->desc.transport.ptr << " ";
+    count = _local_offer->media[0]->desc.fmt_count;
+    for (i=0; i<count; i++) {
+        sdp << _local_offer->media[0]->desc.fmt[i].ptr << " ";
+    }
+    sdp << "\n";
     
     _debug ("LOCAL SDP: \n%s\n", sdp.str().c_str());
 
@@ -352,13 +353,31 @@ void Sdp::set_local_media_capabilities () {
     selected_codecs = Manager::instance().getCodecDescriptorMap().getActiveCodecs(); 
     codecs_list = Manager::instance().getCodecDescriptorMap().getCodecsMap();
     for (i=0; i<selected_codecs.size(); i++){
-        iter = codecs_list.find(selected_codecs[i]);  
-    
-        if (iter==codecs_list.end())
-            return;
-
-        audio->add_codec (iter->second);
+        iter=codecs_list.find(selected_codecs[i]);  
+        if (iter!=codecs_list.end()){
+            audio->add_codec (iter->second);
+        }
     } 
     _local_media_cap.push_back (audio);
     _debug ("%s\n", audio->to_string ().c_str());
 }
+
+void Sdp::attribute_port_to_all_media (int port) {
+
+    std::vector<sdpMedia*> medias;
+    int i, size;    
+
+    medias = get_local_media_cap (); 
+    size = medias.size();
+
+    for(i=0; i<size; i++) {
+        medias[i]->set_port (port);
+    }   
+
+}
+
+std::string Sdp::convert_int_to_string (int value) {
+    std::ostringstream result;
+    result << value;
+    return result.str();
+}
diff --git a/src/sdp.h b/src/sdp.h
index 07e1c28dee..6bd55777f1 100644
--- a/src/sdp.h
+++ b/src/sdp.h
@@ -52,8 +52,6 @@ class Sdp {
          */
         std::vector<sdpMedia*> get_local_media_cap( void ) { return _local_media_cap; }
 
-        void set_local_media_cap (void);
-
          /*
          *  Read accessor. Get the sdp session information
          *
@@ -142,6 +140,14 @@ class Sdp {
          */
         void set_negociated_offer( const pjmedia_sdp_session *sdp );
 
+        /*
+         * Attribute the specified port to every medias provided
+         * This is valid only because we are using one media
+         * We should change this to support multiple medias
+         *
+         * @param port  The media port
+         */
+        void attribute_port_to_all_media (int port);
 
   ///////////////////////////////////////////////////////////////////////////33
         void  setLocalExternAudioPort(int port){ _localAudioPort = port; }
@@ -150,8 +156,6 @@ class Sdp {
 
         void toString (void);
 
-        AudioCodecType getAudioCodec (void) { return _audioCodec; }
-
         /** 
          * Set remote's IP addr. [not protected]
          * @param ip  The remote IP address
@@ -179,12 +183,6 @@ class Sdp {
         /////////////////////////////////////////////////////////////////////////
 
     private:
-        /** 
-         * Set the audio codec used.  [not protected] 
-         * @param audioCodec  The payload of the codec
-         */
-        void setAudioCodec(AudioCodecType audioCodec) { _audioCodec = audioCodec; }
-
         /** Codec Map */
         std::vector<sdpMedia*> _local_media_cap;
 
@@ -288,19 +286,16 @@ class Sdp {
          */
         void sdp_add_media_description();
 
+        std::string convert_int_to_string (int value);
+
         int _localAudioPort;
 
 //////////////////////////////////////////////////////////////////3
-        /** Codec pointer */
-        AudioCodecType _audioCodec;
-
-
         /** Remote's IP address */
         std::string  _remoteIPAddress;
 
         /** Remote's audio port */
         unsigned int _remoteAudioPort;
-
 ////////////////////////////////////////////////////////////////////
               
 };
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index 6aa49bb68e..d1869d176d 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -39,6 +39,14 @@ void get_remote_sdp_from_offer( pjsip_rx_data *rdata, pjmedia_sdp_session** r_sd
 
 int getModId();
 
+/**
+ *  * Set audio (SDP) configuration for a call
+ *   * localport, localip, localexternalport
+ *    * @param call a SIPCall valid pointer
+ *     * @return bool True
+ *      */
+bool setCallAudioLocal(SIPCall* call, std::string localIP, bool stun, std::string server);
+
 /*
  *  The global pool factory
  */
@@ -70,14 +78,6 @@ pj_thread_desc desc;
  */
 void set_voicemail_info( AccountID account, pjsip_msg_body *body );
 
-/**
- * Set audio (SDP) configuration for a call
- * localport, localip, localexternalport
- * @param call a SIPCall valid pointer
- * @return bool True
- */
-bool setCallAudioLocal(SIPCall* call, std::string localIP, bool stun, std::string server);
-
 // Documentated from the PJSIP Developer's Guide, available on the pjsip website/
 
 /*
@@ -995,29 +995,6 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
             return true;
         }
 
-    bool setCallAudioLocal(SIPCall* call, std::string localIP, bool stun, std::string server) 
-    {
-        // Setting Audio
-        unsigned int callLocalAudioPort = RANDOM_LOCAL_PORT;
-        unsigned int callLocalExternAudioPort = callLocalAudioPort;
-        if (stun) {
-            // If use Stun server
-            if (Manager::instance().behindNat(server, callLocalAudioPort)) {
-                callLocalExternAudioPort = Manager::instance().getFirewallPort();
-            }
-        }
-        _debug("            Setting local audio port to: %d\n", callLocalAudioPort);
-        _debug("            Setting local audio port (external) to: %d\n", callLocalExternAudioPort);
-
-        // Set local audio port for SIPCall(id)
-        call->setLocalIp(localIP);
-        call->setLocalAudioPort(callLocalAudioPort);
-        call->setLocalExternAudioPort(callLocalExternAudioPort);
-        call->getLocalSDP()->setLocalExternAudioPort(callLocalExternAudioPort);
-
-        return true;
-    }
-
     void
         SIPVoIPLink::SIPCallServerFailure(SIPCall *call) 
         {
@@ -1579,19 +1556,25 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
         }
     }
 
-    void call_on_media_update( pjsip_inv_session *inv UNUSED, pj_status_t status UNUSED) {
+    void call_on_media_update( pjsip_inv_session *inv, pj_status_t status) {
         _debug("call_on_media_updated\n");
 
         const pjmedia_sdp_session *r_sdp;
+        SIPCall *call;
 
         if (status != PJ_SUCCESS) {
+            _debug ("Error while negociating the offer\n");
             return;
         }
 
         // Get the new sdp, result of the negociation
         pjmedia_sdp_neg_get_active_local( inv->neg, &r_sdp );
-
+        
+        call = reinterpret_cast<SIPCall *> (inv->mod_data[getModId()]);
         // Clean the resulting sdp offer to create a new one (in case of a reinvite)
+        call->getLocalSDP()->clean_session_media();
+        // Set the fresh negociated one
+        call->getLocalSDP()->set_negociated_offer( r_sdp );
     }
 
     void call_on_forked(pjsip_inv_session *inv, pjsip_event *e){
@@ -1884,13 +1867,13 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
             }
 
             // Have to do some stuff with the SDP
+            // Set the codec map, IP, peer number and so on... for the SIPCall object
+            setCallAudioLocal(call, link->getLocalIPAddress(), link->useStun(), link->getStunServer());
             // We retrieve the remote sdp offer in the rdata struct to begin the negociation
             call->getLocalSDP()->set_ip_address(link->getLocalIPAddress());
             get_remote_sdp_from_offer( rdata, &r_sdp );
             call->getLocalSDP()->receiving_initial_offer( r_sdp );
 
-            // Set the codec map, IP, peer number and so on... for the SIPCall object
-            setCallAudioLocal(call, link->getLocalIPAddress(), link->useStun(), link->getStunServer());
 
             call->setConnectionState(Call::Progressing);
             call->setPeerNumber(peerNumber);
@@ -2344,10 +2327,33 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
             return;
 
         call->getLocalSDP()->receiving_initial_offer( (pjmedia_sdp_session*)offer);
-        _debug("audio codec setté dans l'objet call: %i\n", call->getLocalSDP()->getAudioCodec());
         status=pjsip_inv_set_sdp_answer( call->getInvSession(), call->getLocalSDP()->get_local_sdp_session() );
 #endif
 
     }
 
+bool setCallAudioLocal(SIPCall* call, std::string localIP, bool stun, std::string server) {
+        // Setting Audio
+        unsigned int callLocalAudioPort = RANDOM_LOCAL_PORT;
+        unsigned int callLocalExternAudioPort = callLocalAudioPort;
+        if (stun) {
+            // If use Stun server
+            if (Manager::instance().behindNat(server, callLocalAudioPort)) {
+                callLocalExternAudioPort = Manager::instance().getFirewallPort();
+            }
+        }
+        _debug("            Setting local audio port to: %d\n", callLocalAudioPort);
+        _debug("            Setting local audio port (external) to: %d\n", callLocalExternAudioPort);
+
+        // Set local audio port for SIPCall(id)
+        call->setLocalIp(localIP);
+        call->setLocalAudioPort(callLocalAudioPort);
+        call->setLocalExternAudioPort(callLocalExternAudioPort);
+
+        call->getLocalSDP()->attribute_port_to_all_media (callLocalExternAudioPort);
+
+        return true;
+}
+
+
 
-- 
GitLab