[asterisk-commits] rmudgett: branch rmudgett/parking r330819 - /team/rmudgett/parking/main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Aug 3 11:37:49 CDT 2011
Author: rmudgett
Date: Wed Aug 3 11:37:45 2011
New Revision: 330819
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=330819
Log:
Factored manage_parked_call() out of manage_parkinglot() to eliminate
using ast_strdupa() within in a loop in a function.
Modified:
team/rmudgett/parking/main/features.c
Modified: team/rmudgett/parking/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/features.c?view=diff&rev=330819&r1=330818&r2=330819
==============================================================================
--- team/rmudgett/parking/main/features.c (original)
+++ team/rmudgett/parking/main/features.c Wed Aug 3 11:37:45 2011
@@ -4122,214 +4122,252 @@
return options;
}
+/*!
+ * \internal
+ * \brief Run management on a parked call.
+ *
+ * \note The parkinglot parkings list is locked on entry.
+ *
+ * \retval TRUE if the parking completed.
+ */
+static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
+{
+ struct ast_channel *chan = pu->chan; /* shorthand */
+ int tms; /* timeout for this item */
+ int x; /* fd index in channel */
+ struct ast_context *con;
+ int parking_complete = 0;
+
+ tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+ if (tms > pu->parkingtime) {
+/* BUGBUG stop MOH or RINGING depending on what was last sent */
+ /*
+ * Call has been parked too long.
+ * Stop music on hold
+ */
+ ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+
+ /* Get chan, exten from derived kludge */
+ if (pu->peername[0]) {
+ char *peername;
+ char *dash;
+ char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
+ int i;
+
+ peername = ast_strdupa(pu->peername);
+ dash = strrchr(peername, '-');
+ if (dash) {
+ *dash = '\0';
+ }
+
+ peername_flat = ast_strdupa(peername);
+ for (i = 0; peername_flat[i]; i++) {
+ if (peername_flat[i] == '/') {
+ peername_flat[i] = '_';
+ }
+ }
+
+ con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
+ if (!con) {
+ ast_log(LOG_ERROR,
+ "Parking dial context '%s' does not exist and unable to create\n",
+ parking_con_dial);
+ } else {
+ char returnexten[AST_MAX_EXTENSION];
+ struct ast_datastore *features_datastore;
+ struct ast_dial_features *dialfeatures;
+
+ if (!strncmp(peername, "Parked/", 7)) {
+ peername += 7;
+ }
+
+ ast_channel_lock(chan);
+ features_datastore = ast_channel_datastore_find(chan, &dial_features_info,
+ NULL);
+ if (features_datastore && (dialfeatures = features_datastore->data)) {
+ char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
+
+ snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername,
+ callback_dialoptions(&(dialfeatures->features_callee),
+ &(dialfeatures->features_caller), buf, sizeof(buf)));
+ } else { /* Existing default */
+ ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
+ chan->name);
+ snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
+ }
+ ast_channel_unlock(chan);
+
+ ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial",
+ ast_strdup(returnexten), ast_free_ptr, registrar);
+ }
+ 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, parking_con_dial, peername_flat, 1);
+ } else {
+ char parkingslot[AST_MAX_EXTENSION];
+
+ snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+ pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
+ set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
+ }
+ } else {
+ /*
+ * They've been waiting too long, send them back to where they
+ * came. Theoretically they should have their original
+ * extensions and such, but we copy to be on the safe side.
+ */
+ set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+ }
+ post_manager_event("ParkedCallTimeOut", pu);
+ ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
+
+ ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n",
+ pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context,
+ pu->chan->exten, pu->chan->priority);
+
+ /* Start up the PBX, or hang them up */
+ if (ast_pbx_start(chan)) {
+ ast_log(LOG_WARNING,
+ "Unable to restart the PBX for user on '%s', hanging them up...\n",
+ pu->chan->name);
+ ast_hangup(chan);
+ }
+
+ /* And take them out of the parking lot */
+ parking_complete = 1;
+ } else { /* still within parking time, process descriptors */
+ for (x = 0; x < AST_MAX_FDS; x++) {
+ struct ast_frame *f;
+ int y;
+
+ if (chan->fds[x] == -1) {
+ continue; /* nothing on this descriptor */
+ }
+
+ for (y = 0; y < nfds; y++) {
+ if (pfds[y].fd == chan->fds[x]) {
+ /* Found poll record! */
+ break;
+ }
+ }
+ if (y == nfds) {
+ /* Not found */
+ continue;
+ }
+
+ if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
+ /* Next x */
+ continue;
+ }
+
+ if (pfds[y].revents & POLLPRI) {
+ ast_set_flag(chan, AST_FLAG_EXCEPTION);
+ } else {
+ ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+ }
+ chan->fdno = x;
+
+ /* See if they need servicing */
+ f = ast_read(pu->chan);
+ /* Hangup? */
+ if (!f || (f->frametype == AST_FRAME_CONTROL
+ && f->subclass.integer == AST_CONTROL_HANGUP)) {
+ if (f) {
+ ast_frfree(f);
+ }
+ post_manager_event("ParkedCallGiveUp", pu);
+ ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp",
+ NULL);
+
+ /* There's a problem, hang them up */
+ ast_verb(2, "%s got tired of being parked\n", chan->name);
+ ast_hangup(chan);
+
+ /* And take them out of the parking lot */
+ parking_complete = 1;
+ break;
+ } else {
+ /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
+ ast_frfree(f);
+ 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(pu->parkinglot->cfg.mohclass, NULL),
+ (!ast_strlen_zero(pu->parkinglot->cfg.mohclass)
+ ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0));
+ pu->moh_trys++;
+ }
+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
+ }
+ } /* End for */
+ if (x >= AST_MAX_FDS) {
+std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
+ if (chan->fds[x] > -1) {
+ void *tmp = ast_realloc(*new_pfds,
+ (*new_nfds + 1) * sizeof(struct pollfd));
+
+ if (!tmp) {
+ continue;
+ }
+ *new_pfds = tmp;
+ (*new_pfds)[*new_nfds].fd = chan->fds[x];
+ (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
+ (*new_pfds)[*new_nfds].revents = 0;
+ (*new_nfds)++;
+ }
+ }
+ /* Keep track of our shortest wait */
+ if (tms < *ms || *ms < 0) {
+ *ms = tms;
+ }
+ }
+ }
+
+ return parking_complete;
+}
+
/*! \brief Run management on parkinglots, called once per parkinglot */
-static int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
+static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
{
struct parkeduser *pu;
- int res = 0;
-
- /* Lock parking list */
+ struct ast_context *con;
+
+ /* Lock parkings list */
AST_LIST_LOCK(&curlot->parkings);
AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
- struct ast_channel *chan = pu->chan; /* shorthand */
- int tms; /* timeout for this item */
- int x; /* fd index in channel */
- struct ast_context *con;
-
if (pu->notquiteyet) { /* Pretend this one isn't here yet */
continue;
}
- 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 */
- int i;
-
- if (dash) {
- *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] = '_';
- }
- }
-
- con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
- if (!con) {
- ast_log(LOG_ERROR,
- "Parking dial context '%s' does not exist and unable to create\n",
- parking_con_dial);
- } else {
- char returnexten[AST_MAX_EXTENSION];
- struct ast_datastore *features_datastore;
- struct ast_dial_features *dialfeatures = NULL;
-
- ast_channel_lock(chan);
-
- if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
- dialfeatures = features_datastore->data;
-
- ast_channel_unlock(chan);
-
- if (!strncmp(peername, "Parked/", 7)) {
- peername += 7;
- }
-
- if (dialfeatures) {
- char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
- snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
- } else { /* Existing default */
- ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n", chan->name);
- snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
- }
-
- ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
- }
- 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, parking_con_dial, peername_flat, 1);
- } else {
- char parkingslot[AST_MAX_EXTENSION];
-
- snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
- pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
- set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
- }
- }
- } else {
- /* They've been waiting too long, send them back to where they came. Theoretically they
- should have their original extensions and such, but we copy to be on the safe side */
- set_c_e_p(chan, pu->context, pu->exten, pu->priority);
- }
- post_manager_event("ParkedCallTimeOut", pu);
- ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
-
- ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
- /* Start up the PBX, or hang them up */
- if (ast_pbx_start(chan)) {
- ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
- ast_hangup(chan);
- }
- /* And take them out of the parking lot */
+ if (manage_parked_call(pu, pfds, nfds, new_pfds, new_nfds, ms)) {
+ /* Parking is complete for this call so remove it from the parking lot. */
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->cfg.parking_con, AST_DEVICE_NOT_INUSE);
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
+ ast_log(LOG_WARNING,
+ "Whoa, failed to remove the parking extension %s@%s!\n",
+ pu->parkingexten, pu->parkinglot->cfg.parking_con);
+ }
+ notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con,
+ AST_DEVICE_NOT_INUSE);
+ } else {
+ ast_log(LOG_WARNING,
+ "Whoa, parking lot '%s' context '%s' does not exist.\n",
+ pu->parkinglot->name, pu->parkinglot->cfg.parking_con);
+ }
AST_LIST_REMOVE_CURRENT(list);
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;
- int y;
-
- if (chan->fds[x] == -1) {
- continue; /* nothing on this descriptor */
- }
-
- for (y = 0; y < nfds; y++) {
- if (pfds[y].fd == chan->fds[x]) {
- /* Found poll record! */
- break;
- }
- }
- if (y == nfds) {
- /* Not found */
- continue;
- }
-
- if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
- /* Next x */
- continue;
- }
-
- if (pfds[y].revents & POLLPRI) {
- ast_set_flag(chan, AST_FLAG_EXCEPTION);
- } else {
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
- }
- chan->fdno = x;
-
- /* See if they need servicing */
- f = ast_read(pu->chan);
- /* Hangup? */
- if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
- if (f)
- ast_frfree(f);
- post_manager_event("ParkedCallGiveUp", pu);
- ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp", NULL);
-
- /* There's a problem, hang them up*/
- 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->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->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);
- ast_free(pu);
- break;
- } else {
- /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
- ast_frfree(f);
- 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->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 */
- }
- } /* End for */
- if (x >= AST_MAX_FDS) {
-std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
- if (chan->fds[x] > -1) {
- void *tmp = ast_realloc(*new_pfds, (*new_nfds + 1) * sizeof(struct pollfd));
- if (!tmp) {
- continue;
- }
- *new_pfds = tmp;
- (*new_pfds)[*new_nfds].fd = chan->fds[x];
- (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
- (*new_pfds)[*new_nfds].revents = 0;
- (*new_nfds)++;
- }
- }
- /* Keep track of our shortest wait */
- if (tms < *ms || *ms < 0) {
- *ms = tms;
- }
- }
}
}
AST_LIST_TRAVERSE_SAFE_END;
AST_LIST_UNLOCK(&curlot->parkings);
-
- return res;
}
/*!
More information about the asterisk-commits
mailing list