[asterisk-commits] branch oej/test-this-branch r12134 - in /team/oej/test-this-branch: ./ channe...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon Mar 6 13:30:13 MST 2006


Author: oej
Date: Mon Mar  6 14:30:09 2006
New Revision: 12134

URL: http://svn.digium.com/view/asterisk?rev=12134&view=rev
Log:
Adding branch "metermaids-trunk" to this branch.

Modified:
    team/oej/test-this-branch/README.test-this-branch
    team/oej/test-this-branch/channels/chan_local.c
    team/oej/test-this-branch/include/asterisk/features.h
    team/oej/test-this-branch/res/res_features.c

Modified: team/oej/test-this-branch/README.test-this-branch
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/README.test-this-branch?rev=12134&r1=12133&r2=12134&view=diff
==============================================================================
--- team/oej/test-this-branch/README.test-this-branch (original)
+++ team/oej/test-this-branch/README.test-this-branch Mon Mar  6 14:30:09 2006
@@ -26,6 +26,7 @@
 - cdr_radius: CDR support for Radius (#6639, phsultan). See doc/cdrdriver.txt
 - amieventhook-561 rev 11712: Support for manager event hooks (#5161, anthm)
 - func_realtime: Realtime dialplan function (bweschke, #5695)
+- metermaids: Subscription support for parking lots (#5779)
 
 And the following stand-alone patches
 - New CLI commands for global variables (oej, #6506)
@@ -37,7 +38,6 @@
 - Support SIP_CODEC for early media (oej, #6576)
 
 Coming here soon:
-- metermaids: Subscription support for parking lots (#5779)
 - siptransfer: Improved SIP transfer support
 
 All of these exist in the bug tracker. Please report your findings
@@ -48,6 +48,13 @@
 ----------------------------
 - res_features with multiparking craches on AMD64
 - res_features have problems with reload
+
+* Metermaids
+------------
+Metermaids is a way to watch the status of a parking lot through a SIP
+subscription. Add a hint pointing to Local/exten at parkinglot and subscribe
+to that extension. Whenever someone parkings in that parking lot, you
+will see it in the subscribing phone.
 
 * The Generic Jitterbuffer
 --------------------------

Modified: team/oej/test-this-branch/channels/chan_local.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/channels/chan_local.c?rev=12134&r1=12133&r2=12134&view=diff
==============================================================================
--- team/oej/test-this-branch/channels/chan_local.c (original)
+++ team/oej/test-this-branch/channels/chan_local.c Mon Mar  6 14:30:09 2006
@@ -60,9 +60,13 @@
 #include "asterisk/musiconhold.h"
 #include "asterisk/manager.h"
 #include "asterisk/stringfields.h"
+#include "asterisk/devicestate.h"
+#include "asterisk/features.h"
 
 static const char desc[] = "Local Proxy Channel";
 static const char tdesc[] = "Local Proxy Channel Driver";
+
+static int watchid;	/* Metermaid watcher ID assigned by res_features */
 
 static int usecnt =0;
 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
@@ -79,6 +83,7 @@
 static int local_indicate(struct ast_channel *ast, int condition);
 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
+static int local_devicestate(void *data);
 
 /* PBX interface structure for channel registration */
 static const struct ast_channel_tech local_tech = {
@@ -96,6 +101,7 @@
 	.indicate = local_indicate,
 	.fixup = local_fixup,
 	.send_html = local_sendhtml,
+	.devicestate = local_devicestate,
 };
 
 struct local_pvt {
@@ -114,6 +120,37 @@
 };
 
 static AST_LIST_HEAD_STATIC(locals, local_pvt);
+
+/*! \brief Watcher callback for extension state changes in res_features */
+void local_watcher(char *exten, char *context) {
+	if (option_debug > 1)
+		ast_log(LOG_DEBUG, "Got notification of state change for %s@%s\n", exten, context);
+	ast_device_state_changed("local/%s@%s", exten, context);
+	return;
+}
+
+/*! ! \brief Adds devicestate to extensions (for parking mostly) 
+*/
+static int local_devicestate(void *data)
+{
+	char *exten;
+	char *context;
+
+	int res = AST_DEVICE_INVALID;
+		
+	exten = ast_strdupa(data);
+	if ((context  = strchr(exten, '@'))) {
+		*context = '\0';
+		context = context + 1;
+	}
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
+	res = ast_exists_extension(NULL, context, exten, 1, NULL);
+	if (!res)
+		return AST_DEVICE_UNAVAILABLE;
+	else
+		return AST_DEVICE_NOT_INUSE;
+}
 
 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us)
 {
@@ -573,6 +610,9 @@
 		ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
 		return -1;
 	}
+
+	/* Register watcher for parking lots in res_features */
+	watchid = ast_park_metermaid_add(&local_watcher, NULL);
 	ast_cli_register(&cli_show_locals);
 	return 0;
 }
@@ -590,6 +630,7 @@
 
 	/* First, take us out of the channel loop */
 	ast_cli_unregister(&cli_show_locals);
+	ast_park_metermaid_remove(watchid);
 	ast_channel_unregister(&local_tech);
 	if (!AST_LIST_LOCK(&locals)) {
 		/* Hangup all interfaces if they have an owner */

Modified: team/oej/test-this-branch/include/asterisk/features.h
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/include/asterisk/features.h?rev=12134&r1=12133&r2=12134&view=diff
==============================================================================
--- team/oej/test-this-branch/include/asterisk/features.h (original)
+++ team/oej/test-this-branch/include/asterisk/features.h Mon Mar  6 14:30:09 2006
@@ -92,4 +92,17 @@
     \param feature the ast_call_feature object which was registered before*/
 extern void ast_unregister_feature(struct ast_call_feature *feature);
 
+
+/*! \brief Add parking watcher (metermaid) to list. These will be notified when we create
+ 	or remove parking extensions in the dial plan 
+		
+ */
+int ast_park_metermaid_add(void (*maid)(char *exten, char *context), char *context);
+
+/*! Remove parking watcher 
+	\param id	Watcher ID returned by ast_park_metermaid_add()
+	\return -1 on error (ID not found), otherwise 0
+*/
+int ast_park_metermaid_remove(int id);
+
 #endif /* _AST_FEATURES_H */

Modified: team/oej/test-this-branch/res/res_features.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/res/res_features.c?rev=12134&r1=12133&r2=12134&view=diff
==============================================================================
--- team/oej/test-this-branch/res/res_features.c (original)
+++ team/oej/test-this-branch/res/res_features.c Mon Mar  6 14:30:09 2006
@@ -14,22 +14,6 @@
  * 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.
- */
-
-/*----------------- BRANCH NOTE *------------------------------ 
- * This code is under development 
- *
- * Input is appreciated, e-mail to oej at edvina.net
- *
- *	Goal:
- *	 To implement multiple parking lots, so that if you
- *	 run a virtual PBX with many customers in the same
- * 	 Asterisk, you can set up multiple parking lots
- *	 Or one for each group in your company
- * 	 And maybe a special VIP parking lot for the boss :-)
- *
- *	Plase add test reviews to the bug tracker
- *	http://bugs.digium.com/view.php?id=6113
  */
 
 /*! \file
@@ -90,6 +74,18 @@
 
 #define AST_MAX_WATCHERS 256
 
+/*! List of meter maids (parking lot watchers) */
+struct features_parkwatch {
+	void (*callback)(char *exten, char *context);	/*! Callback for notification */
+	int id;						/*! Meter maid ID */
+	char *context;					/*! Watched context */
+	struct features_parkwatch *next;		/*! Next in this simple list */
+};
+
+/*! Metermaid ID */
+struct features_parkwatch *metermaids;
+int metermaidid = 0;
+
 static char *parkedcall = "ParkedCall";
 
 static int parkingtime = DEFAULT_PARK_TIME;		/*!< No more than 45 seconds parked before you do something with them */
@@ -115,6 +111,7 @@
 	int parking_offset;
 	int parkfindnext;
 	int parkingtime;				/*!< Default parking time */
+	int parkaddhints;				/*!< Add hints by default */
 	struct parkeduser *occupiedlots;
 	AST_LIST_ENTRY(ast_parkinglot) list;		/*!< List entry */
 };
@@ -175,6 +172,8 @@
 AST_MUTEX_DEFINE_STATIC(parking_lock);
 
 static pthread_t parking_thread;
+
+STANDARD_LOCAL_USER;
 
 LOCAL_USER_DECL;
 
@@ -291,6 +290,88 @@
 	return adsi_print(chan, message, justify, 1);
 }
 
+/*! Add parking watcher (metermaid) to list. These will be notified when we create
+ 	or remove parking extensions in the dial plan 
+ */
+int ast_park_metermaid_add(void (*maid)(char *exten, char *context), char *context)
+{
+	struct features_parkwatch *newmaid;
+	struct features_parkwatch *maids = metermaids;
+
+	newmaid = malloc(sizeof(struct features_parkwatch));
+	if (!newmaid) {
+		ast_log(LOG_ERROR, "Can't allocate parking watcher, out of memory.\n");
+		return -1;
+	}
+	memset(newmaid, 0, sizeof(struct features_parkwatch));
+
+	/* Spool till end of list */
+	while(maids && maids->next) {
+		maids = maids->next;
+	}
+
+	newmaid->callback = maid;
+	if (context)
+		newmaid->context = strdup(context);
+	newmaid->id = metermaidid;
+
+	/* Generate new ID */
+	metermaidid++;
+
+	/* Link the new object to the list */
+	if (maids)
+		maids->next = newmaid;
+	else
+		metermaids = newmaid;
+	if (option_debug > 1)
+		ast_log(LOG_DEBUG, "Added metermaid # %d\n", metermaidid);
+	return metermaidid;
+}
+
+/*! Remove parking watcher */
+int ast_park_metermaid_remove(int id)
+{
+	struct features_parkwatch *maids = metermaids;
+	struct features_parkwatch *prev = NULL;
+	struct features_parkwatch *kill = NULL;
+
+	while (maids && !kill) {
+		if (maids->id == id) {
+			if (prev) {
+				prev->next = maids->next;
+			} else {
+				metermaids = maids->next;
+			}
+			kill = maids;
+		}
+		prev = maids;
+		maids = maids->next;
+	}
+	if (!kill)
+		return -1;		/* Did not find id */
+	if (kill->context)
+		free(kill->context);
+	free(kill);
+	return 0;
+}
+
+/*! Notify metermaids that we've changed an extension */
+static void notify_metermaids(char *exten, char *context)
+{
+	struct features_parkwatch *maid = metermaids;
+	if (!maid)
+		return;
+	while (maid) {
+		if (!maid->context || !strcmp(context, maid->context))
+			maid->callback(exten, context);
+		maid = maid->next;
+	}
+	if (option_debug > 3)
+		ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
+	return;
+}
+
+
 /*! \brief Find parking lot name from channel */
 static const char *findparkinglotname(struct ast_channel *chan)
 {
@@ -318,8 +399,6 @@
 	char exten[AST_MAX_EXTENSION];
 	struct ast_context *con;
 	const char *parkinglotname;
-	
-
 
 	parkinglotname = findparkinglotname(peer);
 
@@ -438,7 +517,9 @@
 	}
 	if (con) {
 		snprintf(exten, sizeof(exten), "%d", x);
-		ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar);
+	
+		if (ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar) == 0)
+			notify_metermaids(exten, parkinglot->parking_con);	/* Notify watchers */
 	}
 	if (peer) 
 		ast_say_digits(peer, pu->parkingnum, "", peer->language);
@@ -1632,6 +1713,8 @@
 						snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
 						if (ast_context_remove_extension2(con, exten, 1, NULL))
 							ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+						else
+							notify_metermaids(exten, pt->parkinglot->parking_con);
 					} else
 						ast_log(LOG_WARNING, "Whoa, no parking context?\n");
 					free(pt);
@@ -1672,6 +1755,8 @@
 									snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
 									if (ast_context_remove_extension2(con, exten, 1, NULL))
 										ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+									else
+										notify_metermaids(exten, curlot->parking_con);
 								} else
 									ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
 								free(pt);
@@ -1820,6 +1905,8 @@
 			snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
 			if (ast_context_remove_extension2(con, exten, 1, NULL))
 				ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+			else
+				notify_metermaids(exten, pu->parkinglot->parking_con);
 		} else
 			ast_log(LOG_WARNING, "Whoa, no parking context?\n");
 
@@ -2140,6 +2227,20 @@
 	free(ruin);
 }
 
+/*! \brief Add dialplants hints for each parking lot */
+static void park_add_hints(char *context, int start, int stop)
+{
+ 	int numext;
+ 	char device[AST_MAX_EXTENSION];
+ 	char exten[10];
+ 	for (numext = start; numext <= stop; numext++) {
+ 		snprintf(exten, sizeof(exten), "%d", numext);
+ 		snprintf(device, sizeof(device), "Local/%s@%s", exten, context);
+ 		ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
+ 	}
+}
+
+
 /*! \brief Build parkinglot from configuration and chain it in */
 static struct ast_parkinglot *build_parkinglot(char *name, struct ast_variable *var)
 {
@@ -2162,12 +2263,14 @@
 	while(confvar) {
 		if (!strcasecmp(confvar->name, "context")) {
 			ast_copy_string(parkinglot->parking_con, confvar->value, sizeof(parkinglot->parking_con));
+		} else if (!strcasecmp(confvar->name, "parkhints")) {
+			parkinglot->parkaddhints = ast_true(var->value);
 		} else if (!strcasecmp(confvar->name, "parkingtime")) {
 			if ((sscanf(confvar->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
 				ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", confvar->value);
-				parkingtime = DEFAULT_PARK_TIME;
+				parkinglot->parkingtime = DEFAULT_PARK_TIME;
 			} else
-				parkingtime = parkingtime * 1000;
+				parkinglot->parkingtime = parkingtime * 1000;
 		} else if (!strcasecmp(confvar->name, "parkpos")) {
 			if (sscanf(confvar->value, "%d-%d", &start, &end) != 2) {
 				ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", confvar->lineno);
@@ -2203,6 +2306,9 @@
 	if (ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar) == -1)
 		error = 1;
 
+	if (parkinglot->parkaddhints)
+		park_add_hints(parkinglot->parking_con, parkinglot->parking_start, parkinglot->parking_stop);
+
 	if (error) {
 		ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
 		destroy_parkinglot(parkinglot);
@@ -2228,7 +2334,7 @@
 	char *section;
 	char old_parking_ext[AST_MAX_EXTENSION];
 	char old_parking_con[AST_MAX_EXTENSION] = "";
-
+	int res;
 
 	strcpy(old_parking_ext, parking_ext);
 	if (default_parkinglot) {
@@ -2240,6 +2346,7 @@
 			default_parkinglot->parking_stop = 750;
 			default_parkinglot->parking_offset = 0;
 			default_parkinglot->parkfindnext = 0;
+			default_parkinglot->parkaddhints = 0;
 			default_parkinglot->parkingtime = 0;
 		}
 	}
@@ -2416,7 +2523,8 @@
 	
 	/* Remove the old parking extension */
 	if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))	{
-		ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
+		if(!ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
+			notify_metermaids(old_parking_ext, old_parking_con);
 		ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
 	}
 
@@ -2426,7 +2534,13 @@
 			return -1;
 		}
 	}
-	return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
+	res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
+
+	if (default_parkinglot->parkaddhints)
+		park_add_hints(default_parkinglot->parking_con, default_parkinglot->parking_start, default_parkinglot->parking_stop);
+	if (!res)
+		notify_metermaids(ast_parking_ext(), default_parkinglot->parking_con);
+	return res;
 }
 
 int reload(void) {



More information about the asterisk-commits mailing list