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