SIP channel name uniqueness
[asterisk/asterisk.git] / funcs / func_groupcount.c
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 #include "asterisk.h"
25
26 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
27
28 #include "asterisk/module.h"
29 #include "asterisk/channel.h"
30 #include "asterisk/pbx.h"
31 #include "asterisk/utils.h"
32 #include "asterisk/app.h"
33
34 /*** DOCUMENTATION
35         <function name="GROUP_COUNT" language="en_US">
36                 <synopsis>
37                         Counts the number of channels in the specified group.
38                 </synopsis>
39                 <syntax argsep="@">
40                         <parameter name="groupname">
41                                 <para>Group name.</para>
42                         </parameter>
43                         <parameter name="category">
44                                 <para>Category name</para>
45                         </parameter>
46                 </syntax>
47                 <description>
48                         <para>Calculates the group count for the specified group, or uses the
49                         channel's current group if not specifed (and non-empty).</para>
50                 </description>
51         </function>
52         <function name="GROUP_MATCH_COUNT" language="en_US">
53                 <synopsis>
54                         Counts the number of channels in the groups matching the specified pattern.
55                 </synopsis>
56                 <syntax argsep="@">
57                         <parameter name="groupmatch" required="true">
58                                 <para>A standard regular expression used to match a group name.</para>
59                         </parameter>
60                         <parameter name="category">
61                                 <para>Category name.</para>
62                         </parameter>
63                 </syntax>
64                 <description>
65                         <para>Calculates the group count for all groups that match the specified pattern.
66                         Uses standard regular expression matching (see regex(7)).</para>
67                 </description>
68         </function>
69         <function name="GROUP" language="en_US">
70                 <synopsis>
71                         Gets or sets the channel group.
72                 </synopsis>
73                 <syntax>
74                         <parameter name="category">
75                                 <para>Category name.</para>
76                         </parameter>
77                 </syntax>
78                 <description>
79                         <para><replaceable>category</replaceable> can be employed for more fine grained group management. Each channel 
80                         can only be member of exactly one group per <replaceable>category</replaceable>.</para>
81                 </description>
82         </function>
83         <function name="GROUP_LIST" language="en_US">
84                 <synopsis>
85                         Gets a list of the groups set on a channel.
86                 </synopsis>
87                 <syntax />
88                 <description>
89                         <para>Gets a list of the groups set on a channel.</para>
90                 </description>
91         </function>
92
93  ***/
94
95 static int group_count_function_read(struct ast_channel *chan, const char *cmd,
96                                      char *data, char *buf, size_t len)
97 {
98         int ret = -1;
99         int count = -1;
100         char group[80] = "", category[80] = "";
101
102         ast_app_group_split_group(data, group, sizeof(group), category,
103                                   sizeof(category));
104
105         /* If no group has been provided let's find one */
106         if (ast_strlen_zero(group)) {
107                 struct ast_group_info *gi = NULL;
108
109                 ast_app_group_list_rdlock();
110                 for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
111                         if (gi->chan != chan)
112                                 continue;
113                         if (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))
114                                 break;
115                 }
116                 if (gi) {
117                         ast_copy_string(group, gi->group, sizeof(group));
118                         if (!ast_strlen_zero(gi->category))
119                                 ast_copy_string(category, gi->category, sizeof(category));
120                 }
121                 ast_app_group_list_unlock();
122         }
123
124         if ((count = ast_app_group_get_count(group, category)) == -1) {
125                 ast_log(LOG_NOTICE, "No group could be found for channel '%s'\n", chan->name);
126         } else {
127                 snprintf(buf, len, "%d", count);
128                 ret = 0;
129         }
130
131         return ret;
132 }
133
134 static struct ast_custom_function group_count_function = {
135         .name = "GROUP_COUNT",
136         .read = group_count_function_read,
137         .read_max = 12,
138 };
139
140 static int group_match_count_function_read(struct ast_channel *chan,
141                                            const char *cmd, char *data, char *buf,
142                                            size_t len)
143 {
144         int count;
145         char group[80] = "";
146         char category[80] = "";
147
148         ast_app_group_split_group(data, group, sizeof(group), category,
149                                   sizeof(category));
150
151         if (!ast_strlen_zero(group)) {
152                 count = ast_app_group_match_get_count(group, category);
153                 snprintf(buf, len, "%d", count);
154                 return 0;
155         }
156
157         return -1;
158 }
159
160 static struct ast_custom_function group_match_count_function = {
161         .name = "GROUP_MATCH_COUNT",
162         .read = group_match_count_function_read,
163         .read_max = 12,
164         .write = NULL,
165 };
166
167 static int group_function_read(struct ast_channel *chan, const char *cmd,
168                                char *data, char *buf, size_t len)
169 {
170         int ret = -1;
171         struct ast_group_info *gi = NULL;
172         
173         ast_app_group_list_rdlock();
174         
175         for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
176                 if (gi->chan != chan)
177                         continue;
178                 if (ast_strlen_zero(data))
179                         break;
180                 if (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, data))
181                         break;
182         }
183         
184         if (gi) {
185                 ast_copy_string(buf, gi->group, len);
186                 ret = 0;
187         }
188         
189         ast_app_group_list_unlock();
190         
191         return ret;
192 }
193
194 static int group_function_write(struct ast_channel *chan, const char *cmd,
195                                 char *data, const char *value)
196 {
197         char grpcat[256];
198
199         if (!ast_strlen_zero(data)) {
200                 snprintf(grpcat, sizeof(grpcat), "%s@%s", value, data);
201         } else {
202                 ast_copy_string(grpcat, value, sizeof(grpcat));
203         }
204
205         if (ast_app_group_set_channel(chan, grpcat))
206                 ast_log(LOG_WARNING,
207                                 "Setting a group requires an argument (group name)\n");
208
209         return 0;
210 }
211
212 static struct ast_custom_function group_function = {
213         .name = "GROUP",
214         .read = group_function_read,
215         .write = group_function_write,
216 };
217
218 static int group_list_function_read(struct ast_channel *chan, const char *cmd,
219                                     char *data, char *buf, size_t len)
220 {
221         struct ast_group_info *gi = NULL;
222         char tmp1[1024] = "";
223         char tmp2[1024] = "";
224
225         if (!chan)
226                 return -1;
227
228         ast_app_group_list_rdlock();
229
230         for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
231                 if (gi->chan != chan)
232                         continue;
233                 if (!ast_strlen_zero(tmp1)) {
234                         ast_copy_string(tmp2, tmp1, sizeof(tmp2));
235                         if (!ast_strlen_zero(gi->category))
236                                 snprintf(tmp1, sizeof(tmp1), "%s %s@%s", tmp2, gi->group, gi->category);
237                         else
238                                 snprintf(tmp1, sizeof(tmp1), "%s %s", tmp2, gi->group);
239                 } else {
240                         if (!ast_strlen_zero(gi->category))
241                                 snprintf(tmp1, sizeof(tmp1), "%s@%s", gi->group, gi->category);
242                         else
243                                 snprintf(tmp1, sizeof(tmp1), "%s", gi->group);
244                 }
245         }
246         
247         ast_app_group_list_unlock();
248
249         ast_copy_string(buf, tmp1, len);
250
251         return 0;
252 }
253
254 static struct ast_custom_function group_list_function = {
255         .name = "GROUP_LIST",
256         .read = group_list_function_read,
257         .write = NULL,
258 };
259
260 static int unload_module(void)
261 {
262         int res = 0;
263
264         res |= ast_custom_function_unregister(&group_count_function);
265         res |= ast_custom_function_unregister(&group_match_count_function);
266         res |= ast_custom_function_unregister(&group_list_function);
267         res |= ast_custom_function_unregister(&group_function);
268
269         return res;
270 }
271
272 static int load_module(void)
273 {
274         int res = 0;
275
276         res |= ast_custom_function_register(&group_count_function);
277         res |= ast_custom_function_register(&group_match_count_function);
278         res |= ast_custom_function_register(&group_list_function);
279         res |= ast_custom_function_register(&group_function);
280
281         return res;
282 }
283
284 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel group dialplan functions");