From 20dbc5534e6e4df88717d83a3c070f1377885560 Mon Sep 17 00:00:00 2001 From: Olivier CrĂȘte Date: Fri, 2 Mar 2012 19:48:01 -0500 Subject: 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, -- cgit v1.2.3