Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
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)
 
struct ast_moduleAST_MODULE_SELF_SYM (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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const 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_.nosp@m.dial.nosp@m.group.nosp@m.__20.nosp@m.0709@.nosp@m.the-.nosp@m.tilgh.nosp@m.man..nosp@m.com

Definition in file func_dialgroup.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 323 of file func_dialgroup.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 323 of file func_dialgroup.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 323 of file func_dialgroup.c.

◆ dialgroup_read()

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

Definition at line 127 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().

128 {
129  struct ao2_iterator i;
130  struct group *grhead = ao2_find(group_container, data, 0);
131  struct group_entry *entry;
132  size_t bufused = 0;
133  int trunc_warning = 0;
134  int res = 0;
135 
136  if (!grhead) {
137  if (!ast_strlen_zero(cmd)) {
138  ast_log(LOG_WARNING, "No such dialgroup '%s'\n", data);
139  }
140  return -1;
141  }
142 
143  buf[0] = '\0';
144 
145  i = ao2_iterator_init(grhead->entries, 0);
146  while ((entry = ao2_iterator_next(&i))) {
147  int tmp = strlen(entry->name);
148  /* Ensure that we copy only complete names, not partials */
149  if (len - bufused > tmp + 2) {
150  if (bufused != 0)
151  buf[bufused++] = '&';
152  ast_copy_string(buf + bufused, entry->name, len - bufused);
153  bufused += tmp;
154  } else if (trunc_warning++ == 0) {
155  if (!ast_strlen_zero(cmd)) {
156  ast_log(LOG_WARNING, "Dialgroup '%s' is too large. Truncating list.\n", data);
157  } else {
158  res = 1;
159  ao2_ref(entry, -1);
160  break;
161  }
162  }
163  ao2_ref(entry, -1);
164  }
166  ao2_ref(grhead, -1);
167 
168  return res;
169 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct ao2_container * group_container
#define ast_log
Definition: astobj2.c:42
char name[AST_CHANNEL_NAME]
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
Definition: search.h:40
struct ao2_container * entries
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ dialgroup_refreshdb()

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

Definition at line 171 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().

172 {
173  int len = 500, res = 0;
174  char *buf = NULL;
175  char *new_buf;
176  char *dialgroup = ast_strdupa(cdialgroup);
177 
178  do {
179  len *= 2;
180  new_buf = ast_realloc(buf, len);
181  if (!new_buf) {
182  ast_free(buf);
183  return -1;
184  }
185  buf = new_buf;
186 
187  if ((res = dialgroup_read(chan, "", dialgroup, buf, len)) < 0) {
188  ast_free(buf);
189  return -1;
190  }
191  } while (res == 1);
192 
193  if (ast_strlen_zero(buf)) {
194  ast_db_del("dialgroup", cdialgroup);
195  } else {
196  ast_db_put("dialgroup", cdialgroup, buf);
197  }
198  ast_free(buf);
199  return 0;
200 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int dialgroup_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327

◆ dialgroup_write()

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

Definition at line 202 of file func_dialgroup.c.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, 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().

203 {
204  struct group *grhead;
205  struct group_entry *entry;
206  int j, needrefresh = 1;
209  AST_APP_ARG(op);
210  );
211  AST_DECLARE_APP_ARGS(inter,
212  AST_APP_ARG(faces)[100];
213  );
214  char *value = ast_strdupa(cvalue);
215 
217  AST_NONSTANDARD_APP_ARGS(inter, value, '&');
218 
219  if (!(grhead = ao2_find(group_container, args.group, 0))) {
220  /* Create group */
221  grhead = ao2_alloc(sizeof(*grhead), group_destroy);
222  if (!grhead)
223  return -1;
226  if (!grhead->entries) {
227  ao2_ref(grhead, -1);
228  return -1;
229  }
230  ast_copy_string(grhead->name, args.group, sizeof(grhead->name));
231  ao2_link(group_container, grhead);
232  }
233 
234  if (ast_strlen_zero(args.op)) {
235  /* Wholesale replacement of the group */
236  args.op = "add";
237 
238  /* Remove all existing */
239  ao2_ref(grhead->entries, -1);
242  if (!grhead->entries) {
243  ao2_unlink(group_container, grhead);
244  ao2_ref(grhead, -1);
245  return -1;
246  }
247  }
248 
249  if (strcasecmp(args.op, "add") == 0) {
250  for (j = 0; j < inter.argc; j++) {
251  /* Eliminate duplicates */
252  if ((entry = ao2_find(grhead->entries, inter.faces[j], 0))) {
253  ao2_ref(entry, -1);
254  continue;
255  }
256  if ((entry = ao2_alloc(sizeof(*entry), NULL))) {
257  ast_copy_string(entry->name, inter.faces[j], sizeof(entry->name));
258  ao2_link(grhead->entries, entry);
259  ao2_ref(entry, -1);
260  } else {
261  ast_log(LOG_WARNING, "Unable to add '%s' to dialgroup '%s'\n", inter.faces[j], grhead->name);
262  }
263  }
264  } else if (strncasecmp(args.op, "del", 3) == 0) {
265  for (j = 0; j < inter.argc; j++) {
266  if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK))) {
267  ao2_ref(entry, -1);
268  } else {
269  ast_log(LOG_WARNING, "Interface '%s' not found in dialgroup '%s'\n", inter.faces[j], grhead->name);
270  }
271  }
272  } else {
273  ast_log(LOG_ERROR, "Unrecognized operation: %s\n", args.op);
274  needrefresh = 0;
275  }
276  ao2_ref(grhead, -1);
277 
278  if (needrefresh) {
279  dialgroup_refreshdb(chan, args.group);
280  }
281 
282  return 0;
283 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct ao2_container * group_container
#define ast_log
Definition: astobj2.c:42
char name[AST_CHANNEL_NAME]
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
char name[AST_MAX_EXTENSION]
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static int entry_hash_fn(const void *obj, const int flags)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int entry_cmp_fn(void *obj1, void *name2, int flags)
static int dialgroup_refreshdb(struct ast_channel *chan, const char *cdialgroup)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static void group_destroy(void *vgroup)
Definition: search.h:40
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
struct ao2_container * entries
#define AST_APP_ARG(name)
Define an application argument.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ entry_cmp_fn()

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

Definition at line 117 of file func_dialgroup.c.

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

Referenced by dialgroup_write().

118 {
119  struct group_entry *e1 = obj1, *e2 = name2;
120  char *name = name2;
121  if (flags & OBJ_POINTER)
122  return strcmp(e1->name, e2->name) ? 0 : CMP_MATCH | CMP_STOP;
123  else
124  return strcmp(e1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
125 }
#define OBJ_POINTER
Definition: astobj2.h:1154
char name[AST_CHANNEL_NAME]
static const char name[]
Definition: cdr_mysql.c:74

◆ entry_hash_fn()

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

Definition at line 111 of file func_dialgroup.c.

References ast_str_hash(), and group_entry::name.

Referenced by dialgroup_write().

112 {
113  const struct group_entry *e = obj;
114  return ast_str_hash(e->name);
115 }
char name[AST_CHANNEL_NAME]
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ group_cmp_fn()

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

Definition at line 101 of file func_dialgroup.c.

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

Referenced by load_module().

102 {
103  struct group *g1 = obj1, *g2 = name2;
104  char *name = name2;
105  if (flags & OBJ_POINTER)
106  return strcmp(g1->name, g2->name) ? 0 : CMP_MATCH | CMP_STOP;
107  else
108  return strcmp(g1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
109 }
#define OBJ_POINTER
Definition: astobj2.h:1154
char name[AST_MAX_EXTENSION]
static const char name[]
Definition: cdr_mysql.c:74

◆ group_destroy()

static void group_destroy ( void *  vgroup)
static

Definition at line 89 of file func_dialgroup.c.

References ao2_ref, and group::entries.

Referenced by dialgroup_write().

90 {
91  struct group *group = vgroup;
92  ao2_ref(group->entries, -1);
93 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * entries

◆ group_hash_fn()

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

Definition at line 95 of file func_dialgroup.c.

References ast_str_hash(), and group::name.

Referenced by load_module().

96 {
97  const struct group *g = obj;
98  return ast_str_hash(g->name);
99 }
char name[AST_MAX_EXTENSION]
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ load_module()

static int load_module ( void  )
static

Definition at line 298 of file func_dialgroup.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, 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().

299 {
300  struct ast_db_entry *dbtree, *tmp;
301  char groupname[AST_MAX_EXTENSION], *ptr;
302 
305  if (group_container) {
306  /* Refresh groups from astdb */
307  if ((dbtree = ast_db_gettree("dialgroup", NULL))) {
308  for (tmp = dbtree; tmp; tmp = tmp->next) {
309  ast_copy_string(groupname, tmp->key, sizeof(groupname));
310  if ((ptr = strrchr(groupname, '/'))) {
311  ptr++;
312  dialgroup_write(NULL, "", ptr, tmp->data);
313  }
314  }
315  ast_db_freetree(dbtree);
316  }
318  } else {
320  }
321 }
static struct ast_custom_function dialgroup_function
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:598
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
static struct ao2_container * group_container
struct ast_db_entry * next
Definition: astdb.h:32
static int group_hash_fn(const void *obj, const int flags)
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:531
Definition: astdb.h:31
char data[0]
Definition: astdb.h:34
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int group_cmp_fn(void *obj1, void *name2, int flags)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data, const char *cvalue)
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
char * key
Definition: astdb.h:33

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 291 of file func_dialgroup.c.

References ao2_ref, and ast_custom_function_unregister().

292 {
295  return res;
296 }
static struct ast_custom_function dialgroup_function
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static struct ao2_container * group_container
#define ao2_ref(o, delta)
Definition: astobj2.h:464

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 323 of file func_dialgroup.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 323 of file func_dialgroup.c.

◆ dialgroup_function

struct ast_custom_function dialgroup_function
static
Initial value:
= {
.name = "DIALGROUP",
.read = dialgroup_read,
.write = dialgroup_write,
}
static int dialgroup_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data, const char *cvalue)

Definition at line 285 of file func_dialgroup.c.

◆ group_container

struct ao2_container* group_container = NULL
static

Definition at line 78 of file func_dialgroup.c.