aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2001-03-30 18:47:35 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2001-03-30 18:47:35 +0000
commit55d2cccba3339611ae5e0c2866cfcd6cde074503 (patch)
tree6dbad052b03e26abc80395c3efb9c9de27927b46
parent6f57feffd96882d0436a0a183a1f18f5284bf891 (diff)
Version 0.1.7 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@259 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xapps/app_dial.c243
-rwxr-xr-xpbx.c248
2 files changed, 345 insertions, 146 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 722b0795e..abfb2dd37 100755
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -175,6 +175,8 @@ static void *do_parking_thread(void *ignore)
pu = pu->next;
free(pt);
} else if (FD_ISSET(pu->chan->fd, &rfds) || FD_ISSET(pu->chan->fd, &efds)) {
+ if (FD_ISSET(pu->chan->fd, &efds))
+ pu->chan->exception = 1;
/* See if they need servicing */
f = ast_read(pu->chan);
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
@@ -306,6 +308,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
if (o->stillgoing) {
o->chan->blocking = 0;
if (FD_ISSET(o->chan->fd, &rfds) || FD_ISSET(o->chan->fd, &efds)) {
+ if (FD_ISSET(o->chan->fd, &efds))
+ o->chan->exception = 1;
f = ast_read(o->chan);
if (f) {
if (f->frametype == AST_FRAME_CONTROL) {
@@ -347,6 +351,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
}
if (FD_ISSET(in->fd, &rfds) || FD_ISSET(in->fd, &efds)) {
/* After unblocking the entirity of the list, check for the main channel */
+ if (FD_ISSET(in->fd, &efds))
+ in->exception = 1;
f = ast_read(in);
#if 0
if (f && (f->frametype != AST_FRAME_VOICE))
@@ -370,8 +376,7 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
{
/* Copy voice back and forth between the two channels. Give the peer
the ability to transfer calls with '#<extension' syntax. */
- struct ast_channel *cs[3];
- int to = -1, len;
+ int len;
struct ast_frame *f;
struct ast_channel *who;
char newext[256], *ptr;
@@ -382,98 +387,79 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
return -1;
peer->appl = "Bridged Call";
peer->data = chan->name;
- cs[0] = chan;
- cs[1] = peer;
- for (/* ever */;;) {
- who = ast_waitfor_n(cs, 2, &to);
- if (!who) {
- ast_log(LOG_WARNING, "Nobody there??\n");
- continue;
- }
- f = ast_read(who);
- if (!f || ((f->frametype == AST_FRAME_CONTROL) &&
- ((f->subclass == AST_CONTROL_HANGUP) ||
- (f->subclass == AST_CONTROL_BUSY))))
+ for (;;) {
+ res = ast_channel_bridge(chan, peer, AST_BRIDGE_DTMF_CHANNEL_1, &f, &who);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
return -1;
- if ((f->frametype == AST_FRAME_VOICE) ||
- (f->frametype == AST_FRAME_DTMF) ||
- (f->frametype == AST_FRAME_TEXT)) {
- if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
- (f->subclass == '#')) {
- if (f->subclass == '#') {
- memset(newext, 0, sizeof(newext));
- ptr = newext;
- len = ast_pbx_longest_extension(chan->context) + 1;
- if (len < ast_pbx_longest_extension("default") + 1)
- len = ast_pbx_longest_extension("default") + 1;
-
+ }
+
+ if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) ||
+ (f->subclass == AST_CONTROL_CONGESTION)))) {
+ res = -1;
+ break;
+ }
+ if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
+ (f->subclass == '#')) {
+ memset(newext, 0, sizeof(newext));
+ ptr = newext;
+ len = ast_pbx_longest_extension(chan->context) + 1;
+ if (len < ast_pbx_longest_extension("default") + 1)
+ len = ast_pbx_longest_extension("default") + 1;
/* Transfer */
- if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
- break;
- if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
- break;
- ast_stopstream(peer);
- if (res > 0) {
- /* If they've typed a digit already, handle it */
- newext[0] = res;
- ptr++;
- len --;
- }
- res = ast_readstring(peer, ptr, len, 3000, 2000, "#");
- if (res)
- break;
- if (!strcmp(newext, parking_ext)) {
- if (!park_call(chan, peer)) {
- /* We return non-zero, but tell the PBX not to hang the channel when
- the thread dies -- We have to be careful now though. We are responsible for
- hanging up the channel, else it will never be hung up! */
- res=AST_PBX_KEEPALIVE;
- break;
- } else {
- ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
- }
- /* XXX Maybe we should have another message here instead of invalid extension XXX */
- } else if (ast_exists_extension(chan, peer->context, newext, 1)) {
- /* Set the channel's new extension, since it exists, using peer context */
- strncpy(chan->exten, newext, sizeof(chan->exten));
- strncpy(chan->context, peer->context, sizeof(chan->context));
- chan->priority = 0;
- ast_frfree(f);
- res=0;
- break;
- } else if (ast_exists_extension(chan, "default", newext, 1)) {
- /* Set the channel's new extension, since it exists, using peer context */
- strncpy(chan->exten, newext, sizeof(chan->exten));
- strncpy(chan->context, "default", sizeof(chan->context));
- chan->priority = 0;
- ast_frfree(f);
- res=0;
+ if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
+ break;
+ if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
+ break;
+ ast_stopstream(peer);
+ if (res > 0) {
+ /* If they've typed a digit already, handle it */
+ newext[0] = res;
+ ptr++;
+ len --;
+ }
+ res = ast_readstring(peer, ptr, len, 3000, 2000, "#");
+ if (res)
+ break;
+ if (!strcmp(newext, parking_ext)) {
+ if (!park_call(chan, peer)) {
+ /* We return non-zero, but tell the PBX not to hang the channel when
+ the thread dies -- We have to be careful now though. We are responsible for
+ hanging up the channel, else it will never be hung up! */
+ res=AST_PBX_KEEPALIVE;
break;
+ } else {
+ ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
}
- res = ast_streamfile(peer, "pbx-invalid", chan->language);
- if (res)
- break;
- res = ast_waitstream(peer, AST_DIGIT_ANY);
- ast_stopstream(peer);
- res = 0;
+ /* XXX Maybe we should have another message here instead of invalid extension XXX */
+ } else if (ast_exists_extension(chan, peer->context, newext, 1)) {
+ /* Set the channel's new extension, since it exists, using peer context */
+ strncpy(chan->exten, newext, sizeof(chan->exten));
+ strncpy(chan->context, peer->context, sizeof(chan->context));
+ chan->priority = 0;
+ ast_frfree(f);
+ res=0;
+ break;
+ } else if (ast_exists_extension(chan, "default", newext, 1)) {
+ /* Set the channel's new extension, since it exists, using peer context */
+ strncpy(chan->exten, newext, sizeof(chan->exten));
+ strncpy(chan->context, "default", sizeof(chan->context));
+ chan->priority = 0;
+ ast_frfree(f);
+ res=0;
+ break;
}
+ res = ast_streamfile(peer, "pbx-invalid", chan->language);
+ if (res)
+ break;
+ res = ast_waitstream(peer, AST_DIGIT_ANY);
+ ast_stopstream(peer);
+ res = 0;
} else {
-#if 0
- ast_log(LOG_DEBUG, "Read from %s\n", who->name);
+#if 1
+ ast_log(LOG_DEBUG, "Read from %s (%d,%d)\n", who->name, f->frametype, f->subclass);
#endif
- if (who == chan)
- ast_write(peer, f);
- else
- ast_write(chan, f);
}
- ast_frfree(f);
-
- } else
- ast_frfree(f);
- /* Swap who gets priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
}
return res;
}
@@ -482,7 +468,7 @@ static int park_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
- struct ast_channel *peer=NULL, *nchan;
+ struct ast_channel *peer=NULL;
struct parkeduser *pu, *pl=NULL;
int park;
if (!data) {
@@ -509,13 +495,9 @@ static int park_exec(struct ast_channel *chan, void *data)
free(pu);
}
if (peer) {
- /* Build a translator if necessary */
- if (peer->format & chan->format)
- nchan = chan;
- else
- nchan = ast_translator_create(chan, peer->format, AST_DIRECTION_BOTH);
- if (!nchan) {
- ast_log(LOG_WARNING, "Had to drop call because there was no translator for %s to %s.\n", chan->name, peer->name);
+ res = ast_channel_make_compatible(chan, peer);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
ast_hangup(peer);
return -1;
}
@@ -523,9 +505,7 @@ static int park_exec(struct ast_channel *chan, void *data)
were the person called. */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
- res = bridge_call(peer, nchan, 1);
- if (nchan != chan)
- ast_translator_destroy(nchan);
+ res = bridge_call(peer, chan, 1);
/* Simulate the PBX hanging up */
if (res != AST_PBX_KEEPALIVE)
ast_hangup(peer);
@@ -546,7 +526,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
struct localuser *u;
char *info, *peers, *timeout, *tech, *number, *rest, *cur;
struct localuser *outgoing=NULL, *tmp;
- struct ast_channel *peer, *npeer;
+ struct ast_channel *peer;
int to;
int allowredir=0;
char numsubst[AST_MAX_EXTENSION];
@@ -562,25 +542,42 @@ static int dial_exec(struct ast_channel *chan, void *data)
/* Parse our arguments XXX Check for failure XXX */
info = malloc(strlen((char *)data) + AST_MAX_EXTENSION);
+ if (!info) {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return -1;
+ }
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
- peers = strtok(info, "|");
- if (!peers) {
+ peers = info;
+ if (peers) {
+ timeout = strchr(info, '|');
+ if (timeout) {
+ *timeout = '\0';
+ timeout++;
+ }
+ } else
+ timeout = NULL;
+ if (!peers || !strlen(peers)) {
ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
goto out;
}
- timeout = strtok(NULL, "|");
- rest = peers;
+
+ cur = peers;
do {
- cur = strtok(rest, "&");
/* Remember where to start next time */
- rest = strtok(NULL, "\128");
+ rest = strchr(cur, '&');
+ if (rest) {
+ *rest = 0;
+ rest++;
+ }
/* Get a technology/[device:]number pair */
- tech = strtok(cur, "/");
- number = strtok(NULL, "&");
+ tech = cur;
+ number = strchr(tech, '/');
if (!number) {
ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
goto out;
}
+ *number = '\0';
+ number++;
tmp = malloc(sizeof(struct localuser));
if (!tmp) {
ast_log(LOG_WARNING, "Out of memory\n");
@@ -598,15 +595,18 @@ static int dial_exec(struct ast_channel *chan, void *data)
ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
}
/* Request the peer */
- tmp->chan = ast_request(tech, chan->format, numsubst);
+ tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
if (!tmp->chan) {
/* If we can't, just go on to the next call */
ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech);
free(tmp);
+ cur = rest;
continue;
}
tmp->chan->appl = "AppDial";
tmp->chan->data = "(Outgoing Line)";
+ if (chan->callerid)
+ tmp->chan->callerid = strdup(chan->callerid);
/* Place the call, but don't wait on the answer */
res = ast_call(tmp->chan, numsubst, 0);
if (res) {
@@ -627,7 +627,9 @@ static int dial_exec(struct ast_channel *chan, void *data)
tmp->stillgoing = -1;
tmp->next = outgoing;
outgoing = tmp;
- } while(rest);
+ cur = rest;
+ } while(cur);
+
if (timeout)
to = atoi(timeout) * 1000;
else
@@ -649,21 +651,15 @@ static int dial_exec(struct ast_channel *chan, void *data)
conversation. */
hanguptree(outgoing, peer);
outgoing = NULL;
- /* Build a translator if necessary */
- if (peer->format & chan->format)
- npeer = peer;
- else
- npeer = ast_translator_create(peer, chan->format, AST_DIRECTION_BOTH);
- if (!npeer) {
- ast_log(LOG_WARNING, "Had to drop call because there was no translator for %s to %s.\n", chan->name, peer->name);
- ast_hangup(peer);
- res = -1;
- } else {
- res = bridge_call(chan, npeer, allowredir);
- if (npeer != peer)
- ast_translator_destroy(npeer);
+ /* Make sure channels are compatible */
+ res = ast_channel_make_compatible(chan, peer);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
ast_hangup(peer);
+ return -1;
}
+ res = bridge_call(chan, peer, allowredir);
+ ast_hangup(peer);
}
out:
hanguptree(outgoing, NULL);
@@ -711,3 +707,8 @@ int usecount(void)
STANDARD_USECOUNT(res);
return res;
}
+
+char *key()
+{
+ return ASTERISK_GPL_KEY;
+}
diff --git a/pbx.c b/pbx.c
index c84784beb..e70a23f0e 100755
--- a/pbx.c
+++ b/pbx.c
@@ -61,6 +61,11 @@ struct ast_exten {
struct ast_exten *next;
};
+struct ast_include {
+ char name[AST_MAX_EXTENSION];
+ struct ast_include *next;
+};
+
/* An extension context */
struct ast_context {
/* Name of the context */
@@ -71,6 +76,8 @@ struct ast_context {
struct ast_exten *root;
/* Link them together */
struct ast_context *next;
+ /* Include other contexts */
+ struct ast_include *includes;
};
@@ -158,6 +165,9 @@ static int pbx_exec(struct ast_channel *c, /* Channel */
}
+/* Go no deeper than this through includes (not counting loops) */
+#define AST_PBX_MAX_STACK 64
+
#define HELPER_EXISTS 0
#define HELPER_SPAWN 1
#define HELPER_EXEC 2
@@ -185,7 +195,7 @@ static void pbx_destroy(struct ast_pbx *p)
free(p);
}
-static int extension_match(char *pattern, char *data)
+static inline int extension_match(char *pattern, char *data)
{
int match;
/* If they're the same return */
@@ -271,13 +281,82 @@ struct ast_context *ast_context_find(char *name)
return tmp;
}
-static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, int action)
+#define STATUS_NO_CONTEXT 1
+#define STATUS_NO_EXTENSION 2
+#define STATUS_NO_PRIORITY 3
+#define STATUS_SUCCESS 4
+
+static struct ast_exten *pbx_find_extension(char *context, char *exten, int priority, int action, char *incstack[], int *stacklen, int *status)
{
+ int x;
struct ast_context *tmp;
- struct ast_exten *e, *reale;
+ struct ast_exten *e, *eroot;
+ struct ast_include *i;
+ /* Initialize status if appropriate */
+ if (!*stacklen)
+ *status = STATUS_NO_CONTEXT;
+ /* Check for stack overflow */
+ if (*stacklen >= AST_PBX_MAX_STACK) {
+ ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
+ return NULL;
+ }
+ /* Check first to see if we've already been checked */
+ for (x=0;x<*stacklen;x++) {
+ if (!strcasecmp(incstack[x], context))
+ return NULL;
+ }
+ tmp = contexts;
+ while(tmp) {
+ /* Match context */
+ if (!strcasecmp(tmp->name, context)) {
+ if (*status < STATUS_NO_EXTENSION)
+ *status = STATUS_NO_EXTENSION;
+ eroot = tmp->root;
+ while(eroot) {
+ /* Match extension */
+ if (extension_match(eroot->exten, exten) ||
+ ((action == HELPER_CANMATCH) && (extension_close(eroot->exten, exten)))) {
+ e = eroot;
+ if (*status < STATUS_NO_PRIORITY)
+ *status = STATUS_NO_PRIORITY;
+ while(e) {
+ /* Match priority */
+ if (e->priority == priority) {
+ *status = STATUS_SUCCESS;
+ return e;
+ }
+ e = e->peer;
+ }
+ }
+ eroot = eroot->next;
+ }
+ /* Setup the stack */
+ incstack[*stacklen] = tmp->name;
+ (*stacklen)++;
+ /* Now try any includes we have in this context */
+ i = tmp->includes;
+ while(i) {
+ if ((e = pbx_find_extension(i->name, exten, priority, action, incstack, stacklen, status)))
+ return e;
+ i = i->next;
+ }
+ }
+ tmp = tmp->next;
+ }
+ return NULL;
+}
+
+static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, int action)
+{
+ struct ast_exten *e;
struct ast_app *app;
int newstack = 0;
int res;
+ int status = 0;
+ char *incstack[AST_PBX_MAX_STACK];
+ int stacklen = 0;
+
+
if (pthread_mutex_lock(&conlock)) {
ast_log(LOG_WARNING, "Unable to obtain lock\n");
if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH))
@@ -285,6 +364,70 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte
else
return -1;
}
+ e = pbx_find_extension(context, exten, priority, action, incstack, &stacklen, &status);
+ if (e) {
+ switch(action) {
+ case HELPER_CANMATCH:
+ pthread_mutex_unlock(&conlock);
+ return -1;
+ case HELPER_EXISTS:
+ pthread_mutex_unlock(&conlock);
+ return -1;
+ case HELPER_SPAWN:
+ newstack++;
+ /* Fall through */
+ case HELPER_EXEC:
+ app = pbx_findapp(e->app);
+ pthread_mutex_unlock(&conlock);
+ if (app) {
+ strncpy(c->context, context, sizeof(c->context));
+ strncpy(c->exten, exten, sizeof(c->exten));
+ c->priority = priority;
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
+ else if (option_verbose > 2)
+ ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
+ app->name, c->name, (e->data ? (char *)e->data : NULL), (newstack ? "in new stack" : "in same stack"));
+ c->appl = app->name;
+ c->data = e->data;
+ res = pbx_exec(c, app->execute, e->data, newstack);
+ c->appl = NULL;
+ c->data = NULL;
+ pthread_mutex_unlock(&conlock);
+ return res;
+ } else {
+ ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
+ return -1;
+ }
+ default:
+ ast_log(LOG_WARNING, "Huh (%d)?\n", action);
+ return -1;
+ }
+ } else {
+ pthread_mutex_unlock(&conlock);
+ switch(status) {
+ case STATUS_NO_CONTEXT:
+ if (action != HELPER_EXISTS)
+ ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
+ break;
+ case STATUS_NO_EXTENSION:
+ if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH))
+ ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
+ break;
+ case STATUS_NO_PRIORITY:
+ if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH))
+ ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
+ break;
+ default:
+ ast_log(LOG_DEBUG, "Shouldn't happen!\n");
+ }
+ if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH))
+ return -1;
+ else
+ return 0;
+ }
+
+#if 0
tmp = contexts;
while(tmp) {
if (!strcasecmp(tmp->name, context)) {
@@ -370,9 +513,12 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte
return -1;
} else
return 0;
+#endif
}
+
int ast_pbx_longest_extension(char *context)
{
+ /* XXX Not include-aware XXX */
struct ast_context *tmp;
struct ast_exten *e;
int len = 0;
@@ -418,24 +564,36 @@ int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int p
return pbx_extension_helper(c, context, exten, priority, HELPER_SPAWN);
}
-static void *pbx_thread(void *data)
+int ast_pbx_run(struct ast_channel *c)
{
- /* Oh joyeous kernel, we're a new thread, with nothing to do but
- answer this channel and get it going. The setjmp stuff is fairly
- confusing, but necessary to get smooth transitions between
- the execution of different applications (without the use of
- additional threads) */
- struct ast_channel *c = data;
int firstpass = 1;
char digit;
char exten[256];
int pos;
int waittime;
int res=0;
+
+ /* A little initial setup here */
+ if (c->pbx)
+ ast_log(LOG_WARNING, "%s already has PBX structure??\n");
+ c->pbx = malloc(sizeof(struct ast_pbx));
+ if (!c->pbx) {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return -1;
+ }
+ memset(c->pbx, 0, sizeof(struct ast_pbx));
+ /* Set reasonable defaults */
+ c->pbx->rtimeout = 10;
+ c->pbx->dtimeout = 5;
+
if (option_debug)
ast_log(LOG_DEBUG, "PBX_THREAD(%s)\n", c->name);
- else if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s'\n", c->name);
+ else if (option_verbose > 1) {
+ if (c->callerid)
+ ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s' (%s)\n", c->name, c->callerid);
+ else
+ ast_verbose( VERBOSE_PREFIX_2 "Accepting call on '%s'\n", c->name);
+ }
/* Start by trying whatever the channel is set to */
@@ -467,7 +625,7 @@ static void *pbx_thread(void *data)
goto out;
}
/* If we're playing something in the background, wait for it to finish or for a digit */
- if (c->stream || (c->trans && c->trans->stream)) {
+ if (c->stream) {
digit = ast_waitstream(c, AST_DIGIT_ANY);
ast_stopstream(c);
/* Hang up if something goes wrong */
@@ -541,8 +699,20 @@ out:
c->pbx = NULL;
if (res != AST_PBX_KEEPALIVE)
ast_hangup(c);
+ return 0;
+}
+
+static void *pbx_thread(void *data)
+{
+ /* Oh joyeous kernel, we're a new thread, with nothing to do but
+ answer this channel and get it going. The setjmp stuff is fairly
+ confusing, but necessary to get smooth transitions between
+ the execution of different applications (without the use of
+ additional threads) */
+ struct ast_channel *c = data;
+ ast_pbx_run(c);
pthread_exit(NULL);
-
+ return NULL;
}
int ast_pbx_start(struct ast_channel *c)
@@ -552,17 +722,6 @@ int ast_pbx_start(struct ast_channel *c)
ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
return -1;
}
- if (c->pbx)
- ast_log(LOG_WARNING, "%s already has PBX structure??\n");
- c->pbx = malloc(sizeof(struct ast_pbx));
- if (!c->pbx) {
- ast_log(LOG_WARNING, "Out of memory\n");
- return -1;
- }
- memset(c->pbx, 0, sizeof(struct ast_pbx));
- /* Set reasonable defaults */
- c->pbx->rtimeout = 10;
- c->pbx->dtimeout = 5;
/* Start a new thread, and get something handling this channel. */
if (pthread_create(&t, NULL, pbx_thread, c)) {
ast_log(LOG_WARNING, "Failed to create new channel thread\n");
@@ -655,6 +814,7 @@ struct ast_context *ast_context_create(char *name)
strncpy(tmp->name, name, sizeof(tmp->name));
tmp->root = NULL;
tmp->next = contexts;
+ tmp->includes = NULL;
contexts = tmp;
if (option_debug)
ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
@@ -667,6 +827,36 @@ struct ast_context *ast_context_create(char *name)
return tmp;
}
+int ast_context_add_include2(struct ast_context *con, char *value)
+{
+ struct ast_include *inc, *incc, *incl = NULL;
+ inc = malloc(sizeof(struct ast_include));
+ if (!inc) {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return -1;
+ }
+ strncpy(inc->name, value, sizeof(inc->name));
+ inc->next = NULL;
+ pthread_mutex_lock(&con->lock);
+ incc = con->includes;
+ while(incc) {
+ incl = incc;
+ if (!strcasecmp(incc->name, value)) {
+ /* Already there */
+ pthread_mutex_unlock(&con->lock);
+ return 0;
+ }
+ incc = incc->next;
+ }
+ if (incl)
+ incl->next = inc;
+ else
+ con->includes = inc;
+ pthread_mutex_unlock(&con->lock);
+ return 0;
+
+}
+
int ast_add_extension2(struct ast_context *con,
int replace, char *extension, int priority,
char *application, void *data, void (*datad)(void *))
@@ -815,6 +1005,7 @@ int ast_add_extension2(struct ast_context *con,
void ast_context_destroy(struct ast_context *con)
{
struct ast_context *tmp, *tmpl=NULL;
+ struct ast_include *tmpi, *tmpil= NULL;
pthread_mutex_lock(&conlock);
tmp = contexts;
while(tmp) {
@@ -832,6 +1023,13 @@ void ast_context_destroy(struct ast_context *con)
/* Okay, now we're safe to let it go -- in a sense, we were
ready to let it go as soon as we locked it. */
pthread_mutex_unlock(&tmp->lock);
+ for (tmpi = tmp->includes; tmpi; ) {
+ /* Free includes */
+ tmpil = tmpi;
+ tmpi = tmpi->next;
+ free(tmpil);
+ tmpil = tmpi;
+ }
free(tmp);
pthread_mutex_unlock(&conlock);
return;