Add support for 'setvar=' for MGCP device lines, like other channel drivers provide.
authorTilghman Lesher <tilghman@meg.abyt.es>
Wed, 23 Sep 2009 23:38:19 +0000 (23:38 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Wed, 23 Sep 2009 23:38:19 +0000 (23:38 +0000)
(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

CHANGES
channels/chan_mgcp.c
configs/mgcp.conf.sample

diff --git a/CHANGES b/CHANGES
index bba0d41..7358bf0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -50,6 +50,12 @@ IAX2 Changes
  * Added rtsavesysname option into iax.conf to allow the systname to be saved
    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
 ------------
  * Added progress option to the app_dial D() option.  When progress DTMF is
index cc01250..172a3a6 100644 (file)
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/stringfields.h"
 #include "asterisk/abstract_jb.h"
 #include "asterisk/event.h"
+#include "asterisk/chanvars.h"
 
 /*
  * Define to work around buggy dlink MGCP phone firmware which
@@ -363,6 +364,7 @@ struct mgcp_endpoint {
        /* struct ast_rtp *rtp; */
        /* struct sockaddr_in tmpdest; */
        /* 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_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_devicestate(void *data);
 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 = {
        .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_endpoint *me;
        int hasendpoints = 0;
+       struct ast_variable * v = NULL;
+       
 
        switch (cmd) {
        case CLI_INIT:
@@ -1058,9 +1064,13 @@ static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct
                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");
                while(me) {
-                       /* Don't show wilcard endpoint */
-                       if (strcmp(me->name, mg->wcardep) != 0)
-                               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, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
+                       if (me->chanvars) {
+                               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;
                        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)
 {
        struct ast_channel *tmp;
+       struct ast_variable *v = NULL;
        struct mgcp_endpoint *i = sub->parent;
        int fmt;
 
@@ -1517,6 +1528,13 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons
                if (!i->adsi)
                        tmp->adsicpe = AST_ADSI_UNAVAILABLE;
                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)
                        ast_jb_configure(tmp, &global_jbconf);
                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_endpoint *e;
        struct mgcp_subchannel *sub;
+       struct ast_variable *chanvars = NULL;
+
        /*char txident[80];*/
        int i=0, y=0;
        int gw_reload = 0;
@@ -3648,6 +3668,14 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
                                } else {
                                        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")) {
                                ast_copy_string(musicclass, v->value, sizeof(musicclass));
                        } 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);
                                        /* ASSUME we're onhook */
                                        e->hookstate = MGCP_ONHOOK;
+                                       e->chanvars = copy_vars(chanvars);
                                        if (!ep_reload) {
                                                /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
                                                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->transfer = transfer;
                                        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) {
                                                e->onhooktime = time(NULL);
                                                /* 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_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))
+
+               /* 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);
 }
 
@@ -4008,6 +4056,11 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
        if (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->rqnt_queue_lock);
        ast_mutex_destroy(&e->cmd_queue_lock);
@@ -4067,6 +4120,38 @@ static void prune_gateways(void)
        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)
 {
        struct ast_config *cfg;
index fde0a4f..a8f745a 100644 (file)
 ;directmedia   = no
 ;transfer      = no
 ;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
+;clearvars=all          ; Reset list of variables back to none
 ;callerid      = "Duane Cox" <456>     ; now lets setup line 2
 ;callwaiting   = no
 ;callreturn    = yes