Version 0.1.1 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@141 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
1999-12-18 07:01:48 +00:00
parent 86361b6866
commit 28bb339275
4 changed files with 123 additions and 38 deletions

View File

@@ -3,7 +3,7 @@
* *
* Trivial application to dial a channel * 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> * Mark Spencer <markster@linux-support.net>
* *
@@ -17,6 +17,7 @@
#include <asterisk/pbx.h> #include <asterisk/pbx.h>
#include <asterisk/options.h> #include <asterisk/options.h>
#include <asterisk/module.h> #include <asterisk/module.h>
#include <asterisk/translate.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <unistd.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 (chan->state != AST_STATE_UP)
if (ast_answer(chan)) if (ast_answer(chan))
return -1; return -1;
peer->appl = "Bridged Call";
peer->data = chan->name;
cs[0] = chan; cs[0] = chan;
cs[1] = peer; cs[1] = peer;
for (/* ever */;;) { for (/* ever */;;) {
@@ -214,7 +217,9 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
continue; continue;
} }
f = ast_read(who); 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; return -1;
if ((f->frametype == AST_FRAME_VOICE) || if ((f->frametype == AST_FRAME_VOICE) ||
(f->frametype == AST_FRAME_DTMF)) { (f->frametype == AST_FRAME_DTMF)) {
@@ -281,9 +286,11 @@ static int dial_exec(struct ast_channel *chan, void *data)
struct localuser *u; struct localuser *u;
char *info, *peers, *timeout, *tech, *number, *rest, *cur; char *info, *peers, *timeout, *tech, *number, *rest, *cur;
struct localuser *outgoing=NULL, *tmp; struct localuser *outgoing=NULL, *tmp;
struct ast_channel *peer; struct ast_channel *peer, *npeer;
int to; int to;
int allowredir=0; int allowredir=0;
char numsubst[AST_MAX_EXTENSION];
char *newnum;
if (!data) { if (!data) {
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n"); 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); LOCAL_USER_ADD(u);
/* Parse our arguments */ /* Parse our arguments XXX Check for failure XXX */
info = strdup((char *)data); info = malloc(strlen((char *)data) + AST_MAX_EXTENSION);
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION);
peers = strtok(info, "|"); peers = strtok(info, "|");
if (!peers) { if (!peers) {
ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n"); 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, "&"); cur = strtok(rest, "&");
/* Remember where to start next time */ /* Remember where to start next time */
rest = strtok(NULL, "\128"); rest = strtok(NULL, "\128");
/* Get a technology/number pair */ /* Get a technology/[device:]number pair */
tech = strtok(cur, "/"); tech = strtok(cur, "/");
number = strtok(NULL, "&"); number = strtok(NULL, "&");
if (!number) { 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; goto out;
} }
tmp = malloc(sizeof(struct localuser)); tmp = malloc(sizeof(struct localuser));
@@ -318,36 +326,39 @@ static int dial_exec(struct ast_channel *chan, void *data)
goto out; goto out;
} }
tmp->allowredirect = 1; tmp->allowredirect = 1;
strncpy(numsubst, number, sizeof(numsubst));
/* If we're dialing by extension, look at the extension to know what to dial */ /* If we're dialing by extension, look at the extension to know what to dial */
if (!strcasecmp(number, "BYEXTENSION")) { if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
if (option_debug) snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s", chan->exten);
ast_log(LOG_DEBUG, "Dialing by extension %s\n", chan->exten);
number = chan->exten;
/* By default, if we're dialing by extension, don't permit redirecting */ /* By default, if we're dialing by extension, don't permit redirecting */
tmp->allowredirect = 0; tmp->allowredirect = 0;
if (option_debug)
ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
} }
/* Request the peer */ /* Request the peer */
tmp->chan = ast_request(tech, chan->format, number); tmp->chan = ast_request(tech, chan->format, numsubst);
if (!tmp->chan) { if (!tmp->chan) {
/* If we can't, just go on to the next call */ /* If we can't, just go on to the next call */
ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech); ast_log(LOG_WARNING, "Unable to create channel of type '%s'\n", tech);
free(tmp); free(tmp);
continue; continue;
} }
tmp->chan->appl = "AppDial";
tmp->chan->data = "(Outgoing Line)";
/* Place the call, but don't wait on the answer */ /* 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) { if (res) {
/* Again, keep going even if there's an error */ /* Again, keep going even if there's an error */
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res); ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
else if (option_verbose > 2) 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); ast_hangup(tmp->chan);
free(tmp); free(tmp);
continue; continue;
} else } else
if (option_verbose > 2) 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. /* Put them in the list of outgoing thingies... We're ready now.
XXX If we're forcibly removed, these outgoing calls won't get XXX If we're forcibly removed, these outgoing calls won't get
hung up XXX */ hung up XXX */
@@ -376,7 +387,14 @@ static int dial_exec(struct ast_channel *chan, void *data)
conversation. */ conversation. */
hanguptree(outgoing, peer); hanguptree(outgoing, peer);
outgoing = NULL; 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); ast_hangup(peer);
} }
out: out:

View File

@@ -3,7 +3,7 @@
* *
* Voicemail System (did you ever think it could be so easy?) * 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> * 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); ast_log(LOG_WARNING, "No such configuration file %s\n", VOICEMAIL_CONFIG);
return -1; 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 */ /* Make sure they have an entry in the config */
copy = strdup(copy); copy = strdup(copy);
passwd = strtok(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 */ /* Prompt for, and read in the username */
if (ast_readstring(chan, username, sizeof(username), 2000, 5000, "#")) if (ast_readstring(chan, username, sizeof(username), 2000, 5000, "#"))
goto out; goto out;
if (!strlen(username)) {
res = 0;
goto out;
}
if (ast_streamfile(chan, "vm-password")) if (ast_streamfile(chan, "vm-password"))
goto out; goto out;
if (ast_readstring(chan, password, sizeof(password), 2000, 5000, "#")) if (ast_readstring(chan, password, sizeof(password), 2000, 5000, "#"))
goto out; goto out;
copy = ast_variable_retrieve(cfg, chan->context, username); copy = ast_variable_retrieve(cfg, NULL, username);
if (copy) { if (copy) {
copy = strdup(copy); copy = strdup(copy);
strtok(copy, ","); strtok(copy, ",");

View File

@@ -3,7 +3,7 @@
* *
* Channel Management * Channel Management
* *
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC * Copyright (C) 1999, Mark Spencer
* *
* Mark Spencer <markster@linux-support.net> * Mark Spencer <markster@linux-support.net>
* *
@@ -24,6 +24,7 @@
#include <asterisk/channel_pvt.h> #include <asterisk/channel_pvt.h>
#include <asterisk/logger.h> #include <asterisk/logger.h>
#include <asterisk/file.h> #include <asterisk/file.h>
#include <asterisk/translate.h>
struct chanlist { struct chanlist {
char type[80]; char type[80];
@@ -33,6 +34,8 @@ struct chanlist {
struct chanlist *next; struct chanlist *next;
} *backends = NULL; } *backends = NULL;
struct ast_channel *channels = NULL;
/* Protect the channel list (highly unlikely that two things would change /* Protect the channel list (highly unlikely that two things would change
it at the same time, but still! */ 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 *tmp;
struct ast_channel_pvt *pvt; struct ast_channel_pvt *pvt;
pthread_mutex_lock(&chlock);
tmp = malloc(sizeof(struct ast_channel)); tmp = malloc(sizeof(struct ast_channel));
memset(tmp, 0, sizeof(struct ast_channel)); memset(tmp, 0, sizeof(struct ast_channel));
if (tmp) { if (tmp) {
@@ -97,9 +101,14 @@ struct ast_channel *ast_channel_alloc(void)
tmp->state = AST_STATE_DOWN; tmp->state = AST_STATE_DOWN;
tmp->stack = -1; tmp->stack = -1;
tmp->streamid = -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->context, "default", sizeof(tmp->context));
strncpy(tmp->exten, "s", sizeof(tmp->exten)); strncpy(tmp->exten, "s", sizeof(tmp->exten));
tmp->priority=1; tmp->priority=1;
tmp->next = channels;
channels= tmp;
} else { } else {
ast_log(LOG_WARNING, "Unable to create schedule context\n"); ast_log(LOG_WARNING, "Unable to create schedule context\n");
free(tmp); free(tmp);
@@ -112,9 +121,62 @@ struct ast_channel *ast_channel_alloc(void)
} }
} else } else
ast_log(LOG_WARNING, "Out of memory\n"); ast_log(LOG_WARNING, "Out of memory\n");
pthread_mutex_unlock(&chlock);
return tmp; 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 ast_softhangup(struct ast_channel *chan)
{ {
int res = 0; 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); ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
if (chan->pvt->hangup) if (chan->pvt->hangup)
res = chan->pvt->hangup(chan); res = chan->pvt->hangup(chan);
if (chan->pvt->pvt) ast_channel_free(chan);
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);
return res; return res;
} }
@@ -348,6 +399,9 @@ struct ast_channel *ast_request(char *type, int format, void *data)
chan = backends; chan = backends;
while(chan) { while(chan) {
if (!strcasecmp(type, chan->type)) { if (!strcasecmp(type, chan->type)) {
if (!(chan->capabilities & format)) {
format = ast_translator_best_choice(format, chan->capabilities);
}
if (chan->requester) if (chan->requester)
c = chan->requester(type, format, data); c = chan->requester(type, format, data);
pthread_mutex_unlock(&chlock); pthread_mutex_unlock(&chlock);

21
pbx.c
View File

@@ -3,7 +3,7 @@
* *
* Core PBX routines. * Core PBX routines.
* *
* Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC * Copyright (C) 1999, Mark Spencer
* *
* Mark Spencer <markster@linux-support.net> * Mark Spencer <markster@linux-support.net>
* *
@@ -23,7 +23,7 @@
#include <stdio.h> #include <stdio.h>
#include <setjmp.h> #include <setjmp.h>
#include <ctype.h> #include <ctype.h>
#include "asterisk.h"
/* /*
* I M P O R T A N T : * I M P O R T A N T :
@@ -178,7 +178,7 @@ static void pbx_destroy(struct ast_pbx *p)
free(p); free(p);
} }
int extension_match(char *pattern, char *data) static int extension_match(char *pattern, char *data)
{ {
int match; int match;
/* If they're the same return */ /* 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_exten *e;
struct ast_app *app; struct ast_app *app;
int newstack = 0; int newstack = 0;
int res;
if (pthread_mutex_lock(&conlock)) { if (pthread_mutex_lock(&conlock)) {
ast_log(LOG_WARNING, "Unable to obtain lock\n"); ast_log(LOG_WARNING, "Unable to obtain lock\n");
if (action == HELPER_EXISTS) 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) else if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n", 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")); 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 { } else {
ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
return -1; return -1;
@@ -466,6 +472,9 @@ int ast_pbx_start(struct ast_channel *c)
return -1; return -1;
} }
memset(c->pbx, 0, sizeof(struct ast_pbx)); 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. */ /* Start a new thread, and get something handling this channel. */
if (pthread_create(&t, NULL, pbx_thread, c)) { if (pthread_create(&t, NULL, pbx_thread, c)) {
ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 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) int pbx_builtin_answer(struct ast_channel *chan, void *data)
{ {
if (chan->state != AST_STATE_RING) { 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; return 0;
} else } else
return ast_answer(chan); 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); ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
return 0; return 0;
} }
int load_pbx(void) int load_pbx(void)
{ {
int x; int x;