func_dialgroup.c File Reference

Dial group dialplan function. More...

#include "asterisk.h"
#include <sys/stat.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/astobj2.h"
#include "asterisk/astdb.h"

Include dependency graph for func_dialgroup.c:

Go to the source code of this file.

Data Structures

struct  group
struct  group_entry

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int dialgroup_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int dialgroup_refreshdb (struct ast_channel *chan, const char *cdialgroup)
static int dialgroup_write (struct ast_channel *chan, const char *cmd, char *data, const char *cvalue)
static int entry_cmp_fn (void *obj1, void *name2, int flags)
static int entry_hash_fn (const void *obj, const int flags)
static int group_cmp_fn (void *obj1, void *name2, int flags)
static void group_destroy (void *vgroup)
static int group_hash_fn (const void *obj, const int flags)
static int load_module (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Dialgroup dialplan function" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_custom_function dialgroup_function
static struct ao2_containergroup_container = NULL


Detailed Description

Dial group dialplan function.

Author:
Tilghman Lesher <func_dialgroup__200709@the-tilghman.com>

Definition in file func_dialgroup.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 320 of file func_dialgroup.c.

static void __unreg_module ( void   )  [static]

Definition at line 320 of file func_dialgroup.c.

static int dialgroup_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 129 of file func_dialgroup.c.

References ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_copy_string(), ast_log, ast_strlen_zero, group::entries, LOG_WARNING, group_entry::name, and tmp().

Referenced by dialgroup_refreshdb().

00130 {
00131    struct ao2_iterator i;
00132    struct group *grhead = ao2_find(group_container, data, 0);
00133    struct group_entry *entry;
00134    size_t bufused = 0;
00135    int trunc_warning = 0;
00136    int res = 0;
00137 
00138    if (!grhead) {
00139       if (!ast_strlen_zero(cmd)) {
00140          ast_log(LOG_WARNING, "No such dialgroup '%s'\n", data);
00141       }
00142       return -1;
00143    }
00144 
00145    buf[0] = '\0';
00146 
00147    i = ao2_iterator_init(grhead->entries, 0);
00148    while ((entry = ao2_iterator_next(&i))) {
00149       int tmp = strlen(entry->name);
00150       /* Ensure that we copy only complete names, not partials */
00151       if (len - bufused > tmp + 2) {
00152          if (bufused != 0)
00153             buf[bufused++] = '&';
00154          ast_copy_string(buf + bufused, entry->name, len - bufused);
00155          bufused += tmp;
00156       } else if (trunc_warning++ == 0) {
00157          if (!ast_strlen_zero(cmd)) {
00158             ast_log(LOG_WARNING, "Dialgroup '%s' is too large.  Truncating list.\n", data);
00159          } else {
00160             res = 1;
00161             ao2_ref(entry, -1);
00162             break;
00163          }
00164       }
00165       ao2_ref(entry, -1);
00166    }
00167    ao2_iterator_destroy(&i);
00168    ao2_ref(grhead, -1);
00169 
00170    return res;
00171 }

static int dialgroup_refreshdb ( struct ast_channel chan,
const char *  cdialgroup 
) [static]

Definition at line 173 of file func_dialgroup.c.

References ast_db_del(), ast_db_put(), ast_free, ast_realloc, ast_strdupa, ast_strlen_zero, buf, dialgroup_read(), len(), and NULL.

Referenced by dialgroup_write().

00174 {
00175    int len = 500, res = 0;
00176    char *buf = NULL;
00177    char *new_buf;
00178    char *dialgroup = ast_strdupa(cdialgroup);
00179 
00180    do {
00181       len *= 2;
00182       new_buf = ast_realloc(buf, len);
00183       if (!new_buf) {
00184          ast_free(buf);
00185          return -1;
00186       }
00187       buf = new_buf;
00188 
00189       if ((res = dialgroup_read(chan, "", dialgroup, buf, len)) < 0) {
00190          ast_free(buf);
00191          return -1;
00192       }
00193    } while (res == 1);
00194 
00195    if (ast_strlen_zero(buf)) {
00196       ast_db_del("dialgroup", cdialgroup);
00197    } else {
00198       ast_db_put("dialgroup", cdialgroup, buf);
00199    }
00200    ast_free(buf);
00201    return 0;
00202 }

static int dialgroup_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  cvalue 
) [static]

Definition at line 204 of file func_dialgroup.c.

References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ao2_unlink, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, dialgroup_refreshdb(), group::entries, entry_cmp_fn(), entry_hash_fn(), group_destroy(), LOG_ERROR, LOG_WARNING, group_entry::name, group::name, NULL, OBJ_UNLINK, and value.

Referenced by load_module().

00205 {
00206    struct group *grhead;
00207    struct group_entry *entry;
00208    int j, needrefresh = 1;
00209    AST_DECLARE_APP_ARGS(args,
00210       AST_APP_ARG(group);
00211       AST_APP_ARG(op);
00212    );
00213    AST_DECLARE_APP_ARGS(inter,
00214       AST_APP_ARG(faces)[100];
00215    );
00216    char *value = ast_strdupa(cvalue);
00217 
00218    AST_STANDARD_APP_ARGS(args, data);
00219    AST_NONSTANDARD_APP_ARGS(inter, value, '&');
00220 
00221    if (!(grhead = ao2_find(group_container, args.group, 0))) {
00222       /* Create group */
00223       grhead = ao2_alloc(sizeof(*grhead), group_destroy);
00224       if (!grhead)
00225          return -1;
00226       grhead->entries = ao2_container_alloc(37, entry_hash_fn, entry_cmp_fn);
00227       if (!grhead->entries) {
00228          ao2_ref(grhead, -1);
00229          return -1;
00230       }
00231       ast_copy_string(grhead->name, args.group, sizeof(grhead->name));
00232       ao2_link(group_container, grhead);
00233    }
00234 
00235    if (ast_strlen_zero(args.op)) {
00236       /* Wholesale replacement of the group */
00237       args.op = "add";
00238 
00239       /* Remove all existing */
00240       ao2_ref(grhead->entries, -1);
00241       if (!(grhead->entries = ao2_container_alloc(37, entry_hash_fn, entry_cmp_fn))) {
00242          ao2_unlink(group_container, grhead);
00243          ao2_ref(grhead, -1);
00244          return -1;
00245       }
00246    }
00247 
00248    if (strcasecmp(args.op, "add") == 0) {
00249       for (j = 0; j < inter.argc; j++) {
00250          /* Eliminate duplicates */
00251          if ((entry = ao2_find(grhead->entries, inter.faces[j], 0))) {
00252             ao2_ref(entry, -1);
00253             continue;
00254          }
00255          if ((entry = ao2_alloc(sizeof(*entry), NULL))) {
00256             ast_copy_string(entry->name, inter.faces[j], sizeof(entry->name));
00257             ao2_link(grhead->entries, entry);
00258             ao2_ref(entry, -1);
00259          } else {
00260             ast_log(LOG_WARNING, "Unable to add '%s' to dialgroup '%s'\n", inter.faces[j], grhead->name);
00261          }
00262       }
00263    } else if (strncasecmp(args.op, "del", 3) == 0) {
00264       for (j = 0; j < inter.argc; j++) {
00265          if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK))) {
00266             ao2_ref(entry, -1);
00267          } else {
00268             ast_log(LOG_WARNING, "Interface '%s' not found in dialgroup '%s'\n", inter.faces[j], grhead->name);
00269          }
00270       }
00271    } else {
00272       ast_log(LOG_ERROR, "Unrecognized operation: %s\n", args.op);
00273       needrefresh = 0;
00274    }
00275    ao2_ref(grhead, -1);
00276 
00277    if (needrefresh) {
00278       dialgroup_refreshdb(chan, args.group);
00279    }
00280 
00281    return 0;
00282 }

static int entry_cmp_fn ( void *  obj1,
void *  name2,
int  flags 
) [static]

Definition at line 119 of file func_dialgroup.c.

References CMP_MATCH, CMP_STOP, group_entry::name, name, and OBJ_POINTER.

Referenced by dialgroup_write().

00120 {
00121    struct group_entry *e1 = obj1, *e2 = name2;
00122    char *name = name2;
00123    if (flags & OBJ_POINTER)
00124       return strcmp(e1->name, e2->name) ? 0 : CMP_MATCH | CMP_STOP;
00125    else
00126       return strcmp(e1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
00127 }

static int entry_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 113 of file func_dialgroup.c.

References ast_str_hash(), e, and group_entry::name.

Referenced by dialgroup_write().

00114 {
00115    const struct group_entry *e = obj;
00116    return ast_str_hash(e->name);
00117 }

static int group_cmp_fn ( void *  obj1,
void *  name2,
int  flags 
) [static]

Definition at line 103 of file func_dialgroup.c.

References CMP_MATCH, CMP_STOP, group::name, name, and OBJ_POINTER.

Referenced by load_module().

00104 {
00105    struct group *g1 = obj1, *g2 = name2;
00106    char *name = name2;
00107    if (flags & OBJ_POINTER)
00108       return strcmp(g1->name, g2->name) ? 0 : CMP_MATCH | CMP_STOP;
00109    else
00110       return strcmp(g1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
00111 }

static void group_destroy ( void *  vgroup  )  [static]

Definition at line 91 of file func_dialgroup.c.

References ao2_ref, and group::entries.

Referenced by dialgroup_write().

00092 {
00093    struct group *group = vgroup;
00094    ao2_ref(group->entries, -1);
00095 }

static int group_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 97 of file func_dialgroup.c.

References ast_str_hash(), and group::name.

Referenced by load_module().

00098 {
00099    const struct group *g = obj;
00100    return ast_str_hash(g->name);
00101 }

static int load_module ( void   )  [static]

Definition at line 297 of file func_dialgroup.c.

References ao2_container_alloc, ast_copy_string(), ast_custom_function_register, ast_db_freetree(), ast_db_gettree(), AST_MAX_EXTENSION, AST_MODULE_LOAD_DECLINE, ast_db_entry::data, dialgroup_write(), group_cmp_fn(), group_hash_fn(), ast_db_entry::key, ast_db_entry::next, NULL, and tmp().

00298 {
00299    struct ast_db_entry *dbtree, *tmp;
00300    char groupname[AST_MAX_EXTENSION], *ptr;
00301 
00302    if ((group_container = ao2_container_alloc(37, group_hash_fn, group_cmp_fn))) {
00303       /* Refresh groups from astdb */
00304       if ((dbtree = ast_db_gettree("dialgroup", NULL))) {
00305          for (tmp = dbtree; tmp; tmp = tmp->next) {
00306             ast_copy_string(groupname, tmp->key, sizeof(groupname));
00307             if ((ptr = strrchr(groupname, '/'))) {
00308                ptr++;
00309                dialgroup_write(NULL, "", ptr, tmp->data);
00310             }
00311          }
00312          ast_db_freetree(dbtree);
00313       }
00314       return ast_custom_function_register(&dialgroup_function);
00315    } else {
00316       return AST_MODULE_LOAD_DECLINE;
00317    }
00318 }

static int unload_module ( void   )  [static]

Definition at line 290 of file func_dialgroup.c.

References ao2_ref, and ast_custom_function_unregister().

00291 {
00292    int res = ast_custom_function_unregister(&dialgroup_function);
00293    ao2_ref(group_container, -1);
00294    return res;
00295 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Dialgroup dialplan function" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, } [static]

Definition at line 320 of file func_dialgroup.c.

Definition at line 320 of file func_dialgroup.c.

Initial value:

 {
   .name = "DIALGROUP",
   .read = dialgroup_read,
   .write = dialgroup_write,
}

Definition at line 284 of file func_dialgroup.c.

struct ao2_container* group_container = NULL [static]

Definition at line 80 of file func_dialgroup.c.


Generated on Thu Apr 16 06:31:15 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6