summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES33
-rw-r--r--configs/dundi.conf.sample21
-rw-r--r--pbx/pbx_dundi.c38
3 files changed, 71 insertions, 21 deletions
diff --git a/CHANGES b/CHANGES
index 71a55650a..cf3f04efa 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,10 +6,8 @@ Miscellaneous
-------------
* Added the bindaddr option to gtalk.conf.
- * Added the ability to specify arguments to the Dial application when using
- the DUNDi switch in the dialplan.
* Added the ability to customize which sound files are used for some of the
- prompts within the Voicemail application by changing them in voicemail.conf
+ prompts within the Voicemail application by changing them in voicemail.conf
* Argument support for Gosub application
* Ability to set process limits without restarting Asterisk
* SS7 support in chan_zap (via libss7 library)
@@ -85,7 +83,7 @@ Dialplan functions
------------------
* Added the DEVSTATE() dialplan function which allows retrieving any device
state in the dialplan, as well as creating custom device states that are
- controllable from the dialplan.
+ controllable from the dialplan.
* Extend CALLERID() function with "pres" and "ton" parameters to
fetch string representation of calling number presentation indicator
and numeric representation of type of calling number value.
@@ -100,18 +98,27 @@ SIP changes
-----------
* The default SIP useragent= identifier now includes the Asterisk version
* A new option, match_auth_username in sip.conf changes the matching of incoming requests.
- If set, and the incoming request carries authentication info,
- the username to match in the users list is taken from the Digest header
- rather than from the From: field. This feature is considered experimental.
+ If set, and the incoming request carries authentication info,
+ the username to match in the users list is taken from the Digest header
+ rather than from the From: field. This feature is considered experimental.
* The "musiconhold" and "musicclass" settings in sip.conf are now removed,
- since they where replaced by "mohsuggest" and "mohinterpret" in version 1.4
+ since they where replaced by "mohsuggest" and "mohinterpret" in version 1.4
* The "localmask" setting was removed in version 1.2 and the reminder about it
- being removed is now also removed.
+ being removed is now also removed.
* A new option "busy-level" for setting a level of calls where asterisk reports
- a device as busy, to separate it from call-limit
+ a device as busy, to separate it from call-limit
* A new realtime family called "sipregs" is now supported to store SIP registration
- data. If this family is defined, "sippeers" will be used for configuration and
- "sipregs" for registrations. If it's not defined, "sippeers" will be used for
- registration data, as before.
+ data. If this family is defined, "sippeers" will be used for configuration and
+ "sipregs" for registrations. If it's not defined, "sippeers" will be used for
+ registration data, as before.
* The SIPPEER function have new options for port address, call and pickup groups
* Added support for T.140 realtime text in SIP/RTP
+
+DUNDi changes
+-------------
+ * Added the ability to specify arguments to the Dial application when using
+ the DUNDi switch in the dialplan.
+ * Added the ability to set weights for responses dynamically. This can be
+ done using a global variable or a dialplan function. Using the SHELL()
+ function would allow you to have an external script set the weight for
+ each response.
diff --git a/configs/dundi.conf.sample b/configs/dundi.conf.sample
index a1e999726..4b7f15617 100644
--- a/configs/dundi.conf.sample
+++ b/configs/dundi.conf.sample
@@ -125,8 +125,27 @@ autokill=yes
;digexten => default,0,IAX2,guest@lappy/${NUMBER}
;asdf =>
-
;
+; Weights for mappings can be set a few different ways:
+;
+; 1) It can be set as a static number.
+;testmap1 => context1,222,IAX2,guest@peer1/${NUMBER}
+;
+; 2) It can be an Asterisk global variable.
+;testmap2 => context2,${DUNDITESTVAR},IAX2,guest@peer2${NUMBER}
+;
+; 3) It can be retrieved using a dialplan function. This can be extremely
+; useful if you want to let an external script decide what the weight
+; in a response shouuld be.
+;testmap3 => context3,${SHELL(echo 123)},IAX2,guest@peer3/${NUMBER}
+;
+; Note than when using a global variable or dialplan function to set the
+; weight for a mapping, that response caching should be disabled if you
+; plan for these values to change frequently at all. If the results are
+; cached, then any change in value will not take effect until the cache
+; has expired.
+;
+
;
; The remaining sections represent the peers
; that we fundamentally trust. The section name
diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c
index 62c2c558b..21a06a079 100644
--- a/pbx/pbx_dundi.c
+++ b/pbx/pbx_dundi.c
@@ -79,6 +79,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define MAX_PACKET_SIZE 8192
+#define MAX_WEIGHT 59999
+
#define DUNDI_MODEL_INBOUND (1 << 0)
#define DUNDI_MODEL_OUTBOUND (1 << 1)
#define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)
@@ -211,7 +213,8 @@ struct dundi_request {
struct dundi_mapping {
char dcontext[AST_MAX_EXTENSION];
char lcontext[AST_MAX_EXTENSION];
- int weight;
+ int _weight;
+ char *weightstr;
int options;
int tech;
int dead;
@@ -511,6 +514,19 @@ struct dundi_query_state {
char fluffy[0];
};
+static int get_mapping_weight(struct dundi_mapping *map)
+{
+ char buf[32] = "";
+
+ if (map->weightstr) {
+ pbx_substitute_variables_helper(NULL, map->weightstr, buf, sizeof(buf) - 1);
+ if (sscanf(buf, "%d", &map->_weight) != 1)
+ map->_weight = MAX_WEIGHT;
+ }
+
+ return map->_weight;
+}
+
static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
{
struct ast_flags flags = {0};
@@ -539,7 +555,7 @@ static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map
ast_set_flag(&flags, map->options & 0xffff);
ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
dr[anscnt].techint = map->tech;
- dr[anscnt].weight = map->weight;
+ dr[anscnt].weight = get_mapping_weight(map);
dr[anscnt].expiration = dundi_cache_time;
ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
dr[anscnt].eid = *us_eid;
@@ -2591,15 +2607,17 @@ static int dundi_show_requests(int fd, int argc, char *argv[])
static int dundi_show_mappings(int fd, int argc, char *argv[])
{
#define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
-#define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n"
+#define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
struct dundi_mapping *map;
char fs[256];
+ char weight[8];
if (argc != 3)
return RESULT_SHOWUSAGE;
AST_LIST_LOCK(&peers);
ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
AST_LIST_TRAVERSE(&mappings, map, list) {
- ast_cli(fd, FORMAT, map->dcontext, map->weight,
+ snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map));
+ ast_cli(fd, FORMAT, map->dcontext, weight,
ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext,
dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
}
@@ -3871,6 +3889,8 @@ static void destroy_peer(struct dundi_peer *peer)
static void destroy_map(struct dundi_mapping *map)
{
+ if (map->weightstr)
+ free(map->weightstr);
free(map);
}
@@ -3960,11 +3980,15 @@ static void build_mapping(char *name, char *value)
} else if (x >= 4) {
ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
- if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) {
+ if ((sscanf(fields[1], "%d", &map->_weight) == 1) && (map->_weight >= 0) && (map->_weight <= MAX_WEIGHT)) {
ast_copy_string(map->dest, fields[3], sizeof(map->dest));
- if ((map->tech = str2tech(fields[2]))) {
+ if ((map->tech = str2tech(fields[2])))
+ map->dead = 0;
+ } else if (!strncmp(fields[1], "${", 2) && fields[1][strlen(fields[1]) - 1] == '}') {
+ map->weightstr = ast_strdup(fields[1]);
+ ast_copy_string(map->dest, fields[3], sizeof(map->dest));
+ if ((map->tech = str2tech(fields[2])))
map->dead = 0;
- }
} else {
ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
}