[asterisk-commits] jrose: branch jrose/bridge_projects r383396 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 19 16:06:02 CDT 2013


Author: jrose
Date: Tue Mar 19 16:05:58 2013
New Revision: 383396

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383396
Log:
Parking 3/19 - Configuration and entry

Added:
    team/jrose/bridge_projects/include/asterisk/parking.h   (with props)
    team/jrose/bridge_projects/main/parking.c   (with props)
    team/jrose/bridge_projects/res/parking/
    team/jrose/bridge_projects/res/parking/parking_applications.c   (with props)
    team/jrose/bridge_projects/res/parking/parking_controller.c   (with props)
    team/jrose/bridge_projects/res/parking/parking_tools.c   (with props)
    team/jrose/bridge_projects/res/parking/res_parking.h   (with props)
    team/jrose/bridge_projects/res/res_parking.c   (with props)
Modified:
    team/jrose/bridge_projects/include/asterisk/_private.h
    team/jrose/bridge_projects/include/asterisk/config_options.h
    team/jrose/bridge_projects/main/asterisk.c
    team/jrose/bridge_projects/main/config_options.c
    team/jrose/bridge_projects/main/features.c
    team/jrose/bridge_projects/main/manager.c
    team/jrose/bridge_projects/res/Makefile

Modified: team/jrose/bridge_projects/include/asterisk/_private.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/_private.h?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/_private.h (original)
+++ team/jrose/bridge_projects/include/asterisk/_private.h Tue Mar 19 16:05:58 2013
@@ -23,6 +23,7 @@
 int ast_term_init(void);		/*!< Provided by term.c */
 int astdb_init(void);			/*!< Provided by db.c */
 void ast_channels_init(void);		/*!< Provided by channel.c */
+void ast_parking_init(void);		/*!< Provided by parking.c */
 void ast_builtins_init(void);		/*!< Provided by cli.c */
 int ast_cli_perms_init(int reload);	/*!< Provided by cli.c */
 int dnsmgr_init(void);			/*!< Provided by dnsmgr.c */ 

Modified: team/jrose/bridge_projects/include/asterisk/config_options.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/config_options.h?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/config_options.h (original)
+++ team/jrose/bridge_projects/include/asterisk/config_options.h Tue Mar 19 16:05:58 2013
@@ -574,6 +574,13 @@
  * \retval -1 Failure
  */
 int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to);
+
+/*! \brief Read the flags of a config option - useful when using a custom callback for a config option
+ * \param option Pointer to the aco_option struct
+ *
+ * \retval value of the flags on the config option
+ */
+unsigned int aco_option_get_flags(const struct aco_option *option);
 
 /*! \note  Everything below this point is to handle converting varargs
  * containing field names, to varargs containing a count of args, followed

Added: team/jrose/bridge_projects/include/asterisk/parking.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/parking.h?view=auto&rev=383396
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/parking.h (added)
+++ team/jrose/bridge_projects/include/asterisk/parking.h Tue Mar 19 16:05:58 2013
@@ -1,0 +1,93 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Jonathan Rose <jrose 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 Call Parking API
+ *
+ * \author Jonathan Rose <jrose at digium.com>
+ */
+
+#include "asterisk/stringfields.h"
+
+/*! \brief Defines the type of parked call message */
+enum parked_call_event_type {
+	PARKED_CALL = 0,
+	PARKED_CALL_TIMEOUT,
+	PARKED_CALL_GIVEUP,
+	PARKED_CALL_UNPARKED,
+};
+
+/*!
+ * \brief A parked call message payload
+ * \since 12
+ */
+struct parked_call_payload {
+	struct ast_channel_snapshot *parkee;
+	struct ast_channel_snapshot *parker;
+	enum parked_call_event_type event_type;
+	int list_item;
+	int list_size;
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(parkinglot);
+		AST_STRING_FIELD(parkingspace);
+		AST_STRING_FIELD(timeout);
+		AST_STRING_FIELD(duration);
+		AST_STRING_FIELD(list);
+	);
+};
+
+/*!
+ * \brief A parking lot message payload
+ * \since 12
+ */
+struct parking_lot_payload {
+	int list_item;
+	int list_size;
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);
+		AST_STRING_FIELD(starting_space);
+		AST_STRING_FIELD(ending_space);
+		AST_STRING_FIELD(timeout);
+		AST_STRING_FIELD(list);
+	);
+};
+
+/*!
+ * \since 12
+ * \brief Message type for \ref ast_parked_call
+ *
+ * \retval Message type for \ref ast_parked_call
+ */
+struct stasis_message_type *ast_parked_call(void);
+
+/*!
+ * \since 12
+ * \brief Message type for \ref ast_parking_lot
+ *
+ * \retval Message type for \ref ast_parking_lot
+ */
+struct stasis_message_type *ast_parking_lot(void);
+
+/*!
+ * \since 12
+ * \brief A topic which publishes events pertaining generally to parking lots.
+ *
+ * \retval Topic for parking lot events.
+ */
+struct stasis_topic *ast_parking_lot_topic(void);

Propchange: team/jrose/bridge_projects/include/asterisk/parking.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/jrose/bridge_projects/include/asterisk/parking.h
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: team/jrose/bridge_projects/include/asterisk/parking.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/jrose/bridge_projects/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/asterisk.c?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/main/asterisk.c (original)
+++ team/jrose/bridge_projects/main/asterisk.c Tue Mar 19 16:05:58 2013
@@ -4200,6 +4200,7 @@
 	}
 
 	ast_channels_init();
+	ast_parking_init();
 
 	if ((moduleresult = load_modules(1))) {		/* Load modules, pre-load only */
 		printf("%s", term_quit());

Modified: team/jrose/bridge_projects/main/config_options.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/config_options.c?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/main/config_options.c (original)
+++ team/jrose/bridge_projects/main/config_options.c Tue Mar 19 16:05:58 2013
@@ -220,6 +220,11 @@
 	}
 
 	return 0;
+}
+
+unsigned int aco_option_get_flags(const struct aco_option *option)
+{
+	return option->flags;
 }
 
 #ifdef AST_XML_DOCS

Modified: team/jrose/bridge_projects/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/features.c?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/main/features.c (original)
+++ team/jrose/bridge_projects/main/features.c Tue Mar 19 16:05:58 2013
@@ -283,95 +283,6 @@
 			<ref type="application">ParkAndAnnounce</ref>
 		</see-also>
 	</application>
-	<application name="Park" language="en_US">
-		<synopsis>
-			Park yourself.
-		</synopsis>
-		<syntax>
-			<parameter name="timeout">
-				<para>A custom parking timeout for this parked call. Value in milliseconds.</para>
-			</parameter>
-			<parameter name="return_context">
-				<para>The context to return the call to after it times out.</para>
-			</parameter>
-			<parameter name="return_exten">
-				<para>The extension to return the call to after it times out.</para>
-			</parameter>
-			<parameter name="return_priority">
-				<para>The priority to return the call to after it times out.</para>
-			</parameter>
-			<parameter name="options">
-				<para>A list of options for this parked call.</para>
-				<optionlist>
-					<option name="r">
-						<para>Send ringing instead of MOH to the parked call.</para>
-					</option>
-					<option name="R">
-						<para>Randomize the selection of a parking space.</para>
-					</option>
-					<option name="s">
-						<para>Silence announcement of the parking space number.</para>
-					</option>
-				</optionlist>
-			</parameter>
-			<parameter name="parking_lot_name">
-				<para>Specify in which parking lot to park a call.</para>
-				<para>The parking lot used is selected in the following order:</para>
-				<para>1) parking_lot_name option</para>
-				<para>2) <variable>PARKINGLOT</variable> variable</para>
-				<para>3) <literal>CHANNEL(parkinglot)</literal> function
-				(Possibly preset by the channel driver.)</para>
-				<para>4) Default parking lot.</para>
-			</parameter>
-		</syntax>
-		<description>
-			<para>Used to park yourself (typically in combination with a supervised
-			transfer to know the parking space).</para>
-			<para>If you set the <variable>PARKINGEXTEN</variable> variable to a
-			parking space extension in the parking lot, Park() will attempt to park the call
-			on that extension.  If the extension is already is in use then execution
-			will continue at the next priority.</para>
-			<para>If the <literal>parkeddynamic</literal> option is enabled in <filename>features.conf</filename>
-			the following variables can be used to dynamically create new parking lots.</para>
-			<para>If you set the <variable>PARKINGDYNAMIC</variable> variable and this parking lot
-			exists then it will be used as a template for the newly created dynamic lot.  Otherwise,
-			the default parking lot will be used.</para>
-			<para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable then the newly created dynamic
-			parking lot will use this context.</para>
-			<para>If you set the <variable>PARKINGDYNEXTEN</variable> variable then the newly created dynamic
-			parking lot will use this extension to access the parking lot.</para>
-			<para>If you set the <variable>PARKINGDYNPOS</variable> variable then the newly created dynamic parking lot
-			will use those parking postitions.</para>
-			<note>
-				<para>This application must be used as the first extension priority
-				to be recognized as a parking access extension.  DTMF transfers
-				and some channel drivers need this distinction to operate properly.
-				The parking access extension in this case is treated like a dialplan
-				hint.</para>
-			</note>
-			<note>
-				<para>Parking lots automatically create and manage dialplan extensions in
-				the parking lot context.  You do not need to explicitly use this
-				application in your dialplan.  Instead, all you should do is include the
-				parking lot context in your dialplan.</para>
-			</note>
-		</description>
-		<see-also>
-			<ref type="application">ParkAndAnnounce</ref>
-			<ref type="application">ParkedCall</ref>
-		</see-also>
-	</application>
-	<manager name="ParkedCalls" language="en_US">
-		<synopsis>
-			List parked calls.
-		</synopsis>
-		<syntax>
-			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
-		</syntax>
-		<description>
-			<para>List parked calls.</para>
-		</description>
-	</manager>
 	<manager name="Park" language="en_US">
 		<synopsis>
 			Park a channel.
@@ -417,17 +328,6 @@
 		</syntax>
 		<description>
 			<para>Bridge together two channels already in the PBX.</para>
-		</description>
-	</manager>
-	<manager name="Parkinglots" language="en_US">
-		<synopsis>
-			Get a list of parking lots
-		</synopsis>
-		<syntax>
-			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
-		</syntax>
-		<description>
-			<para>List all parking lots as a series of AMI events</para>
 		</description>
 	</manager>
 	<function name="FEATURE" language="en_US">
@@ -5019,116 +4919,6 @@
 	AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
 END_OPTIONS );
 
-/*! \brief Park a call */
-static int park_call_exec(struct ast_channel *chan, const char *data)
-{
-	struct ast_park_call_args args = { 0, };
-	struct ast_flags flags = { 0 };
-	char orig_exten[AST_MAX_EXTENSION];
-	int orig_priority;
-	int res;
-	const char *pl_name;
-	char *parse;
-	struct park_app_args app_args;
-
-	/*
-	 * Cache the original channel name because we are going to
-	 * masquerade the channel.  Prefer the BLINDTRANSFER channel
-	 * name over this channel name.  BLINDTRANSFER could be set if
-	 * the parking access extension did not get detected and we are
-	 * executing the Park application from the dialplan.
-	 *
-	 * The orig_chan_name is used to return the call to the
-	 * originator on parking timeout.
-	 */
-	args.orig_chan_name = ast_strdupa(S_OR(
-		pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), ast_channel_name(chan)));
-
-	/* Answer if call is not up */
-	if (ast_channel_state(chan) != AST_STATE_UP) {
-		if (ast_answer(chan)) {
-			return -1;
-		}
-
-		/* Sleep to allow VoIP streams to settle down */
-		if (ast_safe_sleep(chan, 1000)) {
-			return -1;
-		}
-	}
-
-	/* Process the dialplan application options. */
-	parse = ast_strdupa(data);
-	AST_STANDARD_APP_ARGS(app_args, parse);
-
-	if (!ast_strlen_zero(app_args.timeout)) {
-		if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
-			ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
-			args.timeout = 0;
-		}
-	}
-	if (!ast_strlen_zero(app_args.return_con)) {
-		args.return_con = app_args.return_con;
-	}
-	if (!ast_strlen_zero(app_args.return_ext)) {
-		args.return_ext = app_args.return_ext;
-	}
-	if (!ast_strlen_zero(app_args.return_pri)) {
-		if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
-			ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
-			args.return_pri = 0;
-		}
-	}
-
-	ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
-	args.flags = flags.flags;
-
-	/*
-	 * Setup the exten/priority to be s/1 since we don't know where
-	 * this call should return.
-	 */
-	ast_copy_string(orig_exten, ast_channel_exten(chan), sizeof(orig_exten));
-	orig_priority = ast_channel_priority(chan);
-	ast_channel_exten_set(chan, "s");
-	ast_channel_priority_set(chan, 1);
-
-	/* Park the call */
-	if (!ast_strlen_zero(app_args.pl_name)) {
-		pl_name = app_args.pl_name;
-	} else {
-		pl_name = findparkinglotname(chan);
-	}
-	if (ast_strlen_zero(pl_name)) {
-		/* Parking lot is not specified, so use the default parking lot. */
-		args.parkinglot = parkinglot_addref(default_parkinglot);
-	} else {
-		args.parkinglot = find_parkinglot(pl_name);
-		if (!args.parkinglot && parkeddynamic) {
-			args.parkinglot = create_dynamic_parkinglot(pl_name, chan);
-		}
-	}
-	if (args.parkinglot) {
-		res = masq_park_call(chan, chan, &args);
-		parkinglot_unref(args.parkinglot);
-	} else {
-		/* Parking failed because the parking lot does not exist. */
-		if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
-			ast_stream_and_wait(chan, "pbx-parkingfailed", "");
-		}
-		res = -1;
-	}
-	if (res) {
-		/* Park failed, try to continue in the dialplan. */
-		ast_channel_exten_set(chan, orig_exten);
-		ast_channel_priority_set(chan, orig_priority);
-		res = 0;
-	} else {
-		/* Park succeeded. */
-		res = -1;
-	}
-
-	return res;
-}
-
 /*! \brief Pickup parked call */
 static int parked_call_exec(struct ast_channel *chan, const char *data)
 {
@@ -7184,107 +6974,6 @@
 	AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
 };
 
-static int manager_parkinglot_list(struct mansession *s, const struct message *m)
-{
-	const char *id = astman_get_header(m, "ActionID");
-	char idText[256] = "";
-	struct ao2_iterator iter;
-	struct ast_parkinglot *curlot;
-
-	if (!ast_strlen_zero(id))
-		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
-
-	astman_send_ack(s, m, "Parking lots will follow");
-
-	iter = ao2_iterator_init(parkinglots, 0);
-	while ((curlot = ao2_iterator_next(&iter))) {
-		astman_append(s, "Event: Parkinglot\r\n"
-			"Name: %s\r\n"
-			"StartExten: %d\r\n"
-			"StopExten: %d\r\n"
-			"Timeout: %d\r\n"
-			"\r\n",
-			curlot->name,
-			curlot->cfg.parking_start,
-			curlot->cfg.parking_stop,
-			curlot->cfg.parkingtime ? curlot->cfg.parkingtime / 1000 : curlot->cfg.parkingtime);
-		ao2_ref(curlot, -1);
-	}
-
-	astman_append(s,
-		"Event: ParkinglotsComplete\r\n"
-		"%s"
-		"\r\n",idText);
-
-	return RESULT_SUCCESS;
-}
-
-/*! 
- * \brief Dump parking lot status
- * \param s
- * \param m
- *
- * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
- * \return Always RESULT_SUCCESS
- */
-static int manager_parking_status(struct mansession *s, const struct message *m)
-{
-	struct parkeduser *cur;
-	const char *id = astman_get_header(m, "ActionID");
-	char idText[256] = "";
-	struct ao2_iterator iter;
-	struct ast_parkinglot *curlot;
-	int numparked = 0;
-	long now = time(NULL);
-
-	if (!ast_strlen_zero(id))
-		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
-
-	astman_send_ack(s, m, "Parked calls will follow");
-
-	iter = ao2_iterator_init(parkinglots, 0);
-	while ((curlot = ao2_iterator_next(&iter))) {
-		AST_LIST_LOCK(&curlot->parkings);
-		AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
-			astman_append(s, "Event: ParkedCall\r\n"
-				"Parkinglot: %s\r\n"
-				"Exten: %d\r\n"
-				"Channel: %s\r\n"
-				"From: %s\r\n"
-				"Timeout: %ld\r\n"
-				"Duration: %ld\r\n"
-				"CallerIDNum: %s\r\n"
-				"CallerIDName: %s\r\n"
-				"ConnectedLineNum: %s\r\n"
-				"ConnectedLineName: %s\r\n"
-				"%s"
-				"\r\n",
-				curlot->name,
-				cur->parkingnum, ast_channel_name(cur->chan), cur->peername,
-				(long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - now,
-				now - (long) cur->start.tv_sec,
-				S_COR(ast_channel_caller(cur->chan)->id.number.valid, ast_channel_caller(cur->chan)->id.number.str, ""),	/* XXX in other places it is <unknown> */
-				S_COR(ast_channel_caller(cur->chan)->id.name.valid, ast_channel_caller(cur->chan)->id.name.str, ""),
-				S_COR(ast_channel_connected(cur->chan)->id.number.valid, ast_channel_connected(cur->chan)->id.number.str, ""),	/* XXX in other places it is <unknown> */
-				S_COR(ast_channel_connected(cur->chan)->id.name.valid, ast_channel_connected(cur->chan)->id.name.str, ""),
-				idText);
-			++numparked;
-		}
-		AST_LIST_UNLOCK(&curlot->parkings);
-		ao2_ref(curlot, -1);
-	}
-	ao2_iterator_destroy(&iter);
-
-	astman_append(s,
-		"Event: ParkedCallsComplete\r\n"
-		"Total: %d\r\n"
-		"%s"
-		"\r\n",
-		numparked, idText);
-
-	return RESULT_SUCCESS;
-}
-
 /*!
  * \brief Create manager event for parked calls
  * \param s
@@ -8644,9 +8333,7 @@
 	ast_custom_function_unregister(&feature_function);
 	ast_manager_unregister("Bridge");
 	ast_manager_unregister("Park");
-	ast_manager_unregister("Parkinglots");
-	ast_manager_unregister("ParkedCalls");
-	ast_unregister_application(parkcall);
+
 	ast_unregister_application(parkedcall);
 	ast_unregister_application(app_bridge);
 
@@ -8673,11 +8360,7 @@
 	}
 	ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
 	res = ast_register_application2(parkedcall, parked_call_exec, NULL, NULL, NULL);
-	if (!res)
-		res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
 	if (!res) {
-		ast_manager_register_xml_core("ParkedCalls", 0, manager_parking_status);
-		ast_manager_register_xml_core("Parkinglots", 0, manager_parkinglot_list);
 		ast_manager_register_xml_core("Park", EVENT_FLAG_CALL, manager_park);
 		ast_manager_register_xml_core("Bridge", EVENT_FLAG_CALL, action_bridge);
 	}

Modified: team/jrose/bridge_projects/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/manager.c?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/main/manager.c (original)
+++ team/jrose/bridge_projects/main/manager.c Tue Mar 19 16:05:58 2013
@@ -92,6 +92,7 @@
 #include "asterisk/stringfields.h"
 #include "asterisk/presencestate.h"
 #include "asterisk/stasis.h"
+#include "asterisk/parking.h"
 
 /*** DOCUMENTATION
 	<manager name="Ping" language="en_US">
@@ -1129,6 +1130,8 @@
 };
 
 static struct stasis_subscription *channel_state_sub;
+
+static struct stasis_subscription *parking_lot_sub;
 
 static void acl_change_event_cb(const struct ast_event *event, void *userdata);
 
@@ -7538,6 +7541,82 @@
 		      channel_name, name, value, uniqueid);
 }
 
+static void parked_call(struct parked_call_payload *parked_call)
+{
+	char *event_type;
+
+	switch (parked_call->event_type) {
+	case PARKED_CALL:
+		event_type = "ParkedCall";
+		break;
+	case PARKED_CALL_TIMEOUT:
+		event_type = "ParkedCallTimeOut";
+		break;
+	case PARKED_CALL_GIVEUP:
+		event_type = "ParkedCallGiveUp";
+		break;
+	case PARKED_CALL_UNPARKED:
+		event_type = "UnParkedCall";
+		break;
+	}
+
+	manager_event(EVENT_FLAG_DIALPLAN, event_type,
+			"ParkingSpace: %s\r\n"
+
+			"Channel: %s\r\n"
+			"CallerIDNum: %s\r\n"
+			"CallerIDName: %s\r\n"
+			"ConnectedLineNum: %s\r\n"
+			"ConnectedLineName: %s\r\n"
+			"UniqueID: %s\r\n"
+
+			"ParkingLot: %s\r\n"
+			"Parker: %s\r\n"
+			"Timeout: %s\r\n"
+			"Duration: %s\r\n"
+			"List: %s\r\n"
+			"Item: %d\r\n"
+			"Total: %d\r\n",
+
+			parked_call->parkingspace,
+
+			parked_call->parkee->name,
+			parked_call->parkee->caller_number,
+			parked_call->parkee->caller_name,
+			parked_call->parkee->connected_number,
+			parked_call->parkee->connected_name,
+			parked_call->parkee->uniqueid,
+
+			parked_call->parkinglot,
+			parked_call->parker->name,
+			parked_call->timeout,
+			parked_call->duration,
+			parked_call->list,
+			parked_call->list_item,
+			parked_call->list_size
+		);
+}
+
+static void parking_lot(struct parking_lot_payload *parking_lot)
+{
+	manager_event(EVENT_FLAG_DIALPLAN, "Parkinglot",
+		"Name: %s\r\n"
+		"StartSpace: %s\r\n"
+		"EndSpace: %s\r\n"
+		"Timeout: %s\r\n"
+		"List: %s\r\n"
+		"Item: %d\r\n"
+		"Total: %d\r\n",
+
+		parking_lot->name,
+		parking_lot->starting_space,
+		parking_lot->ending_space,
+		parking_lot->timeout,
+		parking_lot->list,
+		parking_lot->list_item,
+		parking_lot->list_size);
+}
+
 static void channel_event_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
 {
 	if (stasis_message_type(message) == stasis_cache_update()) {
@@ -7554,6 +7633,17 @@
 		const char *name = varset->snapshot ? varset->snapshot->name : "none";
 		const char *uniqueid = varset->snapshot ? varset->snapshot->uniqueid : "none";
 		channel_varset(name, uniqueid, varset->variable, varset->value);
+	} else if (stasis_message_type(message) == ast_parked_call()) {
+		struct parked_call_payload *parked_call_message = stasis_message_data(message);
+		parked_call(parked_call_message);
+	}
+}
+
+static void parking_lot_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
+{
+	if (stasis_message_type(message) == ast_parking_lot()) {
+		struct parking_lot_payload *parking_lot_message = stasis_message_data(message);
+		parking_lot(parking_lot_message);
 	}
 }
 
@@ -7581,6 +7671,9 @@
 	struct ast_manager_user *user;
 
 	channel_state_sub = stasis_unsubscribe(channel_state_sub);
+
+	stasis_unsubscribe(parking_lot_sub);
+	parking_lot_sub = NULL;
 
 	if (registered) {
 		ast_manager_unregister("Ping");
@@ -7679,6 +7772,10 @@
 			channel_event_cb, NULL);
 	}
 
+	if (!parking_lot_sub) {
+		parking_lot_sub = stasis_subscribe(ast_parking_lot_topic(), parking_lot_cb, NULL);
+	}
+
 	if (!registered) {
 		/* Register default actions */
 		ast_manager_register_xml_core("Ping", 0, action_ping);

Added: team/jrose/bridge_projects/main/parking.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/parking.c?view=auto&rev=383396
==============================================================================
--- team/jrose/bridge_projects/main/parking.c (added)
+++ team/jrose/bridge_projects/main/parking.c Tue Mar 19 16:05:58 2013
@@ -1,0 +1,87 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Jonathan Rose <jrose 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 Parking Core
+ *
+ * \author Jonathan Rose <jrose at digium.com>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/_private.h"
+
+#include "asterisk/parking.h"
+#include "asterisk/stasis.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/channel.h"
+
+/*!
+ * On it's own, this component just provides a means of creating
+ * and retrieving stasis elements for the purpose of issuing
+ * stasis messages related to parking. Actual channel parking
+ * functionality is implemented by resource modules such as
+ * res_parking.
+ */
+
+/*! \brief Message type for parked calls */
+static struct stasis_message_type *__parked_call;
+
+/*! \brief Message type for parking lots */
+static struct stasis_message_type *__parking_lot;
+
+/*! \brief Topic for parking lots */
+static struct stasis_topic *__parking_lot_topic;
+
+struct stasis_message_type *ast_parked_call(void)
+{
+	return __parked_call;
+}
+
+struct stasis_message_type *ast_parking_lot(void)
+{
+	return __parking_lot;
+}
+
+struct stasis_topic *ast_parking_lot_topic(void)
+{
+	return __parking_lot_topic;
+}
+
+/*! \internal
+ * \brief Callback to clean up stasis element
+ */
+static void parking_shutdown(void)
+{
+	ao2_cleanup(__parked_call);
+	ao2_cleanup(__parking_lot);
+	ao2_cleanup(__parking_lot_topic);
+	__parked_call = NULL;
+}
+
+void ast_parking_init(void)
+{
+	__parked_call = stasis_message_type_create("ast_parked_call");
+	__parking_lot = stasis_message_type_create("ast_parking_lot");
+
+	__parking_lot_topic = stasis_topic_create("ast_parking_lot_topic");
+	ast_register_atexit(parking_shutdown);
+}

Propchange: team/jrose/bridge_projects/main/parking.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/jrose/bridge_projects/main/parking.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: team/jrose/bridge_projects/main/parking.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/jrose/bridge_projects/res/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/Makefile?view=diff&rev=383396&r1=383395&r2=383396
==============================================================================
--- team/jrose/bridge_projects/res/Makefile (original)
+++ team/jrose/bridge_projects/res/Makefile Tue Mar 19 16:05:58 2013
@@ -68,3 +68,7 @@
 
 clean::
 	rm -f snmp/*.o snmp/*.i ael/*.o ael/*.i ais/*.o ais/*.i
+	rm -f parking/*.o parking/*.i
+
+$(if $(filter res_parking,$(EMBEDDED_MODS)),modules.link,res_parking.so): $(subst .c,.o,$(wildcard parking/*.c))
+$(subst .c,.o,$(wildcard parking/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_parking)

Added: team/jrose/bridge_projects/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_applications.c?view=auto&rev=383396
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_applications.c (added)
+++ team/jrose/bridge_projects/res/parking/parking_applications.c Tue Mar 19 16:05:58 2013
@@ -1,0 +1,245 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Jonathan Rose <jrose 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 Call Parking Applications
+ *
+ * \author Jonathan Rose <jrose at digium.com>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "res_parking.h"
+#include "asterisk/config.h"
+#include "asterisk/config_options.h"
+#include "asterisk/event.h"
+#include "asterisk/utils.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/features.h"
+#include "asterisk/module.h"
+#include "asterisk/app.h"
+#include "asterisk/say.h"
+
+/*** DOCUMENTATION
+	<application name="Park" language="en_US">
+		<synopsis>
+			Park yourself.
+		</synopsis>
+		<syntax>
+			<parameter name="parking_lot_name">
+				<para>Specify in which parking lot to park a call.</para>
+				<para>The parking lot used is selected in the following order:</para>
+				<para>1) parking_lot_name option to this application</para>
+				<para>2) <variable>PARKINGLOT</variable> variable</para>
+				<para>3) <literal>CHANNEL(parkinglot)</literal> function
+				(Possibly preset by the channel driver.)</para>
+				<para>4) Default parking lot.</para>
+			</parameter>
+			<parameter name="options">
+				<para>A list of options for this parked call.</para>
+				<optionlist>
+					<option name="r">
+						<para>Send ringing instead of MOH to the parked call.</para>
+					</option>
+					<option name="R">
+						<para>Randomize the selection of a parking space.</para>
+					</option>
+					<option name="s">
+						<para>Silence announcement of the parking space number.</para>
+					</option>
+					<option name="c">
+						<argument name="context" required="false" />
+						<argument name="extension" required="false" />
+						<argument name="priority" required="true" />
+						<para>If the parking times out, go to this place in the dialplan
+							instead of where the parking lot defines the call should go.
+						</para>
+					</option>
+					<option name="t">
+						<argument name="duration" required="true" />
+						<para>Use a timeout of <literal>duration</literal> seconds instead
+							of the timeout specified by the parking lot.</para>
+						<para>If you set the <variable>PARKINGEXTEN</variable> variable to a
+							parking space extension in the parking lot, Park() will attempt to park the call
+							on that extension.  If the extension is already is in use then execution
+							will continue at the next priority.</para>
+					</option>
+				</optionlist>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Used to park yourself (typically in combination with a supervised
+			transfer to know the parking space).</para>
+		</description>
+		<see-also>
+			<ref type="application">ParkedCall</ref>
+		</see-also>
+	</application>
+
+ ***/
+
+/* Park a call */
+
+enum park_args {
+	OPT_ARG_COMEBACK,
+	OPT_ARG_TIMEOUT,
+	OPT_ARG_ARRAY_SIZE, /* Always the last element of the enum */
+};
+
+enum park_flags {
+	MUXFLAG_RINGING = (1 << 0),
+	MUXFLAG_RANDOMIZE = (1 << 1),
+	MUXFLAG_NOANNOUNCE = (1 << 2),
+	MUXFLAG_COMEBACK_OVERRIDE = (1 << 3),
+	MUXFLAG_TIMEOUT_OVERRIDE = (1 << 4),
+};
+
+AST_APP_OPTIONS(park_opts, {
+	AST_APP_OPTION('r', MUXFLAG_RINGING),
+	AST_APP_OPTION('R', MUXFLAG_RANDOMIZE),
+	AST_APP_OPTION('s', MUXFLAG_NOANNOUNCE),
+	AST_APP_OPTION_ARG('c', MUXFLAG_COMEBACK_OVERRIDE, OPT_ARG_COMEBACK),
+	AST_APP_OPTION_ARG('t', MUXFLAG_TIMEOUT_OVERRIDE, OPT_ARG_TIMEOUT),
+});
+
+static int apply_option_timeout (int *var, char *timeout_arg)
+{
+	if (ast_strlen_zero(timeout_arg)) {
+		ast_log(LOG_ERROR, "No duration value provided for the timeout ('t') option.\n");
+		return -1;
+	}
+
+	if (sscanf(timeout_arg, "%d", var) != 1 || *var < 0) {
+		ast_log(LOG_ERROR, "Duration value provided for timeout ('t') option must be 0 or greater.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int park_exec(struct ast_channel *chan, const char *data)
+{
+	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
+	RAII_VAR(struct parkeduser *, pu, NULL, ao2_cleanup);
+
+	struct ast_bridge *parking_bridge;
+	struct ast_bridge_features chan_features;
+	struct ast_flags flags = { 0 };
+	char *parse;
+	int time_limit = -1;
+	char *comeback_override = NULL;
+
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(lot_name);
+		AST_APP_ARG(options);
+		AST_APP_ARG(other);	/* Any remaining unused arguments */
+	);
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.options) {
+		char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
+		ast_app_parse_options(park_opts, &flags, opts, args.options);
+		if (ast_test_flag(&flags, MUXFLAG_TIMEOUT_OVERRIDE)) {
+			if (apply_option_timeout(&time_limit, opts[OPT_ARG_TIMEOUT])) {
+				return -1;
+			}
+		}
+		if (ast_test_flag(&flags, MUXFLAG_COMEBACK_OVERRIDE)) {
+			comeback_override = ast_strdupa(opts[OPT_ARG_COMEBACK]);
+		}
+	}
+
+	if (ast_strlen_zero(args.lot_name)) {
+		lot = channel_find_parkinglot(chan);
+	} else {
+		lot = parking_lot_get(args.lot_name);
+	}
+
+	if (!lot) {
+		ast_log(LOG_ERROR, "Could not find the requested parking lot\n");
+		return -1;
+	}
+
+	ao2_lock(lot);
+	parking_bridge = get_parkinglot_bridge(lot);
+	ao2_unlock(lot);
+
+	if (!parking_bridge) {
+		ast_log(LOG_ERROR, "Could not acquire holding bridge to park into\n");
+		return -1;
+	}
+
+	/* answer the channel if needed */
+	if (ast_channel_state(chan) != AST_STATE_UP) {
+		ast_answer(chan);
+	}
+
+	pu = generate_parked_user(lot, chan, chan, ast_test_flag(&flags, MUXFLAG_RANDOMIZE), time_limit);
+
+	if (!pu) {
+		ast_log(LOG_ERROR, "Failed to create parked user for channel %s, can not park.\n", ast_channel_name(chan));
+		return -1;
+	}
+
+	/* If we aren't in silence mode, go ahead and announce the parking space */
+	if (!ast_test_flag(&flags, MUXFLAG_NOANNOUNCE)) {
+		ast_say_digits(chan, pu->parking_space, "", ast_channel_language(chan));
+	}
+
+	ast_bridge_features_init(&chan_features);
+
+	/* Set limits and apply channel roles */
+	parking_set_duration(&chan_features, pu, time_limit);
+	parking_channel_set_roles(chan, lot, ast_test_flag(&flags, MUXFLAG_RINGING));
+
+	/* Alright, now wait in the holding bridge until we get removed from it for some reason. */
+	reset_parked_time(pu);
+	ast_bridge_join(parking_bridge, chan, NULL, &chan_features, NULL, 0);
+	/* XXX After this, depending on the conditions of exit we might want to return early. But that comes later. */
+
+	ast_bridge_features_cleanup(&chan_features);
+
+	/* Remove the parked user from the parking lot if it is still in */
+	unpark_parked_user(pu);
+
+	/* Figure out if we need to go somewhere special now that the timeout has occured */
+	if (ast_test_flag(&flags, MUXFLAG_COMEBACK_OVERRIDE)) {
+		if (ast_parseable_goto(chan, comeback_override)) {
+			return -1;
+		}
+	} else {
+		if (comeback_goto(pu, lot)) {
+			return -1;
+		}
+	}
+
+	/* Since this is executed from pbx, it'll automatically bump the priority when we return. We can address that by reducing it by 1 in before returning. Smooth. */
+	ast_channel_priority_set(chan, ast_channel_priority(chan) - 1);
+
+	return ast_check_hangup_locked(chan) ? -1 : 0;
+}
+
+void *parking_get_park_app_cb()
+{
+	return park_exec;
+}

Propchange: team/jrose/bridge_projects/res/parking/parking_applications.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/jrose/bridge_projects/res/parking/parking_applications.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: team/jrose/bridge_projects/res/parking/parking_applications.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/jrose/bridge_projects/res/parking/parking_controller.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_controller.c?view=auto&rev=383396
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_controller.c (added)
+++ team/jrose/bridge_projects/res/parking/parking_controller.c Tue Mar 19 16:05:58 2013
@@ -1,0 +1,429 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Jonathan Rose <jrose 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 Parking Entry, Exit, Events, and other assorted controls.
+ *
+ * \author Jonathan Rose <jrose at digium.com>
+ */
+#include "asterisk.h"
+
+#include "asterisk/logger.h"
+#include "res_parking.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/utils.h"
+#include "asterisk/manager.h"
+#include "asterisk/test.h"
+
+static void parked_call_payload_destructor(void *obj)
+{
+	struct parked_call_payload *park_obj = obj;
+
+	ao2_cleanup(park_obj->parkee);
+	ao2_cleanup(park_obj->parker);
+	ast_string_field_free_memory(park_obj);
+}
+
+void publish_parked_call(struct parkeduser *pu, const char *list, int list_item, int list_size, enum parked_call_event_type event_type)
+{
+	RAII_VAR(struct parked_call_payload *, payload, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+	struct timeval now = ast_tvnow();
+	char timeout_text[32] = "";
+
+	payload = ao2_alloc(sizeof(*payload), parked_call_payload_destructor);
+	if (!payload) {
+		return;
+	}
+
+	if (ast_string_field_init(payload, 32)) {
+		return;
+	}
+
+	if (pu->chan) {
+		payload->parkee = ast_channel_snapshot_create(pu->chan);
+		if (!payload->parkee) {
+			return;
+		}
+	}
+
+	payload->event_type = event_type;
+
+	/* The parked user absolutely must have a parker snapshot for events to be valid. */
+	if (!pu->parker) {
+		return;
+	}
+
+	ao2_ref(pu->parker, +1);
+	payload->parker = pu->parker;
+
+	if (!pu->time_limit) {
+		snprintf(timeout_text, sizeof(timeout_text), "(no time limit)");
+	} else {
+		snprintf(timeout_text, sizeof(timeout_text), "%ld", pu->start.tv_sec + (long) pu->time_limit - now.tv_sec);
+	}
+
+	ast_string_field_set(payload, parkinglot, pu->lot->name);
+	ast_string_field_build(payload, parkingspace, "%d", pu->parking_space);
+	ast_string_field_set(payload, timeout, timeout_text);
+	ast_string_field_build(payload, duration, "%ld", now.tv_sec - pu->start.tv_sec);
+
+	if (list) {
+		ast_string_field_set(payload, list, list);
+		payload->list_item = list_item;
+		payload->list_size = list_size;
+	}
+

[... 1564 lines stripped ...]



More information about the asterisk-commits mailing list