]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
stream: Enforce formats immutability and ensure formats exist.
authorJoshua C. Colp <jcolp@sangoma.com>
Tue, 21 Apr 2020 09:52:24 +0000 (06:52 -0300)
committerKevin Harwell <kharwell@digium.com>
Thu, 23 Apr 2020 14:16:38 +0000 (09:16 -0500)
Some places in Asterisk did not treat the formats on a stream
as immutable when they are.

The ast_stream_get_formats function is now const to enforce this
and parts of Asterisk have been updated to take this into account.
Some violations of this were also fixed along the way.

An additional minor tweak is that streams are now allocated with
an empty format capabilities structure removing the need in various
places to check that one is present on the stream.

ASTERISK-28846

Change-Id: I32f29715330db4ff48edd6f1f359090458a9bfbe

bridges/bridge_native_rtp.c
bridges/bridge_simple.c
bridges/bridge_softmix.c
channels/chan_pjsip.c
channels/pjsip/dialplan_functions.c
doc/UPGRADE-staging/stream_immutable_formats.txt [new file with mode: 0644]
include/asterisk/stream.h
main/stream.c
res/res_pjsip_session.c

index a6addf27110391fbfebb56ba8bc1eab5ec296486..19c6ab525b42058c9fe1c51fbb65c2d946b1acb0 100644 (file)
@@ -859,7 +859,7 @@ static struct ast_stream_topology *native_rtp_request_stream_topology_update(
        struct ast_stream_topology *requested_topology)
 {
        struct ast_stream *stream;
-       struct ast_format_cap *audio_formats = NULL;
+       const struct ast_format_cap *audio_formats = NULL;
        struct ast_stream_topology *new_topology;
        int i;
 
@@ -886,6 +886,8 @@ static struct ast_stream_topology *native_rtp_request_stream_topology_update(
 
        if (audio_formats) {
                for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
+                       struct ast_format_cap *joint;
+
                        stream = ast_stream_topology_get_stream(new_topology, i);
 
                        if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
@@ -893,8 +895,16 @@ static struct ast_stream_topology *native_rtp_request_stream_topology_update(
                                continue;
                        }
 
-                       ast_format_cap_append_from_cap(ast_stream_get_formats(stream), audio_formats,
+                       joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+                       if (!joint) {
+                               continue;
+                       }
+
+                       ast_format_cap_append_from_cap(joint, ast_stream_get_formats(stream),
                                AST_MEDIA_TYPE_AUDIO);
+                       ast_format_cap_append_from_cap(joint, audio_formats, AST_MEDIA_TYPE_AUDIO);
+                       ast_stream_set_formats(stream, joint);
+                       ao2_ref(joint, -1);
                }
        }
 
index 545b3ad1cbe04be718e22dfe757ac239184d1ff6..abda774dd58a02d8f579e9b0c241600b739d5930 100644 (file)
@@ -63,7 +63,7 @@ static struct ast_stream_topology *simple_bridge_request_stream_topology_update(
        struct ast_stream_topology *requested_topology)
 {
        struct ast_stream *stream;
-       struct ast_format_cap *audio_formats = NULL;
+       const struct ast_format_cap *audio_formats = NULL;
        struct ast_stream_topology *new_topology;
        int i;
 
@@ -90,6 +90,8 @@ static struct ast_stream_topology *simple_bridge_request_stream_topology_update(
 
        if (audio_formats) {
                for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
+                       struct ast_format_cap *joint;
+
                        stream = ast_stream_topology_get_stream(new_topology, i);
 
                        if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
@@ -97,8 +99,16 @@ static struct ast_stream_topology *simple_bridge_request_stream_topology_update(
                                continue;
                        }
 
-                       ast_format_cap_append_from_cap(ast_stream_get_formats(stream), audio_formats,
+                       joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+                       if (!joint) {
+                               continue;
+                       }
+
+                       ast_format_cap_append_from_cap(joint, ast_stream_get_formats(stream),
                                AST_MEDIA_TYPE_AUDIO);
+                       ast_format_cap_append_from_cap(joint, audio_formats, AST_MEDIA_TYPE_AUDIO);
+                       ast_stream_set_formats(stream, joint);
+                       ao2_ref(joint, -1);
                }
        }
 
index e1c673496667c183fb0ecb34cbab08ba139e1b67..09218ce99650c664f405590d1d63a2274518334a 100644 (file)
@@ -2575,7 +2575,7 @@ fail:
 static int validate_stream(struct ast_test *test, struct ast_stream *stream,
        const struct stream_parameters *params)
 {
-       struct ast_format_cap *stream_caps;
+       const struct ast_format_cap *stream_caps;
        struct ast_format_cap *params_caps;
 
        if (ast_stream_get_type(stream) != params->type) {
index 5df39c3bd6ace01bf9fee248299832f1c622e71f..99ef6440daea099317d07f33f19cd1d667e83e41 100644 (file)
@@ -820,7 +820,7 @@ static int is_compatible_format(struct ast_sip_session *session, struct ast_fram
 {
        struct ast_stream_topology *topology = session->active_media_state->topology;
        struct ast_stream *stream = ast_stream_topology_get_stream(topology, f->stream_num);
-       struct ast_format_cap *cap = ast_stream_get_formats(stream);
+       const struct ast_format_cap *cap = ast_stream_get_formats(stream);
 
        return ast_format_cap_iscompatible_format(cap, f->subclass.format) != AST_FORMAT_CMP_NOT_EQUAL;
 }
index 7cc4506a5e8b4ca0fc0515c08b4ea4cbe73082ff..2ace3ade3814717a7c735ba1fbde908276fdc0d7 100644 (file)
@@ -1235,7 +1235,7 @@ static int media_offer_read_av(struct ast_sip_session *session, char *buf,
        struct ast_stream_topology *topology;
        int idx;
        struct ast_stream *stream = NULL;
-       struct ast_format_cap *caps;
+       const struct ast_format_cap *caps;
        size_t accum = 0;
 
        if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
@@ -1352,9 +1352,18 @@ static int media_offer_write_av(void *obj)
        if (!stream) {
                return 0;
        }
-       caps = ast_stream_get_formats(stream);
+
+       caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+       if (!caps) {
+               return -1;
+       }
+
+       ast_format_cap_append_from_cap(caps, ast_stream_get_formats(stream),
+               AST_MEDIA_TYPE_UNKNOWN);
        ast_format_cap_remove_by_type(caps, data->media_type);
        ast_format_cap_update_by_allow_disallow(caps, data->value, 1);
+       ast_stream_set_formats(stream, caps);
+       ao2_ref(caps, -1);
 
        return 0;
 }
diff --git a/doc/UPGRADE-staging/stream_immutable_formats.txt b/doc/UPGRADE-staging/stream_immutable_formats.txt
new file mode 100644 (file)
index 0000000..2af5d9b
--- /dev/null
@@ -0,0 +1,9 @@
+Subject: Core
+
+The streams API function ast_stream_get_formats is
+now defined as returning the format capabilities const.
+This has always been the case but was never enforced
+through the API itself. Any consumer of this API that
+is not treating the formats as immutable should update
+their code to create a new format capabilities and set
+it on the stream instead.
index ade740d19da84062a29562db59b3848779bd3a48..381ef36f99f738f59eb9db37d6fb31fc8aef300b 100644 (file)
@@ -164,7 +164,7 @@ void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type);
  *
  * \since 15
  */
-struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream);
+const struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream);
 
 /*!
  * \brief Set the current negotiated formats of a stream
index 626fa3a9caaf4ff48d2be3bf2b4206abe9dfcc21..02e6a548fe9d05447c1bcbad526d796fcf7f1bb3 100644 (file)
@@ -108,6 +108,12 @@ struct ast_stream *ast_stream_alloc(const char *name, enum ast_media_type type)
        stream->group = -1;
        strcpy(stream->name, S_OR(name, "")); /* Safe */
 
+       stream->formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+       if (!stream->formats) {
+               ast_free(stream);
+               return NULL;
+       }
+
        return stream;
 }
 
@@ -179,7 +185,7 @@ void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
        stream->type = type;
 }
 
-struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream)
+const struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream)
 {
        ast_assert(stream != NULL);
 
index 7ff801899dcdadebce069912e02f64fe4f34d44d..dbeb004eff1b436c0e5dd39c83659fa9c6789fc3 100644 (file)
@@ -1751,9 +1751,11 @@ static int sip_session_refresh(struct ast_sip_session *session,
                                                        continue;
                                                } else {
                                                        /* However if the stream is otherwise remaining the same we can keep the formats
-                                                        * that exist on it already which allows media to continue to flow.
+                                                        * that exist on it already which allows media to continue to flow. We don't modify
+                                                        * the format capabilities but do need to cast it so that ao2_bump can raise the
+                                                        * reference count.
                                                         */
-                                                       joint_cap = ao2_bump(ast_stream_get_formats(existing_stream));
+                                                       joint_cap = ao2_bump((struct ast_format_cap *)ast_stream_get_formats(existing_stream));
                                                }
                                        }
                                        ast_stream_set_formats(stream, joint_cap);
@@ -2708,7 +2710,7 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
 
                for (i = 0; i < ast_stream_topology_get_count(req_topology); ++i) {
                        struct ast_stream *req_stream;
-                       struct ast_format_cap *req_cap;
+                       const struct ast_format_cap *req_cap;
                        struct ast_format_cap *joint_cap;
                        struct ast_stream *clone_stream;