summaryrefslogtreecommitdiff
path: root/main/features.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-08-01 20:55:17 +0000
committerMatthew Jordan <mjordan@digium.com>2013-08-01 20:55:17 +0000
commit5c4b482471edb8a839d754dd654dc72605caac66 (patch)
treed164a3ebd03e7101a39929283b75d2318a2f6761 /main/features.c
parentc8a91b5b013c568f3f99e8fb7abc662775c60520 (diff)
Support externally initiated parking requests; remove some dead code
This patch does the following: * It adds support for externally initiated parking requests. In particular, chan_skinny has a protocol level message that initiates a call park. This patch now supports that option, as well as the protocol specific mechanisms in chan_dahdi/sig_analog and chan_mgcp. * A parking bridge features virtual table has been added that provides access to the parking functionality that the Bridging API needs. This includes requests to park an entire 'call' (with little or no additional information, thank you chan_skinny), perform a blind transfer to a parking extension, determine if an extension is a parking extension, as well as the actual "do the parking" request from the Bridging API. * Refactoring in chan_mgcp, chan_skinny, and chan_dahdi to make use of the new functions * The removal of some - but not all - dead parking code from features.c This also fixed blind transferring a multi-party bridge to a parking lot (which was implemented, but had at least one code path where using the parking features kK might not have worked) Review: https://reviewboard.asterisk.org/r/2710 (closes issue ASTERISK-22134) Reported by: Matt Jordan git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396028 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/features.c')
-rw-r--r--main/features.c1342
1 files changed, 0 insertions, 1342 deletions
diff --git a/main/features.c b/main/features.c
index 9490116b7..7162d4e55 100644
--- a/main/features.c
+++ b/main/features.c
@@ -470,20 +470,11 @@ struct ast_parkinglot {
/*! \brief The configured parking lots container. Always at least one - the default parking lot */
static struct ao2_container *parkinglots;
-/*!
- * \brief Default parking lot.
- * \note Holds a parkinglot reference.
- * \note Will not be NULL while running.
- */
-static struct ast_parkinglot *default_parkinglot;
-
/*! Force a config reload to reload regardless of config file timestamp. */
#ifdef TEST_FRAMEWORK
static int force_reload_load;
#endif
-static int parkeddynamic = 0; /*!< Enable creation of parkinglots dynamically */
-
/*!
* \brief Context for parking dialback to parker.
* \note The need for the context is a KLUDGE.
@@ -497,8 +488,6 @@ static char parking_con_dial[] = "park-dial";
/*! Ensure that features.conf reloads on one thread at a time. */
AST_MUTEX_DEFINE_STATIC(features_reload_lock);
-static int adsipark;
-
static char *registrar = "features"; /*!< Registrar for operations */
/*! PARK_APP_NAME application arguments */
@@ -512,9 +501,6 @@ AST_DEFINE_APP_ARGS_TYPE(park_app_args,
AST_APP_ARG(dummy); /*!< Place to put any remaining args string. */
);
-/* module and CLI command definitions */
-static const char *parkcall = "Park";
-
static pthread_t parking_thread;
struct ast_dial_features {
/*! Channel's feature flags. */
@@ -670,50 +656,7 @@ static int add_features_datastore(struct ast_channel *chan, const struct ast_fla
}
/* Forward declarations */
-static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
static void parkinglot_unref(struct ast_parkinglot *parkinglot);
-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);
-static int parkinglot_activate(struct ast_parkinglot *parkinglot);
-static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile);
-
-/*!
- * \internal
- * \brief Get the parking extension if it exists.
- *
- * \param exten_str Parking extension to see if exists.
- * \param chan Channel to autoservice while looking for exten. (Could be NULL)
- * \param context Parking context to look in for exten.
- *
- * \retval exten on success.
- * \retval NULL on error or exten does not exist.
- */
-static struct ast_exten *get_parking_exten(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;
-
- ast_debug(4, "Checking if %s@%s is a parking exten\n", exten_str, context);
- exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL,
- E_MATCH);
- if (!exten) {
- return NULL;
- }
-
- app_at_exten = ast_get_extension_app(exten);
- if (!app_at_exten || strcasecmp(parkcall, app_at_exten)) {
- return NULL;
- }
-
- return exten;
-}
-
-int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
-{
- return get_parking_exten(exten_str, chan, context) ? 1 : 0;
-}
struct ast_bridge_thread_obj
{
@@ -755,46 +698,6 @@ static const struct ast_datastore_info channel_app_data_datastore = {
.destroy = ast_free_ptr,
};
-/*!
- * \brief Announce call parking by ADSI
- * \param chan .
- * \param parkingexten .
- * Create message to show for ADSI, display message.
- * \retval 0 on success.
- * \retval -1 on failure.
- */
-static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
-{
- int res;
- int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
- char tmp[256];
- char *message[5] = {NULL, NULL, NULL, NULL, NULL};
-
- snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
- message[0] = tmp;
- res = ast_adsi_load_session(chan, NULL, 0, 1);
- if (res == -1)
- return res;
- return ast_adsi_print(chan, message, justify, 1);
-}
-
-/*!
- * \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 *name;
-
- /* The channel variable overrides everything */
- name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
- if (!name && !ast_strlen_zero(ast_channel_parkinglot(chan))) {
- /* Use the channel's parking lot. */
- name = ast_channel_parkinglot(chan);
- }
- return name;
-}
-
/*! \brief Notify metermaids that we've changed an extension */
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
{
@@ -857,705 +760,6 @@ struct ast_park_call_args {
/*!
* \internal
- * \brief Create a dynamic parking lot.
- *
- * \param name Dynamic parking lot name to create.
- * \param chan Channel to get dynamic parking lot parameters.
- *
- * \retval parkinglot on success.
- * \retval NULL on error.
- */
-static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
-{
- const char *dyn_context;
- const char *dyn_exten;
- const char *dyn_range;
- const char *template_name;
- struct ast_parkinglot *template_parkinglot = NULL;
- struct ast_parkinglot *parkinglot;
- int dyn_start;
- int dyn_end;
-
- ast_channel_lock(chan);
- template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
- dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
- dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
- dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
- ast_channel_unlock(chan);
-
- if (!ast_strlen_zero(template_name)) {
- template_parkinglot = find_parkinglot(template_name);
- if (!template_parkinglot) {
- ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
- template_name);
- } else if (template_parkinglot->cfg.is_invalid) {
- ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
- template_name);
- parkinglot_unref(template_parkinglot);
- template_parkinglot = NULL;
- }
- }
- if (!template_parkinglot) {
- template_parkinglot = parkinglot_addref(default_parkinglot);
- ast_debug(1, "Using default parking lot for template\n");
- }
-
- parkinglot = copy_parkinglot(name, template_parkinglot);
- if (!parkinglot) {
- ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
- } else {
- /* Configure the dynamic parking lot. */
- if (!ast_strlen_zero(dyn_context)) {
- ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
- sizeof(parkinglot->cfg.parking_con));
- }
- if (!ast_strlen_zero(dyn_exten)) {
- ast_copy_string(parkinglot->cfg.parkext, dyn_exten,
- sizeof(parkinglot->cfg.parkext));
- }
- 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 if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
- ast_log(LOG_WARNING,
- "Format for parking positions is a-b, where a <= b\n");
- } else {
- parkinglot->cfg.parking_start = dyn_start;
- parkinglot->cfg.parking_stop = dyn_end;
- }
- }
-
- /*
- * Sanity check for dynamic parking lot configuration.
- *
- * XXX It may be desirable to instead check if the dynamic
- * parking lot overlaps any existing lots like what is done for
- * a reload.
- */
- if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
- if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)
- && parkinglot->cfg.parkext_exclusive) {
- ast_log(LOG_WARNING,
- "Parking lot '%s' conflicts with template parking lot '%s'!\n"
- "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
- parkinglot->name, template_parkinglot->name);
- }
- if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
- && parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
- || (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
- && parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
- || (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
- && template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
- ast_log(LOG_WARNING,
- "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
- "Change PARKINGDYNPOS.\n",
- parkinglot->name, template_parkinglot->name);
- }
- }
-
- parkinglot_activate(parkinglot);
- ao2_link(parkinglots, parkinglot);
- }
- parkinglot_unref(template_parkinglot);
-
- return parkinglot;
-}
-
-/*!
- * \internal
- * \brief Abort parking a call that has not completed parking yet.
- *
- * \param pu Parked user item to clean up.
- *
- * \note The parking lot parkings list is locked on entry.
- *
- * \return Nothing
- */
-static void park_space_abort(struct parkeduser *pu)
-{
- struct ast_parkinglot *parkinglot;
-
- parkinglot = pu->parkinglot;
-
- /* Put back the parking space just allocated. */
- --parkinglot->next_parking_space;
-
- AST_LIST_REMOVE(&parkinglot->parkings, pu, list);
-
- AST_LIST_UNLOCK(&parkinglot->parkings);
- parkinglot_unref(parkinglot);
- ast_free(pu);
-}
-
-/*!
- * \internal
- * \brief Reserve a parking space in a parking lot for a call being parked.
- *
- * \param park_me Channel being parked.
- * \param parker Channel parking the call.
- * \param args Optional additional parking options when parking a call.
- *
- * \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 *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
-{
- struct parkeduser *pu;
- int i;
- int parking_space = -1;
- const char *parkinglotname;
- const char *parkingexten;
- struct parkeduser *cur;
- struct ast_parkinglot *parkinglot = NULL;
-
- if (args->parkinglot) {
- parkinglot = parkinglot_addref(args->parkinglot);
- parkinglotname = parkinglot->name;
- } else {
- if (parker) {
- parkinglotname = findparkinglotname(parker);
- } else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
- parkinglotname = findparkinglotname(park_me);
- }
- if (!ast_strlen_zero(parkinglotname)) {
- parkinglot = find_parkinglot(parkinglotname);
- } else {
- /* Parking lot is not specified, so use the default parking lot. */
- ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
- parkinglot = parkinglot_addref(default_parkinglot);
- }
- }
-
- /* Dynamically create parkinglot */
- if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
- parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
- }
-
- if (!parkinglot) {
- ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", ast_channel_name(park_me));
- return NULL;
- }
-
- ast_debug(1, "Parking lot: %s\n", parkinglot->name);
- if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
- ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
- parkinglot->name);
- parkinglot_unref(parkinglot);
- return NULL;
- }
-
- /* Allocate memory for parking data */
- if (!(pu = ast_calloc(1, sizeof(*pu)))) {
- parkinglot_unref(parkinglot);
- return NULL;
- }
-
- /* Lock parking list */
- AST_LIST_LOCK(&parkinglot->parkings);
-
- /* Check for channel variable PARKINGEXTEN */
- parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
- if (!ast_strlen_zero(parkingexten)) {
- /*!
- * \note The API forces us to specify a numeric parking slot, even
- * though the architecture would tend to support non-numeric extensions
- * (as are possible with SIP, for example). Hence, we enforce that
- * limitation here. If extout was not numeric, we could permit
- * arbitrary non-numeric extensions.
- */
- if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
- ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
- parkingexten);
- AST_LIST_UNLOCK(&parkinglot->parkings);
- parkinglot_unref(parkinglot);
- ast_free(pu);
- return NULL;
- }
-
- if (parking_space < parkinglot->cfg.parking_start
- || parkinglot->cfg.parking_stop < parking_space) {
- /*
- * Cannot allow park because parking lots are not setup for
- * spaces outside of the lot. (Things like dialplan hints don't
- * exist for outside lot space.)
- */
- ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
- parking_space, parkinglot->name, parkinglot->cfg.parking_start,
- parkinglot->cfg.parking_stop);
- AST_LIST_UNLOCK(&parkinglot->parkings);
- parkinglot_unref(parkinglot);
- ast_free(pu);
- return NULL;
- }
-
- /* Check if requested parking space is in use. */
- AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
- if (cur->parkingnum == parking_space) {
- ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
- parking_space, parkinglot->name);
- AST_LIST_UNLOCK(&parkinglot->parkings);
- parkinglot_unref(parkinglot);
- ast_free(pu);
- return NULL;
- }
- }
- } 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 */
-
- /* 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->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
- start += parkinglot->cfg.parking_start;
- } else if (parkinglot->cfg.parkfindnext
- && parkinglot->cfg.parking_start <= parkinglot->next_parking_space
- && parkinglot->next_parking_space <= parkinglot->cfg.parking_stop) {
- /* Start looking with the next parking space in the lot. */
- start = parkinglot->next_parking_space;
- } else {
- /* Otherwise, just set it to the start position. */
- start = parkinglot->cfg.parking_start;
- }
-
- /* free parking extension linear search: O(n^2) */
- for (i = start; ; i++) {
- /* If we are past the end, wrap around to the first parking slot*/
- 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. */
- if (start_checked) {
- break;
- } else {
- start_checked = 1;
- }
- }
-
- /* Search the list of parked calls already in use for i. If we find it, it's in use. */
- AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
- if (cur->parkingnum == i) {
- break;
- }
- }
- if (!cur) {
- /* We found a parking space. */
- parking_space = i;
- break;
- }
- }
- if (parking_space == -1) {
- /* We did not find a parking space. Lot is full. */
- ast_log(LOG_WARNING, "No more parking spaces in %s\n", parkinglot->name);
- AST_LIST_UNLOCK(&parkinglot->parkings);
- parkinglot_unref(parkinglot);
- ast_free(pu);
- return NULL;
- }
- }
-
- /* Prepare for next parking space search. */
- parkinglot->next_parking_space = parking_space + 1;
-
- snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
- pu->notquiteyet = 1;
- pu->parkingnum = parking_space;
- pu->parkinglot = parkinglot;
- AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
-
- return pu;
-}
-
-/* Park a call */
-static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
-{
- struct parkeduser *pu = args->pu;
- const char *event_from; /*!< Channel name that is parking the call. */
- char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
-
- if (pu == NULL) {
- args->pu = pu = park_space_reserve(chan, peer, args);
- if (pu == NULL) {
- return -1;
- }
- }
-
- ast_channel_appl_set(chan, "Parked Call");
- ast_channel_data_set(chan, NULL);
-
- pu->chan = chan;
-
- /* Put the parked channel on hold if we have two different channels */
- if (chan != peer) {
- if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
- pu->hold_method = AST_CONTROL_RINGING;
- ast_indicate(chan, AST_CONTROL_RINGING);
- } else {
- pu->hold_method = AST_CONTROL_HOLD;
- ast_indicate_data(chan, AST_CONTROL_HOLD,
- 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();
- /* XXX This line was changed to not use get_parkingtime. This is just a placeholder message, because
- * likely this entire function is going away.
- */
- pu->parkingtime = args->timeout;
- if (args->extout)
- *(args->extout) = pu->parkingnum;
-
- if (peer) {
- event_from = S_OR(args->orig_chan_name, ast_channel_name(peer));
-
- /*
- * This is so ugly that it hurts, but implementing
- * get_base_channel() on local channels could have ugly side
- * effects. We could have
- * transferer<->local;1<->local;2<->parking and we need the
- * callback name to be that of transferer. Since local;1/2 have
- * the same name we can be tricky and just grab the bridged
- * channel from the other side of the local.
- */
- if (!strcasecmp(ast_channel_tech(peer)->type, "Local")) {
- struct ast_channel *tmpchan, *base_peer;
- char other_side[AST_CHANNEL_NAME];
- char *c;
-
- ast_copy_string(other_side, event_from, sizeof(other_side));
- if ((c = strrchr(other_side, ';'))) {
- *++c = '1';
- }
- if ((tmpchan = ast_channel_get_by_name(other_side))) {
- ast_channel_lock(tmpchan);
- if ((base_peer = ast_bridged_channel(tmpchan))) {
- ast_copy_string(pu->peername, ast_channel_name(base_peer), sizeof(pu->peername));
- }
- ast_channel_unlock(tmpchan);
- tmpchan = ast_channel_unref(tmpchan);
- }
- } else {
- ast_copy_string(pu->peername, event_from, sizeof(pu->peername));
- }
- } else {
- event_from = S_OR(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"),
- ast_channel_name(chan));
- }
-
- /*
- * Remember what had been dialed, so that if the parking
- * expires, we try to come back to the same place
- */
- pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
-
- /*
- * If extension has options specified, they override all other
- * possibilities such as the returntoorigin flag and transferred
- * context. Information on extension options is lost here, so
- * we set a flag
- */
- ast_copy_string(pu->context,
- S_OR(args->return_con, S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan))),
- sizeof(pu->context));
- ast_copy_string(pu->exten,
- S_OR(args->return_ext, S_OR(ast_channel_macroexten(chan), ast_channel_exten(chan))),
- sizeof(pu->exten));
- pu->priority = args->return_pri ? args->return_pri :
- (ast_channel_macropriority(chan) ? ast_channel_macropriority(chan) : ast_channel_priority(chan));
-
- /*
- * 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;
- }
-
- /* Wake up the (presumably select()ing) thread */
- pthread_kill(parking_thread, SIGURG);
- ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %u seconds\n",
- ast_channel_name(chan), pu->parkingnum, pu->parkinglot->name,
- pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
-
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a call has been parked.</synopsis>
- <syntax>
- <parameter name="Exten">
- <para>The parking lot extension.</para>
- </parameter>
- <parameter name="Parkinglot">
- <para>The name of the parking lot.</para>
- </parameter>
- <parameter name="From">
- <para>The name of the channel that parked the call.</para>
- </parameter>
- </syntax>
- <see-also>
- <ref type="application">Park</ref>
- <ref type="manager">Park</ref>
- <ref type="managerEvent">ParkedCallTimeOut</ref>
- <ref type="managerEvent">ParkedCallGiveUp</ref>
- </see-also>
- </managerEventInstance>
- ***/
- ast_manager_event(chan, EVENT_FLAG_CALL, "ParkedCall",
- "Exten: %s\r\n"
- "Channel: %s\r\n"
- "Parkinglot: %s\r\n"
- "From: %s\r\n"
- "Timeout: %ld\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "ConnectedLineNum: %s\r\n"
- "ConnectedLineName: %s\r\n"
- "Uniqueid: %s\r\n",
- pu->parkingexten, ast_channel_name(chan), pu->parkinglot->name, event_from,
- (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
- S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>"),
- S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "<unknown>"),
- S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "<unknown>"),
- ast_channel_uniqueid(chan)
- );
- ast_debug(4, "peer: %s\n", peer ? ast_channel_name(peer) : "-No peer-");
- ast_debug(4, "args->orig_chan_name: %s\n", args->orig_chan_name ? args->orig_chan_name : "-none-");
- ast_debug(4, "pu->peername: %s\n", pu->peername);
- ast_debug(4, "AMI ParkedCall Channel: %s\n", ast_channel_name(chan));
- ast_debug(4, "AMI ParkedCall From: %s\n", event_from);
-
- if (peer && adsipark && ast_adsi_available(peer)) {
- adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
- ast_adsi_unload_session(peer);
- }
-
- snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
- pu->parkinglot->name);
-
- AST_LIST_UNLOCK(&pu->parkinglot->parkings);
-
- /* Only say number if it's a number and the channel hasn't been masqueraded away */
- if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE)
- && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(ast_channel_name(peer), args->orig_chan_name))) {
- /*
- * If a channel is masqueraded into peer while playing back the
- * parking space number do not continue playing it back. This
- * is the case if an attended transfer occurs.
- */
- ast_set_flag(ast_channel_flags(peer), AST_FLAG_MASQ_NOSTREAM);
- /* Tell the peer channel the number of the parking space */
- ast_say_digits(peer, pu->parkingnum, "", ast_channel_language(peer));
- ast_clear_flag(ast_channel_flags(peer), AST_FLAG_MASQ_NOSTREAM);
- }
- if (peer == chan) { /* pu->notquiteyet = 1 */
- /* Wake up parking thread if we're really done */
- if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
- pu->hold_method = AST_CONTROL_RINGING;
- ast_indicate(chan, AST_CONTROL_RINGING);
- } else {
- pu->hold_method = AST_CONTROL_HOLD;
- ast_indicate_data(chan, AST_CONTROL_HOLD,
- 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);
- }
- return 0;
-}
-
-/*!
- * \brief Park call via masqueraded channel and announce parking spot on peer channel.
- *
- * \param rchan the real channel to be parked
- * \param peer the channel to have the parking read to.
- * \param args Additional parking options when parking a call.
- *
- * \retval 0 on success.
- * \retval -1 on failure.
- */
-static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
-{
- struct ast_channel *chan;
-
- /* Make a new, channel that we'll use to masquerade in the real one */
- chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, ast_channel_accountcode(rchan), ast_channel_exten(rchan),
- ast_channel_context(rchan), ast_channel_linkedid(rchan), ast_channel_amaflags(rchan), "Parked/%s", ast_channel_name(rchan));
- if (!chan) {
- ast_log(LOG_WARNING, "Unable to create parked channel\n");
- if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
- if (peer == rchan) {
- /* Only have one channel to worry about. */
- ast_stream_and_wait(peer, "pbx-parkingfailed", "");
- } else if (peer) {
- /* Have two different channels to worry about. */
- play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
- }
- }
- return -1;
- }
-
- args->pu = park_space_reserve(rchan, peer, args);
- if (!args->pu) {
- ast_hangup(chan);
- if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
- if (peer == rchan) {
- /* Only have one channel to worry about. */
- ast_stream_and_wait(peer, "pbx-parkingfailed", "");
- } else if (peer) {
- /* Have two different channels to worry about. */
- play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
- }
- }
- return -1;
- }
-
- /* Make formats okay */
- ast_format_copy(ast_channel_readformat(chan), ast_channel_readformat(rchan));
- ast_format_copy(ast_channel_writeformat(chan), ast_channel_writeformat(rchan));
-
- if (ast_channel_masquerade(chan, rchan)) {
- park_space_abort(args->pu);
- args->pu = NULL;
- ast_hangup(chan);
- if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
- if (peer == rchan) {
- /* Only have one channel to worry about. */
- ast_stream_and_wait(peer, "pbx-parkingfailed", "");
- } else if (peer) {
- /* Have two different channels to worry about. */
- play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
- }
- }
- return -1;
- }
-
- /* Setup the extensions and such */
- set_c_e_p(chan, ast_channel_context(rchan), ast_channel_exten(rchan), ast_channel_priority(rchan));
-
- /* Setup the macro extension and such */
- ast_channel_macrocontext_set(chan, ast_channel_macrocontext(rchan));
- ast_channel_macroexten_set(chan, ast_channel_macroexten(rchan));
- ast_channel_macropriority_set(chan, ast_channel_macropriority(rchan));
-
- /* Manually do the masquerade to make sure it is complete. */
- ast_do_masquerade(chan);
-
- if (peer == rchan) {
- peer = chan;
- }
-
- /* parking space reserved, return code check unnecessary */
- park_call_full(chan, peer, args);
-
- return 0;
-}
-
-int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
-{
- int res;
- char *parse;
- const char *app_data;
- struct ast_exten *exten;
- struct park_app_args app_args;
- struct ast_park_call_args args = {
- .timeout = timeout,
- .extout = extout,
- };
-
- if (parker) {
- args.orig_chan_name = ast_strdupa(ast_channel_name(parker));
- }
- if (!park_exten || !park_context) {
- return masq_park_call(park_me, parker, &args);
- }
-
- /*
- * Determiine if the specified park extension has an exclusive
- * parking lot to use.
- */
- if (parker && parker != park_me) {
- ast_autoservice_start(park_me);
- }
- exten = get_parking_exten(park_exten, parker, park_context);
- if (exten) {
- app_data = ast_get_extension_app_data(exten);
- if (!app_data) {
- app_data = "";
- }
- parse = ast_strdupa(app_data);
- AST_STANDARD_APP_ARGS(app_args, parse);
-
- if (!ast_strlen_zero(app_args.pl_name)) {
- /* Find the specified exclusive parking lot */
- args.parkinglot = find_parkinglot(app_args.pl_name);
- if (!args.parkinglot && parkeddynamic) {
- args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
- }
- }
- }
- if (parker && parker != park_me) {
- ast_autoservice_stop(park_me);
- }
-
- res = masq_park_call(park_me, parker, &args);
- if (args.parkinglot) {
- parkinglot_unref(args.parkinglot);
- }
- return res;
-}
-
-int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
-{
- struct ast_park_call_args args = {
- .timeout = timeout,
- .extout = extout,
- };
-
- if (peer) {
- args.orig_chan_name = ast_strdupa(ast_channel_name(peer));
- }
- return masq_park_call(rchan, peer, &args);
-}
-
-/*!
- * \internal
- * \brief Play file to specified channel.
- *
- * \param play_to Channel to play audiofile to.
- * \param other Channel to put in autoservice while playing file.
- * \param msg Descriptive name of message type being played.
- * \param audiofile Audio file to play.
- *
- * \retval 0 on success.
- * \retval -1 on error. (Couldn't play file, a channel hung up,...)
- */
-static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
-{
- /* Put other channel in autoservice. */
- if (ast_autoservice_start(other)) {
- return -1;
- }
- ast_autoservice_ignore(other, AST_FRAME_DTMF_BEGIN);
- ast_autoservice_ignore(other, AST_FRAME_DTMF_END);
- if (ast_stream_and_wait(play_to, audiofile, "")) {
- ast_log(LOG_WARNING, "Failed to play %s '%s'!\n", msg, audiofile);
- ast_autoservice_stop(other);
- return -1;
- }
- if (ast_autoservice_stop(other)) {
- return -1;
- }
- return 0;
-}
-
-/*!
- * \internal
* \brief Get the extension for a given builtin feature
*
* \pre expects features_lock to be readlocked
@@ -2643,46 +1847,6 @@ static void *do_parking_thread(void *ignore)
return NULL; /* Never reached */
}
-/*! \brief Find parkinglot by name */
-static struct ast_parkinglot *find_parkinglot(const char *name)
-{
- struct ast_parkinglot *parkinglot;
-
- if (ast_strlen_zero(name)) {
- return NULL;
- }
-
- parkinglot = ao2_find(parkinglots, (void *) name, 0);
- if (parkinglot) {
- ast_debug(1, "Found Parking lot: %s\n", parkinglot->name);
- }
-
- return parkinglot;
-}
-
-/*! \brief Copy parkinglot and store it with new name */
-static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
-{
- struct ast_parkinglot *copylot;
-
- if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
- ao2_ref(copylot, -1);
- return NULL;
- }
-
- copylot = create_parkinglot(name);
- if (!copylot) {
- return NULL;
- }
-
- ast_debug(1, "Building parking lot %s\n", name);
-
- /* Copy the source parking lot configuration. */
- copylot->cfg = parkinglot->cfg;
-
- return copylot;
-}
-
AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
@@ -2699,49 +1863,6 @@ static void parkinglot_unref(struct ast_parkinglot *parkinglot)
ao2_ref(parkinglot, -1);
}
-static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
-{
- int refcount;
-
- refcount = ao2_ref(parkinglot, +1);
- ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
- return parkinglot;
-}
-
-/*! \brief Destroy a parking lot */
-static void parkinglot_destroy(void *obj)
-{
- struct ast_parkinglot *doomed = obj;
-
- /*
- * No need to destroy parked calls here because any parked call
- * holds a parking lot reference. Therefore the parkings list
- * must be empty.
- */
- ast_assert(AST_LIST_EMPTY(&doomed->parkings));
- AST_LIST_HEAD_DESTROY(&doomed->parkings);
-}
-
-/*! \brief Allocate parking lot structure */
-static struct ast_parkinglot *create_parkinglot(const char *name)
-{
- struct ast_parkinglot *newlot;
-
- if (ast_strlen_zero(name)) { /* No name specified */
- return NULL;
- }
-
- newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
- if (!newlot)
- return NULL;
-
- ast_copy_string(newlot->name, name, sizeof(newlot->name));
- newlot->cfg.is_invalid = 1;/* No config is set yet. */
- AST_LIST_HEAD_INIT(&newlot->parkings);
-
- return newlot;
-}
-
/*! Default configuration for default parking lot. */
static const struct parkinglot_cfg parkinglot_cfg_default_default = {
.mohclass = "default",
@@ -2764,26 +1885,6 @@ static const struct parkinglot_cfg parkinglot_cfg_default = {
.comebacktoorigin = DEFAULT_COMEBACK_TO_ORIGIN,
};
-/*!
- * \internal
- * \brief Activate the given parkinglot.
- *
- * \param parkinglot Parking lot to activate.
- *
- * \details
- * Insert into the dialplan the context, parking lot access
- * extension, and optional dialplan hints.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int parkinglot_activate(struct ast_parkinglot *parkinglot)
-{
- /* XXX All parking stuff is being replaced by res_parking */
- parkinglot->disabled = 1;
- return -1;
-}
-
int ast_features_reload(void)
{
struct ast_context *con;
@@ -3636,243 +2737,6 @@ done:
}
#if defined(TEST_FRAMEWORK)
-/*!
- * \internal
- * \brief Convert parking spaces map list to a comma separated string.
- *
- * \param str String buffer to fill.
- * \param spaces Parking spaces map list to convert.
- *
- * \return Nothing
- */
-static void create_spaces_str(struct ast_str **str, struct parking_dp_space_map *spaces)
-{
- const char *comma;
- struct parking_dp_spaces *cur;
-
- ast_str_reset(*str);
- comma = "";
- AST_LIST_TRAVERSE(spaces, cur, node) {
- if (cur->start == cur->stop) {
- ast_str_append(str, 0, "%s%d", comma, cur->start);
- } else {
- ast_str_append(str, 0, "%s%d-%d", comma, cur->start, cur->stop);
- }
- comma = ",";
- }
-}
-#endif /* defined(TEST_FRAMEWORK) */
-
-#if defined(TEST_FRAMEWORK)
-/*!
- * \internal
- * \brief Compare parking spaces map to what is expected.
- *
- * \param test Unit test context.
- * \param spaces Parking spaces map list to check.
- * \param expected String to compare with.
- * \param what What is being compared.
- *
- * \retval 0 successful compare.
- * \retval nonzero if failed to compare.
- */
-static int check_spaces(struct ast_test *test, struct parking_dp_space_map *spaces, const char *expected, const char *what)
-{
- int cmp;
- struct ast_str *str = ast_str_alloca(1024);
-
- create_spaces_str(&str, spaces);
- cmp = strcmp(expected, ast_str_buffer(str));
- if (cmp) {
- ast_test_status_update(test,
- "Unexpected parking space map for %s. Expect:'%s' Got:'%s'\n",
- what, expected, ast_str_buffer(str));
- }
- return cmp;
-}
-#endif /* defined(TEST_FRAMEWORK) */
-
-#if defined(TEST_FRAMEWORK)
-/*!
- * \internal
- * \brief Add a dead space to the dead spaces list.
- *
- * \param context Dead spaces list ptr pretending to be a context name ptr.
- * \param space Dead space to add to the list.
- *
- * \return Nothing
- */
-static void test_add_dead_space(const char *context, int space)
-{
- struct parking_dp_space_map *dead_spaces = (struct parking_dp_space_map *) context;
-
- usage_context_add_spaces(dead_spaces, space, space, NULL, 0);
-}
-#endif /* defined(TEST_FRAMEWORK) */
-
-#if defined(TEST_FRAMEWORK)
-struct test_map {
- const char *ramp;
- int start;
- int stop;
- const char *expect;
-};
-
-/*!
- * \internal
- * \brief Build a parking lot dialplan usage test map from a table.
- *
- * \param test Unit test context.
- * \param lot Parking lot to use to build test usage map.
- * \param table_name Name of passed in table.
- * \param table Usage information to put in the usage map.
- * \param num_entries Number of entries in the table.
- *
- * \retval Created context node on success.
- * \retval NULL on error.
- */
-static struct parking_dp_context *test_build_maps(struct ast_test *test,
- struct ast_parkinglot *lot, const char *table_name, const struct test_map *table,
- size_t num_entries)
-{
- struct parking_dp_context *ctx_node;
- int cur_index = 0;
- char what[40];
-
- snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
- ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
- lot->cfg.parking_start = table->start;
- lot->cfg.parking_stop = table->stop;
- ctx_node = build_dialplan_useage_context(lot);
- if (!ctx_node) {
- ast_test_status_update(test, "Failed to create parking lot context map for %s\n",
- what);
- return NULL;
- }
- if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
- destroy_dialplan_usage_context(ctx_node);
- return NULL;
- }
- while (--num_entries) {
- ++cur_index;
- ++table;
- snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
- ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
- lot->cfg.parking_start = table->start;
- lot->cfg.parking_stop = table->stop;
- if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 1)) {
- ast_test_status_update(test, "Failed to add parking lot data for %s\n", what);
- destroy_dialplan_usage_context(ctx_node);
- return NULL;
- }
- if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
- destroy_dialplan_usage_context(ctx_node);
- return NULL;
- }
- }
- return ctx_node;
-}
-
-static const struct test_map test_old_ctx[] = {
- /* The following order of building ctx is important to test adding items to the lists. */
- { "702", 14, 15, "14-15" },
- { "700", 10, 11, "10-11,14-15" },
- { "701", 18, 19, "10-11,14-15,18-19" },
- { "703", 12, 13, "10-15,18-19" },
- { "704", 16, 17, "10-19" },
-
- /* Parking ramp and space conflicts are intended with these lines. */
- { "704", 9, 19, "9-19" },
- { "704", 9, 20, "9-20" },
- { "704", 8, 21, "8-21" },
-
- /* Add more spaces to ctx to test removing dead parking spaces. */
- { "705", 23, 25, "8-21,23-25" },
- { "706", 28, 31, "8-21,23-25,28-31" },
- { "707", 33, 34, "8-21,23-25,28-31,33-34" },
- { "708", 38, 40, "8-21,23-25,28-31,33-34,38-40" },
- { "709", 42, 43, "8-21,23-25,28-31,33-34,38-40,42-43" },
-};
-
-static const struct test_map test_new_ctx[] = {
- { "702", 4, 5, "4-5" },
- { "704", 24, 26, "4-5,24-26" },
- { "709", 29, 30, "4-5,24-26,29-30" },
- { "710", 32, 35, "4-5,24-26,29-30,32-35" },
- { "711", 37, 39, "4-5,24-26,29-30,32-35,37-39" },
-};
-#endif /* defined(TEST_FRAMEWORK) */
-
-#if defined(TEST_FRAMEWORK)
-/*!
- * \internal
- * \brief Test parking dialplan usage map code.
- *
- * \param test Unit test context.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int test_dialplan_usage_map(struct ast_test *test)
-{
- struct parking_dp_context *old_ctx;
- struct parking_dp_context *new_ctx;
- struct ast_parkinglot *lot;
- struct parking_dp_spaces *spaces;
- struct parking_dp_space_map dead_spaces = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
- int res;
-
- ast_test_status_update(test, "Test parking dialplan usage map code\n");
-
- lot = create_parkinglot("test_lot");
- if (!lot) {
- return -1;
- }
- ast_copy_string(lot->cfg.parking_con, "test-ctx", sizeof(lot->cfg.parking_con));
- lot->cfg.parkext_exclusive = 1;
-
- ast_test_status_update(test,
- "Build old_ctx map\n");
- ast_log(LOG_NOTICE, "6 Ramp and space conflict warnings are expected.\n");
- old_ctx = test_build_maps(test, lot, "test_old_ctx", test_old_ctx,
- ARRAY_LEN(test_old_ctx));
- if (!old_ctx) {
- ao2_ref(lot, -1);
- return -1;
- }
-
- ast_test_status_update(test, "Build new_ctx map\n");
- new_ctx = test_build_maps(test, lot, "test_new_ctx", test_new_ctx,
- ARRAY_LEN(test_new_ctx));
- if (!new_ctx) {
- res = -1;
- goto fail_old_ctx;
- }
-
- ast_test_status_update(test, "Test removing dead parking spaces\n");
- remove_dead_spaces_usage((void *) &dead_spaces, &old_ctx->spaces,
- &new_ctx->spaces, test_add_dead_space);
- if (check_spaces(test, &dead_spaces, "8-21,23,28,31,40,42-43", "dead_spaces")) {
- res = -1;
- goto fail_dead_spaces;
- }
-
- res = 0;
-
-fail_dead_spaces:
- while ((spaces = AST_LIST_REMOVE_HEAD(&dead_spaces, node))) {
- ast_free(spaces);
- }
- destroy_dialplan_usage_context(new_ctx);
-
-fail_old_ctx:
- destroy_dialplan_usage_context(old_ctx);
- ao2_ref(lot, -1);
- return res;
-}
-#endif /* defined(TEST_FRAMEWORK) */
-
-#if defined(TEST_FRAMEWORK)
static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
{
return 0;
@@ -3905,209 +2769,6 @@ static struct ast_channel *create_test_channel(const struct ast_channel_tech *fa
}
#endif /* defined(TEST_FRAMEWORK) */
-#if defined(TEST_FRAMEWORK)
-static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
-{
- struct ast_context *con;
- struct parkeduser *pu_toremove;
- int res = 0;
-
- 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) {
- if (pu_toremove == args->pu) {
- AST_LIST_REMOVE_CURRENT(list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
-
- if (!pu_toremove) {
- ast_log(LOG_WARNING, "Whoa, could not find parking test call!\n");
- return -1;
- }
-
- 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");
- res = -1;
- } else {
- 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");
- res = -1;
- }
-
- parkinglot_unref(pu_toremove->parkinglot);
- ast_free(pu_toremove);
- args->pu = NULL;
-
- if (!res && toremove) {
- ast_hangup(toremove);
- }
- return res;
-}
-#endif /* defined(TEST_FRAMEWORK) */
-
-#if defined(TEST_FRAMEWORK)
-AST_TEST_DEFINE(features_test)
-{
- struct ast_channel *test_channel1 = NULL;
- struct ast_channel *parked_chan = NULL;
- struct ast_parkinglot *dynlot;
- struct ast_park_call_args args = {
- .timeout = DEFAULT_PARK_TIME,
- };
-
- int res = 0;
-
- static const struct ast_channel_tech fake_tech = {
- .fixup = fake_fixup, /* silence warning from masquerade */
- };
-
- static const char unique_lot_1[] = "myuniquetestparkinglot314";
- static const char unique_lot_2[] = "myuniquetestparkinglot3141592654";
- static const char unique_context_1[] = "myuniquetestcontext314";
- static const char unique_context_2[] = "myuniquetestcontext3141592654";
- static const char parkinglot_parkext[] = "750";
- static const char parkinglot_range[] = "751-760";
-
- switch (cmd) {
- case TEST_INIT:
- info->name = "features_test";
- info->category = "/main/features/";
- info->summary = "Features unit test";
- info->description =
- "Tests whether parking respects PARKINGLOT settings";
- return AST_TEST_NOT_RUN;
- case TEST_EXECUTE:
- break;
- }
-
- if (test_dialplan_usage_map(test)) {
- res = -1;
- goto exit_features_test;
- }
-
- /* changing a config option is a bad practice, but must be done in this case */
- parkeddynamic = 1;
-
- ast_test_status_update(test, "Test parking functionality with defaults\n");
- if (!(test_channel1 = create_test_channel(&fake_tech))) {
- res = -1;
- goto exit_features_test;
- }
- if (park_call_full(test_channel1, NULL, &args)) {
- res = -1;
- goto exit_features_test;
- }
- if (unpark_test_channel(test_channel1, &args)) {
- res = -1;
- goto exit_features_test;
- }
-
-
- ast_test_status_update(test, "Check that certain parking options are respected\n");
- if (!(test_channel1 = create_test_channel(&fake_tech))) {
- res = -1;
- goto exit_features_test;
- }
- pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_lot_1);
- pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNCONTEXT", unique_context_1);
- pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNEXTEN", parkinglot_parkext);
- pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
- if (park_call_full(test_channel1, NULL, &args)) {
- res = -1;
- goto exit_features_test;
- }
- /* grab newly created parking lot for destruction in the end */
- dynlot = args.pu->parkinglot;
- if (args.pu->parkingnum != 751
- || strcmp(dynlot->name, unique_lot_1)
- || strcmp(dynlot->cfg.parking_con, unique_context_1)
- || strcmp(dynlot->cfg.parkext, parkinglot_parkext)
- || dynlot->cfg.parking_start != 751
- || dynlot->cfg.parking_stop != 760) {
- ast_test_status_update(test, "Parking settings were not respected\n");
- ast_test_status_update(test, "Dyn-name:%s\n", dynlot->name);
- ast_test_status_update(test, "Dyn-context:%s\n", dynlot->cfg.parking_con);
- ast_test_status_update(test, "Dyn-parkext:%s\n", dynlot->cfg.parkext);
- ast_test_status_update(test, "Dyn-parkpos:%d-%d\n", dynlot->cfg.parking_start,
- dynlot->cfg.parking_stop);
- ast_test_status_update(test, "Parked in space:%d\n", args.pu->parkingnum);
- if (!unpark_test_channel(test_channel1, &args)) {
- test_channel1 = NULL;
- }
- res = -1;
- goto exit_features_test;
- } else {
- ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
- }
- if (unpark_test_channel(test_channel1, &args)) {
- res = -1;
- goto exit_features_test;
- }
-
-
- ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
- if (!(test_channel1 = create_test_channel(&fake_tech))) {
- res = -1;
- goto exit_features_test;
- }
- pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_lot_2);
- pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNCONTEXT", unique_context_2);
- pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNEXTEN", parkinglot_parkext);
- pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
- if (masq_park_call(test_channel1, NULL, &args)) {
- res = -1;
- goto exit_features_test;
- }
- /* hangup zombie channel */
- ast_hangup(test_channel1);
- test_channel1 = NULL;
-
- dynlot = args.pu->parkinglot;
- if (args.pu->parkingnum != 751
- || strcmp(dynlot->name, unique_lot_2)
- || strcmp(dynlot->cfg.parking_con, unique_context_2)
- || strcmp(dynlot->cfg.parkext, parkinglot_parkext)
- || dynlot->cfg.parking_start != 751
- || dynlot->cfg.parking_stop != 760) {
- ast_test_status_update(test, "Parking settings were not respected\n");
- ast_test_status_update(test, "Dyn-name:%s\n", dynlot->name);
- ast_test_status_update(test, "Dyn-context:%s\n", dynlot->cfg.parking_con);
- ast_test_status_update(test, "Dyn-parkext:%s\n", dynlot->cfg.parkext);
- ast_test_status_update(test, "Dyn-parkpos:%d-%d\n", dynlot->cfg.parking_start,
- dynlot->cfg.parking_stop);
- ast_test_status_update(test, "Parked in space:%d\n", args.pu->parkingnum);
- res = -1;
- } else {
- ast_test_status_update(test, "Parking settings for masquerading park verified\n");
- }
-
- /* find the real channel */
- parked_chan = ast_channel_get_by_name("TestChannel1");
- if (unpark_test_channel(parked_chan, &args)) {
- ast_hangup(parked_chan);
- res = -1;
- }
-
-
-exit_features_test:
-
- ast_hangup(test_channel1);
-
- force_reload_load = 1;
- ast_features_reload();
- return res ? AST_TEST_FAIL : AST_TEST_PASS;
-}
-#endif /* defined(TEST_FRAMEWORK) */
-
/*! \internal \brief Clean up resources on Asterisk shutdown */
static void features_shutdown(void)
{
@@ -4152,9 +2813,6 @@ int ast_features_init(void)
res |= ast_manager_register_xml_core("Bridge", EVENT_FLAG_CALL, action_bridge);
res |= ast_devstate_prov_add("Park", metermaidstate);
-#if defined(TEST_FRAMEWORK)
- res |= AST_TEST_REGISTER(features_test);
-#endif /* defined(TEST_FRAMEWORK) */
if (res) {
features_shutdown();