Asterisk - The Open Source Telephony Project GIT-master-a358458
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 324 of file func_dialgroup.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 324 of file func_dialgroup.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

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

129{
130 struct ao2_iterator i;
131 struct group *grhead = ao2_find(group_container, data, 0);
132 struct group_entry *entry;
133 size_t bufused = 0;
134 int trunc_warning = 0;
135 int res = 0;
136
137 if (!grhead) {
138 if (!ast_strlen_zero(cmd)) {
139 ast_log(LOG_WARNING, "No such dialgroup '%s'\n", data);
140 }
141 return -1;
142 }
143
144 buf[0] = '\0';
145
146 i = ao2_iterator_init(grhead->entries, 0);
147 while ((entry = ao2_iterator_next(&i))) {
148 int tmp = strlen(entry->name);
149 /* Ensure that we copy only complete names, not partials */
150 if (len - bufused > tmp + 2) {
151 if (bufused != 0)
152 buf[bufused++] = '&';
153 ast_copy_string(buf + bufused, entry->name, len - bufused);
154 bufused += tmp;
155 } else if (trunc_warning++ == 0) {
156 if (!ast_strlen_zero(cmd)) {
157 ast_log(LOG_WARNING, "Dialgroup '%s' is too large. Truncating list.\n", data);
158 } else {
159 res = 1;
160 ao2_ref(entry, -1);
161 break;
162 }
163 }
164 ao2_ref(entry, -1);
165 }
167 ao2_ref(grhead, -1);
168
169 return res;
170}
#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.
static int tmp()
Definition: bt_open.c:389
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
Definition: search.h:40
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 tmp().

Referenced by dialgroup_refreshdb().

◆ dialgroup_refreshdb()

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

Definition at line 172 of file func_dialgroup.c.

173{
174 int len = 500, res = 0;
175 char *buf = NULL;
176 char *new_buf;
177 char *dialgroup = ast_strdupa(cdialgroup);
178
179 do {
180 len *= 2;
181 new_buf = ast_realloc(buf, len);
182 if (!new_buf) {
183 ast_free(buf);
184 return -1;
185 }
186 buf = new_buf;
187
188 if ((res = dialgroup_read(chan, "", dialgroup, buf, len)) < 0) {
189 ast_free(buf);
190 return -1;
191 }
192 } while (res == 1);
193
194 if (ast_strlen_zero(buf)) {
195 ast_db_del("dialgroup", cdialgroup);
196 } else {
197 ast_db_put("dialgroup", cdialgroup, buf);
198 }
199 ast_free(buf);
200 return 0;
201}
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:342
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
#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 203 of file func_dialgroup.c.

204{
205 struct group *grhead;
206 struct group_entry *entry;
207 int j, needrefresh = 1;
210 AST_APP_ARG(op);
211 );
213 AST_APP_ARG(faces)[100];
214 );
215 char *value = ast_strdupa(cvalue);
216
218 AST_NONSTANDARD_APP_ARGS(inter, value, '&');
219
220 if (!(grhead = ao2_find(group_container, args.group, 0))) {
221 /* Create group */
222 grhead = ao2_alloc(sizeof(*grhead), group_destroy);
223 if (!grhead)
224 return -1;
227 if (!grhead->entries) {
228 ao2_ref(grhead, -1);
229 return -1;
230 }
231 ast_copy_string(grhead->name, args.group, sizeof(grhead->name));
232 ao2_link(group_container, grhead);
233 }
234
235 if (ast_strlen_zero(args.op)) {
236 /* Wholesale replacement of the group */
237 args.op = "add";
238
239 /* Remove all existing */
240 ao2_ref(grhead->entries, -1);
243 if (!grhead->entries) {
245 ao2_ref(grhead, -1);
246 return -1;
247 }
248 }
249
250 if (strcasecmp(args.op, "add") == 0) {
251 for (j = 0; j < inter.argc; j++) {
252 /* Eliminate duplicates */
253 if ((entry = ao2_find(grhead->entries, inter.faces[j], 0))) {
254 ao2_ref(entry, -1);
255 continue;
256 }
257 if ((entry = ao2_alloc(sizeof(*entry), NULL))) {
258 ast_copy_string(entry->name, inter.faces[j], sizeof(entry->name));
259 ao2_link(grhead->entries, entry);
260 ao2_ref(entry, -1);
261 } else {
262 ast_log(LOG_WARNING, "Unable to add '%s' to dialgroup '%s'\n", inter.faces[j], grhead->name);
263 }
264 }
265 } else if (strncasecmp(args.op, "del", 3) == 0) {
266 for (j = 0; j < inter.argc; j++) {
267 if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK))) {
268 ao2_ref(entry, -1);
269 } else {
270 ast_log(LOG_WARNING, "Interface '%s' not found in dialgroup '%s'\n", inter.faces[j], grhead->name);
271 }
272 }
273 } else {
274 ast_log(LOG_ERROR, "Unrecognized operation: %s\n", args.op);
275 needrefresh = 0;
276 }
277 ao2_ref(grhead, -1);
278
279 if (needrefresh) {
280 dialgroup_refreshdb(chan, args.group);
281 }
282
283 return 0;
284}
#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::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 118 of file func_dialgroup.c.

119{
120 struct group_entry *e1 = obj1, *e2 = name2;
121 char *name = name2;
122 if (flags & OBJ_POINTER)
123 return strcmp(e1->name, e2->name) ? 0 : CMP_MATCH | CMP_STOP;
124 else
125 return strcmp(e1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
126}
@ 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
char name[AST_CHANNEL_NAME]

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

113{
114 const struct group_entry *e = obj;
115 return ast_str_hash(e->name);
116}
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 102 of file func_dialgroup.c.

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

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

91{
92 struct group *group = vgroup;
93 ao2_ref(group->entries, -1);
94}

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

97{
98 const struct group *g = obj;
99 return ast_str_hash(g->name);
100}

References ast_str_hash(), and group::name.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 299 of file func_dialgroup.c.

300{
301 struct ast_db_entry *dbtree, *tmp;
302 char groupname[AST_MAX_EXTENSION], *ptr;
303
306 if (group_container) {
307 /* Refresh groups from astdb */
308 if ((dbtree = ast_db_gettree("dialgroup", NULL))) {
309 for (tmp = dbtree; tmp; tmp = tmp->next) {
310 ast_copy_string(groupname, tmp->key, sizeof(groupname));
311 if ((ptr = strrchr(groupname, '/'))) {
312 ptr++;
313 dialgroup_write(NULL, "", ptr, tmp->data);
314 }
315 }
316 ast_db_freetree(dbtree);
317 }
319 } else {
321 }
322}
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:610
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:677
#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:1558
Definition: astdb.h:31

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, dialgroup_function, dialgroup_write(), group_cmp_fn(), group_container, group_hash_fn(), NULL, and tmp().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 292 of file func_dialgroup.c.

293{
296 return res;
297}
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 324 of file func_dialgroup.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

Referenced by load_module(), and unload_module().

◆ group_container

struct ao2_container* group_container = NULL
static