telepathy-rakia: Fix the cases when a media is removed and then re-added

Olivier Crête tester at kemper.freedesktop.org
Tue May 8 10:03:03 PDT 2012


Module: telepathy-rakia
Branch: master
Commit: 20dbc5534e6e4df88717d83a3c070f1377885560
URL:    http://cgit.freedesktop.org/telepathy/telepathy-rakia/commit/?id=20dbc5534e6e4df88717d83a3c070f1377885560

Author: Olivier Crête <olivier.crete at collabora.com>
Date:   Fri Mar  2 19:48:01 2012 -0500

Fix the cases when a media is removed and then re-added

Also simplify the add_media function a bit

---

 rakia/call-channel.c |    6 +-
 rakia/sip-session.c  |  111 ++++++++++++++++++++++++++++++++++++++------------
 rakia/sip-session.h  |    3 +-
 3 files changed, 89 insertions(+), 31 deletions(-)

diff --git a/rakia/call-channel.c b/rakia/call-channel.c
index 5caecb2..23de0cf 100644
--- a/rakia/call-channel.c
+++ b/rakia/call-channel.c
@@ -227,12 +227,12 @@ rakia_call_channel_constructed (GObject *obj)
       if (tp_base_call_channel_has_initial_audio (bcc, &initial_audio_name))
         rakia_sip_session_add_media (self->priv->session,
             TP_MEDIA_STREAM_TYPE_AUDIO, initial_audio_name,
-            RAKIA_DIRECTION_BIDIRECTIONAL, TRUE);
+            RAKIA_DIRECTION_BIDIRECTIONAL);
 
       if (tp_base_call_channel_has_initial_video (bcc, &initial_video_name))
         rakia_sip_session_add_media (self->priv->session,
             TP_MEDIA_STREAM_TYPE_VIDEO, initial_video_name,
-            RAKIA_DIRECTION_BIDIRECTIONAL, TRUE);
+            RAKIA_DIRECTION_BIDIRECTIONAL);
 
       actor = tp_base_channel_get_self_handle (bc);
       reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED;
@@ -379,7 +379,7 @@ rakia_call_channel_add_content (
   RakiaSipMedia *media;
 
   media = rakia_sip_session_add_media (priv->session,
-      type, name, initial_direction, TRUE);
+      type, name, initial_direction);
 
   content = rakia_call_channel_get_content_by_media (self, media);
 
diff --git a/rakia/sip-session.c b/rakia/sip-session.c
index 84e1d14..7284625 100644
--- a/rakia/sip-session.c
+++ b/rakia/sip-session.c
@@ -870,19 +870,23 @@ rakia_sip_session_media_changed (RakiaSipSession *self)
 }
 
 
-RakiaSipMedia*
-rakia_sip_session_add_media (RakiaSipSession *self,
+static RakiaSipMedia *
+rakia_sip_session_add_media_internal (RakiaSipSession *self,
     TpMediaStreamType media_type,
     const gchar *name,
     RakiaDirection direction,
-    gboolean created_locally)
+    const sdp_media_t *sdp_media,
+    gboolean authoritative,
+    gint slot)
 {
   RakiaSipSessionPrivate *priv = RAKIA_SIP_SESSION_GET_PRIVATE (self);
   RakiaSipMedia *media = NULL;
+  gboolean created_locally = (sdp_media == NULL);
 
   SESSION_DEBUG (self, "enter");
 
-  if (rakia_sip_session_supports_media_type (media_type)) {
+  if ((!sdp_media || !sdp_media->m_rejected) &&
+      rakia_sip_session_supports_media_type (media_type)) {
     media = rakia_sip_media_new (self, media_type, name, direction,
         created_locally, priv->hold_requested);
 
@@ -892,17 +896,53 @@ rakia_sip_session_add_media (RakiaSipSession *self,
         G_CALLBACK (rakia_sip_session_media_changed), self,
         G_CONNECT_SWAPPED);
 
-    g_signal_emit (self, signals[SIG_MEDIA_ADDED], 0, media);
+    if (sdp_media == NULL ||
+        rakia_sip_media_set_remote_media (media, sdp_media, authoritative))
+      {
+        g_signal_emit (self, signals[SIG_MEDIA_ADDED], 0, media);
+      }
+    else
+      {
+        rakia_sip_session_remove_media (self, media, 488,
+            "Can not process this SDP");
+        media = NULL;
+      }
   }
 
   /* note: we add an entry even for unsupported media types */
-  g_ptr_array_add (priv->medias, media);
+  if (slot >= 0)
+    {
+      if (slot < priv->medias->len)
+        {
+          g_assert (g_ptr_array_index (priv->medias, slot) == NULL);
+          g_ptr_array_index (priv->medias, slot) = media;
+        }
+      else
+        {
+          g_assert (slot == priv->medias->len);
+          g_ptr_array_add (priv->medias, media);
+        }
+    }
+  else
+    {
+      g_ptr_array_add (priv->medias, media);
+    }
 
   SESSION_DEBUG (self, "exit");
 
   return media;
 }
 
+RakiaSipMedia *
+rakia_sip_session_add_media (RakiaSipSession *self,
+    TpMediaStreamType media_type,
+    const gchar *name,
+    RakiaDirection direction)
+{
+  return rakia_sip_session_add_media_internal (self, media_type, name,
+      direction, NULL, TRUE, -1);
+}
+
 
 static void
 priv_update_remote_hold (RakiaSipSession *self)
@@ -984,42 +1024,61 @@ priv_update_remote_media (RakiaSipSession *self, gboolean authoritative)
 
       media_type = rakia_media_type (sdp_media->m_type);
 
-      if (i >= priv->medias->len)
-        media = rakia_sip_session_add_media (
-                        self,
-                        media_type,
-                        NULL,
-                        /* Don't start sending unless requested by the user */
-                        rakia_direction_from_remote_media (sdp_media),
-                        FALSE);
-      else
+      if (i < priv->medias->len)
         media = g_ptr_array_index(priv->medias, i);
 
+      /* Check if the media type has changed, if it has
+       * just replace the media with the new one.
+       */
+      if (media != NULL && rakia_sip_media_get_media_type (media) != media_type)
+        {
+          g_object_ref (media);
+          g_ptr_array_index (self->priv->medias, i) = NULL;
+          g_signal_emit (self, signals[SIG_MEDIA_REMOVED], 0, media);
+          g_object_unref (media);
+          media = NULL;
+        }
+
+      /* Add the new media if it hasn't been rejected */
+      if (media == NULL && !sdp_media->m_rejected)
+        {
+          media = rakia_sip_session_add_media_internal (
+              self,
+              media_type,
+              NULL,
+              /* Don't start sending unless requested by the user */
+              rakia_direction_from_remote_media (sdp_media) &
+              RAKIA_DIRECTION_RECEIVE,
+              sdp_media, authoritative, i);
+
+          if (media != NULL)
+            has_supported_media = TRUE;
+          continue;
+        }
+
       /* note: it is ok for the media to be NULL (unsupported media type) */
       if (media == NULL)
         continue;
 
       SESSION_DEBUG (self, "setting remote SDP for media %u", i);
 
+      /* Remove rejected medias */
       if (sdp_media->m_rejected)
         {
           SESSION_DEBUG (self, "the media has been rejected, closing");
+          rakia_sip_session_remove_media (self, media, 488,
+              "Can not process this media type");
+          continue;
         }
-      else if (rakia_sip_media_get_media_type (media) != media_type)
-        {
-          /* XXX: close this media and create a new one in its place? */
-          WARNING ("The peer has changed the media type, don't know what to do");
-        }
-      else if (rakia_sip_media_set_remote_media (media, sdp_media,
+
+      if (!rakia_sip_media_set_remote_media (media, sdp_media,
               authoritative))
         {
-          has_supported_media = TRUE;
+          rakia_sip_session_remove_media (self, media, 488,
+              "Can not process this media type");
           continue;
         }
-
-      /* There have been problems with the media update, kill the media */
-      rakia_sip_session_remove_media (self, media, 488,
-          "Can not process this media type");
+      has_supported_media = TRUE;
     }
   g_assert(sdp_media == NULL);
   g_assert(i <= priv->medias->len);
diff --git a/rakia/sip-session.h b/rakia/sip-session.h
index 7ab4cb0..c56ccad 100644
--- a/rakia/sip-session.h
+++ b/rakia/sip-session.h
@@ -96,8 +96,7 @@ RakiaSipSessionState rakia_sip_session_get_state (RakiaSipSession *session);
 RakiaSipMedia* rakia_sip_session_add_media (RakiaSipSession *self,
     TpMediaStreamType media_type,
     const gchar *name,
-    RakiaDirection direction,
-    gboolean created_locally);
+    RakiaDirection direction);
 
 gboolean rakia_sip_session_remove_media (RakiaSipSession *self,
     RakiaSipMedia *media,



More information about the telepathy-commits mailing list