]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip_sdp_rtp: Fix multiple keepalive scheduled items. 61/1161/1
authorJoshua Colp <jcolp@digium.com>
Sat, 29 Aug 2015 01:22:45 +0000 (22:22 -0300)
committerJoshua Colp <jcolp@digium.com>
Sat, 29 Aug 2015 01:49:24 +0000 (20:49 -0500)
The keepalive support in res_pjsip_sdp_rtp currently assumes
that a stream will only be negotiated once. This is false.
If the stream is replaced and later added back it can be
negotiated again causing multiple keepalive scheduled items
to exist. This change explicitly deletes the existing
keepalive scheduled item before adding the new one.

The res_pjsip_sdp_rtp module also does not stop RTP
keepalives or timeout timer if the stream has been
replaced. This change adds a callback to the session media
interface to allow a media stream to be stopped without
the resources being destroyed. This allows the scheduled
items and RTP to be stopped when the stream no longer
exists.

ASTERISK-25356 #close

Change-Id: Ibe6a7cc0927c87326fd5f1c0d4ad889dbfbea1de

include/asterisk/res_pjsip_session.h
res/res_pjsip_sdp_rtp.c
res/res_pjsip_session.c

index 5af19ffca7566a7bf2c2c4e3b14622f009054c0f..7fbeddc7787b912e054888b4b574e4e0a0110b3a 100644 (file)
@@ -350,6 +350,12 @@ struct ast_sip_session_sdp_handler {
         */
        int (*apply_negotiated_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream,
                const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream);
+       /*!
+        * \brief Stop a session_media created by this handler but do not destroy resources
+        * \param session The session for which media is being stopped
+        * \param session_media The media to destroy
+        */
+       void (*stream_stop)(struct ast_sip_session_media *session_media);
        /*!
         * \brief Destroy a session_media created by this handler
         * \param session The session for which media is being destroyed
index 8ac1bb8df8bd763ca137062a72f3e05356e37871..0b431258e392ded8889d80f0220d0d72ade2fe6f 100644 (file)
@@ -1290,6 +1290,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
                 * a NAT. This way there won't be an awkward delay before media starts flowing in some
                 * scenarios.
                 */
+               AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
                session_media->keepalive_sched_id = ast_sched_add_variable(sched, 500, send_keepalive,
                        session_media, 1);
        }
@@ -1341,13 +1342,23 @@ static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struc
        pj_strdup2(tdata->pool, &stream->conn->addr, transport->external_media_address);
 }
 
+/*! \brief Function which stops the RTP instance */
+static void stream_stop(struct ast_sip_session_media *session_media)
+{
+       if (!session_media->rtp) {
+               return;
+       }
+
+       AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
+       AST_SCHED_DEL(sched, session_media->timeout_sched_id);
+       ast_rtp_instance_stop(session_media->rtp);
+}
+
 /*! \brief Function which destroys the RTP instance when session ends */
 static void stream_destroy(struct ast_sip_session_media *session_media)
 {
        if (session_media->rtp) {
-               AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
-               AST_SCHED_DEL(sched, session_media->timeout_sched_id);
-               ast_rtp_instance_stop(session_media->rtp);
+               stream_stop(session_media);
                ast_rtp_instance_destroy(session_media->rtp);
        }
        session_media->rtp = NULL;
@@ -1360,6 +1371,7 @@ static struct ast_sip_session_sdp_handler audio_sdp_handler = {
        .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
        .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
        .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
+       .stream_stop = stream_stop,
        .stream_destroy = stream_destroy,
 };
 
@@ -1370,6 +1382,7 @@ static struct ast_sip_session_sdp_handler video_sdp_handler = {
        .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
        .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
        .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
+       .stream_stop = stream_stop,
        .stream_destroy = stream_destroy,
 };
 
index 79aab76adb1df807153d6e0557c9851d896021e1..8f603c753c57a630acf10a227cd59f8d663510aa 100644 (file)
@@ -362,6 +362,13 @@ static int handle_negotiated_sdp_session_media(void *obj, void *arg, int flags)
                        }
                }
        }
+
+       if (session_media->handler && session_media->handler->stream_stop) {
+               ast_debug(1, "Stopping SDP media stream '%s' as it is not currently negotiated\n",
+                       session_media->stream_type);
+               session_media->handler->stream_stop(session_media);
+       }
+
        return CMP_MATCH;
 }