[asterisk-commits] branch oej/multiparking - r7314
/team/oej/multiparking/res/res_features.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sat Dec 3 15:01:44 CST 2005
Author: oej
Date: Sat Dec 3 15:01:42 2005
New Revision: 7314
URL: http://svn.digium.com/view/asterisk?rev=7314&view=rev
Log:
Actually adding the incomplete multi-parking code.
Modified:
team/oej/multiparking/res/res_features.c
Modified: team/oej/multiparking/res/res_features.c
URL: http://svn.digium.com/view/asterisk/team/oej/multiparking/res/res_features.c?rev=7314&r1=7313&r2=7314&view=diff
==============================================================================
--- team/oej/multiparking/res/res_features.c (original)
+++ team/oej/multiparking/res/res_features.c Sat Dec 3 15:01:42 2005
@@ -16,9 +16,27 @@
* at the top of the source tree.
*/
+/*----------------- BRANCH NOTE *------------------------------
+ * This code is under development
+ *
+ * Input is appreciated, e-mail to oej at edvina.net
+ *
+ * Goal:
+ * To implement multiple parking lots, so that if you
+ * run a virtual PBX with many customers in the same
+ * Asterisk, you can set up multiple parking lots
+ * Or one for each group in your company
+ * And maybe a special VIP parking lot for the boss :-)
+ *
+ * Todo:
+ * - Configuration would be nice. Configuring in source is
+ * strangeley enough not considered very user friendly...
+ * - Make parking lots AST_LIST
+ */
+
/*! \file
*
- * \brief Routines implementing call parking
+ * Routines implementing call parking and other call features
*
*/
@@ -77,36 +95,41 @@
/* No more than 45 seconds parked before you do something with them */
static int parkingtime = DEFAULT_PARK_TIME;
-/* Context for which parking is made accessible */
-static char parking_con[AST_MAX_EXTENSION];
-
-/* Context for dialback for parking (KLUDGE) */
-static char parking_con_dial[AST_MAX_EXTENSION];
-
/* Extension you type to park the call */
-static char parking_ext[AST_MAX_EXTENSION];
-
-static char pickup_ext[AST_MAX_EXTENSION];
+/* This is used in many modules, so for now it's the same for all parking lots */
+static char parking_ext[AST_MAX_EXTENSION] = "700";
+
+static char pickup_ext[AST_MAX_EXTENSION] = "*8";
/* Default sounds */
-static char courtesytone[256];
+static char courtesytone[256] = "";
static char xfersound[256];
static char xferfailsound[256];
-/* First available extension for parking */
-static int parking_start;
-
-/* Last available extension for parking */
-static int parking_stop;
-
-static int parking_offset;
-
-static int parkfindnext;
-
-static int adsipark;
-
-static int transferdigittimeout;
-static int featuredigittimeout;
+/* Structure for parking lots in a linked list. */
+/* You set parkinglot by setting channel var PARKINGLOT for now */
+/* Maybe a channel setting later */
+struct ast_parkinglot {
+ char name[AST_MAX_EXTENSION];
+ 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;
+ struct parkeduser *occupiedlots;
+ struct ast_parkinglot *next; /* Kevin will hate me */
+};
+
+struct ast_parkinglot default_parkinglot = { "default", "parkedcalls", "park-dial", 701, 750, 0, 0, NULL, NULL};
+
+struct ast_parkinglot extra_parkinglot = { "edvina", "edvinapark", "edvina-dial", 501, 550, 0, 0, NULL, NULL };
+struct ast_parkinglot *parkinglots = &default_parkinglot;
+
+static int adsipark = 0;
+
+static int transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
+static int featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
/* Default courtesy tone played when party joins conference */
@@ -125,7 +148,7 @@
static char *synopsis2 = "Park yourself";
-static char *descrip2 = "Park(exten):"
+static char *descrip2 = "Park():"
"Used to park yourself (typically in combination with a supervised\n"
"transfer to know the parking space). This application is always\n"
"registered internally and does not need to be explicitly added\n"
@@ -148,9 +171,9 @@
char peername[1024];
unsigned char moh_trys;
struct parkeduser *next;
+ struct ast_parkinglot *parkinglot;
};
-static struct parkeduser *parkinglot;
AST_MUTEX_DEFINE_STATIC(parking_lock);
@@ -176,6 +199,9 @@
struct ast_channel *chan;
struct ast_channel *peer;
};
+/* Forward declarations */
+int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, struct ast_parkinglot *parkinglot);
+struct ast_parkinglot *find_parkinglot(char *name);
static void check_goto_on_transfer(struct ast_channel *chan)
{
@@ -217,7 +243,6 @@
static void *ast_bridge_call_thread(void *data)
{
struct ast_bridge_thread_obj *tobj = data;
-
tobj->chan->appl = "Transferred Call";
tobj->chan->data = tobj->peer->name;
tobj->peer->appl = "Transferred Call";
@@ -231,6 +256,7 @@
ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
}
+
ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
ast_hangup(tobj->chan);
ast_hangup(tobj->peer);
@@ -240,6 +266,7 @@
return NULL;
}
+
static void ast_bridge_call_thread_launch(void *data)
{
pthread_t thread;
@@ -254,8 +281,6 @@
pthread_setschedparam(thread, SCHED_RR, &sched);
}
-
-
static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
{
int res;
@@ -273,14 +298,25 @@
}
/*--- ast_park_call: Park a call */
-/* We put the user in the parking list, then wake up the parking thread to be sure it looks
- after these channels too */
-int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
+/* We put the user in the parking list, then wake up the parking
+ thread to be sure it looks after these channels too */
+int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, struct ast_parkinglot *parkinglot)
{
struct parkeduser *pu, *cur;
- int i,x,parking_range;
+ int i, x, parking_range;
char exten[AST_MAX_EXTENSION];
struct ast_context *con;
+ char *parkinglotname;
+
+
+ if (!parkinglot)
+ parkinglot = &default_parkinglot;
+ parkinglotname = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
+ if (parkinglotname) {
+ ast_log(LOG_DEBUG, "---------**--------- Found chanvar Parkinglot: %s\n", parkinglotname);
+ parkinglot = find_parkinglot(parkinglotname);
+ }
+ ast_log(LOG_DEBUG, "---------**--------- Parkinglot: %s\n", parkinglot->name);
pu = malloc(sizeof(struct parkeduser));
if (!pu) {
@@ -289,10 +325,10 @@
}
memset(pu, 0, sizeof(struct parkeduser));
ast_mutex_lock(&parking_lock);
- parking_range = parking_stop - parking_start+1;
+ parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
for (i = 0; i < parking_range; i++) {
- x = (i + parking_offset) % parking_range + parking_start;
- cur = parkinglot;
+ x = (i + parkinglot->parking_offset) % parking_range + parkinglot->parking_start;
+ cur = parkinglot->occupiedlots;
while(cur) {
if (cur->parkingnum == x)
break;
@@ -303,17 +339,19 @@
}
if (!(i < parking_range)) {
- ast_log(LOG_WARNING, "No more parking spaces\n");
+ ast_log(LOG_WARNING, "No more parking spaces in parking lot \"%s\"\n", parkinglot->name);
free(pu);
ast_mutex_unlock(&parking_lock);
return -1;
}
- if (parkfindnext)
- parking_offset = x - parking_start + 1;
+ if (parkinglot->parkfindnext)
+ parkinglot->parking_offset = x - parkinglot->parking_start + 1;
+
chan->appl = "Parked Call";
chan->data = NULL;
pu->chan = chan;
+
/* Start music on hold */
if (chan != peer) {
ast_indicate(pu->chan, AST_CONTROL_HOLD);
@@ -321,13 +359,17 @@
}
pu->start = ast_tvnow();
pu->parkingnum = x;
+ pu->parkinglot = parkinglot;
+
if (timeout > 0)
pu->parkingtime = timeout;
else
pu->parkingtime = parkingtime;
+
if (extout)
*extout = x;
- if (peer)
+
+ if (peer) /* Parking channel */
ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
/* Remember what had been dialed, so that if the parking
@@ -344,8 +386,8 @@
pu->priority = chan->macropriority;
else
pu->priority = chan->priority;
- pu->next = parkinglot;
- parkinglot = pu;
+ pu->next = parkinglot->occupiedlots;
+ parkinglot->occupiedlots = pu;
/* If parking a channel directly, don't quiet yet get parking running on it */
if (peer == chan)
pu->notquiteyet = 1;
@@ -353,34 +395,31 @@
/* Wake up the (presumably select()ing) thread */
pthread_kill(parking_thread, SIGURG);
if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
+ ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
manager_event(EVENT_FLAG_CALL, "ParkedCall",
"Exten: %d\r\n"
"Channel: %s\r\n"
+ "Parkinglot: %s\r\n"
"From: %s\r\n"
"Timeout: %ld\r\n"
"CallerID: %s\r\n"
"CallerIDName: %s\r\n\r\n"
- ,pu->parkingnum, pu->chan->name, peer->name
+ ,pu->parkingnum, pu->chan->name, pu->parkinglot->name, peer->name
,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
);
- if (peer) {
- if (adsipark && adsi_available(peer)) {
+ if (peer && adsipark && adsi_available(peer)) {
adsi_announce_park(peer, pu->parkingnum);
- }
- if (adsipark && adsi_available(peer)) {
adsi_unload_session(peer);
- }
- }
- con = ast_context_find(parking_con);
+ }
+ con = ast_context_find(parkinglot->parking_con);
if (!con) {
- con = ast_context_create(NULL, parking_con, registrar);
+ con = ast_context_create(NULL, parkinglot->parking_con, registrar);
if (!con) {
- ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
+ ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
}
}
if (con) {
@@ -396,6 +435,11 @@
pthread_kill(parking_thread, SIGURG);
}
return 0;
+}
+
+int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
+{
+ return ast_park_call_full(chan, peer, timeout, extout, NULL);
}
int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
@@ -1089,7 +1133,8 @@
if ((chan = ast_request(type, format, data, &cause))) {
ast_set_callerid(chan, cid_num, cid_name, cid_num);
- ast_channel_inherit_variables(caller, chan);
+ ast_channel_inherit_variables(caller, chan);
+
if (!ast_call(chan, data, timeout)) {
struct timeval started;
int x, len = 0;
@@ -1464,6 +1509,7 @@
return res;
}
+/*--- do_parking_thred: Take care of parked calls and unpark them if needed */
static void *do_parking_thread(void *ignore)
{
int ms, tms, max;
@@ -1474,6 +1520,7 @@
char *peername,*cp;
char returnexten[AST_MAX_EXTENSION];
struct ast_context *con;
+ struct ast_parkinglot *curlot = &default_parkinglot;
int x;
fd_set rfds, efds;
fd_set nrfds, nefds;
@@ -1485,153 +1532,158 @@
max = -1;
ast_mutex_lock(&parking_lock);
pl = NULL;
- pu = parkinglot;
- FD_ZERO(&nrfds);
- FD_ZERO(&nefds);
- while(pu) {
- 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_moh_stop(pu->chan);
- ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
- /* Get chan, exten from derived kludge */
- if (pu->peername[0]) {
- peername = ast_strdupa(pu->peername);
- cp = strrchr(peername, '-');
- if (cp)
- *cp = 0;
- con = ast_context_find(parking_con_dial);
- if (!con) {
- con = ast_context_create(NULL, parking_con_dial, registrar);
+ /* We need to do this for every parking lot */
+ while (curlot) {
+ pu = curlot->occupiedlots;
+ FD_ZERO(&nrfds);
+ FD_ZERO(&nefds);
+ while(pu) {
+ 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_moh_stop(pu->chan);
+ ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+ /* Get chan, exten from derived kludge */
+ if (pu->peername[0]) {
+ peername = ast_strdupa(pu->peername);
+ cp = strrchr(peername, '-');
+ if (cp)
+ *cp = 0;
+ con = ast_context_find(pu->parkinglot->parking_con_dial);
if (!con) {
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
+ 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) {
+ snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
+ ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
+ }
+ ast_copy_string(pu->chan->exten, peername, sizeof(pu->chan->exten));
+ ast_copy_string(pu->chan->context, pu->parkinglot->parking_con_dial, sizeof(pu->chan->context));
+ pu->chan->priority = 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 */
+ ast_copy_string(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
+ ast_copy_string(pu->chan->context, pu->context, sizeof(pu->chan->context));
+ pu->chan->priority = pu->priority;
+ }
+
+ manager_event(EVENT_FLAG_CALL, "ParkedCallTimeOut",
+ "Exten: %d\r\n"
+ "Channel: %s\r\n"
+ "Parkinglot: %s\r\n"
+ "CallerID: %s\r\n"
+ "CallerIDName: %s\r\n\r\n"
+ ,pu->parkingnum, pu->chan->name, pu->parkinglot->name
+ ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
+ );
+
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_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(pu->chan)) {
+ ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
+ ast_hangup(pu->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) {
+ snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
+ if (ast_context_remove_extension2(con, exten, 1, NULL))
+ ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+ } else
+ ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ free(pt);
+ } else {
+ for (x = 0; x < AST_MAX_FDS; x++) {
+ if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
+ if (FD_ISSET(pu->chan->fds[x], &efds))
+ ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
+ else
+ ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
+ pu->chan->fdno = x;
+ /* See if they need servicing */
+ f = ast_read(pu->chan);
+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
+
+ manager_event(EVENT_FLAG_CALL, "ParkedCallGiveUp",
+ "Exten: %d\r\n"
+ "Channel: %s\r\n"
+ "CallerID: %s\r\n"
+ "CallerIDName: %s\r\n\r\n"
+ ,pu->parkingnum, pu->chan->name
+ ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
+ );
+
+ /* There's a problem, hang them up*/
+ if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
+ ast_hangup(pu->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) {
+ snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
+ if (ast_context_remove_extension2(con, exten, 1, NULL))
+ ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+ } else
+ ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
+ free(pt);
+ 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 && !pu->chan->generatordata) {
+ ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
+ ast_moh_start(pu->chan, NULL);
+ pu->moh_trys++;
+ }
+ goto std; /* XXX Ick: jumping into an else statement??? XXX */
+ }
}
}
- if (con) {
- snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
- ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
+ if (x >= AST_MAX_FDS) {
+ std: for (x=0; x<AST_MAX_FDS; x++) {
+ /* Keep this one for next one */
+ if (pu->chan->fds[x] > -1) {
+ FD_SET(pu->chan->fds[x], &nrfds);
+ FD_SET(pu->chan->fds[x], &nefds);
+ if (pu->chan->fds[x] > max)
+ max = pu->chan->fds[x];
+ }
+ }
+ /* Keep track of our longest wait */
+ if ((tms < ms) || (ms < 0))
+ ms = tms;
+ pl = pu;
+ pu = pu->next;
}
- ast_copy_string(pu->chan->exten, peername, sizeof(pu->chan->exten));
- ast_copy_string(pu->chan->context, parking_con_dial, sizeof(pu->chan->context));
- pu->chan->priority = 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 */
- ast_copy_string(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
- ast_copy_string(pu->chan->context, pu->context, sizeof(pu->chan->context));
- pu->chan->priority = pu->priority;
- }
-
- manager_event(EVENT_FLAG_CALL, "ParkedCallTimeOut",
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n\r\n"
- ,pu->parkingnum, pu->chan->name
- ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
- );
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority);
- /* Start up the PBX, or hang them up */
- if (ast_pbx_start(pu->chan)) {
- ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
- ast_hangup(pu->chan);
- }
- /* And take them out of the parking lot */
- if (pl)
- pl->next = pu->next;
- else
- parkinglot = pu->next;
- pt = pu;
- pu = pu->next;
- con = ast_context_find(parking_con);
- if (con) {
- snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
- if (ast_context_remove_extension2(con, exten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
- free(pt);
- } else {
- for (x = 0; x < AST_MAX_FDS; x++) {
- if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
- if (FD_ISSET(pu->chan->fds[x], &efds))
- ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
- else
- ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
- pu->chan->fdno = x;
- /* See if they need servicing */
- f = ast_read(pu->chan);
- if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
-
- manager_event(EVENT_FLAG_CALL, "ParkedCallGiveUp",
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n\r\n"
- ,pu->parkingnum, pu->chan->name
- ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
- );
-
- /* There's a problem, hang them up*/
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
- ast_hangup(pu->chan);
- /* And take them out of the parking lot */
- if (pl)
- pl->next = pu->next;
- else
- parkinglot = pu->next;
- pt = pu;
- pu = pu->next;
- con = ast_context_find(parking_con);
- if (con) {
- snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
- if (ast_context_remove_extension2(con, exten, 1, NULL))
- ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- } else
- ast_log(LOG_WARNING, "Whoa, no parking context?\n");
- free(pt);
- 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 && !pu->chan->generatordata) {
- ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
- ast_moh_start(pu->chan, NULL);
- pu->moh_trys++;
- }
- goto std; /* XXX Ick: jumping into an else statement??? XXX */
- }
- }
- }
- if (x >= AST_MAX_FDS) {
-std: for (x=0; x<AST_MAX_FDS; x++) {
- /* Keep this one for next one */
- if (pu->chan->fds[x] > -1) {
- FD_SET(pu->chan->fds[x], &nrfds);
- FD_SET(pu->chan->fds[x], &nefds);
- if (pu->chan->fds[x] > max)
- max = pu->chan->fds[x];
- }
- }
- /* Keep track of our longest wait */
- if ((tms < ms) || (ms < 0))
- ms = tms;
- pl = pu;
- pu = pu->next;
}
}
+ curlot = curlot -> next;
}
ast_mutex_unlock(&parking_lock);
rfds = nrfds;
@@ -1644,13 +1696,38 @@
return NULL; /* Never reached */
}
+/*--- find_parkinglot: Find parkinglot by name */
+struct ast_parkinglot *find_parkinglot(char *name)
+{
+ struct ast_parkinglot *parkinglot = &default_parkinglot;
+
+ while(parkinglot) {
+ if (!strcasecmp(parkinglot->name, name)) {
+ ast_log(LOG_DEBUG, "---------**--------- Found Parkinglot: %s\n", parkinglot->name);
+ return parkinglot;
+ }
+ parkinglot = parkinglot->next;
+ }
+ /* We did not find a parking lot */
+ return &default_parkinglot;
+}
+
+/*--- park_call_exec: Park a call */
static int park_call_exec(struct ast_channel *chan, void *data)
{
/* Data is unused at the moment but could contain a parking
lot context eventually */
int res=0;
struct localuser *u;
+ char *parkinglotname;
+ struct ast_parkinglot *parkinglot = &default_parkinglot;
+
LOCAL_USER_ADD(u);
+ parkinglotname = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
+ if (parkinglotname) {
+ ast_log(LOG_DEBUG, "---------**--------- Found chanvar Parkinglot: %s\n", parkinglotname);
+ parkinglot = find_parkinglot(parkinglotname);
+ }
/* Setup the exten/priority to be s/1 since we don't know
where this call should return */
strcpy(chan->exten, "s");
@@ -1660,39 +1737,46 @@
if (!res)
res = ast_safe_sleep(chan, 1000);
if (!res)
- res = ast_park_call(chan, chan, 0, NULL);
+ res = ast_park_call_full(chan, chan, 0, NULL, parkinglot);
LOCAL_USER_REMOVE(u);
if (!res)
res = AST_PBX_KEEPALIVE;
return res;
}
-static int park_exec(struct ast_channel *chan, void *data)
+/*--- park_exec: Pick up parked call in dial plan */
+static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parkinglot *parkinglot)
{
int res=0;
struct localuser *u;
struct ast_channel *peer=NULL;
struct parkeduser *pu, *pl=NULL;
char exten[AST_MAX_EXTENSION];
+ char *parkinglotname;
struct ast_context *con;
int park;
int dres;
struct ast_bridge_config config;
if (!data) {
- ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
+ ast_log(LOG_WARNING, "ParkedCall requires an argument (extension number)\n");
return -1;
}
LOCAL_USER_ADD(u);
park = atoi((char *)data);
ast_mutex_lock(&parking_lock);
- pu = parkinglot;
+ parkinglotname = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
+ if (parkinglotname) {
+ ast_log(LOG_DEBUG, "---------**--------- Found chanvar Parkinglot: %s\n", parkinglotname);
+ parkinglot = find_parkinglot(parkinglotname);
+ }
+ pu = parkinglot->occupiedlots;
while(pu) {
if (pu->parkingnum == park) {
if (pl)
pl->next = pu->next;
else
- parkinglot = pu->next;
+ parkinglot->occupiedlots = pu->next;
break;
}
pl = pu;
@@ -1701,7 +1785,7 @@
ast_mutex_unlock(&parking_lock);
if (pu) {
peer = pu->chan;
- con = ast_context_find(parking_con);
+ con = ast_context_find(pu->parkinglot->parking_con);
if (con) {
snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
if (ast_context_remove_extension2(con, exten, 1, NULL))
@@ -1712,10 +1796,11 @@
manager_event(EVENT_FLAG_CALL, "UnParkedCall",
"Exten: %d\r\n"
"Channel: %s\r\n"
+ "Parkinglot: %s\r\n"
"From: %s\r\n"
"CallerID: %s\r\n"
"CallerIDName: %s\r\n\r\n"
- ,pu->parkingnum, pu->chan->name, chan->name
+ ,pu->parkingnum, pu->chan->name, pu->parkinglot->name, chan->name
,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
);
@@ -1750,7 +1835,7 @@
/* This runs sorta backwards, since we give the incoming channel control, as if it
were the person called. */
if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
+ ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d in lot %s\n", chan->name, park, parkinglot->name);
memset(&config, 0, sizeof(struct ast_bridge_config));
ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
@@ -1782,6 +1867,11 @@
return res;
}
+static int park_exec(struct ast_channel *chan, void *data)
+{
+ return park_exec_full(chan, data, &default_parkinglot);
+}
+
static int handle_showfeatures(int fd, int argc, char *argv[])
{
int i;
@@ -1813,11 +1903,12 @@
}
AST_LIST_UNLOCK(&feature_list);
}
+
ast_cli(fd, "\nCall parking\n");
ast_cli(fd, "------------\n");
ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
- ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
- ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
+ //OEJ FIX ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
+ //OEJ FIX ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
ast_cli(fd,"\n");
return RESULT_SUCCESS;
@@ -1834,22 +1925,32 @@
{
struct parkeduser *cur;
int numparked = 0;
+ struct ast_parkinglot *parkinglot = &default_parkinglot;
+
ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
, "Context", "Extension", "Pri", "Timeout");
ast_mutex_lock(&parking_lock);
- cur = parkinglot;
- while(cur) {
- ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
- ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
- ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
-
- cur = cur->next;
- numparked++;
- }
- ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
+ while (parkinglot) {
+ int lotparked = 0;
+ cur = parkinglot->occupiedlots;
+ if (cur)
+ ast_cli(fd, "*** Parking lot: %s\n", parkinglot->name);
+ while(cur) {
+ ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
+ ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
+ ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
+
+ cur = cur->next;
+ lotparked++;
+ }
+ if (lotparked)
+ ast_cli(fd, "%d parked call%s in this parking lot.\n", lotparked, (numparked != 1) ? "s" : "");
+ parkinglot = parkinglot->next;
+ }
+ ast_cli(fd, "---\n%d parked call%s in total.\n", numparked, (numparked != 1) ? "s" : "");
ast_mutex_unlock(&parking_lock);
@@ -1863,38 +1964,46 @@
static struct ast_cli_entry showparked =
{ { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
-/* Dump lot status */
+/*--- manager_parking_status: Dump lot status in manager */
static int manager_parking_status( struct mansession *s, struct message *m )
{
struct parkeduser *cur;
char *id = astman_get_header(m,"ActionID");
char idText[256] = "";
-
- if (!ast_strlen_zero(id))
+ struct ast_parkinglot *parkinglot = &default_parkinglot;
+
+ if (id && !ast_strlen_zero(id))
snprintf(idText,256,"ActionID: %s\r\n",id);
astman_send_ack(s, m, "Parked calls will follow");
+ /* Do we need to lock all of parking? */
ast_mutex_lock(&parking_lock);
- cur=parkinglot;
- while(cur) {
+
+ while (parkinglot) {
+ cur=parkinglot->occupiedlots;
+ while(cur) {
ast_cli(s->fd, "Event: ParkedCall\r\n"
- "Exten: %d\r\n"
- "Channel: %s\r\n"
- "Timeout: %ld\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- "%s"
- "\r\n"
- ,cur->parkingnum, cur->chan->name
- ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
- ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
- ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
- ,idText);
-
- cur = cur->next;
- }
+ "Exten: %d\r\n"
+ "Channel: %s\r\n"
+ "Parkinglot: %s\r\n"
+ "Timeout: %ld\r\n"
+ "CallerID: %s\r\n"
+ "CallerIDName: %s\r\n"
+ "%s"
+ "\r\n"
+ ,cur->parkingnum, cur->chan->name
+ ,parkinglot->name
+ ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
+ ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
+ ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
+ ,idText);
+
+ cur = cur->next;
+ }
+ parkinglot = parkinglot->next;
+ }
ast_cli(s->fd,
"Event: ParkedCallsComplete\r\n"
@@ -1948,28 +2057,16 @@
struct ast_context *con = NULL;
struct ast_config *cfg = NULL;
struct ast_variable *var = NULL;
- char old_parking_ext[AST_MAX_EXTENSION];
- char old_parking_con[AST_MAX_EXTENSION] = "";
-
- if (!ast_strlen_zero(parking_con)) {
- strcpy(old_parking_ext, parking_ext);
- strcpy(old_parking_con, parking_con);
- }
-
- /* Reset to defaults */
- strcpy(parking_con, "parkedcalls");
- strcpy(parking_con_dial, "park-dial");
- strcpy(parking_ext, "700");
- strcpy(pickup_ext, "*8");
- courtesytone[0] = '\0';
+ struct ast_parkinglot *cur = &default_parkinglot;
+
+ transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
+ featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
+
+ // OEJ Make sure we remove old unused parking lots
+ // When reloading and resetting defaults as in res_features.c
strcpy(xfersound, "beep");
strcpy(xferfailsound, "pbx-invalid");
- parking_start = 701;
- parking_stop = 750;
- parkfindnext = 0;
-
- transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
- featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
+ courtesytone[0] = '\0'; /* No default setting */
cfg = ast_config_load("features.conf");
if (!cfg) {
@@ -1983,7 +2080,7 @@
if (!strcasecmp(var->name, "parkext")) {
ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
} else if (!strcasecmp(var->name, "context")) {
- ast_copy_string(parking_con, var->value, sizeof(parking_con));
+ ast_copy_string(cur->parking_con, var->value, sizeof(cur->parking_con));
} else if (!strcasecmp(var->name, "parkingtime")) {
if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
@@ -1994,11 +2091,11 @@
if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", var->lineno);
} else {
- parking_start = start;
- parking_stop = end;
+ cur->parking_start = start;
+ cur->parking_stop = end;
}
} else if (!strcasecmp(var->name, "findslot")) {
- parkfindnext = (!strcasecmp(var->value, "next"));
+ cur->parkfindnext = (!strcasecmp(var->value, "next"));
} else if (!strcasecmp(var->name, "adsipark")) {
adsipark = ast_true(var->value);
} else if (!strcasecmp(var->name, "transferdigittimeout")) {
@@ -2105,15 +2202,13 @@
}
ast_config_destroy(cfg);
- /* Remove the old parking extension */
- if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
- ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
- ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
- }
-
- if (!(con = ast_context_find(parking_con))) {
- if (!(con = ast_context_create(NULL, parking_con, registrar))) {
- ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
+
+ if (con)
+ ast_context_remove_extension2(con, ast_parking_ext(), 1, registrar);
+
+ if (!(con = ast_context_find(cur->parking_con))) {
+ if (!(con = ast_context_create(NULL, cur->parking_con, registrar))) {
+ ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", cur->parking_con);
return -1;
}
}
@@ -2129,8 +2224,6 @@
int res;
AST_LIST_HEAD_INIT(&feature_list);
- memset(parking_ext, 0, sizeof(parking_ext));
- memset(parking_con, 0, sizeof(parking_con));
if ((res = load_config()))
return res;
@@ -2143,6 +2236,7 @@
if (!res) {
ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
}
+ default_parkinglot.next = &extra_parkinglot; /* Just for testing */
return res;
}
@@ -2166,7 +2260,7 @@
int usecount(void)
{
/* Never allow parking to be unloaded because it will
- unresolve needed symbols in the dialer */
+ unresolve needed symbols in the dialer and chan_sip */
#if 0
int res;
STANDARD_USECOUNT(res);
More information about the asterisk-commits
mailing list