Newer
Older
Mark Spencer
committed
__ast_context_destroy(tmp,tmp->registrar);
}
if (lasttmp) {
lasttmp->next = contexts;
contexts = *extcontexts;
*extcontexts = NULL;
} else
ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
ast_mutex_unlock(&conlock);
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
*/
int ast_context_add_include(char *context, char *include, 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_include2(c, include, 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();
#define FIND_NEXT \
do { \
c = info; \
while(*c && (*c != '|')) c++; \
} while(0)
static void get_timerange(struct ast_include *i, char *times)
{
char *e;
int x;
int s1, s2;
int e1, e2;
/* start disabling all times, fill the fields with 0's, as they may contain garbage */
memset(i->minmask, 0, sizeof(i->minmask));
if (ast_strlen_zero(times) || !strcmp(times, "*")) {
for (x=0;x<24;x++)
i->minmask[x] = (1 << 30) - 1;
return;
}
/* Otherwise expect a range */
e = strchr(times, '-');
if (!e) {
ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
return;
}
*e = '\0';
e++;
while(*e && !isdigit(*e)) e++;
if (!*e) {
ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n");
return;
}
if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times);
return;
}
if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e);
s1 = s1 * 30 + s2/2;
if ((s1 < 0) || (s1 >= 24*30)) {
ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
if ((e1 < 0) || (e1 >= 24*30)) {
ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
return;
}
/* Go through the time and enable each appropriate bit */
for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
i->minmask[x/30] |= (1 << (x % 30));
}
/* Do the last one */
i->minmask[x/30] |= (1 << (x % 30));
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
#else
for (cth=0;cth<24;cth++) {
/* Initialize masks to blank */
i->minmask[cth] = 0;
for (ctm=0;ctm<30;ctm++) {
if (
/* First hour with more than one hour */
(((cth == s1) && (ctm >= s2)) &&
((cth < e1)))
/* Only one hour */
|| (((cth == s1) && (ctm >= s2)) &&
((cth == e1) && (ctm <= e2)))
/* In between first and last hours (more than 2 hours) */
|| ((cth > s1) &&
(cth < e1))
/* Last hour with more than one hour */
|| ((cth > s1) &&
((cth == e1) && (ctm <= e2)))
)
i->minmask[cth] |= (1 << (ctm / 2));
}
}
#endif
}
static char *days[] =
{
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
};
static unsigned int get_dow(char *dow)
{
char *c;
/* The following line is coincidence, really! */
int s, e, x;
if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
return (1 << 7) - 1;
/* Get start and ending days */
c = strchr(dow, '-');
if (c) {
*c = '\0';
c++;
/* Find the start */
s = 0;
while((s < 7) && strcasecmp(dow, days[s])) s++;
if (s >= 7) {
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
return 0;
}
if (c) {
e = 0;
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;
if (ast_strlen_zero(day) || !strcmp(day, "*")) {
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
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
3257
3258
3259
3260
3261
3262
}
/* 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;
if (ast_strlen_zero(mon) || !strcmp(mon, "*"))
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
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;
mask |= (1 << x);
}
/* One last one */
mask |= (1 << x);
return mask;
}
static void build_timing(struct ast_include *i, char *info)
{
char *c;
if (ast_strlen_zero(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;
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
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
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
*/
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) && !strcasecmp(i->data, new_sw->data)) {
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
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
*/
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) &&
Mark Spencer
committed
(!registrar || (registrar == ip->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
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
*/
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
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
*
*/
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();
Mark Spencer
committed
int ast_async_goto(struct ast_channel *chan, char *context, char *exten, int priority)
Mark Spencer
committed
ast_mutex_lock(&chan->lock);
if (chan->pbx) {
/* This channel is currently in the PBX */
if (context && !ast_strlen_zero(context))
strncpy(chan->context, context, sizeof(chan->context) - 1);
if (exten && !ast_strlen_zero(exten))
strncpy(chan->exten, exten, sizeof(chan->context) - 1);
if (priority)
chan->priority = priority - 1;
ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
} 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;
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 && !ast_strlen_zero(context))
strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
else
strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
if (exten && !ast_strlen_zero(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;
/* Masquerade into temp channel */
ast_channel_masquerade(tmpchan, chan);
/* Grab the locks and get going */
ast_mutex_lock(&tmpchan->lock);
Mark Spencer
committed
ast_do_masquerade(tmpchan);
ast_mutex_unlock(&tmpchan->lock);
/* 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;
}
}
Mark Spencer
committed
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;
int res = -1;
chan = ast_channel_walk_locked(NULL);
while(chan) {
if (!strcasecmp(channame, chan->name))
break;
ast_mutex_unlock(&chan->lock);
chan = ast_channel_walk_locked(chan);
if (chan) {
res = ast_async_goto(chan, context, exten, priority);
ast_mutex_unlock(&chan->lock);
}
return res;
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 {
tmp->cidmatch[0] = '\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) {
/* Make sure patterns are always last! */
if ((e->exten[0] != '_') && (extension[0] == '_'))
res = -1;
else if ((e->exten[0] == '_') && (extension[0] != '_'))
res = 1;
else
res= strcmp(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);
}
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
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);
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->next;
/* Con->root must always exist or we couldn't get here */
tmp->peer = con->root;
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)
/* 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)
/* 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)
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);