[asterisk-commits] file: branch file/bridging r100328 - /team/file/bridging/apps/app_dial2.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jan 24 21:01:45 CST 2008


Author: file
Date: Thu Jan 24 21:01:44 2008
New Revision: 100328

URL: http://svn.digium.com/view/asterisk?view=rev&rev=100328
Log:
Add the beginnings of an experiment. This file introduces two dialplan applications, Dial2 and Dial2Bridge. Dial2 performs the actual dialing of devices. Once the other side answers control is returned back to the dialplan and Dial2Bridge can be called to bridge to the answered channel.

Added:
    team/file/bridging/apps/app_dial2.c   (with props)

Added: team/file/bridging/apps/app_dial2.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/apps/app_dial2.c?view=auto&rev=100328
==============================================================================
--- team/file/bridging/apps/app_dial2.c (added)
+++ team/file/bridging/apps/app_dial2.c Thu Jan 24 21:01:44 2008
@@ -1,0 +1,227 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2008, Digium, Inc.
+ *
+ * Joshua Colp <jcolp at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Application to dial a set of devices and bridge to the answered
+ *
+ * \author\verbatim Joshua Colp <jcolp at digium.com> \endverbatim
+ * 
+ * Application to dial a set of devices and bridge to the answered
+ * \ingroup applications
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/file.h"
+#include "asterisk/channel.h"
+#include "asterisk/pbx.h"
+#include "asterisk/module.h"
+#include "asterisk/lock.h"
+#include "asterisk/app.h"
+#include "asterisk/dial.h"
+#include "asterisk/bridging.h"
+
+static char *dial2_app = "Dial2";
+static char *dial2_synopsis = 
+"Dialing Application.";
+static char *dial2_descrip =
+"  Dial2(Technology/resource[&Tech2/resource2...]):\n"
+"This application will place calls to one or more specified channels. As soon\n"
+"as one of the requested channels answers the channel will return to the dialplan.\n"
+"  Unless there is a timeout specified, the Dial application will wait\n"
+"indefinitely until one of the called channels answers, the user hangs up, or\n"
+"if all of the called channels are busy or unavailable. Dialplan executing will\n"
+"continue if no requested channels can be called, or if the timeout expires.\n";
+
+static char *dial2_bridge_app = "Dial2Bridge";
+static char *dial2_bridge_synopsis =
+"Bridging Application.";
+static char *dial2_bridge_descrip =
+"  Dial2Bridge([options]):\n"
+"This application will bridge the current channel to an answered channel dialed\n"
+"using the Dial2 application.\n";
+
+/*! \brief Helper function used by datastores to hangup the dialed channel upon our own hangup */
+static void destroy_callback(void *data)
+{
+	struct ast_channel *chan = data;
+
+	/* Stop autoservice on the other channel */
+	ast_autoservice_stop(chan);
+
+	/* And finally hang it up */
+	ast_hangup(chan);
+
+        return;
+}
+
+/*! \brief Static structure for datastore information */
+static const struct ast_datastore_info dial2_datastore = {
+        .type = "dial2",
+        .destroy = destroy_callback
+};
+
+static int dial2_exec(struct ast_channel *chan, void *data)
+{
+	int res = 0;
+	char *parse = NULL;
+	AST_DECLARE_APP_ARGS(args,
+			     AST_APP_ARG(devices);
+			     AST_APP_ARG(options);
+		);
+	struct ast_dial *dial = NULL;
+	char *devices = NULL, *current_device = NULL;
+	enum ast_dial_result dial_result = AST_DIAL_RESULT_FAILED;
+
+	if (ast_strlen_zero(data)) {
+		ast_log(LOG_WARNING, "%s requires an argument (Technology/resource[&Tech2/resource2...])\n", dial2_app);
+		return -1;
+	}
+
+	/* Since we have data we need to make a local copy so we can modify it */
+	parse = ast_strdupa(data);
+
+	/* Parse out devices and global options */
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	/* If no devices were actually specified disappear now, no use continuing */
+	if (ast_strlen_zero(args.devices)) {
+		ast_log(LOG_WARNING, "%s requires an argument (Technology/resource[&Tech2/resource2...])\n", dial2_app);
+		return -1;
+	}
+	
+	/* Since we have confirmed we have at least the minimum required options let's create a dialing structure to contain our devices */
+	if (!(dial = ast_dial_create())) {
+		ast_log(LOG_WARNING, "Failed to create dialing structure. Bailing out.\n");
+		return -1;
+	}
+
+	/* Now parse through each option and set them on the dialing structure */
+
+	/* Iterate through parsing each device */
+	devices = args.devices;
+	while ((current_device = strsep(&devices, "&"))) {
+		char *technology = current_device, *resource = strchr(current_device, '/');
+
+		/* If no technology or resource is specified continue on to the next device */
+		if (ast_strlen_zero(technology) || ast_strlen_zero(resource)) {
+			ast_log(LOG_WARNING, "Skipping device '%s' in dialing procedure.\n", current_device);
+			continue;
+		}
+
+		/* Add this to the dialing attempt */
+		*resource++ = '\0';
+		ast_dial_append(dial, technology, resource);
+	}
+
+	/* Now we actually try to call the remote side */
+	dial_result = ast_dial_run(dial, chan, 0);
+
+	/* If the end result was that something answered we need to set the proper dialstatus and create the datastore */
+	if (dial_result == AST_DIAL_RESULT_ANSWERED) {
+		struct ast_datastore *datastore = NULL;
+
+		pbx_builtin_setvar_helper(chan, "DIALSTATUS", "ANSWERED");
+
+		if ((datastore = ast_channel_datastore_alloc(&dial2_datastore, NULL))) {
+			ast_autoservice_start(ast_dial_answered(dial));
+			datastore->data = ast_dial_answered_steal(dial);
+			ast_channel_datastore_add(chan, datastore);
+		} else {
+			ast_log(LOG_WARNING, "Failed to allocate memory for Dial2 datastore. Ut roh.\n");
+			ast_hangup(ast_dial_answered(dial));
+		}
+	} else if (dial_result == AST_DIAL_RESULT_TIMEOUT) {
+		pbx_builtin_setvar_helper(chan, "DIALSTATUS", "TIMEOUT");
+	} else if (dial_result == AST_DIAL_RESULT_HANGUP) {
+		pbx_builtin_setvar_helper(chan, "DIALSTATUS", "HANGUP");
+	} else if (dial_result == AST_DIAL_RESULT_UNANSWERED) {
+		pbx_builtin_setvar_helper(chan, "DIALSTATUS", "UNANSWERED");
+	}
+
+	/* Now that the actual dialing attempt is over, drop the dialing structure */
+	ast_dial_destroy(dial);
+
+	return res;
+}
+
+static int dial2_bridge_exec(struct ast_channel *chan, void *data)
+{
+	int res = 0;
+	struct ast_bridge *bridge = NULL;
+	struct ast_datastore *datastore = NULL;
+	struct ast_channel *dialed = NULL;
+
+	/* Try to find the datastore which holds the other channel */
+	if (!(datastore = ast_channel_datastore_find(chan, &dial2_datastore, NULL))) {
+		ast_log(LOG_WARNING, "Could not find a dialed channel. Are you sure they answered?\n");
+		return -1;
+	}
+
+	/* Steal the dialed channel off the datastore and remove the datastore itself, once the bridge is over we will no longer have control */
+	dialed = datastore->data;
+	datastore->data = NULL;
+	ast_channel_datastore_remove(chan, datastore);
+	ast_channel_datastore_free(datastore);
+
+	/* Create a new bridge to bridge chan and dialed together in */
+	if (!(bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE))) {
+		ast_log(LOG_WARNING, "Failed to create bridge to bridge %s and %s together in.\n", chan->name, dialed->name);
+		ast_hangup(dialed);
+		return -1;
+	}
+
+	/* Stop autoservice on the dialed channel since it is going into the bridge */
+	ast_autoservice_stop(dialed);
+
+	/* Finally add in the dialed channel async */
+	ast_bridge_impart(bridge, dialed, NULL, NULL);
+
+	/* Add ourselves in sync */
+	ast_bridge_join(bridge, chan, NULL, NULL);
+
+	/* The bridge is over, someone hung up... destroy it */
+	ast_bridge_destroy(bridge);
+
+	return res;
+}
+
+static int unload_module(void)
+{
+	int res = 0;
+
+	res |= ast_unregister_application(dial2_app);
+	res |= ast_unregister_application(dial2_bridge_app);
+
+	return res;
+}
+
+static int load_module(void)
+{
+	int res = 0;
+
+	res |= ast_register_application(dial2_app, dial2_exec, dial2_synopsis, dial2_descrip);
+	res |= ast_register_application(dial2_bridge_app, dial2_bridge_exec, dial2_bridge_synopsis, dial2_bridge_descrip);
+
+	return res ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing and Bridging Applications");

Propchange: team/file/bridging/apps/app_dial2.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/file/bridging/apps/app_dial2.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/file/bridging/apps/app_dial2.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list