mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-18 18:58:22 +00:00
Merge hint patch, add new variables, and misc. PBX cleanups
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@722 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -35,6 +35,7 @@ ${CALLERIDNUM} Caller ID Number only
|
||||
${EXTEN} Current extension
|
||||
${CONTEXT} Current context
|
||||
${PRIORITY} Current priority
|
||||
${CHANNEL} Current channel name
|
||||
|
||||
There are two reference modes - reference by value and reference by name.
|
||||
To refer to a variable with its name (as an argument to a function that
|
||||
|
1
cdr.c
1
cdr.c
@@ -21,6 +21,7 @@
|
||||
#include <asterisk/callerid.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int ast_default_amaflags = AST_CDR_DOCUMENTATION;
|
||||
|
78
channel.c
78
channel.c
@@ -64,6 +64,7 @@ struct chanlist {
|
||||
char description[80];
|
||||
int capabilities;
|
||||
struct ast_channel * (*requester)(char *type, int format, void *data);
|
||||
int (*devicestate)(void *data);
|
||||
struct chanlist *next;
|
||||
} *backends = NULL;
|
||||
struct ast_channel *channels = NULL;
|
||||
@@ -143,6 +144,13 @@ time_t myt;
|
||||
|
||||
int ast_channel_register(char *type, char *description, int capabilities,
|
||||
struct ast_channel *(*requester)(char *type, int format, void *data))
|
||||
{
|
||||
return ast_channel_register_ex(type, description, capabilities, requester, NULL);
|
||||
}
|
||||
|
||||
int ast_channel_register_ex(char *type, char *description, int capabilities,
|
||||
struct ast_channel *(*requester)(char *type, int format, void *data),
|
||||
int (*devicestate)(void *data))
|
||||
{
|
||||
struct chanlist *chan, *last=NULL;
|
||||
if (PTHREAD_MUTEX_LOCK(&chlock)) {
|
||||
@@ -169,6 +177,7 @@ int ast_channel_register(char *type, char *description, int capabilities,
|
||||
strncpy(chan->description, description, sizeof(chan->description)-1);
|
||||
chan->capabilities = capabilities;
|
||||
chan->requester = requester;
|
||||
chan->devicestate = devicestate;
|
||||
chan->next = NULL;
|
||||
if (last)
|
||||
last->next = chan;
|
||||
@@ -469,6 +478,7 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
struct ast_var_t *vardata;
|
||||
struct ast_frame *f, *fp;
|
||||
struct varshead *headp;
|
||||
char name[AST_CHANNEL_NAME];
|
||||
|
||||
headp=&chan->varshead;
|
||||
|
||||
@@ -489,10 +499,14 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
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);
|
||||
|
||||
strncpy(name, chan->name, sizeof(name)-1);
|
||||
|
||||
/* Stop monitoring */
|
||||
if (chan->monitor) {
|
||||
chan->monitor->stop( chan, 0 );
|
||||
}
|
||||
|
||||
/* Free translatosr */
|
||||
if (chan->pvt->readtrans)
|
||||
ast_translator_free_path(chan->pvt->readtrans);
|
||||
@@ -537,6 +551,8 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
chan->pvt = NULL;
|
||||
free(chan);
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
|
||||
ast_device_state_changed(name);
|
||||
}
|
||||
|
||||
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
|
||||
@@ -1409,6 +1425,7 @@ struct ast_channel *ast_request(char *type, int format, void *data)
|
||||
if (chan->requester)
|
||||
c = chan->requester(type, capabilities, data);
|
||||
if (c) {
|
||||
// ast_device_state_changed(c->name);
|
||||
manager_event(EVENT_FLAG_CALL, "Newchannel",
|
||||
"Channel: %s\r\n"
|
||||
"State: %s\r\n"
|
||||
@@ -1425,6 +1442,66 @@ struct ast_channel *ast_request(char *type, int format, void *data)
|
||||
return c;
|
||||
}
|
||||
|
||||
int ast_parse_device_state(char *device)
|
||||
{
|
||||
char name[AST_CHANNEL_NAME] = "";
|
||||
char *cut;
|
||||
struct ast_channel *chan;
|
||||
|
||||
chan = ast_channel_walk(NULL);
|
||||
while (chan) {
|
||||
strncpy(name, chan->name, sizeof(name)-1);
|
||||
cut = strchr(name,'-');
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
if (!strcmp(name, device))
|
||||
return AST_DEVICE_INUSE;
|
||||
chan = ast_channel_walk(chan);
|
||||
}
|
||||
return AST_DEVICE_UNKNOWN;
|
||||
}
|
||||
|
||||
int ast_device_state(char *device)
|
||||
{
|
||||
char tech[AST_MAX_EXTENSION] = "";
|
||||
char *number;
|
||||
struct chanlist *chanls;
|
||||
int res = 0;
|
||||
|
||||
strncpy(tech, device, sizeof(tech)-1);
|
||||
number = strchr(tech, '/');
|
||||
if (!number) {
|
||||
return AST_DEVICE_INVALID;
|
||||
}
|
||||
*number = 0;
|
||||
number++;
|
||||
|
||||
if (PTHREAD_MUTEX_LOCK(&chlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock channel list\n");
|
||||
return -1;
|
||||
}
|
||||
chanls = backends;
|
||||
while(chanls) {
|
||||
if (!strcasecmp(tech, chanls->type)) {
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
if (!chanls->devicestate)
|
||||
return ast_parse_device_state(device);
|
||||
else {
|
||||
res = chanls->devicestate(number);
|
||||
if (res == AST_DEVICE_UNKNOWN)
|
||||
return ast_parse_device_state(device);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
}
|
||||
chanls = chanls->next;
|
||||
}
|
||||
if (!chanls)
|
||||
ast_log(LOG_WARNING, "No channel type registered for '%s'\n", tech);
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
return AST_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
int ast_call(struct ast_channel *chan, char *addr, int timeout)
|
||||
{
|
||||
/* Place an outgoing call, but don't wait any longer than timeout ms before returning.
|
||||
@@ -1813,6 +1890,7 @@ int ast_setstate(struct ast_channel *chan, int state)
|
||||
int oldstate = chan->_state;
|
||||
chan->_state = state;
|
||||
if (oldstate == AST_STATE_DOWN) {
|
||||
ast_device_state_changed(chan->name);
|
||||
manager_event(EVENT_FLAG_CALL, "Newchannel",
|
||||
"Channel: %s\r\n"
|
||||
"State: %s\r\n"
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/vmodem.h>
|
||||
#include <asterisk/module.h>
|
||||
|
@@ -1740,10 +1740,10 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru
|
||||
char contact[256];
|
||||
char *c;
|
||||
if ((c=getsipuri(ot))) {
|
||||
snprintf(contact, sizeof(contact), "<%s@%s>", c, inet_ntoa(p->ourip));
|
||||
snprintf(contact, sizeof(contact), "<%s@%s:%d>", c, inet_ntoa(p->ourip), ourport);
|
||||
free(c);
|
||||
} else {
|
||||
snprintf(contact, sizeof(contact), "<%s>", inet_ntoa(p->ourip));
|
||||
snprintf(contact, sizeof(contact), "<%s:%d>", inet_ntoa(p->ourip), ourport);
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "%d", p->expirey);
|
||||
add_header(resp, "Expires", tmp);
|
||||
@@ -1754,10 +1754,10 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru
|
||||
very stupidly *sigh* XXX */
|
||||
char *c;
|
||||
if ((c=getsipuri(ot))) {
|
||||
snprintf(contact, sizeof(contact), "<%s@%s>", c, inet_ntoa(p->ourip));
|
||||
snprintf(contact, sizeof(contact), "<%s@%s:%d>", c, inet_ntoa(p->ourip), ourport);
|
||||
free(c);
|
||||
} else {
|
||||
snprintf(contact, sizeof(contact), "<%s>", inet_ntoa(p->ourip));
|
||||
snprintf(contact, sizeof(contact), "<%s:%d>", inet_ntoa(p->ourip), ourport);
|
||||
}
|
||||
add_header(resp, "Contact", contact);
|
||||
}
|
||||
@@ -2048,7 +2048,8 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, c
|
||||
}
|
||||
if (!n)
|
||||
n = l;
|
||||
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%08x", n, l, inet_ntoa(p->ourip), p->tag);
|
||||
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%08x", n, l, inet_ntoa(p->ourip), ourport, p->tag);
|
||||
|
||||
if (strlen(p->username)) {
|
||||
if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) {
|
||||
snprintf(invite, sizeof(invite), "sip:%s@%s:%d",p->username, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
|
||||
|
@@ -58,7 +58,7 @@ struct ast_translator_pvt {
|
||||
|
||||
#define speex_coder_pvt ast_translator_pvt
|
||||
|
||||
static struct ast_translator_pvt *lintospeex_new()
|
||||
static struct ast_translator_pvt *lintospeex_new(void)
|
||||
{
|
||||
struct speex_coder_pvt *tmp;
|
||||
tmp = malloc(sizeof(struct speex_coder_pvt));
|
||||
@@ -77,7 +77,7 @@ static struct ast_translator_pvt *lintospeex_new()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct ast_translator_pvt *speextolin_new()
|
||||
static struct ast_translator_pvt *speextolin_new(void)
|
||||
{
|
||||
struct speex_coder_pvt *tmp;
|
||||
tmp = malloc(sizeof(struct speex_coder_pvt));
|
||||
@@ -95,7 +95,7 @@ static struct ast_translator_pvt *speextolin_new()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct ast_frame *lintospeex_sample()
|
||||
static struct ast_frame *lintospeex_sample(void)
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
@@ -110,7 +110,7 @@ static struct ast_frame *lintospeex_sample()
|
||||
return &f;
|
||||
}
|
||||
|
||||
static struct ast_frame *speextolin_sample()
|
||||
static struct ast_frame *speextolin_sample(void)
|
||||
{
|
||||
static struct ast_frame f;
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
|
@@ -35,6 +35,7 @@ ${CALLERIDNUM} Caller ID Number only
|
||||
${EXTEN} Current extension
|
||||
${CONTEXT} Current context
|
||||
${PRIORITY} Current priority
|
||||
${CHANNEL} Current channel name
|
||||
|
||||
There are two reference modes - reference by value and reference by name.
|
||||
To refer to a variable with its name (as an argument to a function that
|
||||
|
@@ -64,7 +64,7 @@ static char *exts = "alaw|al";
|
||||
|
||||
|
||||
/* Returns time in msec since system boot. */
|
||||
static unsigned long get_time()
|
||||
static unsigned long get_time(void)
|
||||
{
|
||||
struct tms buf;
|
||||
clock_t cur;
|
||||
|
@@ -233,6 +233,19 @@ struct chanmon;
|
||||
/*! Do not transmit voice data */
|
||||
#define AST_STATE_MUTE (1 << 16)
|
||||
|
||||
/*! Device is valid but channel didn't know state */
|
||||
#define AST_DEVICE_UNKNOWN 0
|
||||
/*! Device is not used */
|
||||
#define AST_DEVICE_NOT_INUSE 1
|
||||
/*! Device is in use */
|
||||
#define AST_DEVICE_INUSE 2
|
||||
/*! Device is busy */
|
||||
#define AST_DEVICE_BUSY 3
|
||||
/*! Device is invalid */
|
||||
#define AST_DEVICE_INVALID 4
|
||||
/*! Device is unavailable */
|
||||
#define AST_DEVICE_UNAVAILABLE 5
|
||||
|
||||
//! Requests a channel
|
||||
/*!
|
||||
* \param type type of channel to request
|
||||
@@ -244,6 +257,27 @@ struct chanmon;
|
||||
*/
|
||||
struct ast_channel *ast_request(char *type, int format, void *data);
|
||||
|
||||
//! Search the Channels by Name
|
||||
/*!
|
||||
* \param device like a dialstring
|
||||
* Search the Device in active channels by compare the channelname against
|
||||
* the devicename. Compared are only the first chars to the first '-' char.
|
||||
* Returns an AST_DEVICE_UNKNOWN if no channel found or
|
||||
* AST_DEVICE_INUSE if a channel is found
|
||||
*/
|
||||
int ast_parse_device_state(char *device);
|
||||
|
||||
//! Asks a channel for device state
|
||||
/*!
|
||||
* \param device like a dialstring
|
||||
* Asks a channel for device state, data is normaly a number from dialstring
|
||||
* used by the low level module
|
||||
* Trys the channel devicestate callback if not supported search in the
|
||||
* active channels list for the device.
|
||||
* Returns an AST_DEVICE_??? state -1 on failure
|
||||
*/
|
||||
int ast_device_state(char *device);
|
||||
|
||||
/*!
|
||||
* \param type type of channel to request
|
||||
* \param format requested channel format
|
||||
@@ -271,6 +305,11 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
|
||||
int ast_channel_register(char *type, char *description, int capabilities,
|
||||
struct ast_channel* (*requester)(char *type, int format, void *data));
|
||||
|
||||
/* Same like the upper function but with support for devicestate */
|
||||
int ast_channel_register_ex(char *type, char *description, int capabilities,
|
||||
struct ast_channel *(*requester)(char *type, int format, void *data),
|
||||
int (*devicestate)(void *data));
|
||||
|
||||
//! Unregister a channel class
|
||||
/*
|
||||
* \param type the character string that corresponds to the channel you wish to unregister
|
||||
|
@@ -29,12 +29,27 @@ extern "C" {
|
||||
//! Special return values from applications to the PBX
|
||||
#define AST_PBX_KEEPALIVE 10 /* Destroy the thread, but don't hang up the channel */
|
||||
|
||||
//! Special Priority for an hint
|
||||
#define PRIORITY_HINT -1
|
||||
|
||||
//! Extension states
|
||||
//! No device INUSE or BUSY
|
||||
#define AST_EXTENSION_NOT_INUSE 0
|
||||
//! One or more devices INUSE
|
||||
#define AST_EXTENSION_INUSE 1
|
||||
//! All devices BUSY
|
||||
#define AST_EXTENSION_BUSY 2
|
||||
//! All devices UNAVAILABLE/UNREGISTERED
|
||||
#define AST_EXTENSION_UNAVAILABLE 3
|
||||
|
||||
struct ast_context;
|
||||
struct ast_exten;
|
||||
struct ast_include;
|
||||
struct ast_ignorepat;
|
||||
struct ast_sw;
|
||||
|
||||
typedef int (*ast_notify_cb_type)(char *context, char* id, int state, void *data);
|
||||
|
||||
//! Data structure associated with an asterisk switch
|
||||
struct ast_switch {
|
||||
/*! NULL */
|
||||
@@ -189,6 +204,57 @@ int ast_register_application(char *app, int (*execute)(struct ast_channel *, voi
|
||||
*/
|
||||
int ast_unregister_application(char *app);
|
||||
|
||||
//! Uses hint and devicestate callback to get the state of an extension
|
||||
/*!
|
||||
* \param c this is not important
|
||||
* \param context which context to look in
|
||||
* \param exten which extension to get state
|
||||
* Returns extension state !! = AST_EXTENSION_???
|
||||
*/
|
||||
int ast_extension_state(struct ast_channel *c, char *context, char *exten);
|
||||
|
||||
//! Tells Asterisk the State for Device is changed
|
||||
/*!
|
||||
* \param device devicename like a dialstring
|
||||
* Asterisk polls the new extensionstates and calls the registered
|
||||
* callbacks for the changed extensions
|
||||
* Returns 0 on success, -1 on failure
|
||||
*/
|
||||
int ast_device_state_changed(char *device);
|
||||
|
||||
//! Registers a state change callback
|
||||
/*!
|
||||
* \param context which context to look in
|
||||
* \param exten which extension to get state
|
||||
* \param callback callback to call if state changed
|
||||
* \param data to pass to callback
|
||||
* The callback is called if the state for extension is changed
|
||||
* Return -1 on failure, ID on success
|
||||
*/
|
||||
int ast_extension_state_add(char *context, char *exten,
|
||||
ast_notify_cb_type callback, void *data);
|
||||
|
||||
//! Deletes a registered state change callback by ID
|
||||
/*!
|
||||
* \param id of the callback to delete
|
||||
* Removes the callback from list of callbacks
|
||||
* Return 0 on success, -1 on failure
|
||||
*/
|
||||
int ast_extension_state_del(int id);
|
||||
|
||||
//! If an extension exists, return non-zero
|
||||
/*!
|
||||
* \param hint buffer for hint
|
||||
* \param maxlen size of hint buffer
|
||||
* \param c this is not important
|
||||
* \param context which context to look in
|
||||
* \param exten which extension to search for
|
||||
* If an extension within the given context with the priority PRIORITY_HINT
|
||||
* is found a non zero value will be returned.
|
||||
* Otherwise, 0 is returned.
|
||||
*/
|
||||
int ast_get_hint(char *hint, int maxlen, struct ast_channel *c, char *context, char *exten);
|
||||
|
||||
//! If an extension exists, return non-zero
|
||||
// work
|
||||
/*!
|
||||
|
350
pbx.c
350
pbx.c
@@ -132,6 +132,22 @@ struct ast_app {
|
||||
struct ast_app *next;
|
||||
};
|
||||
|
||||
/* An extension state notify */
|
||||
struct ast_notify_cb {
|
||||
int id;
|
||||
void *data;
|
||||
ast_notify_cb_type callback;
|
||||
struct ast_notify_cb *next;
|
||||
};
|
||||
|
||||
struct ast_notify {
|
||||
struct ast_exten *exten;
|
||||
int laststate;
|
||||
struct ast_notify_cb *callbacks;
|
||||
struct ast_notify *next;
|
||||
};
|
||||
|
||||
|
||||
static int pbx_builtin_prefix(struct ast_channel *, void *);
|
||||
static int pbx_builtin_stripmsd(struct ast_channel *, void *);
|
||||
static int pbx_builtin_answer(struct ast_channel *, void *);
|
||||
@@ -294,6 +310,11 @@ static struct ast_app *apps = NULL;
|
||||
static pthread_mutex_t switchlock = AST_MUTEX_INITIALIZER;
|
||||
struct ast_switch *switches = NULL;
|
||||
|
||||
/* Lock for extension state notifys */
|
||||
static pthread_mutex_t notifylock = AST_MUTEX_INITIALIZER;
|
||||
static int notifycnt = 0;
|
||||
struct ast_notify *notifys = NULL;
|
||||
|
||||
int pbx_exec(struct ast_channel *c, /* Channel */
|
||||
struct ast_app *app,
|
||||
void *data, /* Data for execution */
|
||||
@@ -676,20 +697,19 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, char *cont
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char **cp4)
|
||||
static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char **cp4, char *workspace, int workspacelen)
|
||||
{
|
||||
char *first,*second;
|
||||
int offset,offset2;
|
||||
struct ast_var_t *variables;
|
||||
char *name, *num; /* for callerid name + num variables */
|
||||
struct varshead *headp;
|
||||
char pri[80];
|
||||
headp=&c->varshead;
|
||||
*cp4=NULL;
|
||||
/* Now we have the variable name on cp3 */
|
||||
if ((first=strchr(cp3,':'))) {
|
||||
*first='\0';
|
||||
pbx_substitute_variables_temp(c,cp3,cp4);
|
||||
pbx_substitute_variables_temp(c,cp3,cp4,workspace,workspacelen);
|
||||
if (!(*cp4)) return;
|
||||
offset=atoi(first+1);
|
||||
if ((second=strchr(first+1,':'))) {
|
||||
@@ -711,20 +731,18 @@ static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char *
|
||||
*cp4+=strlen(*cp4)+offset;
|
||||
(*cp4)[offset2] = '\0';
|
||||
} else if (!strcmp(cp3, "CALLERIDNUM")) {
|
||||
char cid[256] = "";
|
||||
if (c->callerid)
|
||||
strncpy(cid, c->callerid, sizeof(cid) - 1);
|
||||
ast_callerid_parse(cid, &name, &num);
|
||||
strncpy(workspace, c->callerid, workspacelen - 1);
|
||||
ast_callerid_parse(workspace, &name, &num);
|
||||
if (num) {
|
||||
ast_shrink_phone_number(num);
|
||||
*cp4 = num;
|
||||
} else
|
||||
*cp4 = "";
|
||||
} else if (!strcmp(cp3, "CALLERIDNAME")) {
|
||||
char cid[256] = "";
|
||||
if (c->callerid)
|
||||
strncpy(cid, c->callerid, sizeof(cid) - 1);
|
||||
ast_callerid_parse(cid, &name, &num);
|
||||
strncpy(workspace, c->callerid, workspacelen - 1);
|
||||
ast_callerid_parse(workspace, &name, &num);
|
||||
if (name)
|
||||
*cp4 = name;
|
||||
else
|
||||
@@ -733,6 +751,11 @@ static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char *
|
||||
*cp4 = c->callerid;
|
||||
if (!(*cp4))
|
||||
*cp4 = "";
|
||||
} else if (!strcmp(cp3, "HINT")) {
|
||||
if (!ast_get_hint(workspace, workspacelen - 1, c, c->context, c->exten))
|
||||
*cp4 = "";
|
||||
else
|
||||
*cp4 = workspace;
|
||||
} else if (!strcmp(cp3, "EXTEN")) {
|
||||
*cp4 = c->exten;
|
||||
} else if (!strncmp(cp3, "EXTEN-", strlen("EXTEN-")) &&
|
||||
@@ -760,8 +783,10 @@ static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char *
|
||||
} else if (!strcmp(cp3, "CONTEXT")) {
|
||||
*cp4 = c->context;
|
||||
} else if (!strcmp(cp3, "PRIORITY")) {
|
||||
snprintf(pri, sizeof(pri), "%d", c->priority);
|
||||
*cp4 = pri;
|
||||
snprintf(workspace, workspacelen, "%d", c->priority);
|
||||
*cp4 = workspace;
|
||||
} else if (!strcmp(cp3, "CHANNEL")) {
|
||||
*cp4 = c->name;
|
||||
} else {
|
||||
AST_LIST_TRAVERSE(headp,variables,entries) {
|
||||
#if 0
|
||||
@@ -796,6 +821,7 @@ static void pbx_substitute_variables_helper(struct ast_channel *c,char *cp1,char
|
||||
char *cp4,*cp2;
|
||||
char *tmp,*wherearewe,*finish=NULL,*ltmp,*lval,*nextvar;
|
||||
int length,variables=0;
|
||||
char workspace[256];
|
||||
|
||||
wherearewe=tmp=cp1;
|
||||
cp2=*ecp2;
|
||||
@@ -854,7 +880,7 @@ static void pbx_substitute_variables_helper(struct ast_channel *c,char *cp1,char
|
||||
cp1=cp2;
|
||||
}
|
||||
if (count) {
|
||||
pbx_substitute_variables_temp(c,cp1,&cp4);
|
||||
pbx_substitute_variables_temp(c,cp1,&cp4, workspace, sizeof(workspace));
|
||||
if (cp4) {
|
||||
/* reset output variable so we could store the result */
|
||||
*cp2='\0';
|
||||
@@ -1080,6 +1106,300 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte
|
||||
|
||||
}
|
||||
|
||||
static struct ast_exten *ast_hint_extension(struct ast_channel *c, char *context, char *exten)
|
||||
{
|
||||
struct ast_exten *e;
|
||||
struct ast_switch *sw;
|
||||
char *data;
|
||||
int status = 0;
|
||||
char *incstack[AST_PBX_MAX_STACK];
|
||||
int stacklen = 0;
|
||||
|
||||
if (ast_pthread_mutex_lock(&conlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to obtain lock\n");
|
||||
return NULL;
|
||||
}
|
||||
e = pbx_find_extension(c, context, exten, PRIORITY_HINT, "", HELPER_EXISTS, incstack, &stacklen, &status, &sw, &data);
|
||||
ast_pthread_mutex_unlock(&conlock);
|
||||
return e;
|
||||
}
|
||||
|
||||
static int ast_extension_state2(struct ast_exten *e)
|
||||
{
|
||||
char hint[AST_MAX_EXTENSION] = "";
|
||||
char *cur, *rest;
|
||||
int res = -1;
|
||||
int allunavailable = 1, allbusy = 1, allfree = 1;
|
||||
int busy = 0;
|
||||
|
||||
strncpy(hint, ast_get_extension_app(e), sizeof(hint)-1);
|
||||
|
||||
cur = hint;
|
||||
do {
|
||||
rest = strchr(cur, '&');
|
||||
if (rest) {
|
||||
*rest = 0;
|
||||
rest++;
|
||||
}
|
||||
|
||||
res = ast_device_state(cur);
|
||||
switch (res) {
|
||||
case AST_DEVICE_NOT_INUSE:
|
||||
allunavailable = 0;
|
||||
allbusy = 0;
|
||||
break;
|
||||
case AST_DEVICE_INUSE:
|
||||
return AST_EXTENSION_INUSE;
|
||||
case AST_DEVICE_BUSY:
|
||||
allunavailable = 0;
|
||||
allfree = 0;
|
||||
busy = 1;
|
||||
break;
|
||||
case AST_DEVICE_UNAVAILABLE:
|
||||
case AST_DEVICE_INVALID:
|
||||
allbusy = 0;
|
||||
allfree = 0;
|
||||
break;
|
||||
default:
|
||||
allunavailable = 0;
|
||||
allbusy = 0;
|
||||
allfree = 0;
|
||||
}
|
||||
cur = rest;
|
||||
} while (cur);
|
||||
|
||||
if (allfree)
|
||||
return AST_EXTENSION_NOT_INUSE;
|
||||
if (allbusy)
|
||||
return AST_EXTENSION_BUSY;
|
||||
if (allunavailable)
|
||||
return AST_EXTENSION_UNAVAILABLE;
|
||||
if (busy)
|
||||
return AST_EXTENSION_INUSE;
|
||||
|
||||
return AST_EXTENSION_NOT_INUSE;
|
||||
}
|
||||
|
||||
|
||||
int ast_extension_state(struct ast_channel *c, char *context, char *exten)
|
||||
{
|
||||
struct ast_exten *e;
|
||||
|
||||
e = ast_hint_extension(c, context, exten);
|
||||
if (!e)
|
||||
return -1;
|
||||
|
||||
return ast_extension_state2(e);
|
||||
}
|
||||
|
||||
int ast_device_state_changed(char *device)
|
||||
{
|
||||
struct ast_notify *list;
|
||||
struct ast_notify_cb *cblist;
|
||||
char hint[AST_MAX_EXTENSION];
|
||||
char *cur, *rest;
|
||||
int state;
|
||||
|
||||
pthread_mutex_lock(¬ifylock);
|
||||
|
||||
list = notifys;
|
||||
|
||||
while (list) {
|
||||
|
||||
strcpy(hint, ast_get_extension_app(list->exten));
|
||||
cur = hint;
|
||||
do {
|
||||
rest = strchr(cur, '&');
|
||||
if (rest) {
|
||||
*rest = 0;
|
||||
rest++;
|
||||
}
|
||||
|
||||
if (!strncmp(cur, device, strlen(cur))) {
|
||||
// Found extension execute callbacks
|
||||
state = ast_extension_state2(list->exten);
|
||||
if ((state != -1) && (state != list->laststate)) {
|
||||
cblist = list->callbacks;
|
||||
while (cblist) {
|
||||
cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
|
||||
cblist = cblist->next;
|
||||
}
|
||||
list->laststate = state;
|
||||
}
|
||||
break;
|
||||
}
|
||||
cur = rest;
|
||||
} while (cur);
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ast_extension_state_add(char *context, char *exten,
|
||||
ast_notify_cb_type callback, void *data)
|
||||
{
|
||||
struct ast_notify *list;
|
||||
struct ast_notify_cb *cblist;
|
||||
struct ast_exten *e;
|
||||
|
||||
pthread_mutex_lock(¬ifylock);
|
||||
list = notifys;
|
||||
|
||||
while (list) {
|
||||
if (!strcmp(list->exten->parent->name, context) &&
|
||||
!strcmp(list->exten->exten, exten))
|
||||
break;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (!list) {
|
||||
e = ast_hint_extension(NULL, context, exten);
|
||||
if (!e) {
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
return -1;
|
||||
}
|
||||
list = malloc(sizeof(struct ast_notify));
|
||||
if (!list) {
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
return -1;
|
||||
}
|
||||
/* Initialize and insert new item */
|
||||
memset(list, 0, sizeof(struct ast_notify));
|
||||
list->exten = e;
|
||||
list->laststate = -1;
|
||||
list->next = notifys;
|
||||
notifys = list;
|
||||
}
|
||||
|
||||
/* Now inserts the callback */
|
||||
cblist = malloc(sizeof(struct ast_notify_cb));
|
||||
if (!cblist) {
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
return -1;
|
||||
}
|
||||
memset(cblist, 0, sizeof(struct ast_notify_cb));
|
||||
cblist->id = notifycnt++;
|
||||
cblist->callback = callback;
|
||||
cblist->data = data;
|
||||
|
||||
cblist->next = list->callbacks;
|
||||
list->callbacks = cblist;
|
||||
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
return cblist->id;
|
||||
}
|
||||
|
||||
static int ast_extension_state_clean(struct ast_exten *e)
|
||||
{
|
||||
/* Cleanup the Notifys if hint is removed */
|
||||
struct ast_notify *list, *prev = NULL;
|
||||
struct ast_notify_cb *cblist, *cbprev;
|
||||
|
||||
pthread_mutex_lock(¬ifylock);
|
||||
|
||||
list = notifys;
|
||||
while(list) {
|
||||
if (list->exten==e) {
|
||||
cbprev = NULL;
|
||||
cblist = list->callbacks;
|
||||
while (cblist) {
|
||||
cbprev = cblist;
|
||||
cblist = cblist->next;
|
||||
cblist->callback(list->exten->parent->name, list->exten->exten, -1, cblist->data);
|
||||
free(cbprev);
|
||||
}
|
||||
list->callbacks = NULL;
|
||||
|
||||
if (!prev) {
|
||||
notifys = list->next;
|
||||
free(list);
|
||||
list = notifys;
|
||||
} else {
|
||||
prev->next = list->next;
|
||||
free(list);
|
||||
list = prev->next;
|
||||
}
|
||||
} else {
|
||||
prev = list;
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ast_extension_state_del(int id)
|
||||
{
|
||||
struct ast_notify *list, *prev = NULL;
|
||||
struct ast_notify_cb *cblist, *cbprev;
|
||||
|
||||
pthread_mutex_lock(¬ifylock);
|
||||
|
||||
list = notifys;
|
||||
while (list) {
|
||||
cblist = list->callbacks;
|
||||
cbprev = NULL;
|
||||
while (cblist) {
|
||||
if (cblist->id==id) {
|
||||
if (!cbprev) {
|
||||
list->callbacks = cblist->next;
|
||||
free(cblist);
|
||||
cblist = list->callbacks;
|
||||
} else {
|
||||
cbprev->next = cblist->next;
|
||||
free(cblist);
|
||||
cblist = cbprev->next;
|
||||
}
|
||||
|
||||
if (!list->callbacks) {
|
||||
if (!prev) {
|
||||
notifys = list->next;
|
||||
free(list);
|
||||
list = notifys;
|
||||
} else {
|
||||
prev->next = list->next;
|
||||
free(list);
|
||||
list = prev->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
cbprev = cblist;
|
||||
cblist = cblist->next;
|
||||
}
|
||||
}
|
||||
|
||||
// we can have only one item
|
||||
if (cblist)
|
||||
break;
|
||||
|
||||
prev = list;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(¬ifylock);
|
||||
if (list)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int ast_get_hint(char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
|
||||
{
|
||||
struct ast_exten *e;
|
||||
e = ast_hint_extension(c, context, exten);
|
||||
if (e) {
|
||||
strncpy(hint, ast_get_extension_app(e), maxlen);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
|
||||
@@ -1544,6 +1864,9 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
|
||||
peer = exten;
|
||||
while (peer) {
|
||||
exten = peer->peer;
|
||||
|
||||
if (!peer->priority==PRIORITY_HINT)
|
||||
ast_extension_state_clean(peer);
|
||||
|
||||
peer->datad(peer->data);
|
||||
free(peer);
|
||||
@@ -1589,6 +1912,8 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
|
||||
}
|
||||
|
||||
/* now, free whole priority extension */
|
||||
if (peer->priority==PRIORITY_HINT)
|
||||
ast_extension_state_clean(peer);
|
||||
peer->datad(peer->data);
|
||||
free(peer);
|
||||
|
||||
@@ -2956,6 +3281,7 @@ int ast_add_extension2(struct ast_context *con,
|
||||
tmp->matchcid = 0;
|
||||
}
|
||||
strncpy(tmp->app, application, sizeof(tmp->app)-1);
|
||||
tmp->parent = con;
|
||||
tmp->data = data;
|
||||
tmp->datad = datad;
|
||||
tmp->registrar = registrar;
|
||||
|
@@ -344,14 +344,16 @@ static int handle_context_remove_extension(int fd, int argc, char *argv[])
|
||||
* why? because atoi (strtol) returns 0 if any characters in
|
||||
* string and whole extension will be removed, it's not good
|
||||
*/
|
||||
while (*c != '\0') {
|
||||
if (strcmp("hint", c)) {
|
||||
while (*c != '\0') {
|
||||
if (!isdigit(*c++)) {
|
||||
ast_cli(fd, "Invalid priority '%s'\n", argv[3]);
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
removing_priority = atoi(argv[3]);
|
||||
}
|
||||
removing_priority = atoi(argv[3]);
|
||||
} else
|
||||
removing_priority = PRIORITY_HINT;
|
||||
|
||||
if (removing_priority == 0) {
|
||||
ast_cli(fd, "If you want to remove whole extension, please " \
|
||||
@@ -983,11 +985,17 @@ static int handle_save_dialplan(int fd, int argc, char *argv[])
|
||||
context_header_written = 1;
|
||||
}
|
||||
|
||||
fprintf(output, "exten => %s,%d,%s,%s\n",
|
||||
ast_get_extension_name(p),
|
||||
ast_get_extension_priority(p),
|
||||
ast_get_extension_app(p),
|
||||
(char *)ast_get_extension_app_data(p));
|
||||
if (!ast_get_extension_priority(p)==PRIORITY_HINT)
|
||||
fprintf(output, "exten => %s,%d,%s,%s\n",
|
||||
ast_get_extension_name(p),
|
||||
ast_get_extension_priority(p),
|
||||
ast_get_extension_app(p),
|
||||
(char *)ast_get_extension_app_data(p));
|
||||
else
|
||||
fprintf(output, "exten => %s,hint,%s\n",
|
||||
ast_get_extension_name(p),
|
||||
ast_get_extension_app(p));
|
||||
|
||||
}
|
||||
p = ast_walk_extension_priorities(e, p);
|
||||
}
|
||||
@@ -1058,6 +1066,7 @@ static int handle_context_add_extension(int fd, int argc, char *argv[])
|
||||
{
|
||||
char *whole_exten;
|
||||
char *exten, *prior;
|
||||
int iprior = -2;
|
||||
char *cidmatch, *app, *app_data;
|
||||
char *start, *end;
|
||||
|
||||
@@ -1075,6 +1084,11 @@ static int handle_context_add_extension(int fd, int argc, char *argv[])
|
||||
cidmatch = NULL;
|
||||
}
|
||||
prior = strsep(&whole_exten,",");
|
||||
if (!strcmp(prior, "hint")) {
|
||||
iprior = PRIORITY_HINT;
|
||||
} else {
|
||||
iprior = atoi(prior);
|
||||
}
|
||||
app = strsep(&whole_exten,",");
|
||||
if ((start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
|
||||
*start = *end = '\0';
|
||||
@@ -1085,9 +1099,11 @@ static int handle_context_add_extension(int fd, int argc, char *argv[])
|
||||
} else
|
||||
app_data = whole_exten;
|
||||
|
||||
if (!exten || !prior || !app || !app_data) return RESULT_SHOWUSAGE;
|
||||
if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT)) return RESULT_SHOWUSAGE;
|
||||
|
||||
if (ast_add_extension(argv[4], argc == 6 ? 1 : 0, exten, atoi(prior), cidmatch, app,
|
||||
if (!app_data)
|
||||
app_data="";
|
||||
if (ast_add_extension(argv[4], argc == 6 ? 1 : 0, exten, iprior, cidmatch, app,
|
||||
(void *)strdup(app_data), free, registrar)) {
|
||||
switch (errno) {
|
||||
case ENOMEM:
|
||||
@@ -1500,6 +1516,7 @@ static int pbx_load_module(void)
|
||||
while(v) {
|
||||
if (!strcasecmp(v->name, "exten")) {
|
||||
char *stringp=NULL;
|
||||
int ipri = -2;
|
||||
tc = strdup(v->value);
|
||||
if(tc!=NULL){
|
||||
stringp=tc;
|
||||
@@ -1509,6 +1526,10 @@ static int pbx_load_module(void)
|
||||
pri = strsep(&stringp, ",");
|
||||
if (!pri)
|
||||
pri="";
|
||||
if (!strcmp(pri,"hint"))
|
||||
ipri=PRIORITY_HINT;
|
||||
else
|
||||
ipri=atoi(pri);
|
||||
appl = stringp;
|
||||
if (!appl)
|
||||
appl="";
|
||||
@@ -1544,7 +1565,7 @@ static int pbx_load_module(void)
|
||||
|
||||
if (!data)
|
||||
data="";
|
||||
if (ast_add_extension2(con, 0, ext, atoi(pri), cidmatch, appl, strdup(data), free, registrar)) {
|
||||
if (ast_add_extension2(con, 0, ext, ipri, cidmatch, appl, strdup(data), free, registrar)) {
|
||||
ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
|
||||
}
|
||||
free(tc);
|
||||
|
Reference in New Issue
Block a user