2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2006, Digium, Inc.
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.
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.
19 * \brief Channel info dialplan functions
21 * \author Kevin P. Fleming <kpfleming@digium.com>
28 <support_level>core</support_level>
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38 #include "asterisk/module.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/bridge.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/utils.h"
43 #include "asterisk/app.h"
44 #include "asterisk/indications.h"
45 #include "asterisk/stringfields.h"
46 #include "asterisk/global_datastores.h"
47 #include "asterisk/bridge_basic.h"
48 #include "asterisk/bridge_after.h"
51 <function name="CHANNELS" language="en_US">
53 Gets the list of channels, optionally filtering by a regular expression.
56 <parameter name="regular_expression" />
59 <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
60 no argument is provided, all known channels are returned. The
61 <replaceable>regular_expression</replaceable> must correspond to
62 the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
63 will be space-delimited.</para>
66 <function name="MASTER_CHANNEL" language="en_US">
68 Gets or sets variables on the master channel
71 <para>Allows access to the channel which created the current channel, if any. If the channel is already
72 a master channel, then accesses local channel variables.</para>
75 <function name="CHANNEL" language="en_US">
77 Gets/sets various pieces of information about the channel.
80 <parameter name="item" required="true">
81 <para>Standard items (provided by all channel technologies) are:</para>
83 <enum name="amaflags">
84 <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
85 When read from a channel, the integer value will always be returned.
86 When written to a channel, both the string format or integer value
89 <enum name="1"><para><literal>OMIT</literal></para></enum>
90 <enum name="2"><para><literal>BILLING</literal></para></enum>
91 <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
94 <enum name="accountcode">
95 <para>R/W the channel's account code.</para>
97 <enum name="audioreadformat">
98 <para>R/O format currently being read.</para>
100 <enum name="audionativeformat">
101 <para>R/O format used natively for audio.</para>
103 <enum name="audiowriteformat">
104 <para>R/O format currently being written.</para>
106 <enum name="dtmf_features">
107 <para>R/W The channel's DTMF bridge features.
108 May include one or more of 'T' 'K' 'H' 'W' and 'X' in a similar manner to options
109 in the <literal>Dial</literal> application. When setting it, the features string
110 must be all upper case.</para>
112 <enum name="callgroup">
113 <para>R/W numeric call pickup groups that this channel is a member.</para>
115 <enum name="pickupgroup">
116 <para>R/W numeric call pickup groups this channel can pickup.</para>
118 <enum name="namedcallgroup">
119 <para>R/W named call pickup groups that this channel is a member.</para>
121 <enum name="namedpickupgroup">
122 <para>R/W named call pickup groups this channel can pickup.</para>
124 <enum name="channeltype">
125 <para>R/O technology used for channel.</para>
127 <enum name="checkhangup">
128 <para>R/O Whether the channel is hanging up (1/0)</para>
130 <enum name="after_bridge_goto">
131 <para>R/W the parseable goto string indicating where the channel is
132 expected to return to in the PBX after exiting the next bridge it joins
133 on the condition that it doesn't hang up. The parseable goto string uses
134 the same syntax as the <literal>Goto</literal> application.</para>
136 <enum name="hangup_handler_pop">
137 <para>W/O Replace the most recently added hangup handler
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>
144 <enum name="hangup_handler_push">
145 <para>W/O Push a hangup handler onto the channel hangup
146 handler stack. The assigned string is passed to the
147 Gosub application when the channel is hung up. Any
148 optionally omitted context and exten are supplied by the
149 channel pushing the handler before it is pushed.</para>
151 <enum name="hangup_handler_wipe">
152 <para>W/O Wipe the entire hangup handler stack and replace
153 with a new hangup handler on the channel if supplied. The
154 assigned string is passed to the Gosub application when
155 the channel is hung up. Any optionally omitted context
156 and exten are supplied by the channel pushing the handler
157 before it is pushed.</para>
159 <enum name="language">
160 <para>R/W language for sounds played.</para>
162 <enum name="musicclass">
163 <para>R/W class (from musiconhold.conf) for hold music.</para>
166 <para>The name of the channel</para>
168 <enum name="parkinglot">
169 <para>R/W parkinglot for parking.</para>
172 <para>R/W set rxgain level on channel drivers that support it.</para>
174 <enum name="secure_bridge_signaling">
175 <para>Whether or not channels bridged to this channel require secure signaling</para>
177 <enum name="secure_bridge_media">
178 <para>Whether or not channels bridged to this channel require secure media</para>
181 <para>R/O state for channel</para>
183 <enum name="tonezone">
184 <para>R/W zone for indications played</para>
186 <enum name="transfercapability">
187 <para>R/W ISDN Transfer Capability, one of:</para>
189 <enum name="SPEECH" />
190 <enum name="DIGITAL" />
191 <enum name="RESTRICTED_DIGITAL" />
192 <enum name="3K1AUDIO" />
193 <enum name="DIGITAL_W_TONES" />
194 <enum name="VIDEO" />
198 <para>R/W set txgain level on channel drivers that support it.</para>
200 <enum name="videonativeformat">
201 <para>R/O format used natively for video</para>
204 <para>R/W whether or not context tracing is enabled, only available
205 <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
208 <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
211 <para>R/O Get the IP address of the peer.</para>
214 <para>R/O Get the source IP address of the peer.</para>
217 <para>R/O Get the URI from the From: header.</para>
220 <para>R/O Get the URI from the Contact: header.</para>
222 <enum name="useragent">
223 <para>R/O Get the useragent.</para>
225 <enum name="peername">
226 <para>R/O Get the name of the peer.</para>
228 <enum name="t38passthrough">
229 <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
230 otherwise <literal>0</literal></para>
233 <para>R/O Get QOS information about the RTP stream</para>
234 <para> This option takes two additional arguments:</para>
235 <para> Argument 1:</para>
236 <para> <literal>audio</literal> Get data about the audio stream</para>
237 <para> <literal>video</literal> Get data about the video stream</para>
238 <para> <literal>text</literal> Get data about the text stream</para>
239 <para> Argument 2:</para>
240 <para> <literal>local_ssrc</literal> Local SSRC (stream ID)</para>
241 <para> <literal>local_lostpackets</literal> Local lost packets</para>
242 <para> <literal>local_jitter</literal> Local calculated jitter</para>
243 <para> <literal>local_maxjitter</literal> Local calculated jitter (maximum)</para>
244 <para> <literal>local_minjitter</literal> Local calculated jitter (minimum)</para>
245 <para> <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
246 <para> <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
247 <para> <literal>local_count</literal> Number of received packets</para>
248 <para> <literal>remote_ssrc</literal> Remote SSRC (stream ID)</para>
249 <para> <literal>remote_lostpackets</literal>Remote lost packets</para>
250 <para> <literal>remote_jitter</literal> Remote reported jitter</para>
251 <para> <literal>remote_maxjitter</literal> Remote calculated jitter (maximum)</para>
252 <para> <literal>remote_minjitter</literal> Remote calculated jitter (minimum)</para>
253 <para> <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
254 <para> <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
255 <para> <literal>remote_count</literal> Number of transmitted packets</para>
256 <para> <literal>rtt</literal> Round trip time</para>
257 <para> <literal>maxrtt</literal> Round trip time (maximum)</para>
258 <para> <literal>minrtt</literal> Round trip time (minimum)</para>
259 <para> <literal>normdevrtt</literal> Round trip time (normal deviation)</para>
260 <para> <literal>stdevrtt</literal> Round trip time (standard deviation)</para>
261 <para> <literal>all</literal> All statistics (in a form suited to logging,
262 but not for parsing)</para>
264 <enum name="rtpdest">
265 <para>R/O Get remote RTP destination information.</para>
266 <para> This option takes one additional argument:</para>
267 <para> Argument 1:</para>
268 <para> <literal>audio</literal> Get audio destination</para>
269 <para> <literal>video</literal> Get video destination</para>
270 <para> <literal>text</literal> Get text destination</para>
271 <para> Defaults to <literal>audio</literal> if unspecified.</para>
273 <enum name="rtpsource">
274 <para>R/O Get source RTP destination information.</para>
275 <para> This option takes one additional argument:</para>
276 <para> Argument 1:</para>
277 <para> <literal>audio</literal> Get audio destination</para>
278 <para> <literal>video</literal> Get video destination</para>
279 <para> <literal>text</literal> Get text destination</para>
280 <para> Defaults to <literal>audio</literal> if unspecified.</para>
283 <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
285 <enum name="osptoken">
286 <para>R/O Get the peer's osptoken.</para>
289 <para>R/O Get the peer's ip address.</para>
291 <enum name="peername">
292 <para>R/O Get the peer's username.</para>
294 <enum name="secure_signaling">
295 <para>R/O Get the if the IAX channel is secured.</para>
297 <enum name="secure_media">
298 <para>R/O Get the if the IAX channel is secured.</para>
301 <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
303 <enum name="dahdi_channel">
304 <para>R/O DAHDI channel related to this channel.</para>
306 <enum name="dahdi_span">
307 <para>R/O DAHDI span related to this channel.</para>
309 <enum name="dahdi_type">
310 <para>R/O DAHDI channel type, one of:</para>
312 <enum name="analog" />
313 <enum name="mfc/r2" />
315 <enum name="pseudo" />
319 <enum name="keypad_digits">
320 <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
322 <enum name="reversecharge">
323 <para>R/O PRI Reverse Charging Indication, one of:</para>
325 <enum name="-1"> <para>None</para></enum>
326 <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
329 <enum name="no_media_path">
330 <para>R/O PRI Nonzero if the channel has no B channel.
331 The channel is either on hold or a call waiting call.</para>
333 <enum name="buffers">
334 <para>W/O Change the channel's buffer policy (for the current call only)</para>
335 <para>This option takes two arguments:</para>
336 <para> Number of buffers,</para>
337 <para> Buffer policy being one of:</para>
338 <para> <literal>full</literal></para>
339 <para> <literal>immediate</literal></para>
340 <para> <literal>half</literal></para>
342 <enum name="echocan_mode">
343 <para>W/O Change the configuration of the active echo
344 canceller on the channel (if any), for the current call
346 <para>Possible values are:</para>
347 <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitalized)</para>
348 <para> <literal>off</literal> Disabled</para>
349 <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
350 completely disabled)</para>
351 <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
354 <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
356 <enum name="faxdetect">
357 <para>R/W Fax Detect</para>
358 <para>Returns 0 or 1</para>
359 <para>Write yes or no</para>
361 <enum name="t38support">
362 <para>R/W t38support</para>
363 <para>Returns 0 or 1</para>
364 <para>Write yes or no</para>
366 <enum name="h323id_url">
367 <para>R/0 Returns caller URL</para>
369 <enum name="caller_h323id">
370 <para>R/0 Returns caller h323id</para>
372 <enum name="caller_dialeddigits">
373 <para>R/0 Returns caller dialed digits</para>
375 <enum name="caller_email">
376 <para>R/0 Returns caller email</para>
378 <enum name="callee_email">
379 <para>R/0 Returns callee email</para>
381 <enum name="callee_dialeddigits">
382 <para>R/0 Returns callee dialed digits</para>
384 <enum name="caller_url">
385 <para>R/0 Returns caller URL</para>
391 <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
392 be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
393 requested that is not available on the current channel will return an empty string.</para>
398 #define locked_copy_string(chan, dest, source, len) \
400 ast_channel_lock(chan); \
401 ast_copy_string(dest, source, len); \
402 ast_channel_unlock(chan); \
404 #define locked_string_field_set(chan, field, source) \
406 ast_channel_lock(chan); \
407 ast_channel_##field##_set(chan, source); \
408 ast_channel_unlock(chan); \
411 static const char * const transfercapability_table[0x20] = {
412 "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
413 "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
414 "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
415 "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
417 static int func_channel_read(struct ast_channel *chan, const char *function,
418 char *data, char *buf, size_t len)
421 struct ast_format_cap *tmpcap;
423 if (!strcasecmp(data, "audionativeformat")) {
426 if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
427 ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
428 tmpcap = ast_format_cap_destroy(tmpcap);
430 } else if (!strcasecmp(data, "videonativeformat")) {
433 if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
434 ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
435 tmpcap = ast_format_cap_destroy(tmpcap);
437 } else if (!strcasecmp(data, "audioreadformat")) {
438 ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
439 } else if (!strcasecmp(data, "audiowriteformat")) {
440 ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
442 } else if (!strcasecmp(data, "trace")) {
443 ast_channel_lock(chan);
444 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
445 ast_channel_unlock(chan);
447 } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
448 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
449 } else if (!strcasecmp(data, "dtmf_features")) {
450 if (ast_bridge_features_ds_get_string(chan, buf, len)) {
453 } else if (!strcasecmp(data, "language"))
454 locked_copy_string(chan, buf, ast_channel_language(chan), len);
455 else if (!strcasecmp(data, "musicclass"))
456 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
457 else if (!strcasecmp(data, "name")) {
458 locked_copy_string(chan, buf, ast_channel_name(chan), len);
459 } else if (!strcasecmp(data, "parkinglot"))
460 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
461 else if (!strcasecmp(data, "state"))
462 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
463 else if (!strcasecmp(data, "channeltype"))
464 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
465 else if (!strcasecmp(data, "accountcode"))
466 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
467 else if (!strcasecmp(data, "checkhangup")) {
468 ast_channel_lock(chan);
469 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
470 ast_channel_unlock(chan);
471 } else if (!strcasecmp(data, "peeraccount"))
472 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
473 else if (!strcasecmp(data, "hangupsource"))
474 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
475 else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
476 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
477 else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
478 locked_copy_string(chan, buf, ast_channel_data(chan), len);
479 else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
480 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
481 else if (!strcasecmp(data, "context") && ast_channel_data(chan))
482 locked_copy_string(chan, buf, ast_channel_context(chan), len);
483 else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
484 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
485 else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
486 locked_copy_string(chan, buf, ast_channel_name(chan), len);
487 else if (!strcasecmp(data, "linkedid")) {
488 ast_channel_lock(chan);
489 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
490 /* fall back on the channel's uniqueid if linkedid is unset */
491 ast_copy_string(buf, ast_channel_uniqueid(chan), len);
494 ast_copy_string(buf, ast_channel_linkedid(chan), len);
496 ast_channel_unlock(chan);
497 } else if (!strcasecmp(data, "peer")) {
498 RAII_VAR(struct ast_channel *, p, NULL, ast_channel_cleanup);
500 ast_channel_lock(chan);
501 p = ast_channel_bridge_peer(chan);
502 if (p || ast_channel_tech(chan)) /* dummy channel? if so, we hid the peer name in the language */
503 ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
505 /* a dummy channel can still pass along bridged peer info via
506 the BRIDGEPEER variable */
507 const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
508 if (!ast_strlen_zero(pname))
509 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
513 ast_channel_unlock(chan);
514 } else if (!strcasecmp(data, "uniqueid")) {
515 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
516 } else if (!strcasecmp(data, "transfercapability")) {
517 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
518 } else if (!strcasecmp(data, "callgroup")) {
521 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
522 } else if (!strcasecmp(data, "pickupgroup")) {
525 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
526 } else if (!strcasecmp(data, "namedcallgroup")) {
527 struct ast_str *tmp_str = ast_str_alloca(1024);
529 locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
530 } else if (!strcasecmp(data, "namedpickupgroup")) {
531 struct ast_str *tmp_str = ast_str_alloca(1024);
533 locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
534 } else if (!strcasecmp(data, "after_bridge_goto")) {
535 ast_bridge_read_after_goto(chan, buf, len);
536 } else if (!strcasecmp(data, "amaflags")) {
537 ast_channel_lock(chan);
538 snprintf(buf, len, "%d", ast_channel_amaflags(chan));
539 ast_channel_unlock(chan);
540 } else if (!strncasecmp(data, "secure_bridge_", 14)) {
541 struct ast_datastore *ds;
543 ast_channel_lock(chan);
544 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
545 struct ast_secure_call_store *encrypt = ds->data;
546 if (!strcasecmp(data, "secure_bridge_signaling")) {
547 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
548 } else if (!strcasecmp(data, "secure_bridge_media")) {
549 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
552 ast_channel_unlock(chan);
553 } 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)) {
554 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
561 static int func_channel_write_real(struct ast_channel *chan, const char *function,
562 char *data, const char *value)
567 if (!strcasecmp(data, "language"))
568 locked_string_field_set(chan, language, value);
569 else if (!strcasecmp(data, "parkinglot"))
570 locked_string_field_set(chan, parkinglot, value);
571 else if (!strcasecmp(data, "musicclass"))
572 locked_string_field_set(chan, musicclass, value);
573 else if (!strcasecmp(data, "accountcode"))
574 locked_string_field_set(chan, accountcode, value);
575 else if (!strcasecmp(data, "userfield"))
576 locked_string_field_set(chan, userfield, value);
577 else if (!strcasecmp(data, "after_bridge_goto")) {
578 if (ast_strlen_zero(value)) {
579 ast_bridge_discard_after_goto(chan);
581 ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
583 } else if (!strcasecmp(data, "amaflags")) {
584 ast_channel_lock(chan);
585 if (isdigit(*value)) {
587 sscanf(value, "%30d", &amaflags);
588 ast_channel_amaflags_set(chan, amaflags);
589 } else if (!strcasecmp(value,"OMIT")){
590 ast_channel_amaflags_set(chan, 1);
591 } else if (!strcasecmp(value,"BILLING")){
592 ast_channel_amaflags_set(chan, 2);
593 } else if (!strcasecmp(value,"DOCUMENTATION")){
594 ast_channel_amaflags_set(chan, 3);
596 ast_channel_unlock(chan);
597 } else if (!strcasecmp(data, "peeraccount"))
598 locked_string_field_set(chan, peeraccount, value);
599 else if (!strcasecmp(data, "hangupsource"))
600 /* XXX - should we be forcing this here? */
601 ast_set_hangupsource(chan, value, 0);
603 else if (!strcasecmp(data, "trace")) {
604 ast_channel_lock(chan);
606 ret = ast_channel_trace_enable(chan);
607 else if (ast_false(value))
608 ret = ast_channel_trace_disable(chan);
611 ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
613 ast_channel_unlock(chan);
616 else if (!strcasecmp(data, "tonezone")) {
617 struct ast_tone_zone *new_zone;
618 if (!(new_zone = ast_get_indication_zone(value))) {
619 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
622 ast_channel_lock(chan);
623 if (ast_channel_zone(chan)) {
624 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
626 ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
627 ast_channel_unlock(chan);
628 new_zone = ast_tone_zone_unref(new_zone);
630 } else if (!strcasecmp(data, "dtmf_features")) {
631 ret = ast_bridge_features_ds_set_string(chan, value);
632 } else if (!strcasecmp(data, "callgroup")) {
633 ast_channel_lock(chan);
634 ast_channel_callgroup_set(chan, ast_get_group(value));
635 ast_channel_unlock(chan);
636 } else if (!strcasecmp(data, "pickupgroup")) {
637 ast_channel_lock(chan);
638 ast_channel_pickupgroup_set(chan, ast_get_group(value));
639 ast_channel_unlock(chan);
640 } else if (!strcasecmp(data, "namedcallgroup")) {
641 struct ast_namedgroups *groups = ast_get_namedgroups(value);
643 ast_channel_lock(chan);
644 ast_channel_named_callgroups_set(chan, groups);
645 ast_channel_unlock(chan);
646 ast_unref_namedgroups(groups);
647 } else if (!strcasecmp(data, "namedpickupgroup")) {
648 struct ast_namedgroups *groups = ast_get_namedgroups(value);
650 ast_channel_lock(chan);
651 ast_channel_named_pickupgroups_set(chan, groups);
652 ast_channel_unlock(chan);
653 ast_unref_namedgroups(groups);
654 } else if (!strcasecmp(data, "txgain")) {
655 sscanf(value, "%4hhd", &gainset);
656 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
657 } else if (!strcasecmp(data, "rxgain")) {
658 sscanf(value, "%4hhd", &gainset);
659 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
660 } else if (!strcasecmp(data, "transfercapability")) {
663 ast_channel_lock(chan);
664 for (i = 0; i < 0x20; i++) {
665 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
666 ast_channel_transfercapability_set(chan, i);
670 ast_channel_unlock(chan);
671 } else if (!strcasecmp(data, "hangup_handler_pop")) {
672 /* Pop one hangup handler before pushing the new handler. */
673 ast_pbx_hangup_handler_pop(chan);
674 ast_pbx_hangup_handler_push(chan, value);
675 } else if (!strcasecmp(data, "hangup_handler_push")) {
676 ast_pbx_hangup_handler_push(chan, value);
677 } else if (!strcasecmp(data, "hangup_handler_wipe")) {
678 /* Pop all hangup handlers before pushing the new handler. */
679 while (ast_pbx_hangup_handler_pop(chan)) {
681 ast_pbx_hangup_handler_push(chan, value);
682 } else if (!strncasecmp(data, "secure_bridge_", 14)) {
683 struct ast_datastore *ds;
684 struct ast_secure_call_store *store;
686 if (!chan || !value) {
690 ast_channel_lock(chan);
691 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
692 if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
693 ast_channel_unlock(chan);
696 if (!(store = ast_calloc(1, sizeof(*store)))) {
697 ast_channel_unlock(chan);
702 ast_channel_datastore_add(chan, ds);
707 if (!strcasecmp(data, "secure_bridge_signaling")) {
708 store->signaling = ast_true(value) ? 1 : 0;
709 } else if (!strcasecmp(data, "secure_bridge_media")) {
710 store->media = ast_true(value) ? 1 : 0;
712 ast_channel_unlock(chan);
713 } else if (!ast_channel_tech(chan)->func_channel_write
714 || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
715 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
723 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
726 ast_chan_write_info_t write_info = {
727 .version = AST_CHAN_WRITE_INFO_T_VERSION,
728 .write_fn = func_channel_write_real,
730 .function = function,
735 res = func_channel_write_real(chan, function, data, value);
736 ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
741 static struct ast_custom_function channel_function = {
743 .read = func_channel_read,
744 .write = func_channel_write,
747 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
749 struct ast_channel *c = NULL;
753 struct ast_channel_iterator *iter;
757 if (!ast_strlen_zero(data)) {
758 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
759 regerror(res, &re, buf, maxlen);
760 ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
765 if (!(iter = ast_channel_iterator_all_new())) {
766 if (!ast_strlen_zero(data)) {
772 while ((c = ast_channel_iterator_next(iter))) {
774 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
775 size_t namelen = strlen(ast_channel_name(c));
776 if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
777 if (!ast_strlen_zero(buf)) {
781 strcat(buf, ast_channel_name(c));
784 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
787 ast_channel_unlock(c);
788 c = ast_channel_unref(c);
791 ast_channel_iterator_destroy(iter);
793 if (!ast_strlen_zero(data)) {
800 static struct ast_custom_function channels_function = {
802 .read = func_channels_read,
805 static int func_mchan_read(struct ast_channel *chan, const char *function,
806 char *data, struct ast_str **buf, ssize_t len)
808 struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
809 char *template = ast_alloca(4 + strlen(data));
810 sprintf(template, "${%s}", data); /* SAFE */
811 ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
813 ast_channel_unref(mchan);
818 static int func_mchan_write(struct ast_channel *chan, const char *function,
819 char *data, const char *value)
821 struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
822 pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
824 ast_channel_unref(mchan);
829 static struct ast_custom_function mchan_function = {
830 .name = "MASTER_CHANNEL",
831 .read2 = func_mchan_read,
832 .write = func_mchan_write,
835 static int unload_module(void)
839 res |= ast_custom_function_unregister(&channel_function);
840 res |= ast_custom_function_unregister(&channels_function);
841 res |= ast_custom_function_unregister(&mchan_function);
846 static int load_module(void)
850 res |= ast_custom_function_register(&channel_function);
851 res |= ast_custom_function_register(&channels_function);
852 res |= ast_custom_function_register(&mchan_function);
857 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");