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>
216 <enum name="recvport">
217 <para>R/O Get the source port of the peer.</para>
220 <para>R/O Get the URI from the From: header.</para>
223 <para>R/O Get the URI from the Contact: header.</para>
225 <enum name="useragent">
226 <para>R/O Get the useragent.</para>
228 <enum name="peername">
229 <para>R/O Get the name of the peer.</para>
231 <enum name="t38passthrough">
232 <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
233 otherwise <literal>0</literal></para>
236 <para>R/O Get QOS information about the RTP stream</para>
237 <para> This option takes two additional arguments:</para>
238 <para> Argument 1:</para>
239 <para> <literal>audio</literal> Get data about the audio stream</para>
240 <para> <literal>video</literal> Get data about the video stream</para>
241 <para> <literal>text</literal> Get data about the text stream</para>
242 <para> Argument 2:</para>
243 <para> <literal>local_ssrc</literal> Local SSRC (stream ID)</para>
244 <para> <literal>local_lostpackets</literal> Local lost packets</para>
245 <para> <literal>local_jitter</literal> Local calculated jitter</para>
246 <para> <literal>local_maxjitter</literal> Local calculated jitter (maximum)</para>
247 <para> <literal>local_minjitter</literal> Local calculated jitter (minimum)</para>
248 <para> <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
249 <para> <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
250 <para> <literal>local_count</literal> Number of received packets</para>
251 <para> <literal>remote_ssrc</literal> Remote SSRC (stream ID)</para>
252 <para> <literal>remote_lostpackets</literal>Remote lost packets</para>
253 <para> <literal>remote_jitter</literal> Remote reported jitter</para>
254 <para> <literal>remote_maxjitter</literal> Remote calculated jitter (maximum)</para>
255 <para> <literal>remote_minjitter</literal> Remote calculated jitter (minimum)</para>
256 <para> <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
257 <para> <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
258 <para> <literal>remote_count</literal> Number of transmitted packets</para>
259 <para> <literal>rtt</literal> Round trip time</para>
260 <para> <literal>maxrtt</literal> Round trip time (maximum)</para>
261 <para> <literal>minrtt</literal> Round trip time (minimum)</para>
262 <para> <literal>normdevrtt</literal> Round trip time (normal deviation)</para>
263 <para> <literal>stdevrtt</literal> Round trip time (standard deviation)</para>
264 <para> <literal>all</literal> All statistics (in a form suited to logging,
265 but not for parsing)</para>
267 <enum name="rtpdest">
268 <para>R/O Get remote RTP destination information.</para>
269 <para> This option takes one additional argument:</para>
270 <para> Argument 1:</para>
271 <para> <literal>audio</literal> Get audio destination</para>
272 <para> <literal>video</literal> Get video destination</para>
273 <para> <literal>text</literal> Get text destination</para>
274 <para> Defaults to <literal>audio</literal> if unspecified.</para>
276 <enum name="rtpsource">
277 <para>R/O Get source RTP destination information.</para>
278 <para> This option takes one additional argument:</para>
279 <para> Argument 1:</para>
280 <para> <literal>audio</literal> Get audio destination</para>
281 <para> <literal>video</literal> Get video destination</para>
282 <para> <literal>text</literal> Get text destination</para>
283 <para> Defaults to <literal>audio</literal> if unspecified.</para>
286 <xi:include xpointer="xpointer(/docs/info[@name='PJSIPCHANNEL'])" />
287 <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
289 <enum name="osptoken">
290 <para>R/O Get the peer's osptoken.</para>
293 <para>R/O Get the peer's ip address.</para>
295 <enum name="peername">
296 <para>R/O Get the peer's username.</para>
298 <enum name="secure_signaling">
299 <para>R/O Get the if the IAX channel is secured.</para>
301 <enum name="secure_media">
302 <para>R/O Get the if the IAX channel is secured.</para>
305 <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
307 <enum name="dahdi_channel">
308 <para>R/O DAHDI channel related to this channel.</para>
310 <enum name="dahdi_span">
311 <para>R/O DAHDI span related to this channel.</para>
313 <enum name="dahdi_type">
314 <para>R/O DAHDI channel type, one of:</para>
316 <enum name="analog" />
317 <enum name="mfc/r2" />
319 <enum name="pseudo" />
323 <enum name="keypad_digits">
324 <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
326 <enum name="reversecharge">
327 <para>R/O PRI Reverse Charging Indication, one of:</para>
329 <enum name="-1"> <para>None</para></enum>
330 <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
333 <enum name="no_media_path">
334 <para>R/O PRI Nonzero if the channel has no B channel.
335 The channel is either on hold or a call waiting call.</para>
337 <enum name="buffers">
338 <para>W/O Change the channel's buffer policy (for the current call only)</para>
339 <para>This option takes two arguments:</para>
340 <para> Number of buffers,</para>
341 <para> Buffer policy being one of:</para>
342 <para> <literal>full</literal></para>
343 <para> <literal>immediate</literal></para>
344 <para> <literal>half</literal></para>
346 <enum name="echocan_mode">
347 <para>W/O Change the configuration of the active echo
348 canceller on the channel (if any), for the current call
350 <para>Possible values are:</para>
351 <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitalized)</para>
352 <para> <literal>off</literal> Disabled</para>
353 <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
354 completely disabled)</para>
355 <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
358 <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
360 <enum name="faxdetect">
361 <para>R/W Fax Detect</para>
362 <para>Returns 0 or 1</para>
363 <para>Write yes or no</para>
365 <enum name="t38support">
366 <para>R/W t38support</para>
367 <para>Returns 0 or 1</para>
368 <para>Write yes or no</para>
370 <enum name="h323id_url">
371 <para>R/0 Returns caller URL</para>
373 <enum name="caller_h323id">
374 <para>R/0 Returns caller h323id</para>
376 <enum name="caller_dialeddigits">
377 <para>R/0 Returns caller dialed digits</para>
379 <enum name="caller_email">
380 <para>R/0 Returns caller email</para>
382 <enum name="callee_email">
383 <para>R/0 Returns callee email</para>
385 <enum name="callee_dialeddigits">
386 <para>R/0 Returns callee dialed digits</para>
388 <enum name="caller_url">
389 <para>R/0 Returns caller URL</para>
395 <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
396 be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
397 requested that is not available on the current channel will return an empty string.</para>
402 #define locked_copy_string(chan, dest, source, len) \
404 ast_channel_lock(chan); \
405 ast_copy_string(dest, source, len); \
406 ast_channel_unlock(chan); \
408 #define locked_string_field_set(chan, field, source) \
410 ast_channel_lock(chan); \
411 ast_channel_##field##_set(chan, source); \
412 ast_channel_unlock(chan); \
415 static const char * const transfercapability_table[0x20] = {
416 "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
417 "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
418 "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
419 "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
421 static int func_channel_read(struct ast_channel *chan, const char *function,
422 char *data, char *buf, size_t len)
425 struct ast_format_cap *tmpcap;
428 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
432 if (!strcasecmp(data, "audionativeformat")) {
433 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
435 struct ast_str *codec_buf = ast_str_alloca(64);
437 ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
438 ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
441 } else if (!strcasecmp(data, "videonativeformat")) {
442 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
444 struct ast_str *codec_buf = ast_str_alloca(64);
446 ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
447 ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
450 } else if (!strcasecmp(data, "audioreadformat")) {
451 ast_copy_string(buf, ast_format_get_name(ast_channel_readformat(chan)), len);
452 } else if (!strcasecmp(data, "audiowriteformat")) {
453 ast_copy_string(buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
455 } else if (!strcasecmp(data, "trace")) {
456 ast_channel_lock(chan);
457 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
458 ast_channel_unlock(chan);
460 } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
461 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
462 } else if (!strcasecmp(data, "dtmf_features")) {
463 if (ast_bridge_features_ds_get_string(chan, buf, len)) {
466 } else if (!strcasecmp(data, "language"))
467 locked_copy_string(chan, buf, ast_channel_language(chan), len);
468 else if (!strcasecmp(data, "musicclass"))
469 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
470 else if (!strcasecmp(data, "name")) {
471 locked_copy_string(chan, buf, ast_channel_name(chan), len);
472 } else if (!strcasecmp(data, "parkinglot"))
473 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
474 else if (!strcasecmp(data, "state"))
475 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
476 else if (!strcasecmp(data, "channeltype"))
477 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
478 else if (!strcasecmp(data, "accountcode"))
479 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
480 else if (!strcasecmp(data, "checkhangup")) {
481 ast_channel_lock(chan);
482 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
483 ast_channel_unlock(chan);
484 } else if (!strcasecmp(data, "peeraccount"))
485 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
486 else if (!strcasecmp(data, "hangupsource"))
487 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
488 else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
489 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
490 else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
491 locked_copy_string(chan, buf, ast_channel_data(chan), len);
492 else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
493 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
494 else if (!strcasecmp(data, "context") && ast_channel_data(chan))
495 locked_copy_string(chan, buf, ast_channel_context(chan), len);
496 else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
497 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
498 else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
499 locked_copy_string(chan, buf, ast_channel_name(chan), len);
500 else if (!strcasecmp(data, "linkedid")) {
501 ast_channel_lock(chan);
502 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
503 /* fall back on the channel's uniqueid if linkedid is unset */
504 ast_copy_string(buf, ast_channel_uniqueid(chan), len);
507 ast_copy_string(buf, ast_channel_linkedid(chan), len);
509 ast_channel_unlock(chan);
510 } else if (!strcasecmp(data, "peer")) {
511 RAII_VAR(struct ast_channel *, p, NULL, ast_channel_cleanup);
513 ast_channel_lock(chan);
514 p = ast_channel_bridge_peer(chan);
515 if (p || ast_channel_tech(chan)) /* dummy channel? if so, we hid the peer name in the language */
516 ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
518 /* a dummy channel can still pass along bridged peer info via
519 the BRIDGEPEER variable */
520 const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
521 if (!ast_strlen_zero(pname))
522 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
526 ast_channel_unlock(chan);
527 } else if (!strcasecmp(data, "uniqueid")) {
528 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
529 } else if (!strcasecmp(data, "transfercapability")) {
530 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
531 } else if (!strcasecmp(data, "callgroup")) {
534 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
535 } else if (!strcasecmp(data, "pickupgroup")) {
538 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
539 } else if (!strcasecmp(data, "namedcallgroup")) {
540 struct ast_str *tmp_str = ast_str_alloca(1024);
542 locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
543 } else if (!strcasecmp(data, "namedpickupgroup")) {
544 struct ast_str *tmp_str = ast_str_alloca(1024);
546 locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
547 } else if (!strcasecmp(data, "after_bridge_goto")) {
548 ast_bridge_read_after_goto(chan, buf, len);
549 } else if (!strcasecmp(data, "amaflags")) {
550 ast_channel_lock(chan);
551 snprintf(buf, len, "%u", ast_channel_amaflags(chan));
552 ast_channel_unlock(chan);
553 } else if (!strncasecmp(data, "secure_bridge_", 14)) {
554 struct ast_datastore *ds;
556 ast_channel_lock(chan);
557 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
558 struct ast_secure_call_store *encrypt = ds->data;
559 if (!strcasecmp(data, "secure_bridge_signaling")) {
560 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
561 } else if (!strcasecmp(data, "secure_bridge_media")) {
562 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
565 ast_channel_unlock(chan);
566 } 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)) {
567 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
574 static int func_channel_write_real(struct ast_channel *chan, const char *function,
575 char *data, const char *value)
580 if (!strcasecmp(data, "language"))
581 locked_string_field_set(chan, language, value);
582 else if (!strcasecmp(data, "parkinglot"))
583 locked_string_field_set(chan, parkinglot, value);
584 else if (!strcasecmp(data, "musicclass"))
585 locked_string_field_set(chan, musicclass, value);
586 else if (!strcasecmp(data, "accountcode"))
587 locked_string_field_set(chan, accountcode, value);
588 else if (!strcasecmp(data, "userfield"))
589 locked_string_field_set(chan, userfield, value);
590 else if (!strcasecmp(data, "after_bridge_goto")) {
591 if (ast_strlen_zero(value)) {
592 ast_bridge_discard_after_goto(chan);
594 ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
596 } else if (!strcasecmp(data, "amaflags")) {
597 ast_channel_lock(chan);
598 if (isdigit(*value)) {
600 sscanf(value, "%30d", &amaflags);
601 ast_channel_amaflags_set(chan, amaflags);
602 } else if (!strcasecmp(value,"OMIT")){
603 ast_channel_amaflags_set(chan, 1);
604 } else if (!strcasecmp(value,"BILLING")){
605 ast_channel_amaflags_set(chan, 2);
606 } else if (!strcasecmp(value,"DOCUMENTATION")){
607 ast_channel_amaflags_set(chan, 3);
609 ast_channel_unlock(chan);
610 } else if (!strcasecmp(data, "peeraccount"))
611 locked_string_field_set(chan, peeraccount, value);
612 else if (!strcasecmp(data, "hangupsource"))
613 /* XXX - should we be forcing this here? */
614 ast_set_hangupsource(chan, value, 0);
616 else if (!strcasecmp(data, "trace")) {
617 ast_channel_lock(chan);
619 ret = ast_channel_trace_enable(chan);
620 else if (ast_false(value))
621 ret = ast_channel_trace_disable(chan);
624 ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
626 ast_channel_unlock(chan);
629 else if (!strcasecmp(data, "tonezone")) {
630 struct ast_tone_zone *new_zone;
631 if (!(new_zone = ast_get_indication_zone(value))) {
632 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
635 ast_channel_lock(chan);
636 if (ast_channel_zone(chan)) {
637 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
639 ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
640 ast_channel_unlock(chan);
641 new_zone = ast_tone_zone_unref(new_zone);
643 } else if (!strcasecmp(data, "dtmf_features")) {
644 ret = ast_bridge_features_ds_set_string(chan, value);
645 } else if (!strcasecmp(data, "callgroup")) {
646 ast_channel_lock(chan);
647 ast_channel_callgroup_set(chan, ast_get_group(value));
648 ast_channel_unlock(chan);
649 } else if (!strcasecmp(data, "pickupgroup")) {
650 ast_channel_lock(chan);
651 ast_channel_pickupgroup_set(chan, ast_get_group(value));
652 ast_channel_unlock(chan);
653 } else if (!strcasecmp(data, "namedcallgroup")) {
654 struct ast_namedgroups *groups = ast_get_namedgroups(value);
656 ast_channel_lock(chan);
657 ast_channel_named_callgroups_set(chan, groups);
658 ast_channel_unlock(chan);
659 ast_unref_namedgroups(groups);
660 } else if (!strcasecmp(data, "namedpickupgroup")) {
661 struct ast_namedgroups *groups = ast_get_namedgroups(value);
663 ast_channel_lock(chan);
664 ast_channel_named_pickupgroups_set(chan, groups);
665 ast_channel_unlock(chan);
666 ast_unref_namedgroups(groups);
667 } else if (!strcasecmp(data, "txgain")) {
668 sscanf(value, "%4hhd", &gainset);
669 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
670 } else if (!strcasecmp(data, "rxgain")) {
671 sscanf(value, "%4hhd", &gainset);
672 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
673 } else if (!strcasecmp(data, "transfercapability")) {
676 ast_channel_lock(chan);
677 for (i = 0; i < 0x20; i++) {
678 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
679 ast_channel_transfercapability_set(chan, i);
683 ast_channel_unlock(chan);
684 } else if (!strcasecmp(data, "hangup_handler_pop")) {
685 /* Pop one hangup handler before pushing the new handler. */
686 ast_pbx_hangup_handler_pop(chan);
687 ast_pbx_hangup_handler_push(chan, value);
688 } else if (!strcasecmp(data, "hangup_handler_push")) {
689 ast_pbx_hangup_handler_push(chan, value);
690 } else if (!strcasecmp(data, "hangup_handler_wipe")) {
691 /* Pop all hangup handlers before pushing the new handler. */
692 while (ast_pbx_hangup_handler_pop(chan)) {
694 ast_pbx_hangup_handler_push(chan, value);
695 } else if (!strncasecmp(data, "secure_bridge_", 14)) {
696 struct ast_datastore *ds;
697 struct ast_secure_call_store *store;
699 if (!chan || !value) {
703 ast_channel_lock(chan);
704 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
705 if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
706 ast_channel_unlock(chan);
709 if (!(store = ast_calloc(1, sizeof(*store)))) {
710 ast_channel_unlock(chan);
715 ast_channel_datastore_add(chan, ds);
720 if (!strcasecmp(data, "secure_bridge_signaling")) {
721 store->signaling = ast_true(value) ? 1 : 0;
722 } else if (!strcasecmp(data, "secure_bridge_media")) {
723 store->media = ast_true(value) ? 1 : 0;
725 ast_channel_unlock(chan);
726 } else if (!ast_channel_tech(chan)->func_channel_write
727 || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
728 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
736 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
739 ast_chan_write_info_t write_info = {
740 .version = AST_CHAN_WRITE_INFO_T_VERSION,
741 .write_fn = func_channel_write_real,
743 .function = function,
749 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
753 res = func_channel_write_real(chan, function, data, value);
754 ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
759 static struct ast_custom_function channel_function = {
761 .read = func_channel_read,
762 .write = func_channel_write,
765 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
767 struct ast_channel *c = NULL;
771 struct ast_channel_iterator *iter;
775 if (!ast_strlen_zero(data)) {
776 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
777 regerror(res, &re, buf, maxlen);
778 ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
783 if (!(iter = ast_channel_iterator_all_new())) {
784 if (!ast_strlen_zero(data)) {
790 while ((c = ast_channel_iterator_next(iter))) {
792 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
793 size_t namelen = strlen(ast_channel_name(c));
794 if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
795 if (!ast_strlen_zero(buf)) {
799 strcat(buf, ast_channel_name(c));
802 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
805 ast_channel_unlock(c);
806 c = ast_channel_unref(c);
809 ast_channel_iterator_destroy(iter);
811 if (!ast_strlen_zero(data)) {
818 static struct ast_custom_function channels_function = {
820 .read = func_channels_read,
823 static int func_mchan_read(struct ast_channel *chan, const char *function,
824 char *data, struct ast_str **buf, ssize_t len)
826 struct ast_channel *mchan;
827 char *template = ast_alloca(4 + strlen(data));
830 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
834 mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
835 sprintf(template, "${%s}", data); /* SAFE */
836 ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
838 ast_channel_unref(mchan);
843 static int func_mchan_write(struct ast_channel *chan, const char *function,
844 char *data, const char *value)
846 struct ast_channel *mchan;
849 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
853 mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
854 pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
856 ast_channel_unref(mchan);
861 static struct ast_custom_function mchan_function = {
862 .name = "MASTER_CHANNEL",
863 .read2 = func_mchan_read,
864 .write = func_mchan_write,
867 static int unload_module(void)
871 res |= ast_custom_function_unregister(&channel_function);
872 res |= ast_custom_function_unregister(&channels_function);
873 res |= ast_custom_function_unregister(&mchan_function);
878 static int load_module(void)
882 res |= ast_custom_function_register(&channel_function);
883 res |= ast_custom_function_register(&channels_function);
884 res |= ast_custom_function_register(&mchan_function);
889 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");