]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
app_dial: Add option "j" to preserve initial stream topology of caller
authorMaximilian Fridrich <m.fridrich@commend.com>
Thu, 30 Nov 2023 08:57:56 +0000 (09:57 +0100)
committerMaximilian Fridrich <m.fridrich@commend.com>
Wed, 6 Dec 2023 21:25:15 +0000 (21:25 +0000)
Resolves: #462

UserNote: The option "j" is now available for the Dial application which
uses the initial stream topology of the caller to create the outgoing
channels.

apps/app_dial.c

index 5be1e0aa6ed48dcaabc701b91c178c3218f66a7f..5b718dc2729d9d00097d1c7adff583efa8dbeb78 100644 (file)
                                        <para>Asterisk will ignore any connected line update requests or any redirecting party
                                        update requests it may receive on this dial attempt.</para>
                                </option>
+                               <option name="j">
+                                       <para>Use the initial stream topology of the caller for outgoing channels, even if the caller topology has changed.</para>
+                                       <para>NOTE: For this option to work, it has to be present in all invocations of Dial that the caller channel goes through.</para>
+                               </option>
                                <option name="k">
                                        <para>Allow the called party to enable parking of the call by sending
                                        the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
@@ -705,6 +709,7 @@ enum {
 #define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43)
 #define OPT_HANGUPCAUSE      (1LLU << 44)
 #define OPT_HEARPULSING      (1LLU << 45)
+#define OPT_TOPOLOGY_PRESERVE (1LLU << 46)
 
 enum {
        OPT_ARG_ANNOUNCE = 0,
@@ -749,6 +754,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
        AST_APP_OPTION('H', OPT_CALLER_HANGUP),
        AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
        AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
+       AST_APP_OPTION('j', OPT_TOPOLOGY_PRESERVE),
        AST_APP_OPTION('k', OPT_CALLEE_PARK),
        AST_APP_OPTION('K', OPT_CALLER_PARK),
        AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
@@ -808,6 +814,16 @@ struct chanlist {
 
 AST_LIST_HEAD_NOLOCK(dial_head, chanlist);
 
+static void topology_ds_destroy(void *data) {
+       struct ast_stream_topology *top = data;
+       ast_stream_topology_free(top);
+}
+
+static const struct ast_datastore_info topology_ds_info = {
+       .type = "app_dial_topology_preserve",
+       .destroy = topology_ds_destroy,
+};
+
 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str **featurecode);
 
 static void chanlist_free(struct chanlist *outgoing)
@@ -2326,6 +2342,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
         */
        struct ast_party_caller caller;
        int max_forwards;
+       struct ast_datastore *topology_ds = NULL;
        SCOPE_ENTER(1, "%s: Data: %s\n", ast_channel_name(chan), data);
 
        /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
@@ -2627,7 +2644,21 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                 */
                ast_party_connected_line_copy(&tmp->connected, ast_channel_connected(chan));
 
-               topology = ast_stream_topology_clone(ast_channel_get_stream_topology(chan));
+               if (ast_test_flag64(&opts, OPT_TOPOLOGY_PRESERVE)) {
+                       topology_ds = ast_channel_datastore_find(chan, &topology_ds_info, NULL);
+
+                       if (!topology_ds && (topology_ds = ast_datastore_alloc(&topology_ds_info, NULL))) {
+                               topology_ds->data = ast_stream_topology_clone(ast_channel_get_stream_topology(chan));
+                               ast_channel_datastore_add(chan, topology_ds);
+                       }
+               }
+
+               if (topology_ds) {
+                       ao2_ref(topology_ds->data, +1);
+                       topology = topology_ds->data;
+               } else {
+                       topology = ast_stream_topology_clone(ast_channel_get_stream_topology(chan));
+               }
 
                ast_channel_unlock(chan);