Dial: Add function to append already-created channel.
authorMark Michelson <mmichelson@digium.com>
Wed, 30 Mar 2016 21:47:15 +0000 (16:47 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 5 Apr 2016 16:55:50 +0000 (11:55 -0500)
The Dial API takes responsiblity for creating an outbound channel when
calling ast_dial_append(). This commit adds a new function,
ast_dial_append_channel(), which allows us to create the channel outside
the Dial API and then to append the channel to the ast_dial structure.

This is useful for situations where the channel's creation and dialing
are distinct operations. Upcoming ARI early bridge work will illustrate
its usage.

ASTERISK-25889

Change-Id: Id8179f64f8f99132f80dead8d5db2030fd2c0509

include/asterisk/dial.h
main/dial.c

index c59257c..168c509 100644 (file)
@@ -76,6 +76,18 @@ struct ast_dial *ast_dial_create(void);
  */
 int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids);
 
+/*!
+ * \brief Append a channel using an actual channel object
+ *
+ * \param dial The ast_dial to add the channel to
+ * \param chan The channel to add to the dial
+ * \retval -1 Failure
+ * \retval non-zero The position of the channel in the list of dialed channels
+ *
+ * \note The chan ref is stolen with a successful return.
+ */
+int ast_dial_append_channel(struct ast_dial *dial, struct ast_channel *chan);
+
 /*! \brief Request all appended channels, but do not dial
  * \param dial Dialing structure
  * \param chan Optional dialing channel
index 127f327..8024758 100644 (file)
@@ -248,22 +248,9 @@ struct ast_dial *ast_dial_create(void)
        return dial;
 }
 
-/*! \brief Append a channel
- * \note Appends a channel to a dialing structure
- * \return Returns channel reference number on success, -1 on failure
- */
-int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
+static int dial_append_common(struct ast_dial *dial, struct ast_dial_channel *channel,
+               const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
 {
-       struct ast_dial_channel *channel = NULL;
-
-       /* Make sure we have required arguments */
-       if (!dial || !tech || !device)
-               return -1;
-
-       /* Allocate new memory for dialed channel structure */
-       if (!(channel = ast_calloc(1, sizeof(*channel))))
-               return -1;
-
        /* Record technology and device for when we actually dial */
        channel->tech = ast_strdup(tech);
        channel->device = ast_strdup(device);
@@ -287,6 +274,60 @@ int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device,
        AST_LIST_INSERT_TAIL(&dial->channels, channel, list);
 
        return channel->num;
+
+}
+
+/*! \brief Append a channel
+ * \note Appends a channel to a dialing structure
+ * \return Returns channel reference number on success, -1 on failure
+ */
+int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
+{
+       struct ast_dial_channel *channel = NULL;
+
+       /* Make sure we have required arguments */
+       if (!dial || !tech || !device)
+               return -1;
+
+       /* Allocate new memory for dialed channel structure */
+       if (!(channel = ast_calloc(1, sizeof(*channel))))
+               return -1;
+
+       return dial_append_common(dial, channel, tech, device, assignedids);
+}
+
+int ast_dial_append_channel(struct ast_dial *dial, struct ast_channel *chan)
+{
+       struct ast_dial_channel *channel;
+       char *tech;
+       char *device;
+       char *dash;
+
+       if (!dial || !chan) {
+               return -1;
+       }
+
+       channel = ast_calloc(1, sizeof(*channel));
+       if (!channel) {
+               return -1;
+       }
+       channel->owner = chan;
+
+       tech = ast_strdupa(ast_channel_name(chan));
+
+       device = strchr(tech, '/');
+       if (!device) {
+               ast_free(channel);
+               return -1;
+       }
+       *device++ = '\0';
+
+       dash = strrchr(device, '-');
+       if (dash) {
+               *dash = '\0';
+       }
+
+       return dial_append_common(dial, channel, tech, device, NULL);
 }
 
 /*! \brief Helper function that requests all channels */
@@ -315,27 +356,29 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
                }
        }
 
-       /* Copy device string over */
-       ast_copy_string(numsubst, channel->device, sizeof(numsubst));
+       if (!channel->owner) {
+               /* Copy device string over */
+               ast_copy_string(numsubst, channel->device, sizeof(numsubst));
 
-       if (cap && ast_format_cap_count(cap)) {
-               cap_request = cap;
-       } else if (requester_cap) {
-               cap_request = requester_cap;
-       } else {
-               cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
-               ast_format_cap_append_by_type(cap_all_audio, AST_MEDIA_TYPE_AUDIO);
-               cap_request = cap_all_audio;
-       }
+               if (cap && ast_format_cap_count(cap)) {
+                       cap_request = cap;
+               } else if (requester_cap) {
+                       cap_request = requester_cap;
+               } else {
+                       cap_all_audio = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+                       ast_format_cap_append_by_type(cap_all_audio, AST_MEDIA_TYPE_AUDIO);
+                       cap_request = cap_all_audio;
+               }
 
-       /* If we fail to create our owner channel bail out */
-       if (!(channel->owner = ast_request(channel->tech, cap_request, &assignedids, chan, numsubst, &channel->cause))) {
+               /* If we fail to create our owner channel bail out */
+               if (!(channel->owner = ast_request(channel->tech, cap_request, &assignedids, chan, numsubst, &channel->cause))) {
+                       ao2_cleanup(cap_all_audio);
+                       return -1;
+               }
+               cap_request = NULL;
+               ao2_cleanup(requester_cap);
                ao2_cleanup(cap_all_audio);
-               return -1;
        }
-       cap_request = NULL;
-       ao2_cleanup(requester_cap);
-       ao2_cleanup(cap_all_audio);
 
        if (chan) {
                ast_channel_lock_both(chan, channel->owner);