Module: sems
Branch: master
Commit: fd592729478cd1bf2899eecb06af0c77806f720c
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=fd592729478cd1bf2899eecb06af0c77806f720c

Author: Raphael Coeffic <[email protected]>
Committer: Raphael Coeffic <[email protected]>
Date:   Tue Dec 13 15:06:36 2011 +0100

adds support for sendrecv/sendonly/recvonly/inactive SDP attributes

Also re-enabled support for 'hold' and 'mute'
- 'hold' in set by application via setOnHold(). It is not touched by any 
attribute received in SDP.
- 'mute' is set according to attributes received in SDP.

'send' and 'recv' attributes in SDP are mirrored based on SDP received and 
overridden by application settings. 

For example:
- if remote SDP says 'sendrecv', but local is 'on_hold', we reply with 
'sendonly'.
- if remote SDP says 'sendonly', but local is NOT 'on_hold', we reply with 
'recvonly'.

---

 core/AmRtpStream.cpp |   50 ++++++++++++++++++++++++++++++--------------------
 core/AmRtpStream.h   |    3 +++
 core/AmSdp.cpp       |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
 core/AmSdp.h         |   11 ++++++++---
 core/AmSession.cpp   |    8 +++++++-
 5 files changed, 94 insertions(+), 27 deletions(-)

diff --git a/core/AmRtpStream.cpp b/core/AmRtpStream.cpp
index c370554..8bece6b 100644
--- a/core/AmRtpStream.cpp
+++ b/core/AmRtpStream.cpp
@@ -550,12 +550,19 @@ void AmRtpStream::setPassiveMode(bool p)
   DBG("The other UA is NATed: switched to passive mode.\n");
 }
 
+void AmRtpStream::getSdp(SdpMedia& m)
+{
+  m.port = getLocalPort();
+  m.nports = 0;
+  m.transport = TP_RTPAVP;
+  m.send = !hold;
+  m.recv = receiving;
+  m.dir = SdpMedia::DirBoth;
+}
+
 void AmRtpStream::getSdpOffer(SdpMedia& offer)
 {
-  offer.port = getLocalPort();
-  offer.nports = 0;
-  offer.transport = TP_RTPAVP;
-  offer.dir = SdpMedia::DirBoth;
+  getSdp(offer);
 
   // TODO: transfer ownership of the payload provider also into AmRtpStream
   session->getPayloadProvider()->getPayloads(offer.payloads);
@@ -563,21 +570,7 @@ void AmRtpStream::getSdpOffer(SdpMedia& offer)
 
 void AmRtpStream::getSdpAnswer(const SdpMedia& offer, SdpMedia& answer)
 {
-  answer.port = getLocalPort();
-  answer.nports = 0;
-  answer.transport = TP_RTPAVP;
-
-  switch(offer.dir){
-  case SdpMedia::DirBoth:
-    answer.dir = SdpMedia::DirBoth;
-    break;
-  case SdpMedia::DirActive:
-    answer.dir = SdpMedia::DirPassive;
-    break;
-  case SdpMedia::DirPassive:
-    answer.dir = SdpMedia::DirActive;
-    break;
-  }
+  getSdp(answer);
 
   // TODO: transfer ownership of the payload provider also into AmRtpStream
   offer.calcAnswer(session->getPayloadProvider(),answer);
@@ -682,7 +675,24 @@ int AmRtpStream::init(AmPayloadProviderInterface* 
payload_provider,
 
   local_telephone_event_pt.reset(local.telephoneEventPayload());
 
-  resume();
+  if(remote_media.send) {
+    resume();
+  }
+  else {
+    pause();
+  }
+
+  if(remote_media.recv && !hold
+     && (remote_media.port != 0)
+#ifndef SUPPORT_IPV6
+     && (r_saddr.sin_addr.s_addr != 0)
+#endif
+     ) {
+    mute = false;
+  }
+  else {
+    mute = true;
+  }
 
 #ifdef WITH_ZRTP  
   if( session->zrtp_audio  ) {
diff --git a/core/AmRtpStream.h b/core/AmRtpStream.h
index 8aa3174..a006d0a 100644
--- a/core/AmRtpStream.h
+++ b/core/AmRtpStream.h
@@ -198,6 +198,9 @@ protected:
 
   void relay(AmRtpPacket* p);
 
+  /** Sets generic parameters on SDP media */
+  void getSdp(SdpMedia& m);
+
 public:
 
   AmRtpPacket* newPacket();
diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp
index d5b2ac0..6a3859f 100644
--- a/core/AmSdp.cpp
+++ b/core/AmSdp.cpp
@@ -223,6 +223,23 @@ void AmSdp::print(string& body) const
       default: break;
       }
 
+      if(media_it->send){
+       if(media_it->recv){
+         out_buf += "a=sendrecv\r\n";
+       }
+       else {
+         out_buf += "a=sendonly\r\n";
+       }
+      }
+      else {
+       if(media_it->recv){
+         out_buf += "a=recvonly\r\n";
+       }
+       else {
+         out_buf += "a=inactive\r\n";
+       }
+      }
+
       // add attributes (media level)
       for (std::vector<SdpAttribute>::const_iterator a_it=
             media_it->attributes.begin(); a_it != media_it->attributes.end(); 
a_it++) {
@@ -279,6 +296,21 @@ void AmSdp::clear()
 void SdpMedia::calcAnswer(const AmPayloadProviderInterface* payload_prov,
                          SdpMedia& answer) const
 {
+  if(!recv) answer.send = false;
+  if(!send) answer.recv = false;
+
+  switch(dir){
+  case SdpMedia::DirBoth:
+    answer.dir = SdpMedia::DirBoth;
+    break;
+  case SdpMedia::DirActive:
+    answer.dir = SdpMedia::DirPassive;
+    break;
+  case SdpMedia::DirPassive:
+    answer.dir = SdpMedia::DirActive;
+    break;
+  }
+
   // Calculate the intersection with the offered set of payloads
   vector<SdpPayload>::const_iterator it = payloads.begin();
   for(; it!= payloads.end(); ++it) {
@@ -306,7 +338,7 @@ void SdpMedia::calcAnswer(const AmPayloadProviderInterface* 
payload_prov,
                it->encoding_name,it->clock_rate,it->encoding_param));
       }
     }
-  }  
+  }
 }
 
 //parser
@@ -883,8 +915,19 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
            DBG("found media attr 'direction', but value is not"
                " followed by cr\n");
        }
-
-    }else{
+    } else if (attr == "sendrecv") {
+      media.send = true;
+      media.recv = true;
+    } else if (attr == "sendonly") {
+      media.send = true;
+      media.recv = false;
+    } else if (attr == "recvonly") {
+      media.send = false;
+      media.recv = true;
+    } else if (attr == "inactive") {
+      media.send = false;
+      media.recv = false;
+    } else {
       attr_check(attr);
       next = parse_until(attr_line, '\r');
       if(next < line_end){
diff --git a/core/AmSdp.h b/core/AmSdp.h
index fa9116a..4bbdc6e 100644
--- a/core/AmSdp.h
+++ b/core/AmSdp.h
@@ -141,15 +141,20 @@ struct SdpMedia
   SdpConnection conn; // c=
   Direction     dir;  // a=direction
 
+  // sendrecv|sendonly|recvonly|inactive
+  bool          send;
+  bool          recv;
+
   std::vector<SdpPayload> payloads;
 
   std::vector<SdpAttribute> attributes; // unknown attributes
 
-  SdpMedia() : conn() {}
+  SdpMedia() : conn(),send(true),recv(true) {}
 
   /**
-   * Checks which payloads are compatible with the payload provider
-   * and inserts them into the answer.
+   * Checks which payloads are compatible with the payload provider,
+   * inserts them into the answer, compute send/recv attributes
+   * and direction according to the offer.
    */
   void calcAnswer(const AmPayloadProviderInterface* payload_prov, 
                  SdpMedia& answer) const;
diff --git a/core/AmSession.cpp b/core/AmSession.cpp
index 3530c95..2fac67f 100644
--- a/core/AmSession.cpp
+++ b/core/AmSession.cpp
@@ -993,7 +993,9 @@ bool AmSession::getSdpAnswer(const AmSdp& offer, AmSdp& 
answer)
     answer.media.push_back(SdpMedia());
     SdpMedia& answer_media = answer.media.back();
 
-    if(m_it->type == MT_AUDIO && audio_1st_stream) {
+    if( m_it->type == MT_AUDIO 
+        && audio_1st_stream 
+        && (m_it->port != 0) ) {
 
       RTPStream()->getSdpAnswer(*m_it,answer_media);
       audio_1st_stream = false;
@@ -1004,7 +1006,11 @@ bool AmSession::getSdpAnswer(const AmSdp& offer, AmSdp& 
answer)
       answer_media.port = 0;
       answer_media.nports = 0;
       answer_media.transport = TP_RTPAVP;
+      answer_media.send = false;
+      answer_media.recv = false;
       answer_media.payloads.clear();
+      if(!m_it->payloads.empty())
+       answer_media.payloads.push_back(m_it->payloads.front());
       answer_media.attributes.clear();
     }
   }

_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to