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
1.0
Mark Spencer 22 years ago
parent a987ef1163
commit e6918cb42e

@ -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

@ -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;

@ -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

@ -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(&notifylock);
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(&notifylock);
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(&notifylock);
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(&notifylock);
return -1;
}
list = malloc(sizeof(struct ast_notify));
if (!list) {
pthread_mutex_unlock(&notifylock);
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(&notifylock);
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(&notifylock);
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(&notifylock);
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(&notifylock);
return 1;
}
int ast_extension_state_del(int id)
{
struct ast_notify *list, *prev = NULL;
struct ast_notify_cb *cblist, *cbprev;
pthread_mutex_lock(&notifylock);
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(&notifylock);
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);

Loading…
Cancel
Save