diff --git a/apps/app_dial.c b/apps/app_dial.c index 021f0d7a865e79dcc00b8736a283e7956bf3d5da..a8070e6fc1a8c7fb4b12f25147c01379d53ea404 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -3,7 +3,7 @@ * * Trivial application to dial a channel * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer <markster@linux-support.net> * @@ -17,6 +17,7 @@ #include <asterisk/pbx.h> #include <asterisk/options.h> #include <asterisk/module.h> +#include <asterisk/translate.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> @@ -205,6 +206,8 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a if (chan->state != AST_STATE_UP) if (ast_answer(chan)) return -1; + peer->appl = "Bridged Call"; + peer->data = chan->name; cs[0] = chan; cs[1] = peer; for (/* ever */;;) { @@ -214,7 +217,9 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a continue; } f = ast_read(who); - if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) + if (!f || ((f->frametype == AST_FRAME_CONTROL) && + ((f->subclass == AST_CONTROL_HANGUP) || + (f->subclass == AST_CONTROL_BUSY)))) return -1; if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)) { @@ -281,9 +286,11 @@ 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; + struct ast_channel *peer, *npeer; int to; int allowredir=0; + char numsubst[AST_MAX_EXTENSION]; + char *newnum; if (!data) { ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n"); @@ -292,8 +299,9 @@ static int dial_exec(struct ast_channel *chan, void *data) LOCAL_USER_ADD(u); - /* Parse our arguments */ - info = strdup((char *)data); + /* Parse our arguments XXX Check for failure XXX */ + info = malloc(strlen((char *)data) + AST_MAX_EXTENSION); + strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION); peers = strtok(info, "|"); if (!peers) { ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n"); @@ -305,11 +313,11 @@ static int dial_exec(struct ast_channel *chan, void *data) cur = strtok(rest, "&"); /* Remember where to start next time */ rest = strtok(NULL, "\128"); - /* Get a technology/number pair */ + /* Get a technology/[device:]number pair */ tech = strtok(cur, "/"); number = strtok(NULL, "&"); if (!number) { - ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n"); + ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n"); goto out; } tmp = malloc(sizeof(struct localuser)); @@ -318,36 +326,39 @@ static int dial_exec(struct ast_channel *chan, void *data) goto out; } tmp->allowredirect = 1; + strncpy(numsubst, number, sizeof(numsubst)); /* If we're dialing by extension, look at the extension to know what to dial */ - if (!strcasecmp(number, "BYEXTENSION")) { - if (option_debug) - ast_log(LOG_DEBUG, "Dialing by extension %s\n", chan->exten); - number = chan->exten; + if ((newnum = strstr(numsubst, "BYEXTENSION"))) { + snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s", chan->exten); /* By default, if we're dialing by extension, don't permit redirecting */ tmp->allowredirect = 0; + if (option_debug) + ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst); } /* Request the peer */ - tmp->chan = ast_request(tech, chan->format, number); + tmp->chan = ast_request(tech, chan->format, 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); continue; } + tmp->chan->appl = "AppDial"; + tmp->chan->data = "(Outgoing Line)"; /* Place the call, but don't wait on the answer */ - res = ast_call(tmp->chan, number, 0); + res = ast_call(tmp->chan, numsubst, 0); if (res) { /* Again, keep going even if there's an error */ if (option_debug) ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res); else if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", number); + ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst); ast_hangup(tmp->chan); free(tmp); continue; } else if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", number); + ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst); /* Put them in the list of outgoing thingies... We're ready now. XXX If we're forcibly removed, these outgoing calls won't get hung up XXX */ @@ -376,7 +387,14 @@ static int dial_exec(struct ast_channel *chan, void *data) conversation. */ hanguptree(outgoing, peer); outgoing = NULL; - res = bridge_call(chan, peer, allowredir); + /* Build a translator if necessary */ + if (peer->format & chan->format) + npeer = peer; + else + npeer = ast_translator_create(peer, chan->format, AST_DIRECTION_BOTH); + res = bridge_call(chan, npeer, allowredir); + if (npeer != peer) + ast_translator_destroy(npeer); ast_hangup(peer); } out: diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index d32a0ef9d6d4e37a1f8f99a13e25e164b73ac204..f2893b3f62bae1e9fed4b07a13bb81a04fd070c5 100755 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -3,7 +3,7 @@ * * Voicemail System (did you ever think it could be so easy?) * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer <markster@linux-support.net> * @@ -153,7 +153,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent) ast_log(LOG_WARNING, "No such configuration file %s\n", VOICEMAIL_CONFIG); return -1; } - if ((copy = ast_variable_retrieve(cfg, chan->context, ext))) { + if ((copy = ast_variable_retrieve(cfg, NULL, ext))) { /* Make sure they have an entry in the config */ copy = strdup(copy); passwd = strtok(copy, ","); @@ -320,11 +320,15 @@ static int vm_execmain(struct ast_channel *chan, void *data) /* Prompt for, and read in the username */ if (ast_readstring(chan, username, sizeof(username), 2000, 5000, "#")) goto out; + if (!strlen(username)) { + res = 0; + goto out; + } if (ast_streamfile(chan, "vm-password")) goto out; if (ast_readstring(chan, password, sizeof(password), 2000, 5000, "#")) goto out; - copy = ast_variable_retrieve(cfg, chan->context, username); + copy = ast_variable_retrieve(cfg, NULL, username); if (copy) { copy = strdup(copy); strtok(copy, ","); diff --git a/channel.c b/channel.c index b4359d20e85a29c58ad82f31405c3f2e5a5e9897..0a18b28187e209c942f68230f87ca9ca4419d4d8 100755 --- a/channel.c +++ b/channel.c @@ -3,7 +3,7 @@ * * Channel Management * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer <markster@linux-support.net> * @@ -24,6 +24,7 @@ #include <asterisk/channel_pvt.h> #include <asterisk/logger.h> #include <asterisk/file.h> +#include <asterisk/translate.h> struct chanlist { char type[80]; @@ -33,6 +34,8 @@ struct chanlist { struct chanlist *next; } *backends = NULL; +struct ast_channel *channels = NULL; + /* Protect the channel list (highly unlikely that two things would change it at the same time, but still! */ @@ -83,6 +86,7 @@ struct ast_channel *ast_channel_alloc(void) { struct ast_channel *tmp; struct ast_channel_pvt *pvt; + pthread_mutex_lock(&chlock); tmp = malloc(sizeof(struct ast_channel)); memset(tmp, 0, sizeof(struct ast_channel)); if (tmp) { @@ -97,9 +101,14 @@ struct ast_channel *ast_channel_alloc(void) tmp->state = AST_STATE_DOWN; tmp->stack = -1; tmp->streamid = -1; + tmp->appl = NULL; + tmp->data = NULL; + pthread_mutex_init(&tmp->lock, NULL); strncpy(tmp->context, "default", sizeof(tmp->context)); strncpy(tmp->exten, "s", sizeof(tmp->exten)); tmp->priority=1; + tmp->next = channels; + channels= tmp; } else { ast_log(LOG_WARNING, "Unable to create schedule context\n"); free(tmp); @@ -112,9 +121,62 @@ struct ast_channel *ast_channel_alloc(void) } } else ast_log(LOG_WARNING, "Out of memory\n"); + pthread_mutex_unlock(&chlock); return tmp; } +struct ast_channel *ast_channel_walk(struct ast_channel *prev) +{ + struct ast_channel *l, *ret=NULL; + pthread_mutex_lock(&chlock); + l = channels; + if (!prev) { + pthread_mutex_unlock(&chlock); + return l; + } + while(l) { + if (l == prev) + ret = l->next; + l = l->next; + } + pthread_mutex_unlock(&chlock); + return ret; + +} + +void ast_channel_free(struct ast_channel *chan) +{ + struct ast_channel *last=NULL, *cur; + pthread_mutex_lock(&chlock); + cur = channels; + while(cur) { + if (cur == chan) { + if (last) + last->next = cur->next; + else + channels = cur->next; + break; + } + last = cur; + cur = cur->next; + } + if (!cur) + ast_log(LOG_WARNING, "Unable to find channel in list\n"); + if (chan->pvt->pvt) + ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); + if (chan->trans) + ast_log(LOG_WARNING, "Hard hangup called on '%s' while a translator is in place! Expect a failure.\n", chan->name); + if (chan->pbx) + ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); + if (chan->dnid) + free(chan->dnid); + if (chan->callerid) + free(chan->callerid); + pthread_mutex_destroy(&chan->lock); + free(chan); + pthread_mutex_unlock(&chlock); +} + int ast_softhangup(struct ast_channel *chan) { int res = 0; @@ -149,18 +211,7 @@ int ast_hangup(struct ast_channel *chan) ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name); if (chan->pvt->hangup) res = chan->pvt->hangup(chan); - if (chan->pvt->pvt) - ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); - if (chan->trans) - ast_log(LOG_WARNING, "Hard hangup called on '%s' while a translator is in place! Expect a failure.\n", chan->name); - if (chan->pbx) - ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); - if (chan->dnid) - free(chan->dnid); - if (chan->callerid) - free(chan->callerid); - free(chan->pvt); - free(chan); + ast_channel_free(chan); return res; } @@ -348,6 +399,9 @@ struct ast_channel *ast_request(char *type, int format, void *data) chan = backends; while(chan) { if (!strcasecmp(type, chan->type)) { + if (!(chan->capabilities & format)) { + format = ast_translator_best_choice(format, chan->capabilities); + } if (chan->requester) c = chan->requester(type, format, data); pthread_mutex_unlock(&chlock); diff --git a/pbx.c b/pbx.c index a95d4151b1d9153988c2e35753457d980fb6d005..23dd88a841231d4fd1399142fec45cfc0919fd21 100755 --- a/pbx.c +++ b/pbx.c @@ -3,7 +3,7 @@ * * Core PBX routines. * - * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * Copyright (C) 1999, Mark Spencer * * Mark Spencer <markster@linux-support.net> * @@ -23,7 +23,7 @@ #include <stdio.h> #include <setjmp.h> #include <ctype.h> - +#include "asterisk.h" /* * I M P O R T A N T : @@ -178,7 +178,7 @@ static void pbx_destroy(struct ast_pbx *p) free(p); } -int extension_match(char *pattern, char *data) +static int extension_match(char *pattern, char *data) { int match; /* If they're the same return */ @@ -219,6 +219,7 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte struct ast_exten *e; struct ast_app *app; int newstack = 0; + int res; if (pthread_mutex_lock(&conlock)) { ast_log(LOG_WARNING, "Unable to obtain lock\n"); if (action == HELPER_EXISTS) @@ -259,7 +260,12 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte 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")); - return pbx_exec(c, app->execute, e->data, newstack); + c->appl = app->name; + c->data = e->data; + res = pbx_exec(c, app->execute, e->data, newstack); + c->appl = NULL; + c->data = NULL; + return res; } else { ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); return -1; @@ -466,6 +472,9 @@ int ast_pbx_start(struct ast_channel *c) 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"); @@ -748,7 +757,8 @@ void ast_context_destroy(struct ast_context *con) int pbx_builtin_answer(struct ast_channel *chan, void *data) { if (chan->state != AST_STATE_RING) { - ast_log(LOG_WARNING, "Ignoring answer request since line is not ringing\n"); + if (option_debug) + ast_log(LOG_DEBUG, "Ignoring answer request since line is not ringing\n"); return 0; } else return ast_answer(chan); @@ -836,7 +846,6 @@ int pbx_builtin_goto(struct ast_channel *chan, void *data) ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1); return 0; } - int load_pbx(void) { int x;