Newer
Older
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
if (e >= 7) {
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
return 0;
}
} else
e = s;
mask = 0;
for (x=s;x!=e;x = (x + 1) % 7) {
mask |= (1 << x);
}
/* One last one */
mask |= (1 << x);
return mask;
}
static unsigned int get_day(char *day)
{
char *c;
/* The following line is coincidence, really! */
int s, e, x;
unsigned int mask;
/* Check for all days */
if (!strlen(day) || !strcmp(day, "*")) {
mask = (1 << 30) + ((1 << 30) - 1);
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
}
/* Get start and ending days */
c = strchr(day, '-');
if (c) {
*c = '\0';
c++;
}
/* Find the start */
if (sscanf(day, "%d", &s) != 1) {
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
return 0;
}
if ((s < 1) || (s > 31)) {
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
return 0;
}
s--;
if (c) {
if (sscanf(c, "%d", &e) != 1) {
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
return 0;
}
if ((e < 1) || (e > 31)) {
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
return 0;
}
e--;
} else
e = s;
mask = 0;
for (x=s;x!=e;x = (x + 1) % 31) {
mask |= (1 << x);
}
mask |= (1 << x);
return mask;
}
static char *months[] =
{
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec",
};
static unsigned int get_month(char *mon)
{
char *c;
/* The following line is coincidence, really! */
int s, e, x;
unsigned int mask;
/* Check for all days */
if (!strlen(mon) || !strcmp(mon, "*"))
return (1 << 12) - 1;
/* Get start and ending days */
c = strchr(mon, '-');
if (c) {
*c = '\0';
c++;
}
/* Find the start */
s = 0;
while((s < 12) && strcasecmp(mon, months[s])) s++;
if (s >= 12) {
ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
return 0;
}
if (c) {
e = 0;
while((e < 12) && strcasecmp(mon, months[e])) e++;
if (e >= 12) {
ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
return 0;
}
} else
e = s;
mask = 0;
for (x=s;x!=e;x = (x + 1) % 12) {
mask |= (1 << x);
}
/* One last one */
mask |= (1 << x);
return mask;
}
static void build_timing(struct ast_include *i, char *info)
{
char *c;
/* Check for empty just in case */
if (!strlen(info))
return;
i->hastime = 1;
/* Assume everything except time */
i->monthmask = (1 << 12) - 1;
i->daymask = (1 << 30) - 1 + (1 << 30);
i->dowmask = (1 << 7) - 1;
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
FIND_NEXT;
/* Info has the time range, start with that */
get_timerange(i, info);
info = c;
if (!info)
return;
FIND_NEXT;
/* Now check for day of week */
i->dowmask = get_dow(info);
info = c;
if (!info)
return;
FIND_NEXT;
/* Now check for the day of the month */
i->daymask = get_day(info);
info = c;
if (!info)
return;
FIND_NEXT;
/* And finally go for the month */
i->monthmask = get_month(info);
}
/*
* errno values
* ENOMEM - out of memory
* EBUSY - can't lock
* EEXIST - already included
* EINVAL - there is no existence of context for inclusion
*/
int ast_context_add_include2(struct ast_context *con, char *value,
char *registrar)
{
struct ast_include *new_include;
struct ast_include *i, *il = NULL; /* include, include_last */
/* allocate new include structure ... */
if (!(new_include = malloc(sizeof(struct ast_include)))) {
ast_log(LOG_ERROR, "Out of memory\n");
errno = ENOMEM;
return -1;
}
/* ... fill in this structure ... */
memset(new_include, 0, sizeof(struct ast_include));
strncpy(new_include->name, value, sizeof(new_include->name)-1);
strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
c = new_include->rname;
/* Strip off timing info */
while(*c && (*c != '|')) c++;
/* Process if it's there */
if (*c) {
build_timing(new_include, c+1);
*c = '\0';
}
new_include->next = NULL;
new_include->registrar = registrar;
/* ... try to lock this context ... */
if (ast_mutex_lock(&con->lock)) {
free(new_include);
errno = EBUSY;
return -1;
}
/* ... go to last include and check if context is already included too... */
i = con->includes;
while (i) {
if (!strcasecmp(i->name, new_include->name)) {
free(new_include);
ast_mutex_unlock(&con->lock);
errno = EEXIST;
return -1;
}
il = i;
i = i->next;
}
/* ... include new context into context list, unlock, return */
if (il)
il->next = new_include;
else
con->includes = new_include;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
ast_mutex_unlock(&con->lock);
return 0;
}
/*
* errno values
* EBUSY - can't lock
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
*/
int ast_context_add_switch(char *context, char *sw, char *data, char *registrar)
{
struct ast_context *c;
if (ast_lock_contexts()) {
errno = EBUSY;
return -1;
}
/* walk contexts ... */
c = ast_walk_contexts(NULL);
while (c) {
/* ... search for the right one ... */
if (!strcmp(ast_get_context_name(c), context)) {
int ret = ast_context_add_switch2(c, sw, data, registrar);
/* ... unlock contexts list and return */
ast_unlock_contexts();
return ret;
}
c = ast_walk_contexts(c);
}
/* we can't find the right context */
ast_unlock_contexts();
return -1;
}
/*
* errno values
* ENOMEM - out of memory
* EBUSY - can't lock
* EEXIST - already included
* EINVAL - there is no existence of context for inclusion
*/
int ast_context_add_switch2(struct ast_context *con, char *value,
char *data, char *registrar)
struct ast_sw *new_sw;
struct ast_sw *i, *il = NULL; /* sw, sw_last */
/* allocate new sw structure ... */
if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
ast_log(LOG_ERROR, "Out of memory\n");
strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
new_sw->next = NULL;
new_sw->registrar = registrar;
/* ... try to lock this context ... */
if (ast_mutex_lock(&con->lock)) {
free(new_sw);
errno = EBUSY;
return -1;
}
/* ... go to last sw and check if context is already swd too... */
i = con->alts;
while (i) {
if (!strcasecmp(i->name, new_sw->name)) {
free(new_sw);
ast_mutex_unlock(&con->lock);
errno = EEXIST;
return -1;
}
il = i;
i = i->next;
}
/* ... sw new context into context list, unlock, return */
if (il)
il->next = new_sw;
else
con->alts = new_sw;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
ast_mutex_unlock(&con->lock);
return 0;
}
/*
* EBUSY - can't lock
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
*/
int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar)
{
struct ast_context *c;
if (ast_lock_contexts()) {
errno = EBUSY;
return -1;
}
c = ast_walk_contexts(NULL);
while (c) {
if (!strcmp(ast_get_context_name(c), context)) {
int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
ast_unlock_contexts();
return ret;
}
c = ast_walk_contexts(c);
}
ast_unlock_contexts();
return -1;
}
int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar)
{
struct ast_ignorepat *ip, *ipl = NULL;
if (ast_mutex_lock(&con->lock)) {
errno = EBUSY;
return -1;
}
ip = con->ignorepats;
while (ip) {
if (!strcmp(ip->pattern, ignorepat) &&
(registrar == ip->registrar || !registrar)) {
if (ipl) {
ipl->next = ip->next;
free(ip);
} else {
con->ignorepats = ip->next;
free(ip);
}
ast_mutex_unlock(&con->lock);
return 0;
}
ipl = ip; ip = ip->next;
}
ast_mutex_unlock(&con->lock);
errno = EINVAL;
return -1;
}
/*
* EBUSY - can't lock
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
*/
int ast_context_add_ignorepat(char *con, char *value, char *registrar)
{
struct ast_context *c;
if (ast_lock_contexts()) {
errno = EBUSY;
return -1;
}
c = ast_walk_contexts(NULL);
while (c) {
if (!strcmp(ast_get_context_name(c), con)) {
int ret = ast_context_add_ignorepat2(c, value, registrar);
ast_unlock_contexts();
return ret;
}
c = ast_walk_contexts(c);
}
ast_unlock_contexts();
return -1;
}
int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *registrar)
{
struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
ignorepat = malloc(sizeof(struct ast_ignorepat));
if (!ignorepat) {
ast_log(LOG_ERROR, "Out of memory\n");
memset(ignorepat, 0, sizeof(struct ast_ignorepat));
strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
ignorepat->next = NULL;
ignorepat->registrar = registrar;
ast_mutex_lock(&con->lock);
ignorepatc = con->ignorepats;
while(ignorepatc) {
ignorepatl = ignorepatc;
if (!strcasecmp(ignorepatc->pattern, value)) {
ast_mutex_unlock(&con->lock);
if (ignorepatl)
ignorepatl->next = ignorepat;
ast_mutex_unlock(&con->lock);
int ast_ignore_pattern(char *context, char *pattern)
{
struct ast_context *con;
struct ast_ignorepat *pat;
con = ast_context_find(context);
if (con) {
pat = con->ignorepats;
while (pat) {
if (ast_extension_match(pat->pattern, pattern))
return 1;
pat = pat->next;
}
}
return 0;
}
/*
* EBUSY - can't lock
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
*
*/
int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
char *application, void *data, void (*datad)(void *), char *registrar)
{
struct ast_context *c;
if (ast_lock_contexts()) {
errno = EBUSY;
return -1;
}
c = ast_walk_contexts(NULL);
while (c) {
if (!strcmp(context, ast_get_context_name(c))) {
int ret = ast_add_extension2(c, replace, extension, priority, callerid,
application, data, datad, registrar);
ast_unlock_contexts();
return ret;
}
c = ast_walk_contexts(c);
}
ast_unlock_contexts();
int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
{
int res = 0;
if (needlock)
ast_mutex_lock(&chan->lock);
if (chan->pbx) {
/* This channel is currently in the PBX */
if (context && strlen(context))
strncpy(chan->context, context, sizeof(chan->context) - 1);
if (exten && strlen(exten))
strncpy(chan->exten, exten, sizeof(chan->context) - 1);
if (priority)
chan->priority = priority - 1;
ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
if (needlock)
ast_mutex_unlock(&chan->lock);
} else {
/* In order to do it when the channel doesn't really exist within
the PBX, we have to make a new channel, masquerade, and start the PBX
at the new location */
struct ast_channel *tmpchan;
struct ast_frame *f;
tmpchan = ast_channel_alloc(0);
if (tmpchan) {
snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
/* Make formats okay */
tmpchan->readformat = chan->readformat;
tmpchan->writeformat = chan->writeformat;
/* Setup proper location */
if (context && strlen(context))
strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
else
strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
if (exten && strlen(exten))
strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
else
strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
if (priority)
tmpchan->priority = priority;
else
tmpchan->priority = chan->priority;
if (needlock)
ast_mutex_unlock(&chan->lock);
/* Masquerade into temp channel */
ast_channel_masquerade(tmpchan, chan);
/* Make the masquerade happen by reading a frame from the tmp channel */
f = ast_read(tmpchan);
if (f)
ast_frfree(f);
/* Start the PBX going on our stolen channel */
if (ast_pbx_start(tmpchan)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
ast_hangup(tmpchan);
res = -1;
}
} else {
res = -1;
if (needlock)
ast_mutex_unlock(&chan->lock);
}
}
return res;
}
int ast_async_goto_by_name(char *channame, char *context, char *exten, int priority)
{
struct ast_channel *chan;
chan = ast_channel_walk(NULL);
while(chan) {
if (!strcasecmp(channame, chan->name))
break;
chan = ast_channel_walk(chan);
}
if (chan)
return ast_async_goto(chan, context, exten, priority, 1);
return -1;
}
static void ext_strncpy(char *dst, char *src, int len)
{
int count=0;
while(*src && (count < len - 1)) {
switch(*src) {
case ' ':
//otherwise exten => [a-b],1,... doesn't work
// case '-':
/* Ignore */
break;
default:
*dst = *src;
dst++;
}
src++;
count++;
}
*dst = '\0';
}
/*
* EBUSY - can't lock
* EEXIST - extension with the same priority exist and no replace is set
*
*/
int replace, char *extension, int priority, char *callerid,
char *application, void *data, void (*datad)(void *),
char *registrar)
#define LOG do { if (option_debug) {\
if (tmp->matchcid) { \
ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
} else { \
ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
} \
} else if (option_verbose > 2) { \
if (tmp->matchcid) { \
ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
} else { \
ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
} \
} } while(0)
/*
* This is a fairly complex routine. Different extensions are kept
* in order by the extension number. Then, extensions of different
* priorities (same extension) are kept in a list, according to the
* peer pointer.
*/
struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
int res;
/* Be optimistic: Build the extension structure first */
tmp = malloc(sizeof(struct ast_exten));
if (tmp) {
ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
if (callerid) {
ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
tmp->matchcid = 1;
} else {
strcpy(tmp->cidmatch, "");
tmp->matchcid = 0;
}
strncpy(tmp->app, application, sizeof(tmp->app)-1);
tmp->parent = con;
tmp->peer = NULL;
tmp->next = NULL;
} else {
ast_log(LOG_ERROR, "Out of memory\n");
if (ast_mutex_lock(&con->lock)) {
free(tmp);
/* And properly destroy the data */
datad(data);
ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
return -1;
}
e = con->root;
while(e) {
res= strcasecmp(e->exten, extension);
if (!res) {
if (!e->matchcid && !tmp->matchcid)
res = 0;
else if (tmp->matchcid && !e->matchcid)
res = 1;
else if (e->matchcid && !tmp->matchcid)
res = -1;
else
res = strcasecmp(e->cidmatch, tmp->cidmatch);
}
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
if (res == 0) {
/* We have an exact match, now we find where we are
and be sure there's no duplicates */
while(e) {
if (e->priority == tmp->priority) {
/* Can't have something exactly the same. Is this a
replacement? If so, replace, otherwise, bonk. */
if (replace) {
if (ep) {
/* We're in the peer list, insert ourselves */
ep->peer = tmp;
tmp->peer = e->peer;
} else if (el) {
/* We're the first extension. Take over e's functions */
el->next = tmp;
tmp->next = e->next;
tmp->peer = e->peer;
} else {
/* We're the very first extension. */
con->root = tmp;
tmp->next = e->next;
tmp->peer = e->peer;
}
if (tmp->priority == PRIORITY_HINT)
ast_change_hint(e,tmp);
/* Destroy the old one */
e->datad(e->data);
free(e);
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
ast_change_hint(e, tmp);
/* And immediately return success. */
LOG;
return 0;
} else {
ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
tmp->datad(tmp->data);
free(tmp);
ast_mutex_unlock(&con->lock);
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
return -1;
}
} else if (e->priority > tmp->priority) {
/* Slip ourselves in just before e */
if (ep) {
/* Easy enough, we're just in the peer list */
ep->peer = tmp;
tmp->peer = e;
} else if (el) {
/* We're the first extension in this peer list */
el->next = tmp;
tmp->next = e->next;
e->next = NULL;
tmp->peer = e;
} else {
/* We're the very first extension altogether */
tmp->next = con->root;
/* Con->root must always exist or we couldn't get here */
tmp->peer = con->root->peer;
con->root = tmp;
}
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
ast_add_hint(tmp);
LOG;
return 0;
}
ep = e;
e = e->peer;
}
/* If we make it here, then it's time for us to go at the very end.
ep *must* be defined or we couldn't have gotten here. */
ep->peer = tmp;
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
ast_add_hint(tmp);
/* And immediately return success. */
LOG;
return 0;
} else if (res > 0) {
/* Insert ourselves just before 'e'. We're the first extension of
this kind */
tmp->next = e;
if (el) {
/* We're in the list somewhere */
el->next = tmp;
} else {
/* We're at the top of the list */
con->root = tmp;
}
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
ast_add_hint(tmp);
/* And immediately return success. */
LOG;
return 0;
}
el = e;
e = e->next;
}
/* If we fall all the way through to here, then we need to be on the end. */
if (el)
el->next = tmp;
else
con->root = tmp;
ast_mutex_unlock(&con->lock);
if (tmp->priority == PRIORITY_HINT)
ast_add_hint(tmp);
struct async_stat {
pthread_t p;
struct ast_channel *chan;
char context[AST_MAX_EXTENSION];
char exten[AST_MAX_EXTENSION];
int priority;
int timeout;
char app[AST_MAX_EXTENSION];
};
static void *async_wait(void *data)
{
struct async_stat *as = data;
struct ast_channel *chan = as->chan;
int timeout = as->timeout;
int res;
struct ast_frame *f;
while(timeout && (chan->_state != AST_STATE_UP)) {
res = ast_waitfor(chan, timeout);
if (res < 1)
break;
if (timeout > -1)
timeout = res;
f = ast_read(chan);
if (!f)
break;
if (f->frametype == AST_FRAME_CONTROL) {
if ((f->subclass == AST_CONTROL_BUSY) ||
(f->subclass == AST_CONTROL_CONGESTION) )
break;
}
ast_frfree(f);
}
if (chan->_state == AST_STATE_UP) {
if (strlen(as->app)) {
app = pbx_findapp(as->app);
if (app) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Lauching %s(%s) on %s\n", as->app, as->appdata, chan->name);
pbx_exec(chan, app, as->appdata, 1);
} else
ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
if (strlen(as->context))
strncpy(chan->context, as->context, sizeof(chan->context) - 1);
if (strlen(as->exten))
strncpy(chan->exten, as->exten, sizeof(chan->exten) - 1);
if (as->priority > 0)
chan->priority = as->priority;
/* Run the PBX */
if (ast_pbx_run(chan)) {
ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
} else {
/* PBX will have taken care of this */
chan = NULL;
}
}
}
free(as);
if (chan)
ast_hangup(chan);
return NULL;
}
Martin Pycko
committed
int ast_pbx_outgoing_exten(char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable, char *account)
{
struct ast_channel *chan;
struct async_stat *as;
int res = -1;
Martin Pycko
committed
struct outgoing_helper oh;
Martin Pycko
committed
LOAD_OH(oh);
chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
pbx_builtin_setaccount(chan, account);
Martin Pycko
committed
res = 0;
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
Martin Pycko
committed
ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
ast_hangup(chan);
res = -1;
}
} else {
if (ast_pbx_start(chan)) {
ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
} else {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
ast_hangup(chan);
}
} else {
/* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
/* check if "failed" exists */
if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
chan = ast_channel_alloc(0);
if (chan) {
strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
if (context && strlen(context))
strncpy(chan->context, context, sizeof(chan->context) - 1);
strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
chan->priority = 1;
if (variable) {
tmp = ast_strdupa(variable);
for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
pbx_builtin_setvar( chan, var );
}
}
ast_pbx_run(chan);
} else
ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
}
}
} else {
as = malloc(sizeof(struct async_stat));
if (!as)
return -1;
memset(as, 0, sizeof(struct async_stat));
chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
if (!chan) {
free(as);
return -1;
}
pbx_builtin_setaccount(chan, account);
as->chan = chan;
strncpy(as->context, context, sizeof(as->context) - 1);
strncpy(as->exten, exten, sizeof(as->exten) - 1);
as->priority = priority;
as->timeout = timeout;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&as->p, &attr, async_wait, as)) {
ast_log(LOG_WARNING, "Failed to start async wait\n");
free(as);
ast_hangup(chan);
return -1;
}
res = 0;
}
return res;
}
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
struct app_tmp {
char app[256];
char data[256];
struct ast_channel *chan;
pthread_t t;
};
static void *ast_pbx_run_app(void *data)
{
struct app_tmp *tmp = data;
struct ast_app *app;
app = pbx_findapp(tmp->app);
if (app) {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Lauching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
pbx_exec(tmp->chan, app, tmp->data, 1);
} else
ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
ast_hangup(tmp->chan);
free(tmp);
return NULL;
}
Martin Pycko
committed
int ast_pbx_outgoing_app(char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account)
{
struct ast_channel *chan;
struct async_stat *as;
struct app_tmp *tmp;
if (!app || !strlen(app))
return -1;
if (sync) {
chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
if (chan) {
pbx_builtin_setaccount(chan, account);
if (variable) {
vartmp = ast_strdupa(variable);
for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
pbx_builtin_setvar( chan, var );
}
if (chan->_state == AST_STATE_UP) {
res = 0;
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
tmp = malloc(sizeof(struct app_tmp));
if (tmp) {
memset(tmp, 0, sizeof(struct app_tmp));
strncpy(tmp->app, app, sizeof(tmp->app) - 1);
strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
tmp->chan = chan;
if (sync > 1) {
ast_pbx_run_app(tmp);