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 <xi:include xpointer="xpointer(/docs/info[@name='PJSIPCHANNEL'])" />
284 <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
286 <enum name="osptoken">
287 <para>R/O Get the peer's osptoken.</para>
290 <para>R/O Get the peer's ip address.</para>
292 <enum name="peername">
293 <para>R/O Get the peer's username.</para>
295 <enum name="secure_signaling">
296 <para>R/O Get the if the IAX channel is secured.</para>
298 <enum name="secure_media">
299 <para>R/O Get the if the IAX channel is secured.</para>
302 <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
304 <enum name="dahdi_channel">
305 <para>R/O DAHDI channel related to this channel.</para>
307 <enum name="dahdi_span">
308 <para>R/O DAHDI span related to this channel.</para>
310 <enum name="dahdi_type">
311 <para>R/O DAHDI channel type, one of:</para>
313 <enum name="analog" />
314 <enum name="mfc/r2" />
316 <enum name="pseudo" />
320 <enum name="keypad_digits">
321 <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
323 <enum name="reversecharge">
324 <para>R/O PRI Reverse Charging Indication, one of:</para>
326 <enum name="-1"> <para>None</para></enum>
327 <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
330 <enum name="no_media_path">
331 <para>R/O PRI Nonzero if the channel has no B channel.
332 The channel is either on hold or a call waiting call.</para>
334 <enum name="buffers">
335 <para>W/O Change the channel's buffer policy (for the current call only)</para>
336 <para>This option takes two arguments:</para>
337 <para> Number of buffers,</para>
338 <para> Buffer policy being one of:</para>
339 <para> <literal>full</literal></para>
340 <para> <literal>immediate</literal></para>
341 <para> <literal>half</literal></para>
343 <enum name="echocan_mode">
344 <para>W/O Change the configuration of the active echo
345 canceller on the channel (if any), for the current call
347 <para>Possible values are:</para>
348 <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitalized)</para>
349 <para> <literal>off</literal> Disabled</para>
350 <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
351 completely disabled)</para>
352 <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
355 <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
357 <enum name="faxdetect">
358 <para>R/W Fax Detect</para>
359 <para>Returns 0 or 1</para>
360 <para>Write yes or no</para>
362 <enum name="t38support">
363 <para>R/W t38support</para>
364 <para>Returns 0 or 1</para>
365 <para>Write yes or no</para>
367 <enum name="h323id_url">
368 <para>R/0 Returns caller URL</para>
370 <enum name="caller_h323id">
371 <para>R/0 Returns caller h323id</para>
373 <enum name="caller_dialeddigits">
374 <para>R/0 Returns caller dialed digits</para>
376 <enum name="caller_email">
377 <para>R/0 Returns caller email</para>
379 <enum name="callee_email">
380 <para>R/0 Returns callee email</para>
382 <enum name="callee_dialeddigits">
383 <para>R/0 Returns callee dialed digits</para>
385 <enum name="caller_url">
386 <para>R/0 Returns caller URL</para>
392 <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
393 be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
394 requested that is not available on the current channel will return an empty string.</para>
399 #define locked_copy_string(chan, dest, source, len) \
401 ast_channel_lock(chan); \
402 ast_copy_string(dest, source, len); \
403 ast_channel_unlock(chan); \
405 #define locked_string_field_set(chan, field, source) \
407 ast_channel_lock(chan); \
408 ast_channel_##field##_set(chan, source); \
409 ast_channel_unlock(chan); \
412 static const char * const transfercapability_table[0x20] = {
413 "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
414 "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
415 "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
416 "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
418 static int func_channel_read(struct ast_channel *chan, const char *function,
419 char *data, char *buf, size_t len)
422 struct ast_format_cap *tmpcap;
425 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
429 if (!strcasecmp(data, "audionativeformat")) {
430 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
432 struct ast_str *codec_buf = ast_str_alloca(64);
434 ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
435 ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
438 } else if (!strcasecmp(data, "videonativeformat")) {
439 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
441 struct ast_str *codec_buf = ast_str_alloca(64);
443 ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
444 ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
447 } else if (!strcasecmp(data, "audioreadformat")) {
448 ast_copy_string(buf, ast_format_get_name(ast_channel_readformat(chan)), len);
449 } else if (!strcasecmp(data, "audiowriteformat")) {
450 ast_copy_string(buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
452 } else if (!strcasecmp(data, "trace")) {
453 ast_channel_lock(chan);
454 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
455 ast_channel_unlock(chan);
457 } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
458 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
459 } else if (!strcasecmp(data, "dtmf_features")) {
460 if (ast_bridge_features_ds_get_string(chan, buf, len)) {
463 } else if (!strcasecmp(data, "language"))
464 locked_copy_string(chan, buf, ast_channel_language(chan), len);
465 else if (!strcasecmp(data, "musicclass"))
466 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
467 else if (!strcasecmp(data, "name")) {
468 locked_copy_string(chan, buf, ast_channel_name(chan), len);
469 } else if (!strcasecmp(data, "parkinglot"))
470 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
471 else if (!strcasecmp(data, "state"))
472 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
473 else if (!strcasecmp(data, "channeltype"))
474 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
475 else if (!strcasecmp(data, "accountcode"))
476 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
477 else if (!strcasecmp(data, "checkhangup")) {
478 ast_channel_lock(chan);
479 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
480 ast_channel_unlock(chan);
481 } else if (!strcasecmp(data, "peeraccount"))
482 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
483 else if (!strcasecmp(data, "hangupsource"))
484 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
485 else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
486 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
487 else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
488 locked_copy_string(chan, buf, ast_channel_data(chan), len);
489 else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
490 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
491 else if (!strcasecmp(data, "context") && ast_channel_data(chan))
492 locked_copy_string(chan, buf, ast_channel_context(chan), len);
493 else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
494 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
495 else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
496 locked_copy_string(chan, buf, ast_channel_name(chan), len);
497 else if (!strcasecmp(data, "linkedid")) {
498 ast_channel_lock(chan);
499 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
500 /* fall back on the channel's uniqueid if linkedid is unset */
501 ast_copy_string(buf, ast_channel_uniqueid(chan), len);
504 ast_copy_string(buf, ast_channel_linkedid(chan), len);
506 ast_channel_unlock(chan);
507 } else if (!strcasecmp(data, "peer")) {
508 RAII_VAR(struct ast_channel *, p, NULL, ast_channel_cleanup);
510 ast_channel_lock(chan);
511 p = ast_channel_bridge_peer(chan);
512 if (p || ast_channel_tech(chan)) /* dummy channel? if so, we hid the peer name in the language */
513 ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
515 /* a dummy channel can still pass along bridged peer info via
516 the BRIDGEPEER variable */
517 const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
518 if (!ast_strlen_zero(pname))
519 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
523 ast_channel_unlock(chan);
524 } else if (!strcasecmp(data, "uniqueid")) {
525 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
526 } else if (!strcasecmp(data, "transfercapability")) {
527 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
528 } else if (!strcasecmp(data, "callgroup")) {
531 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
532 } else if (!strcasecmp(data, "pickupgroup")) {
535 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
536 } else if (!strcasecmp(data, "namedcallgroup")) {
537 struct ast_str *tmp_str = ast_str_alloca(1024);
539 locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
540 } else if (!strcasecmp(data, "namedpickupgroup")) {
541 struct ast_str *tmp_str = ast_str_alloca(1024);
543 locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
544 } else if (!strcasecmp(data, "after_bridge_goto")) {
545 ast_bridge_read_after_goto(chan, buf, len);
546 } else if (!strcasecmp(data, "amaflags")) {
547 ast_channel_lock(chan);
548 snprintf(buf, len, "%u", ast_channel_amaflags(chan));
549 ast_channel_unlock(chan);
550 } else if (!strncasecmp(data, "secure_bridge_", 14)) {
551 struct ast_datastore *ds;
553 ast_channel_lock(chan);
554 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
555 struct ast_secure_call_store *encrypt = ds->data;
556 if (!strcasecmp(data, "secure_bridge_signaling")) {
557 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
558 } else if (!strcasecmp(data, "secure_bridge_media")) {
559 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
562 ast_channel_unlock(chan);
563 } 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)) {
564 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
571 static int func_channel_write_real(struct ast_channel *chan, const char *function,
572 char *data, const char *value)
577 if (!strcasecmp(data, "language"))
578 locked_string_field_set(chan, language, value);
579 else if (!strcasecmp(data, "parkinglot"))
580 locked_string_field_set(chan, parkinglot, value);
581 else if (!strcasecmp(data, "musicclass"))
582 locked_string_field_set(chan, musicclass, value);
583 else if (!strcasecmp(data, "accountcode"))
584 locked_string_field_set(chan, accountcode, value);
585 else if (!strcasecmp(data, "userfield"))
586 locked_string_field_set(chan, userfield, value);
587 else if (!strcasecmp(data, "after_bridge_goto")) {
588 if (ast_strlen_zero(value)) {
589 ast_bridge_discard_after_goto(chan);
591 ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
593 } else if (!strcasecmp(data, "amaflags")) {
594 ast_channel_lock(chan);
595 if (isdigit(*value)) {
597 sscanf(value, "%30d", &amaflags);
598 ast_channel_amaflags_set(chan, amaflags);
599 } else if (!strcasecmp(value,"OMIT")){
600 ast_channel_amaflags_set(chan, 1);
601 } else if (!strcasecmp(value,"BILLING")){
602 ast_channel_amaflags_set(chan, 2);
603 } else if (!strcasecmp(value,"DOCUMENTATION")){
604 ast_channel_amaflags_set(chan, 3);
606 ast_channel_unlock(chan);
607 } else if (!strcasecmp(data, "peeraccount"))
608 locked_string_field_set(chan, peeraccount, value);
609 else if (!strcasecmp(data, "hangupsource"))
610 /* XXX - should we be forcing this here? */
611 ast_set_hangupsource(chan, value, 0);
613 else if (!strcasecmp(data, "trace")) {
614 ast_channel_lock(chan);
616 ret = ast_channel_trace_enable(chan);
617 else if (ast_false(value))
618 ret = ast_channel_trace_disable(chan);
621 ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
623 ast_channel_unlock(chan);
626 else if (!strcasecmp(data, "tonezone")) {
627 struct ast_tone_zone *new_zone;
628 if (!(new_zone = ast_get_indication_zone(value))) {
629 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
632 ast_channel_lock(chan);
633 if (ast_channel_zone(chan)) {
634 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
636 ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
637 ast_channel_unlock(chan);
638 new_zone = ast_tone_zone_unref(new_zone);
640 } else if (!strcasecmp(data, "dtmf_features")) {
641 ret = ast_bridge_features_ds_set_string(chan, value);
642 } else if (!strcasecmp(data, "callgroup")) {
643 ast_channel_lock(chan);
644 ast_channel_callgroup_set(chan, ast_get_group(value));
645 ast_channel_unlock(chan);
646 } else if (!strcasecmp(data, "pickupgroup")) {
647 ast_channel_lock(chan);
648 ast_channel_pickupgroup_set(chan, ast_get_group(value));
649 ast_channel_unlock(chan);
650 } else if (!strcasecmp(data, "namedcallgroup")) {
651 struct ast_namedgroups *groups = ast_get_namedgroups(value);
653 ast_channel_lock(chan);
654 ast_channel_named_callgroups_set(chan, groups);
655 ast_channel_unlock(chan);
656 ast_unref_namedgroups(groups);
657 } else if (!strcasecmp(data, "namedpickupgroup")) {
658 struct ast_namedgroups *groups = ast_get_namedgroups(value);
660 ast_channel_lock(chan);
661 ast_channel_named_pickupgroups_set(chan, groups);
662 ast_channel_unlock(chan);
663 ast_unref_namedgroups(groups);
664 } else if (!strcasecmp(data, "txgain")) {
665 sscanf(value, "%4hhd", &gainset);
666 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
667 } else if (!strcasecmp(data, "rxgain")) {
668 sscanf(value, "%4hhd", &gainset);
669 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
670 } else if (!strcasecmp(data, "transfercapability")) {
673 ast_channel_lock(chan);
674 for (i = 0; i < 0x20; i++) {
675 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
676 ast_channel_transfercapability_set(chan, i);
680 ast_channel_unlock(chan);
681 } else if (!strcasecmp(data, "hangup_handler_pop")) {
682 /* Pop one hangup handler before pushing the new handler. */
683 ast_pbx_hangup_handler_pop(chan);
684 ast_pbx_hangup_handler_push(chan, value);
685 } else if (!strcasecmp(data, "hangup_handler_push")) {
686 ast_pbx_hangup_handler_push(chan, value);
687 } else if (!strcasecmp(data, "hangup_handler_wipe")) {
688 /* Pop all hangup handlers before pushing the new handler. */
689 while (ast_pbx_hangup_handler_pop(chan)) {
691 ast_pbx_hangup_handler_push(chan, value);
692 } else if (!strncasecmp(data, "secure_bridge_", 14)) {
693 struct ast_datastore *ds;
694 struct ast_secure_call_store *store;
696 if (!chan || !value) {
700 ast_channel_lock(chan);
701 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
702 if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
703 ast_channel_unlock(chan);
706 if (!(store = ast_calloc(1, sizeof(*store)))) {
707 ast_channel_unlock(chan);
712 ast_channel_datastore_add(chan, ds);
717 if (!strcasecmp(data, "secure_bridge_signaling")) {
718 store->signaling = ast_true(value) ? 1 : 0;
719 } else if (!strcasecmp(data, "secure_bridge_media")) {
720 store->media = ast_true(value) ? 1 : 0;
722 ast_channel_unlock(chan);
723 } else if (!ast_channel_tech(chan)->func_channel_write
724 || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
725 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
733 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
736 ast_chan_write_info_t write_info = {
737 .version = AST_CHAN_WRITE_INFO_T_VERSION,
738 .write_fn = func_channel_write_real,
740 .function = function,
746 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
750 res = func_channel_write_real(chan, function, data, value);
751 ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
756 static struct ast_custom_function channel_function = {
758 .read = func_channel_read,
759 .write = func_channel_write,
762 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
764 struct ast_channel *c = NULL;
768 struct ast_channel_iterator *iter;
772 if (!ast_strlen_zero(data)) {
773 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
774 regerror(res, &re, buf, maxlen);
775 ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
780 if (!(iter = ast_channel_iterator_all_new())) {
781 if (!ast_strlen_zero(data)) {
787 while ((c = ast_channel_iterator_next(iter))) {
789 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
790 size_t namelen = strlen(ast_channel_name(c));
791 if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
792 if (!ast_strlen_zero(buf)) {
796 strcat(buf, ast_channel_name(c));
799 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
802 ast_channel_unlock(c);
803 c = ast_channel_unref(c);
806 ast_channel_iterator_destroy(iter);
808 if (!ast_strlen_zero(data)) {
815 static struct ast_custom_function channels_function = {
817 .read = func_channels_read,
820 static int func_mchan_read(struct ast_channel *chan, const char *function,
821 char *data, struct ast_str **buf, ssize_t len)
823 struct ast_channel *mchan;
824 char *template = ast_alloca(4 + strlen(data));
827 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
831 mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
832 sprintf(template, "${%s}", data); /* SAFE */
833 ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
835 ast_channel_unref(mchan);
840 static int func_mchan_write(struct ast_channel *chan, const char *function,
841 char *data, const char *value)
843 struct ast_channel *mchan;
846 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
850 mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
851 pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
853 ast_channel_unref(mchan);
858 static struct ast_custom_function mchan_function = {
859 .name = "MASTER_CHANNEL",
860 .read2 = func_mchan_read,
861 .write = func_mchan_write,
864 static int unload_module(void)
868 res |= ast_custom_function_unregister(&channel_function);
869 res |= ast_custom_function_unregister(&channels_function);
870 res |= ast_custom_function_unregister(&mchan_function);
875 static int load_module(void)
879 res |= ast_custom_function_register(&channel_function);
880 res |= ast_custom_function_register(&channels_function);
881 res |= ast_custom_function_register(&mchan_function);
886 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");