[asterisk-commits] rmudgett: branch rmudgett/parking r329059 - in /team/rmudgett/parking: channe...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jul 20 16:58:47 CDT 2011
Author: rmudgett
Date: Wed Jul 20 16:58:43 2011
New Revision: 329059
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=329059
Log:
Work so far.
Modified:
team/rmudgett/parking/channels/chan_dahdi.c
team/rmudgett/parking/channels/chan_iax2.c
team/rmudgett/parking/configs/chan_dahdi.conf.sample
team/rmudgett/parking/configs/features.conf.sample
team/rmudgett/parking/main/asterisk.c
team/rmudgett/parking/main/features.c
Modified: team/rmudgett/parking/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/channels/chan_dahdi.c?view=diff&rev=329059&r1=329058&r2=329059
==============================================================================
--- team/rmudgett/parking/channels/chan_dahdi.c (original)
+++ team/rmudgett/parking/channels/chan_dahdi.c Wed Jul 20 16:58:43 2011
@@ -396,8 +396,6 @@
static char defaultcic[64] = "";
static char defaultozz[64] = "";
-
-static char parkinglot[AST_MAX_EXTENSION] = ""; /*!< Default parking lot for this channel */
/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
static char mwimonitornotify[PATH_MAX] = "";
@@ -16803,8 +16801,6 @@
ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {
ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
- } else if (!strcasecmp(v->name, "parkinglot")) {
- ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
} else if (!strcasecmp(v->name, "stripmsd")) {
ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
confp->chan.stripmsd = atoi(v->value);
Modified: team/rmudgett/parking/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/channels/chan_iax2.c?view=diff&rev=329059&r1=329058&r2=329059
==============================================================================
--- team/rmudgett/parking/channels/chan_iax2.c (original)
+++ team/rmudgett/parking/channels/chan_iax2.c Wed Jul 20 16:58:43 2011
@@ -10692,6 +10692,7 @@
pbx_builtin_setvar_helper(owner, "BLINDTRANSFER", bridged_chan->name);
pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", owner->name);
+/* BUGBUG c cannot be right. C is likely NULL. owner should probably be used instead. */
if (ast_parking_ext_valid(ies.called_number, c, iaxs[fr->callno]->context)) {
ast_debug(1, "Parking call '%s'\n", bridged_chan->name);
if (iax_park(bridged_chan, owner, ies.called_number)) {
Modified: team/rmudgett/parking/configs/chan_dahdi.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/configs/chan_dahdi.conf.sample?view=diff&rev=329059&r1=329058&r2=329059
==============================================================================
--- team/rmudgett/parking/configs/chan_dahdi.conf.sample (original)
+++ team/rmudgett/parking/configs/chan_dahdi.conf.sample Wed Jul 20 16:58:43 2011
@@ -579,6 +579,13 @@
; ('canpark=no' is overridden by 'transfer=yes')
;
canpark=yes
+
+; Sets the default parking lot for call parking.
+; This is setable per channel.
+; Parkinglots are configured in features.conf
+;
+;parkinglot=plaza
+
;
; Support call forward variable
;
Modified: team/rmudgett/parking/configs/features.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/configs/features.conf.sample?view=diff&rev=329059&r1=329058&r2=329059
==============================================================================
--- team/rmudgett/parking/configs/features.conf.sample (original)
+++ team/rmudgett/parking/configs/features.conf.sample Wed Jul 20 16:58:43 2011
@@ -53,8 +53,6 @@
; one of: callee, caller, both, no (default is no)
;parkeddynamic = yes ; Enables dynamically created parkinglots. (default is no)
;adsipark = yes ; if you want ADSI parking announcements
-;findslot => next ; Continue to the 'next' free parking space.
- ; Defaults to 'first' available
;parkedmusicclass=default ; This is the MOH class to use for the parked channel
; as long as the class is not set on the channel directly
; using Set(CHANNEL(musicclass)=whatever) in the dialplan
@@ -94,7 +92,6 @@
;context => edvinapark
;parkext => 799
;parkpos => 800-850
-;findslot => next
; Note that the DTMF features listed below only work when two channels have answered and are bridged together.
; They can not be used while the remote party is ringing or in progress. If you require this feature you can use
Modified: team/rmudgett/parking/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/asterisk.c?view=diff&rev=329059&r1=329058&r2=329059
==============================================================================
--- team/rmudgett/parking/main/asterisk.c (original)
+++ team/rmudgett/parking/main/asterisk.c Wed Jul 20 16:58:43 2011
@@ -3799,7 +3799,10 @@
exit(1);
}
- ast_features_init();
+ if (ast_features_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
if (init_framer()) {
printf("%s", term_quit());
Modified: team/rmudgett/parking/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/features.c?view=diff&rev=329059&r1=329058&r2=329059
==============================================================================
--- team/rmudgett/parking/main/features.c (original)
+++ team/rmudgett/parking/main/features.c Wed Jul 20 16:58:43 2011
@@ -402,35 +402,94 @@
unsigned int options_specified:1;
char peername[1024];
unsigned char moh_trys;
+ /*! Parking lot this entry belongs to. Holds a parking lot reference. */
struct ast_parkinglot *parkinglot;
AST_LIST_ENTRY(parkeduser) list;
};
+/*! Parking lot configuration options. */
+struct parkinglot_cfg {
+ /*! Music class used for parking */
+ char mohclass[MAX_MUSICCLASS];
+ /*! Extension to park calls in this parking lot. */
+ char parkext[AST_MAX_EXTENSION];
+ /*! Context for which parking is made accessible */
+ char parking_con[AST_MAX_EXTENSION];
+ /*! Context for dialback for parking (KLUDGE) */
+ char parking_con_dial[AST_MAX_EXTENSION];
+ /*! First available extension for parking */
+ int parking_start;
+ /*! Last available extension for parking */
+ int parking_stop;
+ /*! Default parking time in ms. */
+ int parkingtime;
+ /*!
+ * \brief Enable DTMF based transfers on bridge when picking up parked calls.
+ *
+ * \details
+ * none(0)
+ * AST_FEATURE_FLAG_BYCALLEE
+ * AST_FEATURE_FLAG_BYCALLER
+ * AST_FEATURE_FLAG_BYBOTH
+ */
+ int parkedcalltransfers;
+ /*!
+ * \brief Enable DTMF based parking on bridge when picking up parked calls.
+ *
+ * \details
+ * none(0)
+ * AST_FEATURE_FLAG_BYCALLEE
+ * AST_FEATURE_FLAG_BYCALLER
+ * AST_FEATURE_FLAG_BYBOTH
+ */
+ int parkedcallreparking;
+ /*!
+ * \brief Enable DTMF based hangup on a bridge when pickup up parked calls.
+ *
+ * \details
+ * none(0)
+ * AST_FEATURE_FLAG_BYCALLEE
+ * AST_FEATURE_FLAG_BYCALLER
+ * AST_FEATURE_FLAG_BYBOTH
+ */
+ int parkedcallhangup;
+ /*!
+ * \brief Enable DTMF based recording on a bridge when picking up parked calls.
+ *
+ * \details
+ * none(0)
+ * AST_FEATURE_FLAG_BYCALLEE
+ * AST_FEATURE_FLAG_BYCALLER
+ * AST_FEATURE_FLAG_BYBOTH
+ */
+ int parkedcallrecording;
+
+ /*! Add parking hints automatically */
+ unsigned int parkaddhints:1;
+/* BUGBUG need to make use is_invalid to prevent use of parking lot. */
+ /*! TRUE if configuration is invalid and the parking lot should not be used. */
+ unsigned int is_invalid:1;
+};
+
/*! \brief Structure for parking lots which are put in a container. */
struct ast_parkinglot {
+ /*! Name of the parking lot. */
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 */
- int parking_stop; /*!< Last available extension for parking */
- int parking_offset;
- int parkfindnext;
- int parkingtime; /*!< Default parking time */
- char mohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
- int parkaddhints; /*!< Add parking hints automatically */
- int parkedcalltransfers; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
- 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 */
+ /*! Parking lot user configuration. */
+ struct parkinglot_cfg cfg;
+
+/* BUGBUG could use the_mark as a disabled parking lot flag if it is set. Do not park any new calls on this lot. */
+ /*! Used during reloads, that which bears the_mark shall be deleted! */
+ unsigned int the_mark:1;
+
+ /*! List of active parkings in this parkinglot */
+ AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings;
};
/*! \brief The list of parking lots configured. Always at least one - the default parking lot */
static struct ao2_container *parkinglots;
-struct ast_parkinglot *default_parkinglot;
+static struct ast_parkinglot *default_parkinglot;
char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
static char courtesytone[256]; /*!< Courtesy tone */
@@ -578,9 +637,7 @@
/* Forward declarations */
static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
static void parkinglot_unref(struct ast_parkinglot *parkinglot);
-static void parkinglot_destroy(void *obj);
-int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *fs);
-struct ast_parkinglot *find_parkinglot(const char *name);
+static struct ast_parkinglot *find_parkinglot(const char *name);
static struct ast_parkinglot *create_parkinglot(const char *name);
static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
@@ -589,7 +646,7 @@
struct ast_parkinglot *parkinglot = obj;
int *parkpos = args;
- if (*parkpos >= parkinglot->parking_start && *parkpos <= parkinglot->parking_stop) {
+ if (*parkpos >= parkinglot->cfg.parking_start && *parkpos <= parkinglot->cfg.parking_stop) {
return CMP_MATCH | CMP_STOP;
}
@@ -601,7 +658,7 @@
struct ast_parkinglot *parkinglot = obj;
const char *parkext = args;
- if (!strcmp(parkinglot->parkext, parkext)) {
+ if (!strcmp(parkinglot->cfg.parkext, parkext)) {
return CMP_MATCH | CMP_STOP;
}
@@ -620,7 +677,7 @@
}
app_at_exten = ast_get_extension_app(exten);
- if (!app_at_exten || strcmp(PARK_APP_NAME, app_at_exten)) {
+ if (!app_at_exten || strcasecmp(PARK_APP_NAME, app_at_exten)) {
return 0;
}
@@ -649,7 +706,8 @@
static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
{
- struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
+ struct ast_parkinglot *parkinglot = obj;
+ struct ast_parkinglot *parkinglot2 = arg;
return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
}
@@ -802,20 +860,21 @@
return ast_adsi_print(chan, message, justify, 1);
}
-/*! \brief Find parking lot name from channel */
+/*!
+ * \brief Find parking lot name from channel
+ * \note Channel needs to be locked while the returned string is in use.
+ */
static const char *findparkinglotname(struct ast_channel *chan)
{
- const char *temp, *parkinglot = NULL;
-
- /* Check if the channel has a parking lot */
- if (!ast_strlen_zero(chan->parkinglot))
+ const char *parkinglot;
+
+ /* The channel variable overrides everything */
+ parkinglot = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
+ if (!parkinglot
+ && !ast_strlen_zero(chan->parkinglot)) {
+ /* Use the channel's parking lot. */
parkinglot = chan->parkinglot;
-
- /* Channel variables override everything */
-
- if ((temp = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
- return temp;
-
+ }
return parkinglot;
}
@@ -874,9 +933,24 @@
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 */
+ /*!
+ * \brief Parkinglot to be parked in, based on parkext
+ * \note BUGBUG check reference use!
+ */
+ struct ast_parkinglot *parkinglot;
};
+/*!
+ * \internal
+ * \brief Reserve a parking space in a parking lot for a call being parked.
+ *
+ * \param chan Channel being parked.
+ * \param peer Channel parking the call.
+ * \param args BUGBUG
+ *
+ * \return Parked call descriptor or NULL if failed.
+ * \note The parking lot list is locked if successful.
+ */
static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
{
struct parkeduser *pu;
@@ -894,7 +968,7 @@
parkinglotname = findparkinglotname(chan);
}
- if (!args->parkinglot) {
+ if (!parkinglot) {
if (parkinglotname) {
parkinglot = find_parkinglot(parkinglotname);
} else {
@@ -919,6 +993,11 @@
if (!ast_strlen_zero(parkinglotname_copy)) {
parkinglot_copy = find_parkinglot(parkinglotname_copy);
+ if (parkinglot_copy && parkinglot_copy->cfg.is_invalid) {
+ ast_debug(1, "Requested parking lot has invalid config.\n");
+ parkinglot_unref(parkinglot);
+ parkinglot = NULL;
+ }
}
if (!parkinglot_copy) {
parkinglot_copy = parkinglot_addref(default_parkinglot);
@@ -928,16 +1007,17 @@
ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
} else {
if (!ast_strlen_zero(dyn_context)) {
- ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
+ ast_copy_string(parkinglot->cfg.parking_con, dyn_context, sizeof(parkinglot->cfg.parking_con));
}
if (!ast_strlen_zero(dyn_range)) {
if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
} else {
- parkinglot->parking_start = dyn_start;
- parkinglot->parking_stop = dyn_end;
+ parkinglot->cfg.parking_start = dyn_start;
+ parkinglot->cfg.parking_stop = dyn_end;
}
}
+/* BUGBUG need to create the dynamic parking lot context and park extension if they do not already exist! */
ao2_link(parkinglots, parkinglot);
}
@@ -962,10 +1042,9 @@
/* Lock parking list */
AST_LIST_LOCK(&parkinglot->parkings);
+
/* Check for channel variable PARKINGEXTEN */
- ast_channel_lock(chan);
parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), ""));
- ast_channel_unlock(chan);
if (!ast_strlen_zero(parkingexten)) {
/*!
* \note The API forces us to specify a numeric parking slot, even
@@ -975,39 +1054,40 @@
* arbitrary non-numeric extensions.
*/
if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
+ ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
AST_LIST_UNLOCK(&parkinglot->parkings);
parkinglot_unref(parkinglot);
- free(pu);
- ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
+ ast_free(pu);
return NULL;
}
snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
- if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
- ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
+ if (ast_exists_extension(NULL, parkinglot->cfg.parking_con, pu->parkingexten, 1, NULL)) {
+ ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->cfg.parking_con);
AST_LIST_UNLOCK(&parkinglot->parkings);
parkinglot_unref(parkinglot);
ast_free(pu);
return NULL;
}
- } else { /* parkingexten not length zero, so find a usable extension in the lot to park the call */
+ } else {
+ /* parkingexten is empty, so find a usable extension in the lot to park the call */
int start; /* The first slot we look in the parkinglot. It can be randomized. */
int start_checked = 0; /* flag raised once the first slot is checked */
struct parkeduser *cur = NULL;
/* If using randomize mode, set start to random position on parking range */
if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
- start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
- start+=parkinglot->parking_start;
+ start = ast_random() % (parkinglot->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
+ start+=parkinglot->cfg.parking_start;
} else { /* Otherwise, just set it to the start position. */
- start = parkinglot->parking_start;
+ start = parkinglot->cfg.parking_start;
}
/* free parking extension linear search: O(n^2) */
- for (i = start; 1; i++) {
+ for (i = start; ; i++) {
/* If we are past the end, wrap around to the first parking slot*/
- if (i == parkinglot->parking_stop + 1) {
- i = parkinglot->parking_start;
+ if (i == parkinglot->cfg.parking_stop + 1) {
+ i = parkinglot->cfg.parking_start;
}
if (i == start) { /* At this point, if start_checked, we've exhausted all the possible slots. */
@@ -1036,15 +1116,12 @@
/* If we exited without a match, our i value was set to -1 and we still have an item in cur. */
if (i == -1 && cur) {
ast_log(LOG_WARNING, "No more parking spaces\n");
- ast_free(pu);
AST_LIST_UNLOCK(&parkinglot->parkings);
parkinglot_unref(parkinglot);
+ ast_free(pu);
return NULL;
}
- /* Set pointer for next parking */
- if (parkinglot->parkfindnext)
- parkinglot->parking_offset = parking_space - parkinglot->parking_start + 1;
snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
}
@@ -1081,13 +1158,13 @@
ast_indicate(pu->chan, AST_CONTROL_RINGING);
} else {
ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
- S_OR(pu->parkinglot->mohclass, NULL),
- !ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
+ S_OR(pu->parkinglot->cfg.mohclass, NULL),
+ !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
}
}
pu->start = ast_tvnow();
- pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->parkingtime;
+ pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->cfg.parkingtime;
if (args->extout)
*(args->extout) = pu->parkingnum;
@@ -1136,7 +1213,7 @@
pu->priority = args->return_pri ? args->return_pri :
(chan->macropriority ? chan->macropriority : chan->priority);
- /* If parking a channel directly, don't quiet yet get parking running on it.
+ /* If parking a channel directly, don't quite yet get parking running on it.
* All parking lot entries are put into the parking lot with notquiteyet on. */
if (peer != chan)
pu->notquiteyet = 0;
@@ -1178,12 +1255,12 @@
ast_adsi_unload_session(peer);
}
- con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con, registrar);
+ con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->cfg.parking_con, registrar);
if (!con) /* Still no context? Bad */
- ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con);
+ ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pu->parkinglot->cfg.parking_con);
if (con) {
if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
- notify_metermaids(pu->parkingexten, pu->parkinglot->parking_con, AST_DEVICE_INUSE);
+ notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con, AST_DEVICE_INUSE);
}
AST_LIST_UNLOCK(&pu->parkinglot->parkings);
@@ -1199,8 +1276,8 @@
if (peer == chan) { /* pu->notquiteyet = 1 */
/* Wake up parking thread if we're really done */
ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
- S_OR(pu->parkinglot->mohclass, NULL),
- !ast_strlen_zero(pu->parkinglot->mohclass) ? strlen(pu->parkinglot->mohclass) + 1 : 0);
+ S_OR(pu->parkinglot->cfg.mohclass, NULL),
+ !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
pu->notquiteyet = 0;
pthread_kill(parking_thread, SIGURG);
}
@@ -1210,7 +1287,8 @@
/*! \brief Park a call */
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);
+/* BUGBUG the next line breaks named parking lots. */
+ struct ast_parkinglot *found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, (char *) parkexten);
struct ast_park_call_args args = {
.timeout = timeout,
@@ -1324,13 +1402,13 @@
args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
AST_LIST_LOCK(&args->pu->parkinglot->parkings);
AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
- con = ast_context_find(args->pu->parkinglot->parking_con);
+ con = ast_context_find(args->pu->parkinglot->cfg.parking_con);
if (con) {
if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
return -1;
} else {
- notify_metermaids(args->pu->parkingexten, pu_toremove->parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
+ notify_metermaids(args->pu->parkingexten, pu_toremove->parkinglot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
}
} else {
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
@@ -1876,6 +1954,7 @@
return AST_FEATURE_RETURN_SUCCESS;
}
+/* BUGBUG the next line breaks named parking lots. */
found_lot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
if (found_lot) {
struct ast_park_call_args args = {
@@ -2072,6 +2151,7 @@
/* 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 */
+/* BUGBUG the next line breaks named parking lots. */
parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_exten_cb, &xferto);
if (parkinglot) {
struct ast_park_call_args args = {
@@ -4105,7 +4185,7 @@
}
/*! \brief Run management on parkinglots, called once per parkinglot */
-int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
+static int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
{
struct parkeduser *pu;
int res = 0;
@@ -4124,10 +4204,12 @@
}
tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
if (tms > pu->parkingtime) {
+/* BUGBUG stop MOH or RINGING depending on what was configured */
/* Stop music on hold */
ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
+/* BUGBUG allocating from the stack within a loop here! */
char *peername = ast_strdupa(pu->peername);
char *dash = strrchr(peername, '-');
char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
@@ -4137,16 +4219,17 @@
*dash = '\0';
}
+/* BUGBUG again allocating from the stack within a loop here! */
peername_flat = ast_strdupa(peername);
for (i = 0; peername_flat[i]; i++) {
if (peername_flat[i] == '/') {
- peername_flat[i]= '_';
+ peername_flat[i] = '_';
}
}
- con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
+ con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->cfg.parking_con_dial, registrar);
if (!con) {
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
+ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->cfg.parking_con_dial);
} else {
char returnexten[AST_MAX_EXTENSION];
struct ast_datastore *features_datastore;
@@ -4173,12 +4256,12 @@
ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
}
- if (pu->options_specified == 1) {
+ if (pu->options_specified) {
/* Park() was called with overriding return arguments, respect those arguments */
set_c_e_p(chan, pu->context, pu->exten, pu->priority);
} else {
if (comebacktoorigin) {
- set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
+ set_c_e_p(chan, pu->parkinglot->cfg.parking_con_dial, peername_flat, 1);
} else {
snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
@@ -4200,16 +4283,17 @@
ast_hangup(chan);
}
/* And take them out of the parking lot */
- con = ast_context_find(pu->parkinglot->parking_con);
+ con = ast_context_find(pu->parkinglot->cfg.parking_con);
if (con) {
if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
else
- notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
+ notify_metermaids(pu->parkingexten, curlot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
AST_LIST_REMOVE_CURRENT(list);
- free(pu);
+ parkinglot_unref(pu->parkinglot);
+ ast_free(pu);
} else { /* still within parking time, process descriptors */
for (x = 0; x < AST_MAX_FDS; x++) {
struct ast_frame *f;
@@ -4255,17 +4339,17 @@
ast_verb(2, "%s got tired of being parked\n", chan->name);
ast_hangup(chan);
/* And take them out of the parking lot */
- con = ast_context_find(curlot->parking_con);
+ con = ast_context_find(curlot->cfg.parking_con);
if (con) {
if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
else
- notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
+ notify_metermaids(pu->parkingexten, curlot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
} 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);
+ ast_free(pu);
break;
} else {
/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
@@ -4273,8 +4357,8 @@
if (pu->moh_trys < 3 && !chan->generatordata) {
ast_debug(1, "MOH on parked call stopped by outside source. Restarting on channel %s.\n", chan->name);
ast_indicate_data(chan, AST_CONTROL_HOLD,
- S_OR(curlot->mohclass, NULL),
- (!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
+ S_OR(curlot->cfg.mohclass, NULL),
+ (!ast_strlen_zero(curlot->cfg.mohclass) ? strlen(curlot->cfg.mohclass) + 1 : 0));
pu->moh_trys++;
}
goto std; /* XXX Ick: jumping into an else statement??? XXX */
@@ -4324,8 +4408,8 @@
struct ao2_iterator iter;
struct ast_parkinglot *curlot;
int ms = -1; /* poll2 timeout, uninitialized */
+
iter = ao2_iterator_init(parkinglots, 0);
-
while ((curlot = ao2_iterator_next(&iter))) {
manage_parkinglot(curlot, pfds, nfds, &new_pfds, &new_nfds, &ms);
ao2_ref(curlot, -1);
@@ -4348,7 +4432,7 @@
}
/*! \brief Find parkinglot by name */
-struct ast_parkinglot *find_parkinglot(const char *name)
+static struct ast_parkinglot *find_parkinglot(const char *name)
{
struct ast_parkinglot *parkinglot;
@@ -4365,25 +4449,24 @@
}
/*! \brief Copy parkinglot and store it with new name */
-struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot) {
+static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
+{
struct ast_parkinglot *copylot;
- if (ast_strlen_zero(name)) { /* No name specified */
+ if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
+ ao2_ref(copylot, -1);
return NULL;
}
- if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
- if (copylot) {
- ao2_ref(copylot, -1);
- }
+
+ copylot = create_parkinglot(name);
+ if (!copylot) {
return NULL;
}
- copylot = create_parkinglot(name);
ast_debug(1, "Building parking lot %s\n", name);
- memcpy(copylot, parkinglot, sizeof(struct ast_parkinglot));
- ast_copy_string(copylot->name, name, sizeof(copylot->name));
- AST_LIST_HEAD_INIT(©lot->parkings);
+ /* Copy the source parking lot configuration. */
+ copylot->cfg = parkinglot->cfg;
return copylot;
}
@@ -4466,6 +4549,7 @@
ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
args.flags = flags.flags;
+/* BUGBUG the next line breaks named parking lots. */
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 */
@@ -4482,31 +4566,34 @@
}
/*! \brief Pickup parked call */
-static int park_exec_full(struct ast_channel *chan, const char *data)
+static int parked_call_exec(struct ast_channel *chan, const char *data)
{
int res = 0;
- struct ast_channel *peer=NULL;
+ struct ast_channel *peer = NULL;
struct parkeduser *pu;
struct ast_context *con;
int park = 0;
struct ast_bridge_config config;
struct ast_parkinglot *parkinglot;
- if (data) {
- park = atoi((char *) data);
- }
-
+ if (!ast_strlen_zero(data)) {
+ if (sscanf(data, "%30u", &park) != 1) {
+ ast_log(LOG_WARNING, "Specified parking extension not a number: %s\n", data);
+ park = -1;
+ }
+ }
+
+/* BUGBUG the next line breaks named parking lots. (it used to just use the chan->parkinglot) */
parkinglot = ao2_callback(parkinglots, 0, find_parkinglot_by_position_cb, (void *) &park);
- if (!parkinglot)
- parkinglot = default_parkinglot;
+ if (!parkinglot) {
+ parkinglot = parkinglot_addref(default_parkinglot);
+ }
AST_LIST_LOCK(&parkinglot->parkings);
AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
- if (!pu->notquiteyet && (!data || pu->parkingnum == park)) {
- if (pu->chan->pbx) { /* do not allow call to be picked up until the PBX thread is finished */
- AST_LIST_UNLOCK(&parkinglot->parkings);
- return -1;
- }
+ if ((ast_strlen_zero(data) || pu->parkingnum == park)
+ && !pu->notquiteyet && !pu->chan->pbx) {
+ /* The parking space has a call and can be picked up now. */
AST_LIST_REMOVE_CURRENT(list);
break;
}
@@ -4516,14 +4603,16 @@
if (pu) {
peer = pu->chan;
- con = ast_context_find(parkinglot->parking_con);
+ con = ast_context_find(parkinglot->cfg.parking_con);
if (con) {
- if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
+ if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- else
- notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
- } else
+ } else {
+ notify_metermaids(pu->parkingexten, parkinglot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
+ }
+ } else {
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ }
ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
@@ -4541,52 +4630,61 @@
S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>")
);
+ parkinglot_unref(pu->parkinglot);
ast_free(pu);
}
+
+/* BUGBUG we need to update connected line for this connection. */
+
/* JK02: it helps to answer the channel if not already up */
- if (chan->_state != AST_STATE_UP)
+ if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
-
- //XXX Why do we unlock here ?
- // uncomment it for now, till my setup with debug_threads and detect_deadlocks starts to complain
- //ASTOBJ_UNLOCK(parkinglot);
+ }
if (peer) {
struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures = NULL;
+/* BUGBUG we should unhold or stop ringing as configured. */
+ ast_indicate(peer, AST_CONTROL_UNHOLD);
+
/* Play a courtesy to the source(s) configured to prefix the bridge connecting */
-
if (!ast_strlen_zero(courtesytone)) {
int error = 0;
- ast_indicate(peer, AST_CONTROL_UNHOLD);
+
+/* BUGBUG we should autoservice the channel not getting the courtesy tone. */
if (parkedplay == 0) {
error = ast_stream_and_wait(chan, courtesytone, "");
} else if (parkedplay == 1) {
error = ast_stream_and_wait(peer, courtesytone, "");
} else if (parkedplay == 2) {
- if (!ast_streamfile(chan, courtesytone, chan->language) &&
- !ast_streamfile(peer, courtesytone, chan->language)) {
+ if (!ast_streamfile(chan, courtesytone, chan->language)
+ && !ast_streamfile(peer, courtesytone, peer->language)) {
/*! \todo XXX we would like to wait on both! */
res = ast_waitstream(chan, "");
- if (res >= 0)
+ if (res >= 0) {
res = ast_waitstream(peer, "");
- if (res < 0)
+ }
+ if (res < 0) {
error = 1;
+ }
+ } else {
+ error = 1;
}
}
if (error) {
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
ast_hangup(peer);
+ parkinglot_unref(parkinglot);
return -1;
}
- } else
- ast_indicate(peer, AST_CONTROL_UNHOLD);
+ }
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
ast_hangup(peer);
+ parkinglot_unref(parkinglot);
return -1;
}
/* This runs sorta backwards, since we give the incoming channel control, as if it
@@ -4602,42 +4700,45 @@
if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
dialfeatures = features_datastore->data;
}
- ast_channel_unlock(peer);
-
- /* When the datastores for both caller and callee are created, both the callee and caller channels
- * use the features_caller flag variable to represent themselves. With that said, the config.features_callee
- * flags should be copied from the datastore's caller feature flags regardless if peer was a callee
- * or caller. */
+
+ /*
+ * When the datastores for both caller and callee are created,
+ * both the callee and caller channels use the features_caller
+ * flag variable to represent themselves. With that said, the
+ * config.features_callee flags should be copied from the
+ * datastore's caller feature flags regardless if peer was a
+ * callee or caller.
+ */
if (dialfeatures) {
ast_copy_flags(&(config.features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
}
-
- if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
+ ast_channel_unlock(peer);
+
+ if ((parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
}
- if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
}
- if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
}
- if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
}
- if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
}
- if ((parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
}
- if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
}
- if ((parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
+ if ((parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->cfg.parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
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);
@@ -4645,21 +4746,18 @@
/* Simulate the PBX hanging up */
ast_hangup(peer);
- return -1;
} else {
/*! \todo XXX Play a message XXX */
- if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
- ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
- ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
- res = -1;
- }
-
+ if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
+ ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark",
+ chan->name);
+ }
+ ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n",
+ chan->name, park);
+ }
+
+ parkinglot_unref(parkinglot);
return -1;
-}
-
-static int park_exec(struct ast_channel *chan, const char *data)
-{
[... 840 lines stripped ...]
More information about the asterisk-commits
mailing list