Asterisk - The Open Source Telephony Project  18.5.0
func_groupcount.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16 
17 /*! \file
18  *
19  * \brief Channel group related dialplan functions
20  *
21  * \ingroup functions
22  */
23 
24 /*** MODULEINFO
25  <support_level>core</support_level>
26  ***/
27 
28 #include "asterisk.h"
29 
30 #include "asterisk/module.h"
31 #include "asterisk/channel.h"
32 #include "asterisk/pbx.h"
33 #include "asterisk/utils.h"
34 #include "asterisk/app.h"
35 
36 /*** DOCUMENTATION
37  <function name="GROUP_COUNT" language="en_US">
38  <synopsis>
39  Counts the number of channels in the specified group.
40  </synopsis>
41  <syntax argsep="@">
42  <parameter name="groupname">
43  <para>Group name.</para>
44  </parameter>
45  <parameter name="category">
46  <para>Category name</para>
47  </parameter>
48  </syntax>
49  <description>
50  <para>Calculates the group count for the specified group, or uses the
51  channel's current group if not specified (and non-empty).</para>
52  </description>
53  </function>
54  <function name="GROUP_MATCH_COUNT" language="en_US">
55  <synopsis>
56  Counts the number of channels in the groups matching the specified pattern.
57  </synopsis>
58  <syntax argsep="@">
59  <parameter name="groupmatch" required="true">
60  <para>A standard regular expression used to match a group name.</para>
61  </parameter>
62  <parameter name="category">
63  <para>A standard regular expression used to match a category name.</para>
64  </parameter>
65  </syntax>
66  <description>
67  <para>Calculates the group count for all groups that match the specified pattern.
68  Note: category matching is applied after matching based on group.
69  Uses standard regular expression matching on both (see regex(7)).</para>
70  </description>
71  </function>
72  <function name="GROUP" language="en_US">
73  <synopsis>
74  Gets or sets the channel group.
75  </synopsis>
76  <syntax>
77  <parameter name="category">
78  <para>Category name.</para>
79  </parameter>
80  </syntax>
81  <description>
82  <para><replaceable>category</replaceable> can be employed for more fine grained group management. Each channel
83  can only be member of exactly one group per <replaceable>category</replaceable>.</para>
84  </description>
85  </function>
86  <function name="GROUP_LIST" language="en_US">
87  <synopsis>
88  Gets a list of the groups set on a channel.
89  </synopsis>
90  <syntax />
91  <description>
92  <para>Gets a list of the groups set on a channel.</para>
93  </description>
94  </function>
95 
96  ***/
97 
98 static int group_count_function_read(struct ast_channel *chan, const char *cmd,
99  char *data, char *buf, size_t len)
100 {
101  int ret = -1;
102  int count = -1;
103  char group[80] = "", category[80] = "";
104 
105  if (!chan) {
106  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
107  return -1;
108  }
109 
110  ast_app_group_split_group(data, group, sizeof(group), category,
111  sizeof(category));
112 
113  /* If no group has been provided let's find one */
114  if (ast_strlen_zero(group)) {
115  struct ast_group_info *gi = NULL;
116 
118  for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
119  if (gi->chan != chan)
120  continue;
121  if (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))
122  break;
123  }
124  if (gi) {
125  ast_copy_string(group, gi->group, sizeof(group));
126  if (!ast_strlen_zero(gi->category))
127  ast_copy_string(category, gi->category, sizeof(category));
128  }
130  }
131 
132  if ((count = ast_app_group_get_count(group, category)) == -1) {
133  ast_log(LOG_NOTICE, "No group could be found for channel '%s'\n", ast_channel_name(chan));
134  } else {
135  snprintf(buf, len, "%d", count);
136  ret = 0;
137  }
138 
139  return ret;
140 }
141 
143  .name = "GROUP_COUNT",
145  .read_max = 12,
146 };
147 
149  const char *cmd, char *data, char *buf,
150  size_t len)
151 {
152  char group[80] = "";
153  char category[80] = "";
154 
155  ast_app_group_split_group(data, group, sizeof(group), category,
156  sizeof(category));
157 
158  if (!ast_strlen_zero(group)) {
159  int count;
160  count = ast_app_group_match_get_count(group, category);
161  snprintf(buf, len, "%d", count);
162  return 0;
163  }
164 
165  return -1;
166 }
167 
169  .name = "GROUP_MATCH_COUNT",
171  .read_max = 12,
172  .write = NULL,
173 };
174 
175 static int group_function_read(struct ast_channel *chan, const char *cmd,
176  char *data, char *buf, size_t len)
177 {
178  int ret = -1;
179  struct ast_group_info *gi = NULL;
180 
181  if (!chan) {
182  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
183  return -1;
184  }
185 
187 
188  for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
189  if (gi->chan != chan)
190  continue;
191  if (ast_strlen_zero(data))
192  break;
193  if (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, data))
194  break;
195  }
196 
197  if (gi) {
198  ast_copy_string(buf, gi->group, len);
199  ret = 0;
200  }
201 
203 
204  return ret;
205 }
206 
207 static int group_function_write(struct ast_channel *chan, const char *cmd,
208  char *data, const char *value)
209 {
210  char grpcat[256];
211 
212  if (!chan) {
213  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
214  return -1;
215  }
216 
217  if (!value) {
218  return -1;
219  }
220 
221  if (!ast_strlen_zero(data)) {
222  snprintf(grpcat, sizeof(grpcat), "%s@%s", value, data);
223  } else {
224  ast_copy_string(grpcat, value, sizeof(grpcat));
225  }
226 
227  if (ast_app_group_set_channel(chan, grpcat))
229  "Setting a group requires an argument (group name)\n");
230 
231  return 0;
232 }
233 
235  .name = "GROUP",
236  .read = group_function_read,
237  .write = group_function_write,
238 };
239 
240 static int group_list_function_read(struct ast_channel *chan, const char *cmd,
241  char *data, char *buf, size_t len)
242 {
243  struct ast_group_info *gi = NULL;
244  char tmp1[1024] = "";
245  char tmp2[1024] = "";
246 
247  if (!chan)
248  return -1;
249 
251 
252  for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
253  if (gi->chan != chan)
254  continue;
255  if (!ast_strlen_zero(tmp1)) {
256  ast_copy_string(tmp2, tmp1, sizeof(tmp2));
257  if (!ast_strlen_zero(gi->category))
258  snprintf(tmp1, sizeof(tmp1), "%s %s@%s", tmp2, gi->group, gi->category);
259  else
260  snprintf(tmp1, sizeof(tmp1), "%s %s", tmp2, gi->group);
261  } else {
262  if (!ast_strlen_zero(gi->category))
263  snprintf(tmp1, sizeof(tmp1), "%s@%s", gi->group, gi->category);
264  else
265  snprintf(tmp1, sizeof(tmp1), "%s", gi->group);
266  }
267  }
268 
270 
271  ast_copy_string(buf, tmp1, len);
272 
273  return 0;
274 }
275 
277  .name = "GROUP_LIST",
278  .read = group_list_function_read,
279  .write = NULL,
280 };
281 
282 static int unload_module(void)
283 {
284  int res = 0;
285 
286  res |= ast_custom_function_unregister(&group_count_function);
287  res |= ast_custom_function_unregister(&group_match_count_function);
288  res |= ast_custom_function_unregister(&group_list_function);
289  res |= ast_custom_function_unregister(&group_function);
290 
291  return res;
292 }
293 
294 static int load_module(void)
295 {
296  int res = 0;
297 
298  res |= ast_custom_function_register(&group_count_function);
299  res |= ast_custom_function_register(&group_match_count_function);
300  res |= ast_custom_function_register(&group_list_function);
301  res |= ast_custom_function_register(&group_function);
302 
303  return res;
304 }
305 
306 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel group dialplan functions");
const char * name
Definition: pbx.h:119
Main Channel structure associated with a channel.
channel group info
Definition: channel.h:2938
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
struct ast_group_info * ast_app_group_list_head(void)
Get the head of the group count list.
Definition: main/app.c:2189
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
static struct ast_custom_function group_count_function
static struct ast_custom_function group_match_count_function
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
static struct ast_custom_function group_function
static int group_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
static struct ast_custom_function group_list_function
static int group_function_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
static int group_match_count_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
char * group
Definition: channel.h:2941
Core PBX routines and definitions.
struct ast_channel * chan
Definition: channel.h:2939
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int unload_module(void)
#define LOG_NOTICE
Definition: logger.h:263
int ast_app_group_list_unlock(void)
Unlock the group count list.
Definition: main/app.c:2194
static int load_module(void)
int ast_app_group_split_group(const char *data, char *group, int group_max, char *category, int category_max)
Split a group string into group and category, returning a default category if none is provided...
Definition: main/app.c:2009
int ast_app_group_match_get_count(const char *groupmatch, const char *category)
Get the current channel count of all groups that match the specified pattern and category.
Definition: main/app.c:2103
char * category
Definition: channel.h:2940
int ast_app_group_list_rdlock(void)
Read Lock the group count list.
Definition: main/app.c:2184
static int group_list_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_group_info::@248 group_list
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static int group_count_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
Set the group for a channel, splitting the provided data into group and category, if specified...
Definition: main/app.c:2036
int ast_app_group_get_count(const char *group, const char *category)
Get the current channel count of the specified group and category.
Definition: main/app.c:2083