[asterisk-commits] jpeeler: trunk r286939 - in /trunk: ./ channels/ channels/sip/include/ config...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Sep 15 14:24:02 CDT 2010


Author: jpeeler
Date: Wed Sep 15 14:23:56 2010
New Revision: 286939

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=286939
Log:
Merged revisions 286931 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r286931 | jpeeler | 2010-09-15 14:22:15 -0500 (Wed, 15 Sep 2010) | 16 lines
  
  Add parking extension for non-default parking lots.
  
  This is a new feature that allows for parking to custom parking lots to be
  accessed directly, rather than with channel variables or by changing the
  default parking lot. The extension is set with the parkext option just as the
  default parking lot is done. Also, the manager action has been updated to
  optionally allow a specified parking lot.
  
  (closes issue #14882)
  Reported by: vmikhnevych
  Patches: 
        patch_14882.txt uploaded by mnick (license 874)
        modified by me
  
  Review: https://reviewboard.asterisk.org/r/884/
........

Modified:
    trunk/   (props changed)
    trunk/CHANGES
    trunk/channels/chan_dahdi.c
    trunk/channels/chan_iax2.c
    trunk/channels/chan_mgcp.c
    trunk/channels/chan_sip.c
    trunk/channels/sig_analog.c
    trunk/channels/sip/include/sip.h
    trunk/configs/features.conf.sample
    trunk/include/asterisk/features.h
    trunk/main/features.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Wed Sep 15 14:23:56 2010
@@ -436,6 +436,7 @@
    conform more closely to similar events.
  * Added a new eventfilter option per user to allow whitelisting and blacklisting
    of events.
+ * Added optional parkinglot variable for park command.
 
 Channel Event Logging
 ---------------------
@@ -1515,6 +1516,8 @@
   * Added cli command 'features reload' to reload call features from features.conf
   * Moved into core asterisk binary.
   * Changed the default setting for featuredigittimeout to 2000 ms from 500 ms.
+  * Added the ability for custom parking lots to be configured with their own
+    parking extension with the parkext option.
 
 Language Support Changes
 ------------------------

Modified: trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Wed Sep 15 14:23:56 2010
@@ -9739,7 +9739,7 @@
 				tone_zone_play_tone(p->subs[idx].dfd, -1);
 			else
 				tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
-			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
+			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
 				if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
 					if (getforward) {
 						/* Record this as the forwarding extension */
@@ -9875,7 +9875,7 @@
 				getforward = 0;
 				memset(exten, 0, sizeof(exten));
 				len = 0;
-			} else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
+			} else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
 						p->subs[SUB_THREEWAY].owner &&
 						ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
 				/* This is a three way call, the main call being a real channel,

Modified: trunk/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_iax2.c?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Wed Sep 15 14:23:56 2010
@@ -9112,7 +9112,7 @@
 	memset(&ied1, 0, sizeof(ied1));
 	mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
 	/* Must be started */
-	if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
+	if (ast_parking_ext_valid(callednum, NULL, context) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
 		dpstatus = IAX_DPSTATUS_EXISTS;
 	} else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
 		dpstatus = IAX_DPSTATUS_CANEXIST;
@@ -9167,6 +9167,7 @@
 struct iax_dual {
 	struct ast_channel *chan1;
 	struct ast_channel *chan2;
+	const char *parkexten;
 };
 
 static void *iax_park_thread(void *stuff)
@@ -9183,13 +9184,13 @@
 	f = ast_read(chan1);
 	if (f)
 		ast_frfree(f);
-	res = ast_park_call(chan1, chan2, 0, &ext);
+	res = ast_park_call(chan1, chan2, 0, d->parkexten, &ext);
 	ast_hangup(chan2);
 	ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
 	return NULL;
 }
 
-static int iax_park(struct ast_channel *chan1, struct ast_channel *chan2)
+static int iax_park(struct ast_channel *chan1, struct ast_channel *chan2, const char *parkexten)
 {
 	struct iax_dual *d;
 	struct ast_channel *chan1m, *chan2m;
@@ -9231,6 +9232,7 @@
 	if ((d = ast_calloc(1, sizeof(*d)))) {
 		d->chan1 = chan1m;
 		d->chan2 = chan2m;
+		d->parkexten = parkexten;
 		if (!ast_pthread_create_detached_background(&th, NULL, iax_park_thread, d)) {
 			return 0;
 		}
@@ -10604,10 +10606,10 @@
 					}
 
 					pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name);
-					if (!strcmp(ies.called_number, ast_parking_ext())) {
+					if (ast_parking_ext_valid(ies.called_number, c, iaxs[fr->callno]->context)) {
 						struct ast_channel *saved_channel = iaxs[fr->callno]->owner;
 						ast_mutex_unlock(&iaxsl[fr->callno]);
-						if (iax_park(bridged_chan, saved_channel)) {
+						if (iax_park(bridged_chan, saved_channel, ies.called_number)) {
 							ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name);
 						} else {
 							ast_debug(1, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);

Modified: trunk/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_mgcp.c?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/channels/chan_mgcp.c (original)
+++ trunk/channels/chan_mgcp.c Wed Sep 15 14:23:56 2010
@@ -3107,7 +3107,7 @@
 			getforward = 0;
 			memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
 			len = 0;
-		} else if (!strcmp(p->dtmf_buf, ast_parking_ext()) &&
+		} else if (ast_parking_ext_valid(p->dtmf_buf, chan, chan->context) &&
 			sub->next->owner && ast_bridged_channel(sub->next->owner)) {
 			/* This is a three way call, the main call being a real channel,
 			   and we're parking the first call. */

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Sep 15 14:23:56 2010
@@ -1260,7 +1260,7 @@
 static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);
 static void check_pendings(struct sip_pvt *p);
 static void *sip_park_thread(void *stuff);
-static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno);
+static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno, char *parkexten);
 static int sip_sipredirect(struct sip_pvt *p, const char *dest);
 static int is_method_allowed(unsigned int *allowed_methods, enum sipmethod method);
 
@@ -4877,7 +4877,9 @@
 	ast_string_field_set(dialog, cid_name, peer->cid_name);
 	ast_string_field_set(dialog, cid_tag, peer->cid_tag);
 	ast_string_field_set(dialog, mwi_from, peer->mwi_from);
-	ast_string_field_set(dialog, parkinglot, peer->parkinglot);
+	if (!ast_strlen_zero(peer->parkinglot)) {
+		ast_string_field_set(dialog, parkinglot, peer->parkinglot);
+	}
 	ast_string_field_set(dialog, engine, peer->engine);
 	ref_proxy(dialog, obproxy_get(dialog, peer));
 	dialog->callgroup = peer->callgroup;
@@ -14891,7 +14893,9 @@
 	ast_string_field_set(p, subscribecontext, peer->subscribecontext);
 	ast_string_field_set(p, mohinterpret, peer->mohinterpret);
 	ast_string_field_set(p, mohsuggest, peer->mohsuggest);
-	ast_string_field_set(p, parkinglot, peer->parkinglot);
+	if (!ast_strlen_zero(peer->parkinglot)) {
+		ast_string_field_set(p, parkinglot, peer->parkinglot);
+	}
 	ast_string_field_set(p, engine, peer->engine);
 	p->disallowed_methods = peer->disallowed_methods;
 	set_pvt_allowed_methods(p, req);
@@ -20054,7 +20058,7 @@
 		return NULL;
 	}
 
-	res = ast_park_call(transferee, transferer, 0, &ext);
+	res = ast_park_call(transferee, transferer, 0, d->parkexten, &ext);
 	
 
 #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
@@ -20091,7 +20095,7 @@
 /*! \brief Park a call using the subsystem in res_features.c
 	This is executed in a separate thread
 */
-static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno)
+static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno, char *parkexten)
 {
 	struct sip_dual *d;
 	struct ast_channel *transferee, *transferer;
@@ -20172,6 +20176,7 @@
 		d->chan1 = transferee;	/* Transferee */
 		d->chan2 = transferer;	/* Transferer */
 		d->seqno = seqno;
+		d->parkexten = parkexten;
 		if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) {
 			/* Could not start thread */
 			deinit_req(&d->req);
@@ -22064,9 +22069,8 @@
 		/* Fallthrough if we can't find the call leg internally */
 	}
 
-
 	/* Parking a call */
-	if (p->refer->localtransfer && !strcmp(p->refer->refer_to, ast_parking_ext())) {
+	if (p->refer->localtransfer && ast_parking_ext_valid(p->refer->refer_to, p->owner, p->owner->context)) {
 		/* Must release c's lock now, because it will not longer be accessible after the transfer! */
 		*nounlock = 1;
 		ast_channel_unlock(current.chan1);
@@ -22083,7 +22087,7 @@
 			p->refer->refer_to);
 		if (sipdebug)
 			ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", current.chan2->name, current.chan1->name);
-		sip_park(current.chan2, current.chan1, req, seqno);
+		sip_park(current.chan2, current.chan1, req, seqno, p->refer->refer_to);
 		return res;
 	}
 
@@ -26486,6 +26490,7 @@
 	ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833);			/*!< Default DTMF setting: RFC2833 */
 	ast_set_flag(&global_flags[0], SIP_DIRECT_MEDIA);			/*!< Allow re-invites */
 	ast_copy_string(default_engine, DEFAULT_ENGINE, sizeof(default_engine));
+	ast_copy_string(default_parkinglot, DEFAULT_PARKINGLOT, sizeof(default_parkinglot));
 
 	/* Debugging settings, always default to off */
 	dumphistory = FALSE;
@@ -26994,7 +26999,9 @@
 				ast_log(LOG_WARNING, "subscribe_network_change_event value %s is not valid at line %d.\n", v->value, v->lineno);
 			}
 		} else if (!strcasecmp(v->name, "snom_aoc_enabled")) {
-				ast_set2_flag(&global_flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
+			ast_set2_flag(&global_flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
+		} else if (!strcasecmp(v->name, "parkinglot")) {
+			ast_copy_string(default_parkinglot, v->value, sizeof(default_parkinglot));
 		}
 	}
 

Modified: trunk/channels/sig_analog.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sig_analog.c?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/channels/sig_analog.c (original)
+++ trunk/channels/sig_analog.c Wed Sep 15 14:23:56 2010
@@ -1939,7 +1939,7 @@
 			} else {
 				analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
 			}
-			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
+			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
 				if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
 					if (getforward) {
 						/* Record this as the forwarding extension */
@@ -2090,7 +2090,7 @@
 				getforward = 0;
 				memset(exten, 0, sizeof(exten));
 				len = 0;
-			} else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
+			} else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
 						p->subs[ANALOG_SUB_THREEWAY].owner &&
 						ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
 				/* This is a three way call, the main call being a real channel,

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Wed Sep 15 14:23:56 2010
@@ -768,6 +768,7 @@
 	struct ast_channel *chan2;   /*!< Second channel involved */
 	struct sip_request req;      /*!< Request that caused the transfer (REFER) */
 	int seqno;                   /*!< Sequence number */
+	const char *parkexten;
 };
 
 /*! \brief Parameters to the transmit_invite function */

Modified: trunk/configs/features.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/features.conf.sample?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/configs/features.conf.sample (original)
+++ trunk/configs/features.conf.sample Wed Sep 15 14:23:56 2010
@@ -3,7 +3,7 @@
 ;
 
 [general]
-parkext => 700			; What extension to dial to park	(all parking lots)
+parkext => 700			; What extension to dial to park
 parkpos => 701-720		; What extensions to park calls on. (defafult parking lot)
 				; These needs to be numeric, as Asterisk starts from the start position
 				; and increments with one for the next parked call.
@@ -85,6 +85,7 @@
 ;
 ;[parkinglot_edvina]
 ;context => edvinapark
+;parkext => 799
 ;parkpos => 800-850
 ;findslot => next
 

Modified: trunk/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/features.h?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/include/asterisk/features.h (original)
+++ trunk/include/asterisk/features.h Wed Sep 15 14:23:56 2010
@@ -35,6 +35,7 @@
 #define FEATURE_MOH_LEN		80  /* same as MAX_MUSICCLASS from channel.h */
 
 #define PARK_APP_NAME "Park"
+#define DEFAULT_PARKINGLOT "default"	/*!< Default parking lot */
 
 #define AST_FEATURE_RETURN_HANGUP           -1
 #define AST_FEATURE_RETURN_SUCCESSBREAK     0
@@ -90,7 +91,7 @@
  * \retval 0 on success.
  * \retval -1 on failure.
 */
-int ast_park_call(struct ast_channel *chan, struct ast_channel *host, int timeout, int *extout);
+int ast_park_call(struct ast_channel *chan, struct ast_channel *host, int timeout, const char *parkexten, int *extout);
 
 /*! 
  * \brief Park a call via a masqueraded channel
@@ -106,10 +107,11 @@
 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
 
 /*! 
- * \brief Determine system parking extension
- * \returns the call parking extension for drivers that provide special call parking help 
+ * \brief Determine if parking extension exists in a given context
+ * \retval 0 if extension does not exist
+ * \retval 1 if extension does exist
 */
-const char *ast_parking_ext(void);
+int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context);
 
 /*! \brief Determine system call pickup extension */
 const char *ast_pickup_ext(void);

Modified: trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/features.c?view=diff&rev=286939&r1=286938&r2=286939
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Wed Sep 15 14:23:56 2010
@@ -257,6 +257,9 @@
 			<parameter name="Timeout">
 				<para>Number of milliseconds to wait before callback.</para>
 			</parameter>
+			<parameter name="Parkinglot">
+				<para>Parking lot to park channel in.</para>
+			</parameter>
 		</syntax>
 		<description>
 			<para>Park a channel.</para>
@@ -289,10 +292,10 @@
  ***/
 
 #define DEFAULT_PARK_TIME 45000
+#define DEFAULT_PARK_EXTENSION "700"
 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000
 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
-#define DEFAULT_PARKINGLOT "default"			/*!< Default parking lot */
 #define DEFAULT_ATXFER_DROP_CALL 0
 #define DEFAULT_ATXFER_LOOP_DELAY 10000
 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
@@ -345,6 +348,7 @@
 /*! \brief Structure for parking lots which are put in a container. */
 struct ast_parkinglot {
 	char name[AST_MAX_CONTEXT];
+	char parkext[AST_MAX_EXTENSION];				/*!< Parkingextension */
 	char parking_con[AST_MAX_EXTENSION];		/*!< Context for which parking is made accessible */
 	char parking_con_dial[AST_MAX_EXTENSION];	/*!< Context for dialback for parking (KLUDGE) */
 	int parking_start;				/*!< First available extension for parking */
@@ -358,6 +362,7 @@
 	int parkedcallreparking;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
 	int parkedcallhangup;                           /*!< Enable DTMF based hangup on a bridge when pickup up parked calls */
 	int parkedcallrecording;                        /*!< Enable DTMF based recording on a bridge when picking up parked calls */
+	unsigned short the_mark:1;                      /*!< Used during reloads, that which bears the_mark shall be deleted! */
 	AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
 };
 
@@ -443,9 +448,47 @@
 static struct ast_parkinglot *create_parkinglot(const char *name);
 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
 
-const char *ast_parking_ext(void)
-{
-	return parking_ext;
+static int find_parkinglot_by_position_cb(void *obj, void *args, int flags)
+{
+	struct ast_parkinglot *parkinglot = obj;
+	int *parkpos = args;
+
+	if (*parkpos >= parkinglot->parking_start && *parkpos <= parkinglot->parking_stop) {
+		return CMP_MATCH | CMP_STOP;
+	}
+
+	return 0;
+}
+
+static int find_parkinglot_by_exten_cb(void *obj, void *args, int flags)
+{
+	struct ast_parkinglot *parkinglot = obj;
+	const char *parkext = args;
+
+	if (!strcmp(parkinglot->parkext, parkext)) {
+		return CMP_MATCH | CMP_STOP;
+	}
+
+	return 0;
+}
+
+int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
+{
+	struct ast_exten *exten;
+	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
+	const char *app_at_exten;
+
+	exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL, E_MATCH);
+	if (!exten) {
+		return 0;
+	}
+
+	app_at_exten = ast_get_extension_app(exten);
+	if (!app_at_exten || strcmp(PARK_APP_NAME, app_at_exten)) {
+		return 0;
+	}
+
+	return 1;
 }
 
 const char *ast_pickup_ext(void)
@@ -692,6 +735,7 @@
 	uint32_t flags;
 	/*! Parked user that has already obtained a parking space */
 	struct parkeduser *pu;
+	struct ast_parkinglot *parkinglot; /*! parkinglot to be parked in, based on parkext */
 };
 
 static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
@@ -700,17 +744,25 @@
 	int i, parking_space = -1, parking_range;
 	const char *parkinglotname = NULL;
 	const char *parkingexten;
-	struct ast_parkinglot *parkinglot = NULL;
-
-	if (peer)
+	struct ast_parkinglot *parkinglot;
+
+	if (args->parkinglot) {
+		parkinglot = args->parkinglot;
+		parkinglotname = parkinglot->name;
+	} else if (peer) {
 		parkinglotname = findparkinglotname(peer);
-	else /* peer was NULL, check chan (ParkAndAnnounce / res_agi) */
+	} else { /* peer was NULL, check chan (ParkAndAnnounce / res_agi) */
 		parkinglotname = findparkinglotname(chan);
-
-	if (parkinglotname) {
-		ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglotname);
-		parkinglot = find_parkinglot(parkinglotname);
-
+	}
+
+	if (!args->parkinglot) {
+		if (parkinglotname) {
+			parkinglot = find_parkinglot(parkinglotname);
+		} else {
+			ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
+			parkinglot = parkinglot_addref(default_parkinglot);
+		}
+		ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglot->name);
 	}
 
 	/* Dynamically create parkinglot */
@@ -761,8 +813,7 @@
 		parkinglot = parkinglot_addref(default_parkinglot);
 	}
 
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
+	ast_debug(1, "Parkinglot: %s\n", parkinglot->name);
 
 	/* Allocate memory for parking data */
 	if (!(pu = ast_calloc(1, sizeof(*pu)))) {
@@ -844,9 +895,8 @@
 
 	pu->notquiteyet = 1;
 	pu->parkingnum = parking_space;
-	pu->parkinglot = parkinglot_addref(parkinglot);
+	pu->parkinglot = parkinglot;
 	AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
-	parkinglot_unref(parkinglot);
 
 	return pu;
 }
@@ -1001,21 +1051,27 @@
 }
 
 /*! \brief Park a call */
-int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
-{
+int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, const char *parkexten, int *extout)
+{
+	struct ast_parkinglot *found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, (void *) parkexten);
+
 	struct ast_park_call_args args = {
 		.timeout = timeout,
 		.extout = extout,
+		.parkinglot = found_lot,
 	};
 
 	return park_call_full(chan, peer, &args);
 }
 
+/*!
+ * \param rchan is the transferee
+ * \param peer is the transferer
+ */
 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, struct ast_park_call_args *args)
 {
 	struct ast_channel *chan;
 	struct ast_frame *f;
-	int park_status;
 	struct ast_park_call_args park_args = {0,};
 
 	if (!args) {
@@ -1025,8 +1081,9 @@
 	}
 
 	if ((args->pu = park_space_reserve(rchan, peer, args)) == NULL) {
-		if (peer)
-			ast_stream_and_wait(peer, "beeperr", "");
+		if (peer) {
+			ast_stream_and_wait(peer, "pbx-parkingfailed", "");
+		}
 		return AST_FEATURE_RETURN_PARKFAILED;
 	}
 
@@ -1061,12 +1118,8 @@
 		args->orig_chan_name = ast_strdupa(peer->name);
 	}
 
-	park_status = park_call_full(chan, peer, args);
-	if (park_status == 1) {
-	/* would be nice to play "invalid parking extension" */
-		ast_hangup(chan);
-		return -1;
-	}
+	/* parking space reserved, return code check unnecessary */
+	park_call_full(chan, peer, args);
 
 	return 0;
 }
@@ -1077,14 +1130,9 @@
 	return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
 }
 
-static int masq_park_call_announce_args(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
+static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
 {
 	return masq_park_call(rchan, peer, 0, NULL, 1, args);
-}
-
-static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
-{
-	return masq_park_call(rchan, peer, timeout, extout, 1, NULL);
 }
 
 #ifdef TEST_FRAMEWORK
@@ -1271,6 +1319,38 @@
 		*callee = peer;
 		*caller = chan;
 	}
+}
+
+static int parkcall_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, struct ast_park_call_args *args)
+{
+	int res = 0;
+
+	if (args) {
+		ast_debug(1, "Parkinglot specified for builtin_parkcall: %s\n", args->parkinglot->name);
+	}
+
+	/* we used to set chan's exten and priority to "s" and 1
+	   here, but this generates (in some cases) an invalid
+	   extension, and if "s" exists, could errantly
+	   cause execution of extensions you don't expect. It
+	   makes more sense to let nature take its course
+	   when chan finishes, and let the pbx do its thing
+	   and hang up when the park is over.
+	*/
+	if (chan->_state != AST_STATE_UP)
+		res = ast_answer(chan);
+	if (!res)
+		res = ast_safe_sleep(chan, 1000);
+
+	if (!res) { /* one direction used to call park_call.... */
+		struct ast_channel *parker;
+		struct ast_channel *parkee;
+		set_peers(&parker, &parkee, peer, chan, sense);
+		res = masq_park_call_announce(parkee, parker, args);
+		/* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
+	}
+
+	return res;
 }
 
 /*! 
@@ -1287,30 +1367,7 @@
 */
 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
 {
-	struct ast_channel *parker;
-	struct ast_channel *parkee;
-	int res = 0;
-
-	set_peers(&parker, &parkee, peer, chan, sense);
-	/* we used to set chan's exten and priority to "s" and 1
-	   here, but this generates (in some cases) an invalid
-	   extension, and if "s" exists, could errantly
-	   cause execution of extensions you don't expect. It
-	   makes more sense to let nature take its course
-	   when chan finishes, and let the pbx do its thing
-	   and hang up when the park is over.
-	*/
-	if (chan->_state != AST_STATE_UP)
-		res = ast_answer(chan);
-	if (!res)
-		res = ast_safe_sleep(chan, 1000);
-
-	if (!res) { /* one direction used to call park_call.... */
-		res = masq_park_call_announce(parkee, parker, 0, NULL);
-		/* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
-	}
-
-	return res;
+	return parkcall_helper(chan, peer, config, code, sense, NULL);
 }
 
 /*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
@@ -1620,6 +1677,7 @@
 	struct ast_channel *transferer;
 	struct ast_channel *transferee;
 	const char *transferer_real_context;
+	struct ast_parkinglot *found_lot = NULL;
 	char xferto[256];
 	int res, parkstatus = 0;
 
@@ -1647,11 +1705,16 @@
 		finishup(transferee);
 		return res;
 	}
-	if (!strcmp(xferto, ast_parking_ext())) {
+
+	found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
+	if (found_lot) {
+		struct ast_park_call_args args = {
+			.parkinglot = found_lot,
+		};
 		res = finishup(transferee);
 		if (res)
 			res = -1;
-		else if (!(parkstatus = masq_park_call_announce(transferee, transferer, 0, NULL))) {	/* success */
+		else if (!(parkstatus = masq_park_call_announce(transferee, transferer, &args))) {	/* success */
 			/* We return non-zero, but tell the PBX not to hang the channel when
 			   the thread dies -- We have to be careful now though.  We are responsible for 
 			   hanging up the channel, else it will never be hung up! */
@@ -1706,7 +1769,7 @@
 	} else {
 		ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
 	}
-	if (parkstatus != AST_FEATURE_RETURN_PARKFAILED && ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
+	if (parkstatus != AST_FEATURE_RETURN_PARKFAILED && ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) { /* Play 'extension does not exist' */
 		finishup(transferee);
 		return -1;
 	}
@@ -1769,6 +1832,7 @@
 	struct ast_party_connected_line connected_line;
 	struct ast_datastore *features_datastore;
 	struct ast_dial_features *dialfeatures = NULL;
+	struct ast_parkinglot *parkinglot;
 
 	ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
 	set_peers(&transferer, &transferee, peer, chan, sense);
@@ -1811,12 +1875,16 @@
 		return AST_FEATURE_RETURN_SUCCESS;
 	}
 
- 	/* If we are attended transfering to parking, just use builtin_parkcall instead of trying to track all of
- 	 * the different variables for handling this properly with a builtin_atxfer */
- 	if (!strcmp(xferto, ast_parking_ext())) {
- 		finishup(transferee);
- 		return builtin_parkcall(chan, peer, config, code, sense, data);
- 	}
+	/* If we are attended transfering to parking, just use parkcall_helper instead of trying to track all of
+	 * the different variables for handling this properly with a builtin_atxfer */
+	parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
+	if (parkinglot) {
+		struct ast_park_call_args args = {
+			.parkinglot = parkinglot,
+		};
+		finishup(transferee);
+		return parkcall_helper(chan, peer, config, code, sense, &args);
+	}
 
 	l = strlen(xferto);
 	snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);	/* append context */
@@ -3762,6 +3830,7 @@
 					} else
 						ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
 					AST_LIST_REMOVE_CURRENT(list);
+					parkinglot_unref(pu->parkinglot);
 					free(pu);
 					break;
 				} else {
@@ -3847,18 +3916,16 @@
 /*! \brief Find parkinglot by name */
 struct ast_parkinglot *find_parkinglot(const char *name)
 {
-	struct ast_parkinglot *parkinglot = NULL;
-	struct ast_parkinglot tmp_parkinglot;
-	
-	if (ast_strlen_zero(name))
+	struct ast_parkinglot *parkinglot;
+
+	if (ast_strlen_zero(name)) {
 		return NULL;
-
-	ast_copy_string(tmp_parkinglot.name, name, sizeof(tmp_parkinglot.name));
-
-	parkinglot = ao2_find(parkinglots, &tmp_parkinglot, OBJ_POINTER);
-
-	if (parkinglot && option_debug)
-		ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
+	}
+
+	parkinglot = ao2_find(parkinglots, (void *) name, 0);
+	if (parkinglot) {
+		ast_debug(1, "Found Parkinglot: %s\n", parkinglot->name);
+	}
 
 	return parkinglot;
 }
@@ -3870,7 +3937,10 @@
 	if (ast_strlen_zero(name)) { /* No name specified */
 		return NULL;
 	}
-	if (find_parkinglot(name)) { /* Parkinglot with that name allready exists */
+	if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
+		if (copylot) {
+			ao2_ref(copylot, -1);
+		}
 		return NULL;
 	}
 
@@ -3962,7 +4032,8 @@
 		ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
 		args.flags = flags.flags;
 
-		res = masq_park_call_announce_args(chan, chan, &args);
+		args.parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &orig_exten);
+		res = masq_park_call_announce(chan, chan, &args);
 		/* Continue on in the dialplan */
 		if (res == 1) {
 			ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
@@ -3977,7 +4048,7 @@
 }
 
 /*! \brief Pickup parked call */
-static int park_exec_full(struct ast_channel *chan, const char *data, struct ast_parkinglot *parkinglot)
+static int park_exec_full(struct ast_channel *chan, const char *data)
 {
 	int res = 0;
 	struct ast_channel *peer=NULL;
@@ -3985,11 +4056,13 @@
 	struct ast_context *con;
 	int park = 0;
 	struct ast_bridge_config config;
-
-	if (data)
+	struct ast_parkinglot *parkinglot;
+
+	if (data) {
 		park = atoi((char *) data);
-
-	parkinglot = find_parkinglot(findparkinglotname(chan)); 	
+	}
+
+	parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_position_cb, (void *) &park);
 	if (!parkinglot)
 		parkinglot = default_parkinglot;
 
@@ -4126,6 +4199,7 @@
 			ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
 		}
 
+		parkinglot_unref(parkinglot);
 		res = ast_bridge_call(chan, peer, &config);
 
 		pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
@@ -4147,7 +4221,7 @@
 
 static int park_exec(struct ast_channel *chan, const char *data) 
 {
-	return park_exec_full(chan, data, default_parkinglot);
+	return park_exec_full(chan, data);
 }
 
 /*! \brief Unreference parkinglot object. If no more references,
@@ -4155,15 +4229,13 @@
 static void parkinglot_unref(struct ast_parkinglot *parkinglot) 
 {
 	int refcount = ao2_ref(parkinglot, -1);
-	if (option_debug > 2)
-		ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
+	ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
 }
 
 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
 {
 	int refcount = ao2_ref(parkinglot, +1);
-	if (option_debug > 2)
-		ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
+	ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
 	return parkinglot;
 }
 
@@ -4193,10 +4265,28 @@
 	con = ast_context_find(ruin->parking_con);
 	if (con)
 		ast_context_destroy(con, registrar);
-	ao2_unlink(parkinglots, ruin);
-}
-
-/*! \brief Build parkinglot from configuration and chain it in */
+}
+
+/*! 
+ * \brief Add parking hints for all defined parking lots 
+ * \param context
+ * \param start starting parkinglot number
+ * \param stop ending parkinglot number
+*/
+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), "park:%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 if it doesn't already exist */
 static struct ast_parkinglot *build_parkinglot(char *name, struct ast_variable *var)
 {
 	struct ast_parkinglot *parkinglot;
@@ -4224,6 +4314,8 @@
 	while(confvar) {
 		if (!strcasecmp(confvar->name, "context")) {
 			ast_copy_string(parkinglot->parking_con, confvar->value, sizeof(parkinglot->parking_con));
+		} else if (!strcasecmp(confvar->name, "parkext")) {
+			ast_copy_string(parkinglot->parkext, confvar->value, sizeof(parkinglot->parkext));
 		} else if (!strcasecmp(confvar->name, "parkingtime")) {
 			if ((sscanf(confvar->value, "%30d", &parkinglot->parkingtime) != 1) || (parkinglot->parkingtime < 1)) {
 				ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", confvar->value);
@@ -4283,6 +4375,10 @@
 	if (parkinglot->parkingtime == 0) {
 		parkinglot->parkingtime = DEFAULT_PARK_TIME;
 	}
+	if (ast_strlen_zero(parkinglot->parkext)) {
+		ast_debug(2, "no parkext specified for %s - setting it to %s\n", parkinglot->name, DEFAULT_PARK_EXTENSION);
+		ast_copy_string(parkinglot->parkext, DEFAULT_PARK_EXTENSION, sizeof(parkinglot->parkext));
+	}
 
 	if (!var) {	/* Default parking lot */
 		ast_copy_string(parkinglot->parking_con, "parkedcalls", sizeof(parkinglot->parking_con));
@@ -4304,22 +4400,26 @@
 
 	/* Add a parking extension into the context */
 	if (!error && !oldparkinglot) {
-		if (!ast_strlen_zero(ast_parking_ext())) {
-			if (ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), ast_free_ptr, registrar) == -1)
+		if (!ast_strlen_zero(parkinglot->parkext)) {
+			if (ast_add_extension2(con, 1, parkinglot->parkext, 1, NULL, NULL, parkcall, strdup(""), ast_free_ptr, registrar) == -1)
 				error = 1;
 		}
 	}
+
+	/* Add parking hints */
+	if (parkinglot->parkaddhints)
+		park_add_hints(parkinglot->parking_con, parkinglot->parking_start, parkinglot->parking_stop);
 
 	ao2_unlock(parkinglot);
 
 	if (error) {
 		ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
 		parkinglot_destroy(parkinglot);
+		parkinglot_unref(parkinglot);
 		return NULL;
 	}
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
-
+	ast_debug(1, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
+	parkinglot->the_mark = 0;
 
 	/* Move it into the list, if it wasn't already there */
 	if (!oldparkinglot) {
@@ -4328,26 +4428,6 @@
 	parkinglot_unref(parkinglot);
 
 	return parkinglot;
-}
-
-
-/*! 
- * \brief Add parking hints for all defined parking lots 
- * \param context
- * \param start starting parkinglot number
- * \param stop ending parkinglot number
-*/
-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), "park:%s@%s", exten, context);
-		ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
-	}
 }
 
 static int load_config(void) 
@@ -4360,8 +4440,6 @@
 	struct ast_variable *var = NULL;
 	struct feature_group *fg = NULL;
 	struct ast_flags config_flags = { 0 };
-	char old_parking_ext[AST_MAX_EXTENSION];
-	char old_parking_con[AST_MAX_EXTENSION] = "";
 	char *ctg; 
 	static const char * const categories[] = { 
 		/* Categories in features.conf that are not
@@ -4372,32 +4450,27 @@
 		"applicationmap"
 	};
 
+	default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
 	if (default_parkinglot) {
-		strcpy(old_parking_con, default_parkinglot->parking_con);
-		strcpy(old_parking_ext, parking_ext);
-	} else {
-		default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
-		if (default_parkinglot) {
-			ao2_lock(default_parkinglot);
-			default_parkinglot->parking_start = 701;
-			default_parkinglot->parking_stop = 750;
-			default_parkinglot->parking_offset = 0;
-			default_parkinglot->parkfindnext = 0;
-			default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
-			ao2_unlock(default_parkinglot);
-		}
-	}
+		ao2_lock(default_parkinglot);
+		ast_copy_string(default_parkinglot->parkext, DEFAULT_PARK_EXTENSION, sizeof(default_parkinglot->parkext));
+		default_parkinglot->parking_start = 701;
+		default_parkinglot->parking_stop = 750;
+		default_parkinglot->parking_offset = 0;
+		default_parkinglot->parkfindnext = 0;
+		default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
+		ao2_unlock(default_parkinglot);
+	}
+	
 	if (default_parkinglot) {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Configuration of default parkinglot done.\n");
+		ast_debug(1, "Configuration of default parkinglot done.\n");
 	} else {
 		ast_log(LOG_ERROR, "Configuration of default parkinglot failed.\n");
 		return -1;
 	}
-	
 
 	/* Reset to defaults */
-	strcpy(parking_ext, "700");
+	strcpy(default_parkinglot->parkext, DEFAULT_PARK_EXTENSION);
 	strcpy(pickup_ext, "*8");
 	courtesytone[0] = '\0';
 	strcpy(xfersound, "beep");
@@ -4428,7 +4501,7 @@
 	}
 	for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
 		if (!strcasecmp(var->name, "parkext")) {
-			ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
+			ast_copy_string(default_parkinglot->parkext, var->value, sizeof(default_parkinglot->parkext));
 		} else if (!strcasecmp(var->name, "context")) {
 			ast_copy_string(default_parkinglot->parking_con, var->value, sizeof(default_parkinglot->parking_con));
 		} else if (!strcasecmp(var->name, "parkingtime")) {
@@ -4682,22 +4755,15 @@
 
 	ast_config_destroy(cfg);
 
-	/* Remove the old parking extension */
-	if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))	{
-		if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar, 0))
-				notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
-		ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
-	}
-	
 	if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->parking_con, registrar))) {
 		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
 		return -1;
 	}
-	res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);

[... 107 lines stripped ...]



More information about the asterisk-commits mailing list