Sat Apr 26 2014 22:02:51

Asterisk developer's documentation


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, }
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, and group_entry::name.

Referenced by dialgroup_refreshdb().

{
   struct ao2_iterator i;
   struct group *grhead = ao2_find(group_container, data, 0);
   struct group_entry *entry;
   size_t bufused = 0;
   int trunc_warning = 0;
   int res = 0;

   if (!grhead) {
      if (!ast_strlen_zero(cmd)) {
         ast_log(LOG_WARNING, "No such dialgroup '%s'\n", data);
      }
      return -1;
   }

   buf[0] = '\0';

   i = ao2_iterator_init(grhead->entries, 0);
   while ((entry = ao2_iterator_next(&i))) {
      int tmp = strlen(entry->name);
      /* Ensure that we copy only complete names, not partials */
      if (len - bufused > tmp + 2) {
         if (bufused != 0)
            buf[bufused++] = '&';
         ast_copy_string(buf + bufused, entry->name, len - bufused);
         bufused += tmp;
      } else if (trunc_warning++ == 0) {
         if (!ast_strlen_zero(cmd)) {
            ast_log(LOG_WARNING, "Dialgroup '%s' is too large.  Truncating list.\n", data);
         } else {
            res = 1;
            ao2_ref(entry, -1);
            break;
         }
      }
      ao2_ref(entry, -1);
   }
   ao2_iterator_destroy(&i);
   ao2_ref(grhead, -1);

   return res;
}
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_strlen_zero(), dialgroup_read(), and len().

Referenced by dialgroup_write().

{
   int len = 500, res = 0;
   char *buf = NULL;
   char *new_buf;
   char *dialgroup = ast_strdupa(cdialgroup);

   do {
      len *= 2;
      new_buf = ast_realloc(buf, len);
      if (!new_buf) {
         ast_free(buf);
         return -1;
      }
      buf = new_buf;

      if ((res = dialgroup_read(chan, "", dialgroup, buf, len)) < 0) {
         ast_free(buf);
         return -1;
      }
   } while (res == 1);

   if (ast_strlen_zero(buf)) {
      ast_db_del("dialgroup", cdialgroup);
   } else {
      ast_db_put("dialgroup", cdialgroup, buf);
   }
   ast_free(buf);
   return 0;
}
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_strlen_zero(), dialgroup_refreshdb(), group::entries, entry_cmp_fn(), entry_hash_fn(), group_destroy(), LOG_ERROR, LOG_WARNING, group_entry::name, group::name, OBJ_UNLINK, and value.

Referenced by load_module().

{
   struct group *grhead;
   struct group_entry *entry;
   int j, needrefresh = 1;
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(group);
      AST_APP_ARG(op);
   );
   AST_DECLARE_APP_ARGS(inter,
      AST_APP_ARG(faces)[100];
   );
   char *value = ast_strdupa(cvalue);

   AST_STANDARD_APP_ARGS(args, data);
   AST_NONSTANDARD_APP_ARGS(inter, value, '&');

   if (!(grhead = ao2_find(group_container, args.group, 0))) {
      /* Create group */
      grhead = ao2_alloc(sizeof(*grhead), group_destroy);
      if (!grhead)
         return -1;
      grhead->entries = ao2_container_alloc(37, entry_hash_fn, entry_cmp_fn);
      if (!grhead->entries) {
         ao2_ref(grhead, -1);
         return -1;
      }
      ast_copy_string(grhead->name, args.group, sizeof(grhead->name));
      ao2_link(group_container, grhead);
   }

   if (ast_strlen_zero(args.op)) {
      /* Wholesale replacement of the group */
      args.op = "add";

      /* Remove all existing */
      ao2_ref(grhead->entries, -1);
      if (!(grhead->entries = ao2_container_alloc(37, entry_hash_fn, entry_cmp_fn))) {
         ao2_unlink(group_container, grhead);
         ao2_ref(grhead, -1);
         return -1;
      }
   }

   if (strcasecmp(args.op, "add") == 0) {
      for (j = 0; j < inter.argc; j++) {
         /* Eliminate duplicates */
         if ((entry = ao2_find(grhead->entries, inter.faces[j], 0))) {
            ao2_ref(entry, -1);
            continue;
         }
         if ((entry = ao2_alloc(sizeof(*entry), NULL))) {
            ast_copy_string(entry->name, inter.faces[j], sizeof(entry->name));
            ao2_link(grhead->entries, entry);
            ao2_ref(entry, -1);
         } else {
            ast_log(LOG_WARNING, "Unable to add '%s' to dialgroup '%s'\n", inter.faces[j], grhead->name);
         }
      }
   } else if (strncasecmp(args.op, "del", 3) == 0) {
      for (j = 0; j < inter.argc; j++) {
         if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK))) {
            ao2_ref(entry, -1);
         } else {
            ast_log(LOG_WARNING, "Interface '%s' not found in dialgroup '%s'\n", inter.faces[j], grhead->name);
         }
      }
   } else {
      ast_log(LOG_ERROR, "Unrecognized operation: %s\n", args.op);
      needrefresh = 0;
   }
   ao2_ref(grhead, -1);

   if (needrefresh) {
      dialgroup_refreshdb(chan, args.group);
   }

   return 0;
}
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, name, group_entry::name, and OBJ_POINTER.

Referenced by dialgroup_write().

{
   struct group_entry *e1 = obj1, *e2 = name2;
   char *name = name2;
   if (flags & OBJ_POINTER)
      return strcmp(e1->name, e2->name) ? 0 : CMP_MATCH | CMP_STOP;
   else
      return strcmp(e1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
}
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(), and group_entry::name.

Referenced by dialgroup_write().

{
   const struct group_entry *e = obj;
   return ast_str_hash(e->name);
}
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, name, group::name, and OBJ_POINTER.

Referenced by load_module().

{
   struct group *g1 = obj1, *g2 = name2;
   char *name = name2;
   if (flags & OBJ_POINTER)
      return strcmp(g1->name, g2->name) ? 0 : CMP_MATCH | CMP_STOP;
   else
      return strcmp(g1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
}
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().

{
   struct group *group = vgroup;
   ao2_ref(group->entries, -1);
}
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().

{
   const struct group *g = obj;
   return ast_str_hash(g->name);
}
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, and ast_db_entry::next.

{
   struct ast_db_entry *dbtree, *tmp;
   char groupname[AST_MAX_EXTENSION], *ptr;

   if ((group_container = ao2_container_alloc(37, group_hash_fn, group_cmp_fn))) {
      /* Refresh groups from astdb */
      if ((dbtree = ast_db_gettree("dialgroup", NULL))) {
         for (tmp = dbtree; tmp; tmp = tmp->next) {
            ast_copy_string(groupname, tmp->key, sizeof(groupname));
            if ((ptr = strrchr(groupname, '/'))) {
               ptr++;
               dialgroup_write(NULL, "", ptr, tmp->data);
            }
         }
         ast_db_freetree(dbtree);
      }
      return ast_custom_function_register(&dialgroup_function);
   } else {
      return AST_MODULE_LOAD_DECLINE;
   }
}
static int unload_module ( void  ) [static]

Definition at line 290 of file func_dialgroup.c.

References ao2_ref, and ast_custom_function_unregister().


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, } [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.