Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 = AST_BUILDOPT_SUM, .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 327 of file func_dialgroup.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 327 of file func_dialgroup.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 327 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 131 of file func_dialgroup.c.

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

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

Referenced by dialgroup_refreshdb().

◆ dialgroup_refreshdb()

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

Definition at line 175 of file func_dialgroup.c.

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

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().

◆ dialgroup_write()

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

Definition at line 206 of file func_dialgroup.c.

207{
208 struct group *grhead;
209 struct group_entry *entry;
210 int j, needrefresh = 1;
213 AST_APP_ARG(op);
214 );
216 AST_APP_ARG(faces)[100];
217 );
218 char *value = ast_strdupa(cvalue);
219
221 AST_NONSTANDARD_APP_ARGS(inter, value, '&');
222
223 if (!(grhead = ao2_find(group_container, args.group, 0))) {
224 /* Create group */
225 grhead = ao2_alloc(sizeof(*grhead), group_destroy);
226 if (!grhead)
227 return -1;
230 if (!grhead->entries) {
231 ao2_ref(grhead, -1);
232 return -1;
233 }
234 ast_copy_string(grhead->name, args.group, sizeof(grhead->name));
235 ao2_link(group_container, grhead);
236 }
237
238 if (ast_strlen_zero(args.op)) {
239 /* Wholesale replacement of the group */
240 args.op = "add";
241
242 /* Remove all existing */
243 ao2_ref(grhead->entries, -1);
246 if (!grhead->entries) {
248 ao2_ref(grhead, -1);
249 return -1;
250 }
251 }
252
253 if (strcasecmp(args.op, "add") == 0) {
254 for (j = 0; j < inter.argc; j++) {
255 /* Eliminate duplicates */
256 if ((entry = ao2_find(grhead->entries, inter.faces[j], 0))) {
257 ao2_ref(entry, -1);
258 continue;
259 }
260 if ((entry = ao2_alloc(sizeof(*entry), NULL))) {
261 ast_copy_string(entry->name, inter.faces[j], sizeof(entry->name));
262 ao2_link(grhead->entries, entry);
263 ao2_ref(entry, -1);
264 } else {
265 ast_log(LOG_WARNING, "Unable to add '%s' to dialgroup '%s'\n", inter.faces[j], grhead->name);
266 }
267 }
268 } else if (strncasecmp(args.op, "del", 3) == 0) {
269 for (j = 0; j < inter.argc; j++) {
270 if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK))) {
271 ao2_ref(entry, -1);
272 } else {
273 ast_log(LOG_WARNING, "Interface '%s' not found in dialgroup '%s'\n", inter.faces[j], grhead->name);
274 }
275 }
276 } else {
277 ast_log(LOG_ERROR, "Unrecognized operation: %s\n", args.op);
278 needrefresh = 0;
279 }
280 ao2_ref(grhead, -1);
281
282 if (needrefresh) {
283 dialgroup_refreshdb(chan, args.group);
284 }
285
286 return 0;
287}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static int entry_cmp_fn(void *obj1, void *name2, int flags)
static int dialgroup_refreshdb(struct ast_channel *chan, const char *cdialgroup)
static int entry_hash_fn(const void *obj, const int flags)
static void group_destroy(void *vgroup)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define LOG_ERROR
char name[AST_MAX_EXTENSION]
int value
Definition: syslog.c:37
const char * args

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_container, group_destroy(), LOG_ERROR, LOG_WARNING, group_entry::name, group::name, NULL, OBJ_UNLINK, and value.

Referenced by load_module().

◆ entry_cmp_fn()

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

Definition at line 121 of file func_dialgroup.c.

122{
123 struct group_entry *e1 = obj1, *e2 = name2;
124 char *name = name2;
125 if (flags & OBJ_POINTER)
126 return strcmp(e1->name, e2->name) ? 0 : CMP_MATCH | CMP_STOP;
127 else
128 return strcmp(e1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
129}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_POINTER
Definition: astobj2.h:1150
static const char name[]
Definition: format_mp3.c:68

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

Referenced by dialgroup_write().

◆ entry_hash_fn()

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

Definition at line 115 of file func_dialgroup.c.

116{
117 const struct group_entry *e = obj;
118 return ast_str_hash(e->name);
119}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259

References ast_str_hash(), and group_entry::name.

Referenced by dialgroup_write().

◆ group_cmp_fn()

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

Definition at line 105 of file func_dialgroup.c.

106{
107 struct group *g1 = obj1, *g2 = name2;
108 char *name = name2;
109 if (flags & OBJ_POINTER)
110 return strcmp(g1->name, g2->name) ? 0 : CMP_MATCH | CMP_STOP;
111 else
112 return strcmp(g1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
113}

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

Referenced by load_module().

◆ group_destroy()

static void group_destroy ( void *  vgroup)
static

Definition at line 93 of file func_dialgroup.c.

94{
95 struct group *group = vgroup;
96 ao2_ref(group->entries, -1);
97}

References ao2_ref, and group::entries.

Referenced by dialgroup_write().

◆ group_hash_fn()

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

Definition at line 99 of file func_dialgroup.c.

100{
101 const struct group *g = obj;
102 return ast_str_hash(g->name);
103}

References ast_str_hash(), and group::name.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 302 of file func_dialgroup.c.

303{
304 struct ast_db_entry *dbtree, *tmp;
305 char groupname[AST_MAX_EXTENSION], *ptr;
306
309 if (group_container) {
310 /* Refresh groups from astdb */
311 if ((dbtree = ast_db_gettree("dialgroup", NULL))) {
312 for (tmp = dbtree; tmp; tmp = tmp->next) {
313 ast_copy_string(groupname, tmp->key, sizeof(groupname));
314 if ((ptr = strrchr(groupname, '/'))) {
315 ptr++;
316 dialgroup_write(NULL, "", ptr, tmp->data);
317 }
318 }
319 ast_db_freetree(dbtree);
320 }
322 } else {
324 }
325}
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: db.c:635
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: db.c:695
#define AST_MAX_EXTENSION
Definition: channel.h:134
static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data, const char *cvalue)
static struct ast_custom_function dialgroup_function
static int group_cmp_fn(void *obj1, void *name2, int flags)
static int group_hash_fn(const void *obj, const int flags)
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
char data[0]
Definition: astdb.h:34

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_function, dialgroup_write(), group_cmp_fn(), group_container, group_hash_fn(), ast_db_entry::key, ast_db_entry::next, and NULL.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 295 of file func_dialgroup.c.

296{
299 return res;
300}
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

References ao2_ref, ast_custom_function_unregister(), dialgroup_function, and group_container.

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

Definition at line 327 of file func_dialgroup.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 327 of file func_dialgroup.c.

◆ dialgroup_function

struct ast_custom_function dialgroup_function
static
Initial value:
= {
.name = "DIALGROUP",
.read = dialgroup_read,
.write = dialgroup_write,
}

Definition at line 289 of file func_dialgroup.c.

Referenced by load_module(), and unload_module().

◆ group_container

struct ao2_container* group_container = NULL
static