[asterisk-commits] mvanbaak: branch group/multiparking r104052 - /team/group/multiparking/main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Feb 23 09:54:37 CST 2008
Author: mvanbaak
Date: Sat Feb 23 09:54:36 2008
New Revision: 104052
URL: http://svn.digium.com/view/asterisk?view=rev&rev=104052
Log:
create manager function for parked calls in parking lots
Modified:
team/group/multiparking/main/features.c
Modified: team/group/multiparking/main/features.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/main/features.c?view=diff&rev=104052&r1=104051&r2=104052
==============================================================================
--- team/group/multiparking/main/features.c (original)
+++ team/group/multiparking/main/features.c Sat Feb 23 09:54:36 2008
@@ -2257,6 +2257,174 @@
);
}
+/*! \brief Run management on parkinglots, collad once per parkinglot */
+int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds)
+{
+
+ int ms = -1; /* select timeout, uninitialized */
+ int max = -1; /* max fd, none there yet */
+ struct parkeduser *pu, *pl = NULL, *pt = NULL;
+ int res = 0;
+
+ parkinglot_addref(curlot);
+ pu = curlot->occupiedlots;
+ while(pu) {
+ 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 */
+ pl = pu;
+ pu = pu->next;
+ continue;
+ }
+ tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+ if (tms > pu->parkingtime) {
+ /* Stop music on hold */
+ ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+ /* Get chan, exten from derived kludge */
+ if (pu->peername[0]) {
+ char *peername = ast_strdupa(pu->peername);
+ char *cp = strrchr(peername, '-');
+ char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
+ int i;
+
+
+ if (cp)
+ *cp = 0;
+ ast_copy_string(peername_flat,peername,sizeof(peername_flat));
+ for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
+ if (peername_flat[i] == '/')
+ peername_flat[i]= '0';
+ }
+ con = ast_context_find(pu->parkinglot->parking_con_dial);
+ if (!con) {
+ con = ast_context_create(NULL, pu->parkinglot->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);
+ }
+
+ if (con)
+ ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
+
+ if (comebacktoorigin)
+ set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername, 1);
+ else {
+ char parkingslot[AST_MAX_EXTENSION];
+ ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
+ snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+ pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
+ set_c_e_p(chan, "parkedcallstimeout", peername, 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_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 (pl)
+ pl->next = pu->next;
+ else
+ curlot->occupiedlots = pu->next;
+ pt = pu;
+ pu = pu->next;
+ con = ast_context_find(pt->parkinglot->parking_con);
+ if (con) {
+ if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+ ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+ else
+ notify_metermaids(pt->parkingexten, curlot->parking_con);
+ } else
+ ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ free(pt);
+ parkinglot_unref(curlot);
+ } else { /* still within parking time, process descriptors */
+ for (x = 0; x < AST_MAX_FDS; x++) {
+ struct ast_frame *f;
+
+ if ((chan->fds[x] == -1) && (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds)))
+ continue;
+
+ if (FD_ISSET(chan->fds[x], efds))
+ 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 == AST_CONTROL_HANGUP))) {
+ if (f)
+ ast_frfree(f);
+ post_manager_event("ParkedCallGiveUp", pu);
+
+ /* 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 */
+ if (pl)
+ pl->next = pu->next;
+ else
+ curlot->occupiedlots = pu->next;
+ pt = pu;
+ pu = pu->next;
+ con = ast_context_find(curlot->parking_con);
+ if (con) {
+ if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+ ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+ else
+ notify_metermaids(pt->parkingexten, curlot->parking_con);
+ } else
+ ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
+ free(pt);
+ parkinglot_unref(curlot);
+ 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(parkmohclass, NULL),
+ !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 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) {
+ FD_SET(chan->fds[x], nrfds);
+ FD_SET(chan->fds[x], nefds);
+ if (chan->fds[x] > max)
+ max = chan->fds[x];
+ }
+ }
+ /* Keep track of our shortest wait */
+ if (tms < ms || ms < 0)
+ ms = tms;
+ pl = pu;
+ pu = pu->next;
+ }
+ }
+ }
+ return res;
+}
+
/*!
* \brief Take care of parked calls and unpark them if needed
* \param ignore unused var.
@@ -2274,146 +2442,19 @@
FD_ZERO(&efds);
for (;;) {
-SKREP
- struct parkeduser *pu;
+ int res = 0;
int ms = -1; /* select timeout, uninitialized */
int max = -1; /* max fd, none there yet */
fd_set nrfds, nefds; /* args for the next select */
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
- AST_LIST_LOCK(&parkings);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&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) {
- ast_indicate(chan, AST_CONTROL_UNHOLD);
- /* Get chan, exten from derived kludge */
- if (pu->peername[0]) {
- char *peername = ast_strdupa(pu->peername);
- char *cp = strrchr(peername, '-');
- char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
- int i;
-
- if (cp)
- *cp = 0;
- ast_copy_string(peername_flat,peername,sizeof(peername_flat));
- for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
- if (peername_flat[i] == '/')
- peername_flat[i]= '0';
- }
- con = ast_context_find(parking_con_dial);
- if (!con) {
- con = ast_context_create(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);
- }
- if (con) {
- ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
- }
- if (comebacktoorigin) {
- set_c_e_p(chan, parking_con_dial, peername_flat, 1);
- } else {
- ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
- snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
- pbx_builtin_setvar_helper(pu->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_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, 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", chan->name);
- ast_hangup(chan);
- }
- /* And take them out of the parking lot */
- AST_LIST_REMOVE_CURRENT(list);
- con = ast_context_find(parking_con);
- if (con) {
- if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- else
- notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
- ast_free(pu);
- } else { /* still within parking time, process descriptors */
- for (x = 0; x < AST_MAX_FDS; x++) {
- struct ast_frame *f;
-
- if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
- continue; /* nothing on this descriptor */
-
- if (FD_ISSET(chan->fds[x], &efds))
- 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(chan);
- if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
- if (f)
- ast_frfree(f);
- post_manager_event("ParkedCallGiveUp", pu);
-
- /* 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 */
- AST_LIST_REMOVE_CURRENT(list);
- con = ast_context_find(parking_con);
- if (con) {
- if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- else
- notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
- ast_free(pu);
- break;
- } else {
- /*! \todo 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.\n");
- ast_indicate_data(chan, AST_CONTROL_HOLD,
- S_OR(parkmohclass, NULL),
- !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
- pu->moh_trys++;
- }
- goto std; /*! \todo 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) {
- FD_SET(chan->fds[x], &nrfds);
- FD_SET(chan->fds[x], &nefds);
- if (chan->fds[x] > max)
- max = chan->fds[x];
- }
- }
- /* Keep track of our shortest wait */
- if (tms < ms || ms < 0)
- ms = tms;
- }
- }
- } /* end while */
+ ASTOBJ_CONTAINER_TRAVERSE(&parkinglots, 1, do {
+
+ ASTOBJ_WRLOCK(iterator);
+ res = manage_parkinglot(iterator, &rfds, &efds, &nrfds, &nefds);
+ ASTOBJ_UNLOCK(iterator);
+ } while (0) );
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&parkings);
rfds = nrfds;
More information about the asterisk-commits
mailing list