aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_followme.c
diff options
context:
space:
mode:
authorfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2007-07-30 16:02:01 +0000
committerfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2007-07-30 16:02:01 +0000
commita4d755219b76df844fbe983f6c92a7795c4c4118 (patch)
tree7deed236b6a82c73f1fa24833ef1a1a26a7c468f /apps/app_followme.c
parent8a73d0de9a9187441d9390b3cbd20094835293c7 (diff)
Minor clean up of app_followme.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@77773 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_followme.c')
-rw-r--r--apps/app_followme.c783
1 files changed, 396 insertions, 387 deletions
diff --git a/apps/app_followme.c b/apps/app_followme.c
index ac3807f3b..e4d697787 100644
--- a/apps/app_followme.c
+++ b/apps/app_followme.c
@@ -162,7 +162,7 @@ static char statusprompt[PATH_MAX] = "followme/status";
static char sorryprompt[PATH_MAX] = "followme/sorry";
-static AST_LIST_HEAD_STATIC(followmes, call_followme);
+static AST_RWLIST_HEAD_STATIC(followmes, call_followme);
AST_LIST_HEAD_NOLOCK(findme_user_listptr, findme_user);
static void free_numbers(struct call_followme *f)
@@ -282,7 +282,6 @@ static int reload_followme(void)
char *cat = NULL, *tmp;
struct ast_variable *var;
struct number *cur, *nm;
- int new, idx;
char numberstr[90];
int timeout;
char *timeoutstr;
@@ -291,21 +290,21 @@ static int reload_followme(void)
const char *declinecallstr;
const char *tmpstr;
- cfg = ast_config_load("followme.conf");
- if (!cfg) {
+ if (!(cfg = ast_config_load("followme.conf"))) {
ast_log(LOG_WARNING, "No follow me config file (followme.conf), so no follow me\n");
return 0;
}
- AST_LIST_LOCK(&followmes);
+ AST_RWLIST_WRLOCK(&followmes);
/* Reset Global Var Values */
featuredigittimeout = 5000;
/* Mark all profiles as inactive for the moment */
- AST_LIST_TRAVERSE(&followmes, f, entry) {
+ AST_RWLIST_TRAVERSE(&followmes, f, entry) {
f->active = 0;
}
+
featuredigittostr = ast_variable_retrieve(cfg, "general", "featuredigittimeout");
if (!ast_strlen_zero(featuredigittostr)) {
@@ -347,77 +346,83 @@ static int reload_followme(void)
/* Chug through config file */
while ((cat = ast_category_browse(cfg, cat))) {
+ int new = 0;
+
if (!strcasecmp(cat, "general"))
continue;
- /* Define a new profile */
+
/* Look for an existing one */
AST_LIST_TRAVERSE(&followmes, f, entry) {
if (!strcasecmp(f->name, cat))
break;
}
+
ast_debug(1, "New profile %s.\n", cat);
+
if (!f) {
/* Make one then */
f = alloc_profile(cat);
new = 1;
- } else
- new = 0;
-
- if (f) {
- if (!new)
- ast_mutex_lock(&f->lock);
- /* Re-initialize the profile */
- init_profile(f);
- free_numbers(f);
- var = ast_variable_browse(cfg, cat);
- while(var) {
- if (!strcasecmp(var->name, "number")) {
- /* Add a new number */
- ast_copy_string(numberstr, var->value, sizeof(numberstr));
- if ((tmp = strchr(numberstr, ','))) {
- *tmp = '\0';
- tmp++;
- timeoutstr = ast_strdupa(tmp);
- if ((tmp = strchr(timeoutstr, ','))) {
- *tmp = '\0';
- tmp++;
- numorder = atoi(tmp);
- if (numorder < 0)
- numorder = 0;
- } else
+ }
+
+ /* Totally fail if we fail to find/create an entry */
+ if (!f)
+ continue;
+
+ if (!new)
+ ast_mutex_lock(&f->lock);
+ /* Re-initialize the profile */
+ init_profile(f);
+ free_numbers(f);
+ var = ast_variable_browse(cfg, cat);
+ while(var) {
+ if (!strcasecmp(var->name, "number")) {
+ int idx = 0;
+
+ /* Add a new number */
+ ast_copy_string(numberstr, var->value, sizeof(numberstr));
+ if ((tmp = strchr(numberstr, ','))) {
+ *tmp++ = '\0';
+ timeoutstr = ast_strdupa(tmp);
+ if ((tmp = strchr(timeoutstr, ','))) {
+ *tmp++ = '\0';
+ numorder = atoi(tmp);
+ if (numorder < 0)
numorder = 0;
- timeout = atoi(timeoutstr);
- if (timeout < 0)
- timeout = 25;
- } else {
- timeout = 25;
+ } else
numorder = 0;
- }
-
- if (!numorder) {
- idx = 1;
- AST_LIST_TRAVERSE(&f->numbers, nm, entry)
- idx++;
- numorder = idx;
- }
- cur = create_followme_number(numberstr, timeout, numorder);
- AST_LIST_INSERT_TAIL(&f->numbers, cur, entry);
+ timeout = atoi(timeoutstr);
+ if (timeout < 0)
+ timeout = 25;
} else {
- profile_set_param(f, var->name, var->value, var->lineno, 1);
- ast_debug(2, "Logging parameter %s with value %s from lineno %d\n", var->name, var->value, var->lineno);
+ timeout = 25;
+ numorder = 0;
}
- var = var->next;
- } /* End while(var) loop */
-
- if (!new)
- ast_mutex_unlock(&f->lock);
- else
- AST_LIST_INSERT_HEAD(&followmes, f, entry);
- }
+
+ if (!numorder) {
+ idx = 1;
+ AST_LIST_TRAVERSE(&f->numbers, nm, entry)
+ idx++;
+ numorder = idx;
+ }
+ cur = create_followme_number(numberstr, timeout, numorder);
+ AST_LIST_INSERT_TAIL(&f->numbers, cur, entry);
+ } else {
+ profile_set_param(f, var->name, var->value, var->lineno, 1);
+ ast_debug(2, "Logging parameter %s with value %s from lineno %d\n", var->name, var->value, var->lineno);
+ }
+ var = var->next;
+ } /* End while(var) loop */
+
+ if (!new)
+ ast_mutex_unlock(&f->lock);
+ else
+ AST_RWLIST_INSERT_HEAD(&followmes, f, entry);
}
+
ast_config_destroy(cfg);
- AST_LIST_UNLOCK(&followmes);
+ AST_RWLIST_UNLOCK(&followmes);
return 1;
}
@@ -470,13 +475,13 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
int pos;
struct ast_channel *winner;
struct ast_frame *f;
- int ctstatus;
+ int ctstatus = 0;
int dg;
struct findme_user *tmpuser;
int to = 0;
int livechannels = 0;
int tmpto;
- long totalwait = 0, wtd, towas = 0;
+ long totalwait = 0, wtd = 0, towas = 0;
char *callfromname;
char *pressbuttonname;
@@ -485,244 +490,244 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
callfromname = ast_strdupa(tpargs->callfromprompt);
pressbuttonname = ast_strdupa(tpargs->optionsprompt);
- if (!AST_LIST_EMPTY(findme_user_list)) {
- if (!caller) {
- ast_verb(3, "Original caller hungup. Cleanup.\n");
- clear_calling_tree(findme_user_list);
- return NULL;
- }
- ctstatus = 0;
- totalwait = nm->timeout * 1000;
- wtd = 0;
- while (!ctstatus) {
- to = 1000;
- pos = 1;
- livechannels = 0;
- watchers[0] = caller;
+ if (AST_LIST_EMPTY(findme_user_list)) {
+ ast_verb(3, "couldn't reach at this number.\n");
+ return NULL;
+ }
+
+ if (!caller) {
+ ast_verb(3, "Original caller hungup. Cleanup.\n");
+ clear_calling_tree(findme_user_list);
+ return NULL;
+ }
+
+ totalwait = nm->timeout * 1000;
+
+ while (!ctstatus) {
+ to = 1000;
+ pos = 1;
+ livechannels = 0;
+ watchers[0] = caller;
- dg = 0;
- winner = NULL;
- AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
- if (tmpuser->state >= 0 && tmpuser->ochan) {
- if (tmpuser->state == 3)
- tmpuser->digts += (towas - wtd);
- if (tmpuser->digts && (tmpuser->digts > featuredigittimeout)) {
- ast_verb(3, "We've been waiting for digits longer than we should have.\n");
- if (!ast_strlen_zero(namerecloc)) {
- tmpuser->state = 1;
- tmpuser->digts = 0;
- if (!ast_streamfile(tmpuser->ochan, callfromname, tmpuser->ochan->language)) {
- ast_sched_runq(tmpuser->ochan->sched);
- } else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
- return NULL;
- }
+ dg = 0;
+ winner = NULL;
+ AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
+ if (tmpuser->state >= 0 && tmpuser->ochan) {
+ if (tmpuser->state == 3)
+ tmpuser->digts += (towas - wtd);
+ if (tmpuser->digts && (tmpuser->digts > featuredigittimeout)) {
+ ast_verb(3, "We've been waiting for digits longer than we should have.\n");
+ if (!ast_strlen_zero(namerecloc)) {
+ tmpuser->state = 1;
+ tmpuser->digts = 0;
+ if (!ast_streamfile(tmpuser->ochan, callfromname, tmpuser->ochan->language)) {
+ ast_sched_runq(tmpuser->ochan->sched);
} else {
- tmpuser->state = 2;
- tmpuser->digts = 0;
- if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
- ast_sched_runq(tmpuser->ochan->sched);
- else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
- return NULL;
- }
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
+ return NULL;
+ }
+ } else {
+ tmpuser->state = 2;
+ tmpuser->digts = 0;
+ if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
+ ast_sched_runq(tmpuser->ochan->sched);
+ else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
+ return NULL;
}
}
- if (tmpuser->ochan->stream) {
- ast_sched_runq(tmpuser->ochan->sched);
- tmpto = ast_sched_wait(tmpuser->ochan->sched);
- if (tmpto > 0 && tmpto < to)
- to = tmpto;
- else if (tmpto < 0 && !tmpuser->ochan->timingfunc) {
- ast_stopstream(tmpuser->ochan);
- if (tmpuser->state == 1) {
- ast_verb(3, "Playback of the call-from file appears to be done.\n");
- if (!ast_streamfile(tmpuser->ochan, namerecloc, tmpuser->ochan->language)) {
- tmpuser->state = 2;
- } else {
- ast_log(LOG_NOTICE, "Unable to playback %s. Maybe the caller didn't record their name?\n", namerecloc);
- memset(tmpuser->yn, 0, sizeof(tmpuser->yn));
- tmpuser->ynidx = 0;
- if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language))
- tmpuser->state = 3;
- else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", pressbuttonname);
- return NULL;
- }
- }
- } else if (tmpuser->state == 2) {
- ast_verb(3, "Playback of name file appears to be done.\n");
+ }
+ if (tmpuser->ochan->stream) {
+ ast_sched_runq(tmpuser->ochan->sched);
+ tmpto = ast_sched_wait(tmpuser->ochan->sched);
+ if (tmpto > 0 && tmpto < to)
+ to = tmpto;
+ else if (tmpto < 0 && !tmpuser->ochan->timingfunc) {
+ ast_stopstream(tmpuser->ochan);
+ if (tmpuser->state == 1) {
+ ast_verb(3, "Playback of the call-from file appears to be done.\n");
+ if (!ast_streamfile(tmpuser->ochan, namerecloc, tmpuser->ochan->language)) {
+ tmpuser->state = 2;
+ } else {
+ ast_log(LOG_NOTICE, "Unable to playback %s. Maybe the caller didn't record their name?\n", namerecloc);
memset(tmpuser->yn, 0, sizeof(tmpuser->yn));
tmpuser->ynidx = 0;
- if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) {
+ if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language))
tmpuser->state = 3;
-
- } else {
+ else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", pressbuttonname);
return NULL;
}
- } else if (tmpuser->state == 3) {
- ast_verb(3, "Playback of the next step file appears to be done.\n");
- tmpuser->digts = 0;
}
+ } else if (tmpuser->state == 2) {
+ ast_verb(3, "Playback of name file appears to be done.\n");
+ memset(tmpuser->yn, 0, sizeof(tmpuser->yn));
+ tmpuser->ynidx = 0;
+ if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) {
+ tmpuser->state = 3;
+
+ } else {
+ return NULL;
+ }
+ } else if (tmpuser->state == 3) {
+ ast_verb(3, "Playback of the next step file appears to be done.\n");
+ tmpuser->digts = 0;
}
}
- watchers[pos++] = tmpuser->ochan;
- livechannels++;
}
+ watchers[pos++] = tmpuser->ochan;
+ livechannels++;
}
-
- tmpto = to;
- if (to < 0) {
- to = 1000;
- tmpto = 1000;
- }
- towas = to;
- winner = ast_waitfor_n(watchers, pos, &to);
- tmpto -= to;
- totalwait -= tmpto;
- wtd = to;
- if (totalwait <= 0) {
- ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
- clear_calling_tree(findme_user_list);
- return NULL;
- }
- if (winner) {
- /* Need to find out which channel this is */
- dg = 0;
- while ((winner != watchers[dg]) && (dg < 256))
- dg++;
- AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry)
- if (tmpuser->ochan == winner)
+ }
+
+ tmpto = to;
+ if (to < 0) {
+ to = 1000;
+ tmpto = 1000;
+ }
+ towas = to;
+ winner = ast_waitfor_n(watchers, pos, &to);
+ tmpto -= to;
+ totalwait -= tmpto;
+ wtd = to;
+ if (totalwait <= 0) {
+ ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
+ clear_calling_tree(findme_user_list);
+ return NULL;
+ }
+ if (winner) {
+ /* Need to find out which channel this is */
+ dg = 0;
+ while ((winner != watchers[dg]) && (dg < 256))
+ dg++;
+ AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry)
+ if (tmpuser->ochan == winner)
+ break;
+ f = ast_read(winner);
+ if (f) {
+ if (f->frametype == AST_FRAME_CONTROL) {
+ switch(f->subclass) {
+ case AST_CONTROL_HANGUP:
+ if (option_verbose > 2)
+ ast_verb(3, "%s received a hangup frame.\n", winner->name);
+ if (dg == 0) {
+ ast_verb(3, "The calling channel hungup. Need to drop everyone else.\n");
+ clear_calling_tree(findme_user_list);
+ ctstatus = -1;
+ }
break;
- f = ast_read(winner);
- if (f) {
- if (f->frametype == AST_FRAME_CONTROL) {
- switch(f->subclass) {
- case AST_CONTROL_HANGUP:
- if (option_verbose > 2)
- ast_verb(3, "%s received a hangup frame.\n", winner->name);
- if (dg == 0) {
- ast_verb(3, "The calling channel hungup. Need to drop everyone else.\n");
- clear_calling_tree(findme_user_list);
- ctstatus = -1;
- }
- break;
- case AST_CONTROL_ANSWER:
- if (option_verbose > 2)
- ast_verb(3, "%s answered %s\n", winner->name, caller->name);
- /* If call has been answered, then the eventual hangup is likely to be normal hangup */
- winner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
- caller->hangupcause = AST_CAUSE_NORMAL_CLEARING;
- ast_verb(3, "Starting playback of %s\n", callfromname);
- if (dg > 0) {
- if (!ast_strlen_zero(namerecloc)) {
- if (!ast_streamfile(winner, callfromname, winner->language)) {
- ast_sched_runq(winner->sched);
- tmpuser->state = 1;
- } else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
- ast_frfree(f);
- return NULL;
- }
- } else {
- tmpuser->state = 2;
- if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
- ast_sched_runq(tmpuser->ochan->sched);
- else {
- ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
- ast_frfree(f);
- return NULL;
- }
+ case AST_CONTROL_ANSWER:
+ if (option_verbose > 2)
+ ast_verb(3, "%s answered %s\n", winner->name, caller->name);
+ /* If call has been answered, then the eventual hangup is likely to be normal hangup */
+ winner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ caller->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ ast_verb(3, "Starting playback of %s\n", callfromname);
+ if (dg > 0) {
+ if (!ast_strlen_zero(namerecloc)) {
+ if (!ast_streamfile(winner, callfromname, winner->language)) {
+ ast_sched_runq(winner->sched);
+ tmpuser->state = 1;
+ } else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
+ ast_frfree(f);
+ return NULL;
+ }
+ } else {
+ tmpuser->state = 2;
+ if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
+ ast_sched_runq(tmpuser->ochan->sched);
+ else {
+ ast_log(LOG_WARNING, "Unable to playback %s.\n", tpargs->norecordingprompt);
+ ast_frfree(f);
+ return NULL;
}
}
- break;
- case AST_CONTROL_BUSY:
- ast_verb(3, "%s is busy\n", winner->name);
- break;
- case AST_CONTROL_CONGESTION:
- ast_verb(3, "%s is circuit-busy\n", winner->name);
- break;
- case AST_CONTROL_RINGING:
- ast_verb(3, "%s is ringing\n", winner->name);
- break;
- case AST_CONTROL_PROGRESS:
- ast_verb(3, "%s is making progress passing it to %s\n", winner->name, caller->name);
- break;
- case AST_CONTROL_VIDUPDATE:
- ast_verb(3, "%s requested a video update, passing it to %s\n", winner->name, caller->name);
- break;
- case AST_CONTROL_PROCEEDING:
- ast_verb(3, "%s is proceeding passing it to %s\n", winner->name,caller->name);
- break;
- case AST_CONTROL_HOLD:
- ast_verb(3, "Call on %s placed on hold\n", winner->name);
- break;
- case AST_CONTROL_UNHOLD:
- ast_verb(3, "Call on %s left from hold\n", winner->name);
- break;
- case AST_CONTROL_OFFHOOK:
- case AST_CONTROL_FLASH:
- /* Ignore going off hook and flash */
- break;
- case -1:
- ast_verb(3, "%s stopped sounds\n", winner->name);
- break;
- default:
- ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
- break;
}
- }
- if (tmpuser && tmpuser->state == 3 && f->frametype == AST_FRAME_DTMF) {
- if (winner->stream)
- ast_stopstream(winner);
- tmpuser->digts = 0;
- ast_debug(1, "DTMF received: %c\n",(char) f->subclass);
- tmpuser->yn[tmpuser->ynidx] = (char) f->subclass;
- tmpuser->ynidx++;
- ast_debug(1, "DTMF string: %s\n", tmpuser->yn);
- if (tmpuser->ynidx >= ynlongest) {
- ast_debug(1, "reached longest possible match - doing evals\n");
- if (!strcmp(tmpuser->yn, tpargs->takecall)) {
- ast_debug(1, "Match to take the call!\n");
- ast_frfree(f);
- return tmpuser->ochan;
- }
- if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
- ast_debug(1, "Next in dial plan step requested.\n");
- *status = 1;
- ast_frfree(f);
- return NULL;
- }
-
+ break;
+ case AST_CONTROL_BUSY:
+ ast_verb(3, "%s is busy\n", winner->name);
+ break;
+ case AST_CONTROL_CONGESTION:
+ ast_verb(3, "%s is circuit-busy\n", winner->name);
+ break;
+ case AST_CONTROL_RINGING:
+ ast_verb(3, "%s is ringing\n", winner->name);
+ break;
+ case AST_CONTROL_PROGRESS:
+ ast_verb(3, "%s is making progress passing it to %s\n", winner->name, caller->name);
+ break;
+ case AST_CONTROL_VIDUPDATE:
+ ast_verb(3, "%s requested a video update, passing it to %s\n", winner->name, caller->name);
+ break;
+ case AST_CONTROL_PROCEEDING:
+ ast_verb(3, "%s is proceeding passing it to %s\n", winner->name,caller->name);
+ break;
+ case AST_CONTROL_HOLD:
+ ast_verb(3, "Call on %s placed on hold\n", winner->name);
+ break;
+ case AST_CONTROL_UNHOLD:
+ ast_verb(3, "Call on %s left from hold\n", winner->name);
+ break;
+ case AST_CONTROL_OFFHOOK:
+ case AST_CONTROL_FLASH:
+ /* Ignore going off hook and flash */
+ break;
+ case -1:
+ ast_verb(3, "%s stopped sounds\n", winner->name);
+ break;
+ default:
+ ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
+ break;
+ }
+ }
+ if (tmpuser && tmpuser->state == 3 && f->frametype == AST_FRAME_DTMF) {
+ if (winner->stream)
+ ast_stopstream(winner);
+ tmpuser->digts = 0;
+ ast_debug(1, "DTMF received: %c\n",(char) f->subclass);
+ tmpuser->yn[tmpuser->ynidx] = (char) f->subclass;
+ tmpuser->ynidx++;
+ ast_debug(1, "DTMF string: %s\n", tmpuser->yn);
+ if (tmpuser->ynidx >= ynlongest) {
+ ast_debug(1, "reached longest possible match - doing evals\n");
+ if (!strcmp(tmpuser->yn, tpargs->takecall)) {
+ ast_debug(1, "Match to take the call!\n");
+ ast_frfree(f);
+ return tmpuser->ochan;
}
+ if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
+ ast_debug(1, "Next in dial plan step requested.\n");
+ *status = 1;
+ ast_frfree(f);
+ return NULL;
+ }
+
}
-
- ast_frfree(f);
- } else {
- if (winner) {
- ast_debug(1, "we didn't get a frame. hanging up. dg is %d\n",dg);
- if (!dg) {
- clear_calling_tree(findme_user_list);
+ }
+
+ ast_frfree(f);
+ } else {
+ if (winner) {
+ ast_debug(1, "we didn't get a frame. hanging up. dg is %d\n",dg);
+ if (!dg) {
+ clear_calling_tree(findme_user_list);
+ return NULL;
+ } else {
+ tmpuser->state = -1;
+ ast_hangup(winner);
+ livechannels--;
+ ast_debug(1, "live channels left %d\n", livechannels);
+ if (!livechannels) {
+ ast_verb(3, "no live channels left. exiting.\n");
return NULL;
- } else {
- tmpuser->state = -1;
- ast_hangup(winner);
- livechannels--;
- ast_debug(1, "live channels left %d\n", livechannels);
- if (!livechannels) {
- ast_verb(3, "no live channels left. exiting.\n");
- return NULL;
- }
}
}
- }
-
- } else
- ast_debug(1, "timed out waiting for action\n");
- }
-
- } else {
- ast_verb(3, "couldn't reach at this number.\n");
+ }
+ }
+
+ } else
+ ast_debug(1, "timed out waiting for action\n");
}
/* --- WAIT FOR WINNER NUMBER END! -----------*/
@@ -889,134 +894,138 @@ static int app_exec(struct ast_channel *chan, void *data)
AST_APP_ARG(followmeid);
AST_APP_ARG(options);
);
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
+ return -1;
+ }
if (!(argstr = ast_strdupa((char *)data))) {
ast_log(LOG_ERROR, "Out of memory!\n");
return -1;
}
- if (!data) {
- ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n",app);
+ AST_STANDARD_APP_ARGS(args, argstr);
+
+ if (ast_strlen_zero(args.followmeid)) {
+ ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
return -1;
}
- AST_STANDARD_APP_ARGS(args, argstr);
-
- if (!ast_strlen_zero(args.followmeid))
- AST_LIST_LOCK(&followmes);
- AST_LIST_TRAVERSE(&followmes, f, entry) {
+ AST_RWLIST_RDLOCK(&followmes);
+ AST_RWLIST_TRAVERSE(&followmes, f, entry) {
if (!strcasecmp(f->name, args.followmeid) && (f->active))
break;
}
- AST_LIST_UNLOCK(&followmes);
-
+ AST_RWLIST_UNLOCK(&followmes);
+
ast_debug(1, "New profile %s.\n", args.followmeid);
- if (!f) {
- ast_log(LOG_WARNING, "Profile requested, %s, not found in the configuration.\n", args.followmeid);
- res = 0;
- } else {
- /* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */
-
-
- if (args.options)
- ast_app_parse_options(followme_opts, &targs.followmeflags, NULL, args.options);
-
- /* Lock the profile lock and copy out everything we need to run with before unlocking it again */
- ast_mutex_lock(&f->lock);
- targs.mohclass = ast_strdupa(f->moh);
- ast_copy_string(targs.context, f->context, sizeof(targs.context));
- ast_copy_string(targs.takecall, f->takecall, sizeof(targs.takecall));
- ast_copy_string(targs.nextindp, f->nextindp, sizeof(targs.nextindp));
- ast_copy_string(targs.callfromprompt, f->callfromprompt, sizeof(targs.callfromprompt));
- ast_copy_string(targs.norecordingprompt, f->norecordingprompt, sizeof(targs.norecordingprompt));
- ast_copy_string(targs.optionsprompt, f->optionsprompt, sizeof(targs.optionsprompt));
- ast_copy_string(targs.plsholdprompt, f->plsholdprompt, sizeof(targs.plsholdprompt));
- ast_copy_string(targs.statusprompt, f->statusprompt, sizeof(targs.statusprompt));
- ast_copy_string(targs.sorryprompt, f->sorryprompt, sizeof(targs.sorryprompt));
- /* Copy the numbers we're going to use into another list in case the master list should get modified
- (and locked) while we're trying to do a follow-me */
- AST_LIST_HEAD_INIT_NOLOCK(&targs.cnumbers);
- AST_LIST_TRAVERSE(&f->numbers, nm, entry) {
- newnm = create_followme_number(nm->number, nm->timeout, nm->order);
- AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
- }
- ast_mutex_unlock(&f->lock);
-
- if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG))
- ast_stream_and_wait(chan, targs.statusprompt, "");
-
- snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid);
- duration = 5;
- if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME))
- if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, 128, 0, NULL) < 0)
- goto outrun;
-
- /* The following call looks like we're going to playback the file, but we're actually */
- /* just checking to see if we *can* play it. */
- if (ast_streamfile(chan, namerecloc, chan->language))
- ast_copy_string(namerecloc, "", sizeof(namerecloc));
- else
- ast_stopstream(chan);
+ if (!f) {
+ ast_log(LOG_WARNING, "Profile requested, %s, not found in the configuration.\n", args.followmeid);
+ return 0;
+ }
- if (ast_streamfile(chan, targs.plsholdprompt, chan->language))
- goto outrun;
- if (ast_waitstream(chan, "") < 0)
+ /* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */
+ if (args.options)
+ ast_app_parse_options(followme_opts, &targs.followmeflags, NULL, args.options);
+
+ /* Lock the profile lock and copy out everything we need to run with before unlocking it again */
+ ast_mutex_lock(&f->lock);
+ targs.mohclass = ast_strdupa(f->moh);
+ ast_copy_string(targs.context, f->context, sizeof(targs.context));
+ ast_copy_string(targs.takecall, f->takecall, sizeof(targs.takecall));
+ ast_copy_string(targs.nextindp, f->nextindp, sizeof(targs.nextindp));
+ ast_copy_string(targs.callfromprompt, f->callfromprompt, sizeof(targs.callfromprompt));
+ ast_copy_string(targs.norecordingprompt, f->norecordingprompt, sizeof(targs.norecordingprompt));
+ ast_copy_string(targs.optionsprompt, f->optionsprompt, sizeof(targs.optionsprompt));
+ ast_copy_string(targs.plsholdprompt, f->plsholdprompt, sizeof(targs.plsholdprompt));
+ ast_copy_string(targs.statusprompt, f->statusprompt, sizeof(targs.statusprompt));
+ ast_copy_string(targs.sorryprompt, f->sorryprompt, sizeof(targs.sorryprompt));
+ /* Copy the numbers we're going to use into another list in case the master list should get modified
+ (and locked) while we're trying to do a follow-me */
+ AST_LIST_HEAD_INIT_NOLOCK(&targs.cnumbers);
+ AST_LIST_TRAVERSE(&f->numbers, nm, entry) {
+ newnm = create_followme_number(nm->number, nm->timeout, nm->order);
+ AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
+ }
+ ast_mutex_unlock(&f->lock);
+
+ if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG))
+ ast_stream_and_wait(chan, targs.statusprompt, "");
+
+ snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid);
+ duration = 5;
+
+ if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME))
+ if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, 128, 0, NULL) < 0)
goto outrun;
- ast_moh_start(chan, S_OR(targs.mohclass, NULL), NULL);
-
- targs.status = 0;
- targs.chan = chan;
- ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc));
-
- findmeexec(&targs);
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&targs.cnumbers, nm, entry) {
- AST_LIST_REMOVE_CURRENT(&targs.cnumbers, entry);
- ast_free(nm);
- }
- AST_LIST_TRAVERSE_SAFE_END
- if (!ast_strlen_zero(namerecloc))
- unlink(namerecloc);
-
- if (targs.status != 100) {
- ast_moh_stop(chan);
- if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG))
- ast_stream_and_wait(chan, targs.sorryprompt, "");
- res = 0;
- } else {
- caller = chan;
- outbound = targs.outbound;
- /* Bridge the two channels. */
-
- memset(&config,0,sizeof(struct ast_bridge_config));
- ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
- ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
- ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
-
- ast_moh_stop(caller);
- /* Be sure no generators are left on it */
- ast_deactivate_generator(caller);
- /* Make sure channels are compatible */
- res = ast_channel_make_compatible(caller, outbound);
- if (res < 0) {
- ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", caller->name, outbound->name);
- ast_hangup(outbound);
- goto outrun;
- }
- time(&answer_time);
- res = ast_bridge_call(caller,outbound,&config);
- time(&end_time);
- snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
- pbx_builtin_setvar_helper(caller, "DIALEDTIME", toast);
- snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
- pbx_builtin_setvar_helper(caller, "ANSWEREDTIME", toast);
- if (outbound)
- ast_hangup(outbound);
- res = 1;
+ /* The following call looks like we're going to playback the file, but we're actually */
+ /* just checking to see if we *can* play it. */
+ if (ast_streamfile(chan, namerecloc, chan->language))
+ ast_copy_string(namerecloc, "", sizeof(namerecloc));
+ else
+ ast_stopstream(chan);
+
+ if (ast_streamfile(chan, targs.plsholdprompt, chan->language))
+ goto outrun;
+ if (ast_waitstream(chan, "") < 0)
+ goto outrun;
+ ast_moh_start(chan, S_OR(targs.mohclass, NULL), NULL);
+
+ targs.status = 0;
+ targs.chan = chan;
+ ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc));
+
+ findmeexec(&targs);
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&targs.cnumbers, nm, entry) {
+ AST_LIST_REMOVE_CURRENT(&targs.cnumbers, entry);
+ ast_free(nm);
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+
+ if (!ast_strlen_zero(namerecloc))
+ unlink(namerecloc);
+
+ if (targs.status != 100) {
+ ast_moh_stop(chan);
+ if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG))
+ ast_stream_and_wait(chan, targs.sorryprompt, "");
+ res = 0;
+ } else {
+ caller = chan;
+ outbound = targs.outbound;
+ /* Bridge the two channels. */
+
+ memset(&config,0,sizeof(struct ast_bridge_config));
+ ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
+ ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
+ ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
+
+ ast_moh_stop(caller);
+ /* Be sure no generators are left on it */
+ ast_deactivate_generator(caller);
+ /* Make sure channels are compatible */
+ res = ast_channel_make_compatible(caller, outbound);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", caller->name, outbound->name);
+ ast_hangup(outbound);
+ goto outrun;
}
+ time(&answer_time);
+ res = ast_bridge_call(caller,outbound,&config);
+ time(&end_time);
+ snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
+ pbx_builtin_setvar_helper(caller, "DIALEDTIME", toast);
+ snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
+ pbx_builtin_setvar_helper(caller, "ANSWEREDTIME", toast);
+ if (outbound)
+ ast_hangup(outbound);
+ res = 1;
}
+
outrun:
return res;
@@ -1029,13 +1038,13 @@ static int unload_module(void)
ast_unregister_application(app);
/* Free Memory. Yeah! I'm free! */
- AST_LIST_LOCK(&followmes);
- while ((f = AST_LIST_REMOVE_HEAD(&followmes, entry))) {
+ AST_RWLIST_WRLOCK(&followmes);
+ while ((f = AST_RWLIST_REMOVE_HEAD(&followmes, entry))) {
free_numbers(f);
ast_free(f);
}
- AST_LIST_UNLOCK(&followmes);
+ AST_RWLIST_UNLOCK(&followmes);
return 0;
}