Thu Apr 28 2011 17:16:06

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
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Dialgroup dialplan function" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
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 309 of file func_dialgroup.c.

static void __unreg_module ( void  ) [static]

Definition at line 309 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 125 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 OBJ_POINTER.

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, OBJ_POINTER);
   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);

   return res;
}
static int dialgroup_refreshdb ( struct ast_channel chan,
const char *  cdialgroup 
) [static]

Definition at line 168 of file func_dialgroup.c.

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

Referenced by dialgroup_write().

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

   do {
      len *= 2;
      buf = ast_realloc(buf, len);

      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 193 of file func_dialgroup.c.

References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ao2_unlink, 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, and OBJ_UNLINK.

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 115 of file func_dialgroup.c.

References CMP_MATCH, CMP_STOP, group_entry::name, 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 109 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 99 of file func_dialgroup.c.

References CMP_MATCH, CMP_STOP, group::name, 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 87 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 93 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 286 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 279 of file func_dialgroup.c.

References ao2_ref, and ast_custom_function_unregister().


Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Dialgroup dialplan function" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 309 of file func_dialgroup.c.

Definition at line 309 of file func_dialgroup.c.

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

Definition at line 273 of file func_dialgroup.c.

struct ao2_container* group_container = NULL [static]

Definition at line 76 of file func_dialgroup.c.