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