func_channel: Read/Write after_bridge_goto option
[asterisk/asterisk.git] / funcs / func_channel.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 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 info dialplan functions
20  *
21  * \author Kevin P. Fleming <kpfleming@digium.com>
22  * \author Ben Winslow
23  * 
24  * \ingroup functions
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include <regex.h>
36 #include <ctype.h>
37
38 #include "asterisk/module.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/bridging.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/utils.h"
43 #include "asterisk/app.h"
44 #include "asterisk/indications.h"
45 #include "asterisk/stringfields.h"
46 #include "asterisk/global_datastores.h"
47
48 /*** DOCUMENTATION
49         <function name="CHANNELS" language="en_US">
50                 <synopsis>
51                         Gets the list of channels, optionally filtering by a regular expression.
52                 </synopsis>
53                 <syntax>
54                         <parameter name="regular_expression" />
55                 </syntax>
56                 <description>
57                         <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
58                         no argument is provided, all known channels are returned. The
59                         <replaceable>regular_expression</replaceable> must correspond to
60                         the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
61                         will be space-delimited.</para>
62                 </description>
63         </function>
64         <function name="MASTER_CHANNEL" language="en_US">
65                 <synopsis>
66                         Gets or sets variables on the master channel
67                 </synopsis>
68                 <description>
69                         <para>Allows access to the channel which created the current channel, if any.  If the channel is already
70                         a master channel, then accesses local channel variables.</para>
71                 </description>
72         </function>
73         <function name="CHANNEL" language="en_US">
74                 <synopsis>
75                         Gets/sets various pieces of information about the channel.
76                 </synopsis>
77                 <syntax>
78                         <parameter name="item" required="true">
79                                 <para>Standard items (provided by all channel technologies) are:</para>
80                                 <enumlist>
81                                         <enum name="amaflags">
82                                                 <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
83                                                 When read from a channel, the integer value will always be returned.
84                                                 When written to a channel, both the string format or integer value
85                                                 is accepted.</para>
86                                                 <enumlist>
87                                                         <enum name="1"><para><literal>OMIT</literal></para></enum>
88                                                         <enum name="2"><para><literal>BILLING</literal></para></enum>
89                                                         <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
90                                                 </enumlist>
91                                         </enum>
92                                         <enum name="accountcode">
93                                                 <para>R/W the channel's account code.</para>
94                                         </enum>
95                                         <enum name="audioreadformat">
96                                                 <para>R/O format currently being read.</para>
97                                         </enum>
98                                         <enum name="audionativeformat">
99                                                 <para>R/O format used natively for audio.</para>
100                                         </enum>
101                                         <enum name="audiowriteformat">
102                                                 <para>R/O format currently being written.</para>
103                                         </enum>
104                                         <enum name="callgroup">
105                                                 <para>R/W numeric call pickup groups that this channel is a member.</para>
106                                         </enum>
107                                         <enum name="pickupgroup">
108                                                 <para>R/W numeric call pickup groups this channel can pickup.</para>
109                                         </enum>
110                                         <enum name="namedcallgroup">
111                                                 <para>R/W named call pickup groups that this channel is a member.</para>
112                                         </enum>
113                                         <enum name="namedpickupgroup">
114                                                 <para>R/W named call pickup groups this channel can pickup.</para>
115                                         </enum>
116                                         <enum name="channeltype">
117                                                 <para>R/O technology used for channel.</para>
118                                         </enum>
119                                         <enum name="checkhangup">
120                                                 <para>R/O Whether the channel is hanging up (1/0)</para>
121                                         </enum>
122                                         <enum name="after_bridge_goto">
123                                                 <para>R/W the parseable goto string indicating where the channel is
124                                                 expected to return to in the PBX after exiting the next bridge it joins
125                                                 on the condition that it doesn't hang up. The parseable goto string uses
126                                                 the same syntax as the <literal>Goto</literal> application.</para>
127                                         </enum>
128                                         <enum name="hangup_handler_pop">
129                                                 <para>W/O Replace the most recently added hangup handler
130                                                 with a new hangup handler on the channel if supplied.  The
131                                                 assigned string is passed to the Gosub application when
132                                                 the channel is hung up.  Any optionally omitted context
133                                                 and exten are supplied by the channel pushing the handler
134                                                 before it is pushed.</para>
135                                         </enum>
136                                         <enum name="hangup_handler_push">
137                                                 <para>W/O Push a hangup handler onto the channel hangup
138                                                 handler stack.  The assigned string is passed to the
139                                                 Gosub application when the channel is hung up.  Any
140                                                 optionally omitted context and exten are supplied by the
141                                                 channel pushing the handler before it is pushed.</para>
142                                         </enum>
143                                         <enum name="hangup_handler_wipe">
144                                                 <para>W/O Wipe the entire hangup handler stack and replace
145                                                 with a new hangup handler on the channel if supplied.  The
146                                                 assigned string is passed to the Gosub application when
147                                                 the channel is hung up.  Any optionally omitted context
148                                                 and exten are supplied by the channel pushing the handler
149                                                 before it is pushed.</para>
150                                         </enum>
151                                         <enum name="language">
152                                                 <para>R/W language for sounds played.</para>
153                                         </enum>
154                                         <enum name="musicclass">
155                                                 <para>R/W class (from musiconhold.conf) for hold music.</para>
156                                         </enum>
157                                         <enum name="name">
158                                                 <para>The name of the channel</para>
159                                         </enum>
160                                         <enum name="parkinglot">
161                                                 <para>R/W parkinglot for parking.</para>
162                                         </enum>
163                                         <enum name="rxgain">
164                                                 <para>R/W set rxgain level on channel drivers that support it.</para>
165                                         </enum>
166                                         <enum name="secure_bridge_signaling">
167                                                 <para>Whether or not channels bridged to this channel require secure signaling</para>
168                                         </enum>
169                                         <enum name="secure_bridge_media">
170                                                 <para>Whether or not channels bridged to this channel require secure media</para>
171                                         </enum>
172                                         <enum name="state">
173                                                 <para>R/O state for channel</para>
174                                         </enum>
175                                         <enum name="tonezone">
176                                                 <para>R/W zone for indications played</para>
177                                         </enum>
178                                         <enum name="transfercapability">
179                                                 <para>R/W ISDN Transfer Capability, one of:</para>
180                                                 <enumlist>
181                                                         <enum name="SPEECH" />
182                                                         <enum name="DIGITAL" />
183                                                         <enum name="RESTRICTED_DIGITAL" />
184                                                         <enum name="3K1AUDIO" />
185                                                         <enum name="DIGITAL_W_TONES" />
186                                                         <enum name="VIDEO" />
187                                                 </enumlist>
188                                         </enum>
189                                         <enum name="txgain">
190                                                 <para>R/W set txgain level on channel drivers that support it.</para>
191                                         </enum>
192                                         <enum name="videonativeformat">
193                                                 <para>R/O format used natively for video</para>
194                                         </enum>
195                                         <enum name="trace">
196                                                 <para>R/W whether or not context tracing is enabled, only available
197                                                 <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
198                                         </enum>
199                                 </enumlist>
200                                 <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
201                                 <enumlist>
202                                         <enum name="peerip">
203                                                 <para>R/O Get the IP address of the peer.</para>
204                                         </enum>
205                                         <enum name="recvip">
206                                                 <para>R/O Get the source IP address of the peer.</para>
207                                         </enum>
208                                         <enum name="from">
209                                                 <para>R/O Get the URI from the From: header.</para>
210                                         </enum>
211                                         <enum name="uri">
212                                                 <para>R/O Get the URI from the Contact: header.</para>
213                                         </enum>
214                                         <enum name="useragent">
215                                                 <para>R/O Get the useragent.</para>
216                                         </enum>
217                                         <enum name="peername">
218                                                 <para>R/O Get the name of the peer.</para>
219                                         </enum>
220                                         <enum name="t38passthrough">
221                                                 <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
222                                                 otherwise <literal>0</literal></para>
223                                         </enum>
224                                         <enum name="rtpqos">
225                                                 <para>R/O Get QOS information about the RTP stream</para>
226                                                 <para>    This option takes two additional arguments:</para>
227                                                 <para>    Argument 1:</para>
228                                                 <para>     <literal>audio</literal>             Get data about the audio stream</para>
229                                                 <para>     <literal>video</literal>             Get data about the video stream</para>
230                                                 <para>     <literal>text</literal>              Get data about the text stream</para>
231                                                 <para>    Argument 2:</para>
232                                                 <para>     <literal>local_ssrc</literal>        Local SSRC (stream ID)</para>
233                                                 <para>     <literal>local_lostpackets</literal> Local lost packets</para>
234                                                 <para>     <literal>local_jitter</literal>      Local calculated jitter</para>
235                                                 <para>     <literal>local_maxjitter</literal>   Local calculated jitter (maximum)</para>
236                                                 <para>     <literal>local_minjitter</literal>   Local calculated jitter (minimum)</para>
237                                                 <para>     <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
238                                                 <para>     <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
239                                                 <para>     <literal>local_count</literal>       Number of received packets</para>
240                                                 <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
241                                                 <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
242                                                 <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
243                                                 <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
244                                                 <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
245                                                 <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
246                                                 <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
247                                                 <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
248                                                 <para>     <literal>rtt</literal>               Round trip time</para>
249                                                 <para>     <literal>maxrtt</literal>            Round trip time (maximum)</para>
250                                                 <para>     <literal>minrtt</literal>            Round trip time (minimum)</para>
251                                                 <para>     <literal>normdevrtt</literal>        Round trip time (normal deviation)</para>
252                                                 <para>     <literal>stdevrtt</literal>          Round trip time (standard deviation)</para>
253                                                 <para>     <literal>all</literal>               All statistics (in a form suited to logging,
254                                                 but not for parsing)</para>
255                                         </enum>
256                                         <enum name="rtpdest">
257                                                 <para>R/O Get remote RTP destination information.</para>
258                                                 <para>   This option takes one additional argument:</para>
259                                                 <para>    Argument 1:</para>
260                                                 <para>     <literal>audio</literal>             Get audio destination</para>
261                                                 <para>     <literal>video</literal>             Get video destination</para>
262                                                 <para>     <literal>text</literal>              Get text destination</para>
263                                         </enum>
264                                 </enumlist>
265                                 <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
266                                 <enumlist>
267                                         <enum name="peerip">
268                                                 <para>R/O Get the peer's ip address.</para>
269                                         </enum>
270                                         <enum name="peername">
271                                                 <para>R/O Get the peer's username.</para>
272                                         </enum>
273                                 </enumlist>
274                                 <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
275                                 <enumlist>
276                                         <enum name="dahdi_channel">
277                                                 <para>R/O DAHDI channel related to this channel.</para>
278                                         </enum>
279                                         <enum name="dahdi_span">
280                                                 <para>R/O DAHDI span related to this channel.</para>
281                                         </enum>
282                                         <enum name="dahdi_type">
283                                                 <para>R/O DAHDI channel type, one of:</para>
284                                                 <enumlist>
285                                                         <enum name="analog" />
286                                                         <enum name="mfc/r2" />
287                                                         <enum name="pri" />
288                                                         <enum name="pseudo" />
289                                                         <enum name="ss7" />
290                                                 </enumlist>
291                                         </enum>
292                                         <enum name="keypad_digits">
293                                                 <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
294                                         </enum>
295                                         <enum name="reversecharge">
296                                                 <para>R/O PRI Reverse Charging Indication, one of:</para>
297                                                 <enumlist>
298                                                         <enum name="-1"> <para>None</para></enum>
299                                                         <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
300                                                 </enumlist>
301                                         </enum>
302                                         <enum name="no_media_path">
303                                                 <para>R/O PRI Nonzero if the channel has no B channel.
304                                                 The channel is either on hold or a call waiting call.</para>
305                                         </enum>
306                                         <enum name="buffers">
307                                                 <para>W/O Change the channel's buffer policy (for the current call only)</para>
308                                                 <para>This option takes two arguments:</para>
309                                                 <para>  Number of buffers,</para>
310                                                 <para>  Buffer policy being one of:</para>
311                                                 <para>      <literal>full</literal></para>
312                                                 <para>      <literal>immediate</literal></para>
313                                                 <para>      <literal>half</literal></para>
314                                         </enum>
315                                         <enum name="echocan_mode">
316                                                 <para>W/O Change the configuration of the active echo
317                                                 canceller on the channel (if any), for the current call
318                                                 only.</para>
319                                                 <para>Possible values are:</para>
320                                                 <para>  <literal>on</literal>   Normal mode (the echo canceller is actually reinitalized)</para>
321                                                 <para>  <literal>off</literal>  Disabled</para>
322                                                 <para>  <literal>fax</literal>  FAX/data mode (NLP disabled if possible, otherwise
323                                                         completely disabled)</para>
324                                                 <para>  <literal>voice</literal>        Voice mode (returns from FAX mode, reverting the changes that were made)</para>
325                                         </enum>
326                                 </enumlist>
327                                 <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
328                                 <enumlist>
329                                         <enum name="faxdetect">
330                                                 <para>Fax Detect [R/W]</para>
331                                                 <para>Returns 0 or 1</para>
332                                                 <para>Write yes or no</para>
333                                         </enum>
334                                         <enum name="t38support">
335                                                 <para>t38support [R/W]</para>
336                                                 <para>Returns 0 or 1</para>
337                                                 <para>Write yes or no</para>
338                                         </enum>
339                                         <enum name="h323id">
340                                                 <para>Returns h323id [R]</para>
341                                         </enum>
342                                 </enumlist>
343                         </parameter>
344                 </syntax>
345                 <description>
346                         <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
347                         be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
348                         requested that is not available on the current channel will return an empty string.</para>
349                 </description>
350         </function>
351  ***/
352
353 #define locked_copy_string(chan, dest, source, len) \
354         do { \
355                 ast_channel_lock(chan); \
356                 ast_copy_string(dest, source, len); \
357                 ast_channel_unlock(chan); \
358         } while (0)
359 #define locked_string_field_set(chan, field, source) \
360         do { \
361                 ast_channel_lock(chan); \
362                 ast_channel_##field##_set(chan, source); \
363                 ast_channel_unlock(chan); \
364         } while (0)
365
366 static const char * const transfercapability_table[0x20] = {
367         "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
368         "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
369         "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
370         "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
371
372 static int func_channel_read(struct ast_channel *chan, const char *function,
373                              char *data, char *buf, size_t len)
374 {
375         int ret = 0;
376         struct ast_format_cap *tmpcap;
377
378         if (!strcasecmp(data, "audionativeformat")) {
379                 char tmp[512];
380
381                 if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
382                         ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
383                         tmpcap = ast_format_cap_destroy(tmpcap);
384                 }
385         } else if (!strcasecmp(data, "videonativeformat")) {
386                 char tmp[512];
387
388                 if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
389                         ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
390                         tmpcap = ast_format_cap_destroy(tmpcap);
391                 }
392         } else if (!strcasecmp(data, "audioreadformat")) {
393                 ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
394         } else if (!strcasecmp(data, "audiowriteformat")) {
395                 ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
396 #ifdef CHANNEL_TRACE
397         } else if (!strcasecmp(data, "trace")) {
398                 ast_channel_lock(chan);
399                 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
400                 ast_channel_unlock(chan);
401 #endif
402         } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan))
403                 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
404         else if (!strcasecmp(data, "language"))
405                 locked_copy_string(chan, buf, ast_channel_language(chan), len);
406         else if (!strcasecmp(data, "musicclass"))
407                 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
408         else if (!strcasecmp(data, "name")) {
409                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
410         } else if (!strcasecmp(data, "parkinglot"))
411                 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
412         else if (!strcasecmp(data, "state"))
413                 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
414         else if (!strcasecmp(data, "channeltype"))
415                 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
416         else if (!strcasecmp(data, "accountcode"))
417                 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
418         else if (!strcasecmp(data, "checkhangup")) {
419                 ast_channel_lock(chan);
420                 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
421                 ast_channel_unlock(chan);
422         } else if (!strcasecmp(data, "peeraccount"))
423                 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
424         else if (!strcasecmp(data, "hangupsource"))
425                 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
426         else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
427                 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
428         else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
429                 locked_copy_string(chan, buf, ast_channel_data(chan), len);
430         else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
431                 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
432         else if (!strcasecmp(data, "context") && ast_channel_data(chan))
433                 locked_copy_string(chan, buf, ast_channel_context(chan), len);
434         else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
435                 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
436         else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
437                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
438         else if (!strcasecmp(data, "linkedid")) {
439                 ast_channel_lock(chan);
440                 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
441                         /* fall back on the channel's uniqueid if linkedid is unset */
442                         ast_copy_string(buf, ast_channel_uniqueid(chan), len);
443                 }
444                 else {
445                         ast_copy_string(buf, ast_channel_linkedid(chan), len);
446                 }
447                 ast_channel_unlock(chan);
448         } else if (!strcasecmp(data, "peer")) {
449                 struct ast_channel *p;
450
451                 ast_channel_lock(chan);
452                 p = ast_bridged_channel(chan);
453                 if (p || ast_channel_tech(chan)) /* dummy channel? if so, we hid the peer name in the language */
454                         ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
455                 else {
456                         /* a dummy channel can still pass along bridged peer info via
457                            the BRIDGEPEER variable */
458                         const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
459                         if (!ast_strlen_zero(pname))
460                                 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
461                         else
462                                 buf[0] = 0;
463                 }
464                 ast_channel_unlock(chan);
465         } else if (!strcasecmp(data, "uniqueid")) {
466                 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
467         } else if (!strcasecmp(data, "transfercapability")) {
468                 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
469         } else if (!strcasecmp(data, "callgroup")) {
470                 char groupbuf[256];
471
472                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
473         } else if (!strcasecmp(data, "pickupgroup")) {
474                 char groupbuf[256];
475
476                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
477         } else if (!strcasecmp(data, "namedcallgroup")) {
478                 struct ast_str *tmp_str = ast_str_alloca(1024);
479
480                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
481         } else if (!strcasecmp(data, "namedpickupgroup")) {
482                 struct ast_str *tmp_str = ast_str_alloca(1024);
483
484                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
485         } else if (!strcasecmp(data, "after_bridge_goto")) {
486                 ast_after_bridge_goto_read(chan, buf, len);
487         } else if (!strcasecmp(data, "amaflags")) {
488                 ast_channel_lock(chan);
489                 snprintf(buf, len, "%d", ast_channel_amaflags(chan));
490                 ast_channel_unlock(chan);
491         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
492                 struct ast_datastore *ds;
493
494                 ast_channel_lock(chan);
495                 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
496                         struct ast_secure_call_store *encrypt = ds->data;
497                         if (!strcasecmp(data, "secure_bridge_signaling")) {
498                                 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
499                         } else if (!strcasecmp(data, "secure_bridge_media")) {
500                                 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
501                         }
502                 }
503                 ast_channel_unlock(chan);
504         } else if (!ast_channel_tech(chan) || !ast_channel_tech(chan)->func_channel_read || ast_channel_tech(chan)->func_channel_read(chan, function, data, buf, len)) {
505                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
506                 ret = -1;
507         }
508
509         return ret;
510 }
511
512 static int func_channel_write_real(struct ast_channel *chan, const char *function,
513                               char *data, const char *value)
514 {
515         int ret = 0;
516         signed char gainset;
517
518         if (!strcasecmp(data, "language"))
519                 locked_string_field_set(chan, language, value);
520         else if (!strcasecmp(data, "parkinglot"))
521                 locked_string_field_set(chan, parkinglot, value);
522         else if (!strcasecmp(data, "musicclass"))
523                 locked_string_field_set(chan, musicclass, value);
524         else if (!strcasecmp(data, "accountcode"))
525                 locked_string_field_set(chan, accountcode, value);
526         else if (!strcasecmp(data, "userfield"))
527                 locked_string_field_set(chan, userfield, value);
528         else if (!strcasecmp(data, "after_bridge_goto")) {
529                 if (ast_strlen_zero(value)) {
530                         ast_after_bridge_goto_discard(chan);
531                 } else {
532                         ast_after_bridge_set_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
533                 }
534         } else if (!strcasecmp(data, "amaflags")) {
535                 ast_channel_lock(chan);
536                 if (isdigit(*value)) {
537                         int amaflags;
538                         sscanf(value, "%30d", &amaflags);
539                         ast_channel_amaflags_set(chan, amaflags);
540                 } else if (!strcasecmp(value,"OMIT")){
541                         ast_channel_amaflags_set(chan, 1);
542                 } else if (!strcasecmp(value,"BILLING")){
543                         ast_channel_amaflags_set(chan, 2);
544                 } else if (!strcasecmp(value,"DOCUMENTATION")){
545                         ast_channel_amaflags_set(chan, 3);
546                 }
547                 ast_channel_unlock(chan);
548         } else if (!strcasecmp(data, "peeraccount"))
549                 locked_string_field_set(chan, peeraccount, value);
550         else if (!strcasecmp(data, "hangupsource"))
551                 /* XXX - should we be forcing this here? */
552                 ast_set_hangupsource(chan, value, 0);
553 #ifdef CHANNEL_TRACE
554         else if (!strcasecmp(data, "trace")) {
555                 ast_channel_lock(chan);
556                 if (ast_true(value)) 
557                         ret = ast_channel_trace_enable(chan);
558                 else if (ast_false(value))
559                         ret = ast_channel_trace_disable(chan);
560                 else {
561                         ret = -1;
562                         ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
563                 }
564                 ast_channel_unlock(chan);
565         }
566 #endif
567         else if (!strcasecmp(data, "tonezone")) {
568                 struct ast_tone_zone *new_zone;
569                 if (!(new_zone = ast_get_indication_zone(value))) {
570                         ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
571                         ret = -1;       
572                 } else {
573                         ast_channel_lock(chan);
574                         if (ast_channel_zone(chan)) {
575                                 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
576                         }
577                         ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
578                         ast_channel_unlock(chan);
579                         new_zone = ast_tone_zone_unref(new_zone);
580                 }
581         } else if (!strcasecmp(data, "callgroup")) {
582                 ast_channel_lock(chan);
583                 ast_channel_callgroup_set(chan, ast_get_group(value));
584                 ast_channel_unlock(chan);
585         } else if (!strcasecmp(data, "pickupgroup")) {
586                 ast_channel_lock(chan);
587                 ast_channel_pickupgroup_set(chan, ast_get_group(value));
588                 ast_channel_unlock(chan);
589         } else if (!strcasecmp(data, "namedcallgroup")) {
590                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
591
592                 ast_channel_lock(chan);
593                 ast_channel_named_callgroups_set(chan, groups);
594                 ast_channel_unlock(chan);
595                 ast_unref_namedgroups(groups);
596         } else if (!strcasecmp(data, "namedpickupgroup")) {
597                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
598
599                 ast_channel_lock(chan);
600                 ast_channel_named_pickupgroups_set(chan, groups);
601                 ast_channel_unlock(chan);
602                 ast_unref_namedgroups(groups);
603         } else if (!strcasecmp(data, "txgain")) {
604                 sscanf(value, "%4hhd", &gainset);
605                 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
606         } else if (!strcasecmp(data, "rxgain")) {
607                 sscanf(value, "%4hhd", &gainset);
608                 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
609         } else if (!strcasecmp(data, "transfercapability")) {
610                 unsigned short i;
611
612                 ast_channel_lock(chan);
613                 for (i = 0; i < 0x20; i++) {
614                         if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
615                                 ast_channel_transfercapability_set(chan, i);
616                                 break;
617                         }
618                 }
619                 ast_channel_unlock(chan);
620         } else if (!strcasecmp(data, "hangup_handler_pop")) {
621                 /* Pop one hangup handler before pushing the new handler. */
622                 ast_pbx_hangup_handler_pop(chan);
623                 ast_pbx_hangup_handler_push(chan, value);
624         } else if (!strcasecmp(data, "hangup_handler_push")) {
625                 ast_pbx_hangup_handler_push(chan, value);
626         } else if (!strcasecmp(data, "hangup_handler_wipe")) {
627                 /* Pop all hangup handlers before pushing the new handler. */
628                 while (ast_pbx_hangup_handler_pop(chan)) {
629                 }
630                 ast_pbx_hangup_handler_push(chan, value);
631         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
632                 struct ast_datastore *ds;
633                 struct ast_secure_call_store *store;
634
635                 if (!chan || !value) {
636                         return -1;
637                 }
638
639                 ast_channel_lock(chan);
640                 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
641                         if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
642                                 ast_channel_unlock(chan);
643                                 return -1;
644                         }
645                         if (!(store = ast_calloc(1, sizeof(*store)))) {
646                                 ast_channel_unlock(chan);
647                                 ast_free(ds);
648                                 return -1;
649                         }
650                         ds->data = store;
651                         ast_channel_datastore_add(chan, ds);
652                 } else {
653                         store = ds->data;
654                 }
655
656                 if (!strcasecmp(data, "secure_bridge_signaling")) {
657                         store->signaling = ast_true(value) ? 1 : 0;
658                 } else if (!strcasecmp(data, "secure_bridge_media")) {
659                         store->media = ast_true(value) ? 1 : 0;
660                 }
661                 ast_channel_unlock(chan);
662         } else if (!ast_channel_tech(chan)->func_channel_write
663                  || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
664                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
665                                 data);
666                 ret = -1;
667         }
668
669         return ret;
670 }
671
672 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
673 {
674         int res;
675         ast_chan_write_info_t write_info = {
676                 .version = AST_CHAN_WRITE_INFO_T_VERSION,
677                 .write_fn = func_channel_write_real,
678                 .chan = chan,
679                 .function = function,
680                 .data = data,
681                 .value = value,
682         };
683
684         res = func_channel_write_real(chan, function, data, value);
685         ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
686
687         return res;
688 }
689
690 static struct ast_custom_function channel_function = {
691         .name = "CHANNEL",
692         .read = func_channel_read,
693         .write = func_channel_write,
694 };
695
696 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
697 {
698         struct ast_channel *c = NULL;
699         regex_t re;
700         int res;
701         size_t buflen = 0;
702         struct ast_channel_iterator *iter;
703
704         buf[0] = '\0';
705
706         if (!ast_strlen_zero(data)) {
707                 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
708                         regerror(res, &re, buf, maxlen);
709                         ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
710                         return -1;
711                 }
712         }
713
714         if (!(iter = ast_channel_iterator_all_new())) {
715                 if (!ast_strlen_zero(data)) {
716                         regfree(&re);
717                 }
718                 return -1;
719         }
720
721         while ((c = ast_channel_iterator_next(iter))) {
722                 ast_channel_lock(c);
723                 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
724                         size_t namelen = strlen(ast_channel_name(c));
725                         if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
726                                 if (!ast_strlen_zero(buf)) {
727                                         strcat(buf, " ");
728                                         buflen++;
729                                 }
730                                 strcat(buf, ast_channel_name(c));
731                                 buflen += namelen;
732                         } else {
733                                 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
734                         }
735                 }
736                 ast_channel_unlock(c);
737                 c = ast_channel_unref(c);
738         }
739
740         ast_channel_iterator_destroy(iter);
741
742         if (!ast_strlen_zero(data)) {
743                 regfree(&re);
744         }
745
746         return 0;
747 }
748
749 static struct ast_custom_function channels_function = {
750         .name = "CHANNELS",
751         .read = func_channels_read,
752 };
753
754 static int func_mchan_read(struct ast_channel *chan, const char *function,
755                              char *data, struct ast_str **buf, ssize_t len)
756 {
757         struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
758         char *template = ast_alloca(4 + strlen(data));
759         sprintf(template, "${%s}", data); /* SAFE */
760         ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
761         if (mchan) {
762                 ast_channel_unref(mchan);
763         }
764         return 0;
765 }
766
767 static int func_mchan_write(struct ast_channel *chan, const char *function,
768                               char *data, const char *value)
769 {
770         struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
771         pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
772         if (mchan) {
773                 ast_channel_unref(mchan);
774         }
775         return 0;
776 }
777
778 static struct ast_custom_function mchan_function = {
779         .name = "MASTER_CHANNEL",
780         .read2 = func_mchan_read,
781         .write = func_mchan_write,
782 };
783
784 static int unload_module(void)
785 {
786         int res = 0;
787
788         res |= ast_custom_function_unregister(&channel_function);
789         res |= ast_custom_function_unregister(&channels_function);
790         res |= ast_custom_function_unregister(&mchan_function);
791
792         return res;
793 }
794
795 static int load_module(void)
796 {
797         int res = 0;
798
799         res |= ast_custom_function_register(&channel_function);
800         res |= ast_custom_function_register(&channels_function);
801         res |= ast_custom_function_register(&mchan_function);
802
803         return res;
804 }
805
806 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");