mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 04:30:28 +00:00
Add support for 'setvar=' for MGCP device lines, like other channel drivers provide.
(closes issue #14818) Reported by: alea-soluciones Patches: chan_mgcp-setvars-svn-trunk-r219899.patch uploaded by alea (license 514) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@219952 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -50,6 +50,12 @@ IAX2 Changes
|
|||||||
* Added rtsavesysname option into iax.conf to allow the systname to be saved
|
* Added rtsavesysname option into iax.conf to allow the systname to be saved
|
||||||
on realtime updates.
|
on realtime updates.
|
||||||
|
|
||||||
|
MGCP Changes
|
||||||
|
------------
|
||||||
|
* Added ability to preset channel variables on indicated lines with the setvar
|
||||||
|
configuration option. Also, clearvars=all resets the list of variables back
|
||||||
|
to none.
|
||||||
|
|
||||||
Applications
|
Applications
|
||||||
------------
|
------------
|
||||||
* Added progress option to the app_dial D() option. When progress DTMF is
|
* Added progress option to the app_dial D() option. When progress DTMF is
|
||||||
|
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
#include "asterisk/stringfields.h"
|
#include "asterisk/stringfields.h"
|
||||||
#include "asterisk/abstract_jb.h"
|
#include "asterisk/abstract_jb.h"
|
||||||
#include "asterisk/event.h"
|
#include "asterisk/event.h"
|
||||||
|
#include "asterisk/chanvars.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define to work around buggy dlink MGCP phone firmware which
|
* Define to work around buggy dlink MGCP phone firmware which
|
||||||
@@ -363,6 +364,7 @@ struct mgcp_endpoint {
|
|||||||
/* struct ast_rtp *rtp; */
|
/* struct ast_rtp *rtp; */
|
||||||
/* struct sockaddr_in tmpdest; */
|
/* struct sockaddr_in tmpdest; */
|
||||||
/* message go the the endpoint and not the channel so they stay here */
|
/* message go the the endpoint and not the channel so they stay here */
|
||||||
|
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
|
||||||
struct mgcp_endpoint *next;
|
struct mgcp_endpoint *next;
|
||||||
struct mgcp_gateway *parent;
|
struct mgcp_gateway *parent;
|
||||||
};
|
};
|
||||||
@@ -430,6 +432,8 @@ static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
|
|||||||
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
|
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
|
||||||
static int mgcp_devicestate(void *data);
|
static int mgcp_devicestate(void *data);
|
||||||
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
|
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
|
||||||
|
static struct ast_variable *add_var(const char *buf, struct ast_variable *list);
|
||||||
|
static struct ast_variable *copy_vars(struct ast_variable *src);
|
||||||
|
|
||||||
static const struct ast_channel_tech mgcp_tech = {
|
static const struct ast_channel_tech mgcp_tech = {
|
||||||
.type = "MGCP",
|
.type = "MGCP",
|
||||||
@@ -1038,6 +1042,8 @@ static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct
|
|||||||
struct mgcp_gateway *mg;
|
struct mgcp_gateway *mg;
|
||||||
struct mgcp_endpoint *me;
|
struct mgcp_endpoint *me;
|
||||||
int hasendpoints = 0;
|
int hasendpoints = 0;
|
||||||
|
struct ast_variable * v = NULL;
|
||||||
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case CLI_INIT:
|
case CLI_INIT:
|
||||||
@@ -1058,9 +1064,13 @@ static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct
|
|||||||
me = mg->endpoints;
|
me = mg->endpoints;
|
||||||
ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static");
|
ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static");
|
||||||
while(me) {
|
while(me) {
|
||||||
/* Don't show wilcard endpoint */
|
ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
|
||||||
if (strcmp(me->name, mg->wcardep) != 0)
|
if (me->chanvars) {
|
||||||
ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
|
ast_cli(a->fd, " Variables:\n");
|
||||||
|
for (v = me->chanvars ; v ; v = v->next) {
|
||||||
|
ast_cli(a->fd, " %s = '%s'\n", v->name, v->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
hasendpoints = 1;
|
hasendpoints = 1;
|
||||||
me = me->next;
|
me = me->next;
|
||||||
}
|
}
|
||||||
@@ -1469,6 +1479,7 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
|
|||||||
static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
|
static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
|
||||||
{
|
{
|
||||||
struct ast_channel *tmp;
|
struct ast_channel *tmp;
|
||||||
|
struct ast_variable *v = NULL;
|
||||||
struct mgcp_endpoint *i = sub->parent;
|
struct mgcp_endpoint *i = sub->parent;
|
||||||
int fmt;
|
int fmt;
|
||||||
|
|
||||||
@@ -1517,6 +1528,13 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons
|
|||||||
if (!i->adsi)
|
if (!i->adsi)
|
||||||
tmp->adsicpe = AST_ADSI_UNAVAILABLE;
|
tmp->adsicpe = AST_ADSI_UNAVAILABLE;
|
||||||
tmp->priority = 1;
|
tmp->priority = 1;
|
||||||
|
|
||||||
|
/* Set channel variables for this call from configuration */
|
||||||
|
for (v = i->chanvars ; v ; v = v->next) {
|
||||||
|
char valuebuf[1024];
|
||||||
|
pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
|
||||||
|
}
|
||||||
|
|
||||||
if (sub->rtp)
|
if (sub->rtp)
|
||||||
ast_jb_configure(tmp, &global_jbconf);
|
ast_jb_configure(tmp, &global_jbconf);
|
||||||
if (state != AST_STATE_DOWN) {
|
if (state != AST_STATE_DOWN) {
|
||||||
@@ -3548,6 +3566,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
|
|||||||
struct mgcp_gateway *gw;
|
struct mgcp_gateway *gw;
|
||||||
struct mgcp_endpoint *e;
|
struct mgcp_endpoint *e;
|
||||||
struct mgcp_subchannel *sub;
|
struct mgcp_subchannel *sub;
|
||||||
|
struct ast_variable *chanvars = NULL;
|
||||||
|
|
||||||
/*char txident[80];*/
|
/*char txident[80];*/
|
||||||
int i=0, y=0;
|
int i=0, y=0;
|
||||||
int gw_reload = 0;
|
int gw_reload = 0;
|
||||||
@@ -3648,6 +3668,14 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
|
|||||||
} else {
|
} else {
|
||||||
amaflags = y;
|
amaflags = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (!strcasecmp(v->name, "setvar")) {
|
||||||
|
chanvars = add_var(v->value, chanvars);
|
||||||
|
} else if (!strcasecmp(v->name, "clearvars")) {
|
||||||
|
if (chanvars) {
|
||||||
|
ast_variables_destroy(chanvars);
|
||||||
|
chanvars = NULL;
|
||||||
|
}
|
||||||
} else if (!strcasecmp(v->name, "musiconhold")) {
|
} else if (!strcasecmp(v->name, "musiconhold")) {
|
||||||
ast_copy_string(musicclass, v->value, sizeof(musicclass));
|
ast_copy_string(musicclass, v->value, sizeof(musicclass));
|
||||||
} else if (!strcasecmp(v->name, "parkinglot")) {
|
} else if (!strcasecmp(v->name, "parkinglot")) {
|
||||||
@@ -3757,6 +3785,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
|
|||||||
e->onhooktime = time(NULL);
|
e->onhooktime = time(NULL);
|
||||||
/* ASSUME we're onhook */
|
/* ASSUME we're onhook */
|
||||||
e->hookstate = MGCP_ONHOOK;
|
e->hookstate = MGCP_ONHOOK;
|
||||||
|
e->chanvars = copy_vars(chanvars);
|
||||||
if (!ep_reload) {
|
if (!ep_reload) {
|
||||||
/*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
|
/*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
|
||||||
for (i = 0; i < MAX_SUBS; i++) {
|
for (i = 0; i < MAX_SUBS; i++) {
|
||||||
@@ -3858,6 +3887,16 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
|
|||||||
e->slowsequence = slowsequence;
|
e->slowsequence = slowsequence;
|
||||||
e->transfer = transfer;
|
e->transfer = transfer;
|
||||||
e->threewaycalling = threewaycalling;
|
e->threewaycalling = threewaycalling;
|
||||||
|
|
||||||
|
/* If we already have a valid chanvars, it's not a new endpoint (it's a reload),
|
||||||
|
so first, free previous mem
|
||||||
|
*/
|
||||||
|
if (e->chanvars) {
|
||||||
|
ast_variables_destroy(e->chanvars);
|
||||||
|
e->chanvars = NULL;
|
||||||
|
}
|
||||||
|
e->chanvars = copy_vars(chanvars);
|
||||||
|
|
||||||
if (!ep_reload) {
|
if (!ep_reload) {
|
||||||
e->onhooktime = time(NULL);
|
e->onhooktime = time(NULL);
|
||||||
/* ASSUME we're onhook */
|
/* ASSUME we're onhook */
|
||||||
@@ -3920,18 +3959,27 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
|
|||||||
ast_mutex_destroy(&gw->msgs_lock);
|
ast_mutex_destroy(&gw->msgs_lock);
|
||||||
ast_free(gw);
|
ast_free(gw);
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
gw->defaddr.sin_family = AF_INET;
|
|
||||||
gw->addr.sin_family = AF_INET;
|
|
||||||
if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port))
|
|
||||||
gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
|
|
||||||
if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
|
|
||||||
gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
|
|
||||||
if (gw->addr.sin_addr.s_addr)
|
|
||||||
if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
|
|
||||||
memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
|
|
||||||
|
|
||||||
|
/* Return NULL */
|
||||||
|
gw_reload = 1;
|
||||||
|
} else {
|
||||||
|
gw->defaddr.sin_family = AF_INET;
|
||||||
|
gw->addr.sin_family = AF_INET;
|
||||||
|
if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
|
||||||
|
gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
|
||||||
|
}
|
||||||
|
if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
|
||||||
|
gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
|
||||||
|
}
|
||||||
|
if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) {
|
||||||
|
memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chanvars) {
|
||||||
|
ast_variables_destroy(chanvars);
|
||||||
|
chanvars = NULL;
|
||||||
|
}
|
||||||
return (gw_reload ? NULL : gw);
|
return (gw_reload ? NULL : gw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4008,6 +4056,11 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
|
|||||||
if (e->mwi_event_sub)
|
if (e->mwi_event_sub)
|
||||||
ast_event_unsubscribe(e->mwi_event_sub);
|
ast_event_unsubscribe(e->mwi_event_sub);
|
||||||
|
|
||||||
|
if (e->chanvars) {
|
||||||
|
ast_variables_destroy(e->chanvars);
|
||||||
|
e->chanvars = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ast_mutex_destroy(&e->lock);
|
ast_mutex_destroy(&e->lock);
|
||||||
ast_mutex_destroy(&e->rqnt_queue_lock);
|
ast_mutex_destroy(&e->rqnt_queue_lock);
|
||||||
ast_mutex_destroy(&e->cmd_queue_lock);
|
ast_mutex_destroy(&e->cmd_queue_lock);
|
||||||
@@ -4067,6 +4120,38 @@ static void prune_gateways(void)
|
|||||||
ast_mutex_unlock(&gatelock);
|
ast_mutex_unlock(&gatelock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
|
||||||
|
{
|
||||||
|
struct ast_variable *tmpvar = NULL;
|
||||||
|
char *varname = ast_strdupa(buf), *varval = NULL;
|
||||||
|
|
||||||
|
if ((varval = strchr(varname, '='))) {
|
||||||
|
*varval++ = '\0';
|
||||||
|
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
|
||||||
|
tmpvar->next = list;
|
||||||
|
list = tmpvar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief
|
||||||
|
* duplicate a list of channel variables, \return the copy.
|
||||||
|
*/
|
||||||
|
static struct ast_variable *copy_vars(struct ast_variable *src)
|
||||||
|
{
|
||||||
|
struct ast_variable *res = NULL, *tmp, *v = NULL;
|
||||||
|
|
||||||
|
for (v = src ; v ; v = v->next) {
|
||||||
|
if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
|
||||||
|
tmp->next = res;
|
||||||
|
res = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int reload_config(int reload)
|
static int reload_config(int reload)
|
||||||
{
|
{
|
||||||
struct ast_config *cfg;
|
struct ast_config *cfg;
|
||||||
|
@@ -99,7 +99,10 @@
|
|||||||
;directmedia = no
|
;directmedia = no
|
||||||
;transfer = no
|
;transfer = no
|
||||||
;dtmfmode = inband
|
;dtmfmode = inband
|
||||||
|
;setvar=one=1 ; Set channel variables associated with this incoming line
|
||||||
|
;setvar=two=2
|
||||||
;line => aaln/1 ; now lets save this config to line1 aka aaln/1
|
;line => aaln/1 ; now lets save this config to line1 aka aaln/1
|
||||||
|
;clearvars=all ; Reset list of variables back to none
|
||||||
;callerid = "Duane Cox" <456> ; now lets setup line 2
|
;callerid = "Duane Cox" <456> ; now lets setup line 2
|
||||||
;callwaiting = no
|
;callwaiting = no
|
||||||
;callreturn = yes
|
;callreturn = yes
|
||||||
|
Reference in New Issue
Block a user