Merge changes from team/russell/dundi_results

This introduces two new dialplan functions: DUNDIQUERY and DUNDIRESULT.
DUNDIQUERY lets you intitiate a DUNDi query from the dialplan.  Then,
DUNDIRESULT will let you find out how many results there are, and access each
one without having to the query again.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@62267 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.0
Russell Bryant 18 years ago
parent 3f414d2aea
commit c59b8876aa

@ -69,6 +69,9 @@ DUNDi changes
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.
* Added two new dialplan functions, DUNDIQUERY and DUNDIRESULT. These
functions will allow you to initiate a DUNDi query from the dialplan,
find out how many results there are, and access each one.
Voicemail Changes
-----------------

@ -72,6 +72,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/aes.h"
#include "asterisk/app.h"
#include "dundi-parser.h"
@ -3838,13 +3839,200 @@ static struct ast_custom_function dundi_function = {
.syntax = "DUNDILOOKUP(number[|context[|options]])",
.desc = "This will do a DUNDi lookup of the given phone number.\n"
"If no context is given, the default will be e164. The result of\n"
"this function will the Technology/Resource found in the DUNDi\n"
"lookup. If no results were found, the result will be blank.\n"
"this function will return the Technology/Resource found in the first result\n"
"in the DUNDi lookup. If no results were found, the result will be blank.\n"
"If the 'b' option is specified, the internal DUNDi cache will\n"
"be bypassed.\n",
.read = dundifunc_read,
};
enum {
OPT_BYPASS_CACHE = (1 << 0),
};
AST_APP_OPTIONS(dundi_query_opts, BEGIN_OPTIONS
AST_APP_OPTION('b', OPT_BYPASS_CACHE),
END_OPTIONS );
unsigned int dundi_result_id;
struct dundi_result_datastore {
struct dundi_result results[MAX_RESULTS];
unsigned int num_results;
unsigned int id;
};
static void drds_destroy(struct dundi_result_datastore *drds)
{
free(drds);
}
static void drds_destroy_cb(void *data)
{
struct dundi_result_datastore *drds = data;
drds_destroy(drds);
}
const struct ast_datastore_info dundi_result_datastore_info = {
.type = "DUNDIQUERY",
.destroy = drds_destroy_cb,
};
static int dundi_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
struct ast_module_user *u;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(number);
AST_APP_ARG(context);
AST_APP_ARG(options);
);
struct ast_flags opts = { 0, };
char *parse;
struct dundi_result_datastore *drds;
struct ast_datastore *datastore;
u = ast_module_user_add(chan);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n");
ast_module_user_remove(u);
return -1;
}
if (!chan) {
ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n");
ast_module_user_remove(u);
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.options))
ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options);
if (ast_strlen_zero(args.context))
args.context = "e164";
if (!(drds = ast_calloc(1, sizeof(*drds)))) {
ast_module_user_remove(u);
return -1;
}
drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1);
snprintf(buf, len, "%u", drds->id);
if (!(datastore = ast_channel_datastore_alloc(&dundi_result_datastore_info, buf))) {
drds_destroy(drds);
ast_module_user_remove(u);
return -1;
}
datastore->data = drds;
drds->num_results = dundi_lookup(drds->results, ARRAY_LEN(drds->results), NULL, args.context,
args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
if (drds->num_results > 0)
sort_results(drds->results, drds->num_results);
ast_channel_datastore_add(chan, datastore);
ast_module_user_remove(u);
return 0;
}
static struct ast_custom_function dundi_query_function = {
.name = "DUNDIQUERY",
.synopsis = "Initiate a DUNDi query.",
.syntax = "DUNDIQUERY(number[|context[|options]])",
.desc = "This will do a DUNDi lookup of the given phone number.\n"
"If no context is given, the default will be e164. The result of\n"
"this function will be a numeric ID that can be used to retrieve\n"
"the results with the DUNDIRESULT function. If the 'b' option is\n"
"is specified, the internal DUNDi cache will be bypassed.\n",
.read = dundi_query_read,
};
static int dundi_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
struct ast_module_user *u;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(id);
AST_APP_ARG(resultnum);
);
char *parse;
unsigned int num;
struct dundi_result_datastore *drds;
struct ast_datastore *datastore;
int res = -1;
u = ast_module_user_add(chan);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n");
goto finish;
}
if (!chan) {
ast_log(LOG_ERROR, "DUNDRESULT can not be used without a channel!\n");
goto finish;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.resultnum)) {
ast_log(LOG_ERROR, "A result number must be given to DUNDIRESULT!\n");
goto finish;
}
if (!(datastore = ast_channel_datastore_find(chan, &dundi_result_datastore_info, args.id))) {
ast_log(LOG_WARNING, "No DUNDi results found for query ID '%s'\n", args.id);
goto finish;
}
drds = datastore->data;
if (!strcasecmp(args.resultnum, "getnum")) {
snprintf(buf, len, "%u", drds->num_results);
res = 0;
goto finish;
}
if (sscanf(args.resultnum, "%u", &num) != 1) {
ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to DUNDIRESULT!\n",
args.resultnum);
goto finish;
}
if (num && num <= drds->num_results) {
snprintf(buf, len, "%s/%s", drds->results[num - 1].tech, drds->results[num - 1].dest);
res = 0;
} else
ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id);
finish:
ast_module_user_remove(u);
return res;
}
static struct ast_custom_function dundi_result_function = {
.name = "DUNDIRESULT",
.synopsis = "Retrieve results from a DUNDIQUERY",
.syntax = "DUNDIRESULT(id|resultnum)",
.desc = "This function will retrieve results from a previous use\n"
"of the DUNDIQUERY function.\n"
" id - This argument is the identifier returned by the DUNDIQUERY function.\n"
" resultnum - This is the number of the result that you want to retrieve.\n"
" Results start at 1. If this argument is specified as \"getnum\",\n"
" then it will return the total number of results that are available.\n",
.read = dundi_result_read,
};
static void mark_peers(void)
{
struct dundi_peer *peer;
@ -4526,6 +4714,8 @@ static int unload_module(void)
ast_cli_unregister_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry));
ast_unregister_switch(&dundi_switch);
ast_custom_function_unregister(&dundi_function);
ast_custom_function_unregister(&dundi_query_function);
ast_custom_function_unregister(&dundi_result_function);
sched_context_destroy(sched);
return 0;
@ -4590,6 +4780,8 @@ static int load_module(void)
if (ast_register_switch(&dundi_switch))
ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
ast_custom_function_register(&dundi_function);
ast_custom_function_register(&dundi_query_function);
ast_custom_function_register(&dundi_result_function);
if (option_verbose > 1) {
ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n",

Loading…
Cancel
Save