Asterisk - The Open Source Telephony Project  21.4.1
func_channel.c
Go to the documentation of this file.
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  * \author Naveen Albert <asterisk@phreaknet.org>
24  *
25  * \ingroup functions
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include <regex.h>
35 #include <ctype.h>
36 
37 #include "asterisk/module.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/bridge.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"
46 #include "asterisk/bridge_basic.h"
47 #include "asterisk/bridge_after.h"
48 #include "asterisk/max_forwards.h"
49 
50 /*** DOCUMENTATION
51  <function name="CHANNELS" language="en_US">
52  <synopsis>
53  Gets the list of channels, optionally filtering by a regular expression.
54  </synopsis>
55  <syntax>
56  <parameter name="regular_expression" />
57  </syntax>
58  <description>
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>
64  </description>
65  </function>
66  <function name="CHANNEL_EXISTS" language="en_US">
67  <since>
68  <version>16.22.0</version>
69  <version>18.8.0</version>
70  <version>19.0.0</version>
71  </since>
72  <synopsis>
73  Checks if the specified channel exists.
74  </synopsis>
75  <syntax>
76  <parameter name="name_or_uid" required="true">
77  <para>The name or unique ID of the channel to check.</para>
78  </parameter>
79  </syntax>
80  <description>
81  <para>Returns 1 if the channel <replaceable>name_or_uid</replaceable> exists, 0 if not.</para>
82  </description>
83  </function>
84  <function name="MASTER_CHANNEL" language="en_US">
85  <synopsis>
86  Gets or sets variables on the master channel
87  </synopsis>
88  <description>
89  <para>Allows access to the oldest channel associated with the current
90  channel if it still exists. If the channel is the master channel or
91  the master channel no longer exists then access local channel variables
92  instead. In other words, the master channel is the channel identified by
93  the channel's linkedid.</para>
94  </description>
95  </function>
96  <function name="CHANNEL" language="en_US">
97  <synopsis>
98  Gets/sets various pieces of information about the channel.
99  </synopsis>
100  <syntax>
101  <parameter name="item" required="true">
102  <para>Standard items (provided by all channel technologies) are:</para>
103  <enumlist>
104  <enum name="amaflags">
105  <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
106  When read from a channel, the integer value will always be returned.
107  When written to a channel, both the string format or integer value
108  is accepted.</para>
109  <enumlist>
110  <enum name="1"><para><literal>OMIT</literal></para></enum>
111  <enum name="2"><para><literal>BILLING</literal></para></enum>
112  <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
113  </enumlist>
114  </enum>
115  <enum name="accountcode">
116  <para>R/W the channel's account code.</para>
117  </enum>
118  <enum name="audioreadformat">
119  <para>R/O format currently being read.</para>
120  </enum>
121  <enum name="audionativeformat">
122  <para>R/O format used natively for audio.</para>
123  </enum>
124  <enum name="audiowriteformat">
125  <para>R/O format currently being written.</para>
126  </enum>
127  <enum name="dtmf_features">
128  <para>R/W The channel's DTMF bridge features.
129  May include one or more of 'T' 'K' 'H' 'W' and 'X' in a similar manner to options
130  in the <literal>Dial</literal> application. When setting it, the features string
131  must be all upper case.</para>
132  </enum>
133  <enum name="callgroup">
134  <para>R/W numeric call pickup groups that this channel is a member.</para>
135  </enum>
136  <enum name="pickupgroup">
137  <para>R/W numeric call pickup groups this channel can pickup.</para>
138  </enum>
139  <enum name="namedcallgroup">
140  <para>R/W named call pickup groups that this channel is a member.</para>
141  </enum>
142  <enum name="namedpickupgroup">
143  <para>R/W named call pickup groups this channel can pickup.</para>
144  </enum>
145  <enum name="channeltype">
146  <para>R/O technology used for channel.</para>
147  </enum>
148  <enum name="checkhangup">
149  <para>R/O Whether the channel is hanging up (1/0)</para>
150  </enum>
151  <enum name="digitdetect">
152  <para>R/W Enable or disable DTMF detection on channel drivers that support it.</para>
153  <para>If set on a DAHDI channel, this will only disable DTMF detection, not pulse dialing detection.
154  To disable pulse dialing, use the <literal>dialmode</literal> option.</para>
155  <para>On DAHDI channels, this will disable DSP if it is not needed for anything else.
156  This will prevent DTMF detection regardless of the <literal>dialmode</literal> setting.</para>
157  </enum>
158  <enum name="faxdetect">
159  <para>R/W Enable or disable fax detection on channel drivers that support it.</para>
160  </enum>
161  <enum name="after_bridge_goto">
162  <para>R/W the parseable goto string indicating where the channel is
163  expected to return to in the PBX after exiting the next bridge it joins
164  on the condition that it doesn't hang up. The parseable goto string uses
165  the same syntax as the <literal>Goto</literal> application.</para>
166  </enum>
167  <enum name="hangup_handler_pop">
168  <para>W/O Replace the most recently added hangup handler
169  with a new hangup handler on the channel if supplied. The
170  assigned string is passed to the Gosub application when
171  the channel is hung up. Any optionally omitted context
172  and exten are supplied by the channel pushing the handler
173  before it is pushed.</para>
174  </enum>
175  <enum name="hangup_handler_push">
176  <para>W/O Push a hangup handler onto the channel hangup
177  handler stack. The assigned string is passed to the
178  Gosub application when the channel is hung up. Any
179  optionally omitted context and exten are supplied by the
180  channel pushing the handler before it is pushed.</para>
181  </enum>
182  <enum name="hangup_handler_wipe">
183  <para>W/O Wipe the entire hangup handler stack and replace
184  with a new hangup handler on the channel if supplied. The
185  assigned string is passed to the Gosub application when
186  the channel is hung up. Any optionally omitted context
187  and exten are supplied by the channel pushing the handler
188  before it is pushed.</para>
189  </enum>
190  <enum name="onhold">
191  <para>R/O Whether or not the channel is onhold. (1/0)</para>
192  </enum>
193  <enum name="language">
194  <para>R/W language for sounds played.</para>
195  </enum>
196  <enum name="musicclass">
197  <para>R/W class (from musiconhold.conf) for hold music.</para>
198  </enum>
199  <enum name="name">
200  <para>The name of the channel</para>
201  </enum>
202  <enum name="parkinglot">
203  <para>R/W parkinglot for parking.</para>
204  </enum>
205  <enum name="relaxdtmf">
206  <para>W/O Enable or disable relaxed DTMF detection for channel drivers that support it,
207  overriding any setting previously defaulted by the channel driver.</para>
208  </enum>
209  <enum name="rxgain">
210  <para>R/W set rxgain level on channel drivers that support it.</para>
211  </enum>
212  <enum name="secure_bridge_signaling">
213  <para>Whether or not channels bridged to this channel require secure signaling (1/0)</para>
214  </enum>
215  <enum name="secure_bridge_media">
216  <para>Whether or not channels bridged to this channel require secure media (1/0)</para>
217  </enum>
218  <enum name="state">
219  <para>R/O state of the channel</para>
220  </enum>
221  <enum name="tdd">
222  <para>R/W Enable or disable TDD mode on channel drivers that support it.</para>
223  <para>When reading this option, 1 indicates TDD mode enabled, 0 indicates TDD mode disabled,
224  and <literal>mate</literal> indicates TDD mate mode.</para>
225  </enum>
226  <enum name="tonezone">
227  <para>R/W zone for indications played</para>
228  </enum>
229  <enum name="transfercapability">
230  <para>R/W ISDN Transfer Capability, one of:</para>
231  <enumlist>
232  <enum name="SPEECH" />
233  <enum name="DIGITAL" />
234  <enum name="RESTRICTED_DIGITAL" />
235  <enum name="3K1AUDIO" />
236  <enum name="DIGITAL_W_TONES" />
237  <enum name="VIDEO" />
238  </enumlist>
239  </enum>
240  <enum name="txgain">
241  <para>R/W set txgain level on channel drivers that support it.</para>
242  </enum>
243  <enum name="videonativeformat">
244  <para>R/O format used natively for video</para>
245  </enum>
246  <enum name="hangupsource">
247  <para>R/W returns the channel responsible for hangup.</para>
248  </enum>
249  <enum name="appname">
250  <para>R/O returns the internal application name.</para>
251  </enum>
252  <enum name="appdata">
253  <para>R/O returns the application data if available.</para>
254  </enum>
255  <enum name="exten">
256  <para>R/O returns the extension for an outbound channel.</para>
257  </enum>
258  <enum name="context">
259  <para>R/O returns the context for an outbound channel.</para>
260  </enum>
261  <enum name="lastexten">
262  <para>R/O returns the last unique extension for an outbound channel.</para>
263  </enum>
264  <enum name="lastcontext">
265  <para>R/O returns the last unique context for an outbound channel.</para>
266  </enum>
267  <enum name="channame">
268  <para>R/O returns the channel name for an outbound channel.</para>
269  </enum>
270  <enum name="uniqueid">
271  <para>R/O returns the channel uniqueid.</para>
272  </enum>
273  <enum name="linkedid">
274  <para>R/O returns the linkedid if available, otherwise returns the uniqueid.</para>
275  </enum>
276  <enum name="max_forwards">
277  <para>R/W The maximum number of forwards allowed.</para>
278  </enum>
279  <enum name="callid">
280  <para>R/O Call identifier log tag associated with the channel
281  e.g., <literal>[C-00000000]</literal>.</para>
282  </enum>
283  </enumlist>
284  <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL'])" />
285  </parameter>
286  </syntax>
287  <description>
288  <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
289  be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
290  requested that is not available on the current channel will return an empty string.</para>
291  <example title="Standard CHANNEL item examples">
292  ; Push a hangup handler subroutine existing at dialplan
293  ; location default,s,1 onto the current channel
294  same => n,Set(CHANNEL(hangup_handler_push)=default,s,1)
295 
296  ; Set the current tonezone to Germany (de)
297  same => n,Set(CHANNEL(tonezone)=de)
298 
299  ; Set the allowed maximum number of forwarding attempts
300  same => n,Set(CHANNEL(max_forwards)=10)
301 
302  ; If this channel is ejected from its next bridge, and if
303  ; the channel is not hung up, begin executing dialplan at
304  ; location default,after-bridge,1
305  same => n,Set(CHANNEL(after_bridge_goto)=default,after-bridge,1)
306 
307  ; Log the current state of the channel
308  same => n,Log(NOTICE, This channel is: ${CHANNEL(state)})
309  </example>
310  <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL_EXAMPLES'])" />
311  <para>The following channel variables are available as special built-in
312  dialplan channel variables. These variables cannot be set or modified
313  and are read-only.</para>
314  <variablelist>
315  <variable name="CALLINGPRES">
316  <para>Caller ID presentation for incoming calls (PRI channels)</para>
317  </variable>
318  <variable name="CALLINGANI2">
319  <para>Caller ANI2 (PRI channels)</para>
320  </variable>
321  <variable name="CALLINGTON">
322  <para>Caller Type of Number (PRI channels)</para>
323  </variable>
324  <variable name="CALLINGTNS">
325  <para>Transit Network Selector (PRI channels)</para>
326  </variable>
327  <variable name="EXTEN">
328  <para>Current extension</para>
329  </variable>
330  <variable name="CONTEXT">
331  <para>Current context</para>
332  </variable>
333  <variable name="PRIORITY">
334  <para>Current priority</para>
335  </variable>
336  <variable name="CHANNEL">
337  <para>Current channel name</para>
338  </variable>
339  <variable name="UNIQUEID">
340  <para>Current call unique identifier</para>
341  </variable>
342  <variable name="HANGUPCAUSE">
343  <para>Asterisk cause of hangup (inbound/outbound)</para>
344  </variable>
345  </variablelist>
346  </description>
347  </function>
348  ***/
349 
350 #define locked_copy_string(chan, dest, source, len) \
351  do { \
352  ast_channel_lock(chan); \
353  ast_copy_string(dest, source, len); \
354  ast_channel_unlock(chan); \
355  } while (0)
356 #define locked_string_field_set(chan, field, source) \
357  do { \
358  ast_channel_lock(chan); \
359  ast_channel_##field##_set(chan, source); \
360  ast_channel_unlock(chan); \
361  } while (0)
362 
363 static const char * const transfercapability_table[0x20] = {
364  "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
365  "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
366  "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
367  "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
368 
369 static int func_channel_read(struct ast_channel *chan, const char *function,
370  char *data, char *buf, size_t len)
371 {
372  int ret = 0;
373  struct ast_format_cap *tmpcap;
374 
375  if (!chan) {
376  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
377  return -1;
378  }
379 
380  if (!strcasecmp(data, "audionativeformat")) {
382  if (tmpcap) {
383  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
384 
385  ast_channel_lock(chan);
386  ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
387  ast_channel_unlock(chan);
388  ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
389  ao2_ref(tmpcap, -1);
390  }
391  } else if (!strcasecmp(data, "videonativeformat")) {
393  if (tmpcap) {
394  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
395 
396  ast_channel_lock(chan);
397  ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
398  ast_channel_unlock(chan);
399  ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
400  ao2_ref(tmpcap, -1);
401  }
402  } else if (!strcasecmp(data, "audioreadformat")) {
403  locked_copy_string(chan, buf, ast_format_get_name(ast_channel_readformat(chan)), len);
404  } else if (!strcasecmp(data, "audiowriteformat")) {
405  locked_copy_string(chan, buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
406  } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
407  locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
408  } else if (!strcasecmp(data, "dtmf_features")) {
409  if (ast_bridge_features_ds_get_string(chan, buf, len)) {
410  buf[0] = '\0';
411  }
412  } else if (!strcasecmp(data, "language"))
413  locked_copy_string(chan, buf, ast_channel_language(chan), len);
414  else if (!strcasecmp(data, "musicclass"))
415  locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
416  else if (!strcasecmp(data, "name")) {
417  locked_copy_string(chan, buf, ast_channel_name(chan), len);
418  } else if (!strcasecmp(data, "parkinglot"))
419  locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
420  else if (!strcasecmp(data, "state"))
421  locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
422  else if (!strcasecmp(data, "onhold")) {
423  locked_copy_string(chan, buf,
424  ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len);
425  } else if (!strcasecmp(data, "channeltype"))
426  locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
427  else if (!strcasecmp(data, "accountcode"))
428  locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
429  else if (!strcasecmp(data, "checkhangup")) {
430  locked_copy_string(chan, buf, ast_check_hangup(chan) ? "1" : "0", len);
431  } else if (!strcasecmp(data, "peeraccount"))
432  locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
433  else if (!strcasecmp(data, "hangupsource"))
434  locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
435  else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
436  locked_copy_string(chan, buf, ast_channel_appl(chan), len);
437  else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
438  locked_copy_string(chan, buf, ast_channel_data(chan), len);
439  else if (!strcasecmp(data, "exten"))
440  locked_copy_string(chan, buf, ast_channel_exten(chan), len);
441  else if (!strcasecmp(data, "context"))
442  locked_copy_string(chan, buf, ast_channel_context(chan), len);
443  else if (!strcasecmp(data, "lastexten"))
444  locked_copy_string(chan, buf, ast_channel_lastexten(chan), len);
445  else if (!strcasecmp(data, "lastcontext"))
446  locked_copy_string(chan, buf, ast_channel_lastcontext(chan), len);
447  else if (!strcasecmp(data, "userfield"))
448  locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
449  else if (!strcasecmp(data, "channame"))
450  locked_copy_string(chan, buf, ast_channel_name(chan), len);
451  else if (!strcasecmp(data, "linkedid")) {
452  ast_channel_lock(chan);
453  if (ast_strlen_zero(ast_channel_linkedid(chan))) {
454  /* fall back on the channel's uniqueid if linkedid is unset */
455  ast_copy_string(buf, ast_channel_uniqueid(chan), len);
456  }
457  else {
458  ast_copy_string(buf, ast_channel_linkedid(chan), len);
459  }
460  ast_channel_unlock(chan);
461  } else if (!strcasecmp(data, "peer")) {
462  struct ast_channel *peer;
463 
464  peer = ast_channel_bridge_peer(chan);
465  if (peer) {
466  /* Only real channels could have a bridge peer this way. */
467  ast_channel_lock(peer);
468  ast_copy_string(buf, ast_channel_name(peer), len);
469  ast_channel_unlock(peer);
470  ast_channel_unref(peer);
471  } else {
472  buf[0] = '\0';
473  ast_channel_lock(chan);
474  if (!ast_channel_tech(chan)) {
475  const char *pname;
476 
477  /*
478  * A dummy channel can still pass along bridged peer info
479  * via the BRIDGEPEER variable.
480  *
481  * A horrible kludge, but... how else?
482  */
483  pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
484  if (!ast_strlen_zero(pname)) {
485  ast_copy_string(buf, pname, len);
486  }
487  }
488  ast_channel_unlock(chan);
489  }
490  } else if (!strcasecmp(data, "uniqueid")) {
491  locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
492  } else if (!strcasecmp(data, "transfercapability")) {
493  locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
494  } else if (!strcasecmp(data, "callgroup")) {
495  char groupbuf[256];
496 
497  locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
498  } else if (!strcasecmp(data, "pickupgroup")) {
499  char groupbuf[256];
500 
501  locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
502  } else if (!strcasecmp(data, "namedcallgroup")) {
503  struct ast_str *tmp_str = ast_str_alloca(1024);
504 
505  locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
506  } else if (!strcasecmp(data, "namedpickupgroup")) {
507  struct ast_str *tmp_str = ast_str_alloca(1024);
508 
509  locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
510  } else if (!strcasecmp(data, "after_bridge_goto")) {
511  ast_bridge_read_after_goto(chan, buf, len);
512  } else if (!strcasecmp(data, "amaflags")) {
513  ast_channel_lock(chan);
514  snprintf(buf, len, "%u", ast_channel_amaflags(chan));
515  ast_channel_unlock(chan);
516  } else if (!strncasecmp(data, "secure_bridge_", 14)) {
517  struct ast_datastore *ds;
518 
519  buf[0] = '\0';
520  ast_channel_lock(chan);
521  if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
522  struct ast_secure_call_store *encrypt = ds->data;
523 
524  if (!strcasecmp(data, "secure_bridge_signaling")) {
525  snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
526  } else if (!strcasecmp(data, "secure_bridge_media")) {
527  snprintf(buf, len, "%s", encrypt->media ? "1" : "");
528  }
529  }
530  ast_channel_unlock(chan);
531  } else if (!strcasecmp(data, "max_forwards")) {
532  ast_channel_lock(chan);
533  snprintf(buf, len, "%d", ast_max_forwards_get(chan));
534  ast_channel_unlock(chan);
535  } else if (!strcasecmp(data, "callid")) {
536  ast_callid callid;
537 
538  buf[0] = '\0';
539  ast_channel_lock(chan);
540  callid = ast_channel_callid(chan);
541  if (callid) {
542  ast_callid_strnprint(buf, len, callid);
543  }
544  ast_channel_unlock(chan);
545  } else if (!strcasecmp(data, "tdd")) {
546  char status;
547  int status_size = (int) sizeof(status);
548  ret = ast_channel_queryoption(chan, AST_OPTION_TDD, &status, &status_size, 0);
549  if (!ret) {
550  ast_copy_string(buf, status == 2 ? "mate" : status ? "1" : "0", len);
551  }
552  } else if (!strcasecmp(data, "digitdetect")) {
553  char status;
554  int status_size = (int) sizeof(status);
555  ret = ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &status, &status_size, 0);
556  if (!ret) {
557  ast_copy_string(buf, status ? "1" : "0", len);
558  }
559  } else if (!strcasecmp(data, "faxdetect")) {
560  char status;
561  int status_size = (int) sizeof(status);
562  ret = ast_channel_queryoption(chan, AST_OPTION_FAX_DETECT, &status, &status_size, 0);
563  if (!ret) {
564  ast_copy_string(buf, status ? "1" : "0", len);
565  }
566  } else if (!strcasecmp(data, "device_name")) {
567  ret = ast_channel_get_device_name(chan, buf, len);
568  } 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)) {
569  ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
570  ret = -1;
571  }
572 
573  return ret;
574 }
575 
576 static int func_channel_write_real(struct ast_channel *chan, const char *function,
577  char *data, const char *value)
578 {
579  int ret = 0;
580  signed char gainset;
581 
582  if (!strcasecmp(data, "language"))
583  locked_string_field_set(chan, language, value);
584  else if (!strcasecmp(data, "parkinglot"))
585  locked_string_field_set(chan, parkinglot, value);
586  else if (!strcasecmp(data, "musicclass"))
587  locked_string_field_set(chan, musicclass, value);
588  else if (!strcasecmp(data, "accountcode"))
589  locked_string_field_set(chan, accountcode, value);
590  else if (!strcasecmp(data, "userfield"))
591  locked_string_field_set(chan, userfield, value);
592  else if (!strcasecmp(data, "after_bridge_goto")) {
593  if (ast_strlen_zero(value)) {
595  } else {
596  ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
597  }
598  } else if (!strcasecmp(data, "amaflags")) {
599  int amaflags;
600 
601  if (isdigit(*value)) {
602  if (sscanf(value, "%30d", &amaflags) != 1) {
603  amaflags = AST_AMA_NONE;
604  }
605  } else {
606  amaflags = ast_channel_string2amaflag(value);
607  }
608  ast_channel_lock(chan);
609  ast_channel_amaflags_set(chan, amaflags);
610  ast_channel_unlock(chan);
611  } else if (!strcasecmp(data, "peeraccount"))
612  locked_string_field_set(chan, peeraccount, value);
613  else if (!strcasecmp(data, "hangupsource"))
614  /* XXX - should we be forcing this here? */
615  ast_set_hangupsource(chan, value, 0);
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);
620  ret = -1;
621  } else {
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)));
625  }
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);
629  }
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);
642 
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);
649 
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, "tdd")) {
655  char enabled;
656  if (!strcasecmp(value, "mate")) {
657  enabled = 2;
658  } else {
659  enabled = ast_true(value) ? 1 : 0;
660  }
661  ast_channel_setoption(chan, AST_OPTION_TDD, &enabled, sizeof(enabled), 0);
662  } else if (!strcasecmp(data, "relaxdtmf")) {
663  char enabled = ast_true(value) ? 1 : 0;
664  ast_channel_setoption(chan, AST_OPTION_RELAXDTMF, &enabled, sizeof(enabled), 0);
665  } else if (!strcasecmp(data, "txgain")) {
666  sscanf(value, "%4hhd", &gainset);
667  ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
668  } else if (!strcasecmp(data, "rxgain")) {
669  sscanf(value, "%4hhd", &gainset);
670  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
671  } else if (!strcasecmp(data, "digitdetect")) {
672  char enabled = ast_true(value) ? 1 : 0;
673  ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &enabled, sizeof(enabled), 0);
674  } else if (!strcasecmp(data, "faxdetect")) {
675  char enabled = ast_true(value) ? 1 : 0;
676  ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &enabled, sizeof(enabled), 0);
677  } else if (!strcasecmp(data, "transfercapability")) {
678  unsigned short i;
679 
680  ast_channel_lock(chan);
681  for (i = 0; i < 0x20; i++) {
682  if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
683  ast_channel_transfercapability_set(chan, i);
684  break;
685  }
686  }
687  ast_channel_unlock(chan);
688  } else if (!strcasecmp(data, "hangup_handler_pop")) {
689  /* Pop one hangup handler before pushing the new handler. */
691  ast_pbx_hangup_handler_push(chan, value);
692  } else if (!strcasecmp(data, "hangup_handler_push")) {
693  ast_pbx_hangup_handler_push(chan, value);
694  } else if (!strcasecmp(data, "hangup_handler_wipe")) {
695  /* Pop all hangup handlers before pushing the new handler. */
696  while (ast_pbx_hangup_handler_pop(chan)) {
697  }
698  ast_pbx_hangup_handler_push(chan, value);
699  } else if (!strncasecmp(data, "secure_bridge_", 14)) {
700  struct ast_datastore *ds;
701  struct ast_secure_call_store *store;
702 
703  if (!chan || !value) {
704  return -1;
705  }
706 
707  ast_channel_lock(chan);
708  if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
709  if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
710  ast_channel_unlock(chan);
711  return -1;
712  }
713  if (!(store = ast_calloc(1, sizeof(*store)))) {
714  ast_channel_unlock(chan);
715  ast_free(ds);
716  return -1;
717  }
718  ds->data = store;
719  ast_channel_datastore_add(chan, ds);
720  } else {
721  store = ds->data;
722  }
723 
724  if (!strcasecmp(data, "secure_bridge_signaling")) {
725  store->signaling = ast_true(value) ? 1 : 0;
726  } else if (!strcasecmp(data, "secure_bridge_media")) {
727  store->media = ast_true(value) ? 1 : 0;
728  }
729  ast_channel_unlock(chan);
730  } else if (!strcasecmp(data, "max_forwards")) {
731  int max_forwards;
732  if (sscanf(value, "%d", &max_forwards) != 1) {
733  ast_log(LOG_WARNING, "Unable to set max forwards to '%s'\n", value);
734  ret = -1;
735  } else {
736  ast_channel_lock(chan);
737  ret = ast_max_forwards_set(chan, max_forwards);
738  ast_channel_unlock(chan);
739  }
740  } else if (!ast_channel_tech(chan)->func_channel_write
741  || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
742  ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
743  data);
744  ret = -1;
745  }
746 
747  return ret;
748 }
749 
750 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
751 {
752  int res;
753  ast_chan_write_info_t write_info = {
755  .write_fn = func_channel_write_real,
756  .chan = chan,
757  .function = function,
758  .data = data,
759  .value = value,
760  };
761 
762  if (!chan) {
763  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
764  return -1;
765  }
766 
767  res = func_channel_write_real(chan, function, data, value);
768  ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
769 
770  return res;
771 }
772 
773 static struct ast_custom_function channel_function = {
774  .name = "CHANNEL",
775  .read = func_channel_read,
776  .write = func_channel_write,
777 };
778 
779 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
780 {
781  struct ast_channel *c = NULL;
782  regex_t re;
783  int res;
784  size_t buflen = 0;
785  struct ast_channel_iterator *iter;
786 
787  buf[0] = '\0';
788 
789  if (!ast_strlen_zero(data)) {
790  if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
791  regerror(res, &re, buf, maxlen);
792  ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
793  return -1;
794  }
795  }
796 
797  if (!(iter = ast_channel_iterator_all_new())) {
798  if (!ast_strlen_zero(data)) {
799  regfree(&re);
800  }
801  return -1;
802  }
803 
804  while ((c = ast_channel_iterator_next(iter))) {
805  ast_channel_lock(c);
806  if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
807  size_t namelen = strlen(ast_channel_name(c));
808  if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
809  if (!ast_strlen_zero(buf)) {
810  strcat(buf, " ");
811  buflen++;
812  }
813  strcat(buf, ast_channel_name(c));
814  buflen += namelen;
815  } else {
816  ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
817  }
818  }
819  ast_channel_unlock(c);
820  c = ast_channel_unref(c);
821  }
822 
824 
825  if (!ast_strlen_zero(data)) {
826  regfree(&re);
827  }
828 
829  return 0;
830 }
831 
832 static struct ast_custom_function channels_function = {
833  .name = "CHANNELS",
834  .read = func_channels_read,
835 };
836 
837 static int func_chan_exists_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
838 {
839  struct ast_channel *chan_found = NULL;
840 
841  if (ast_strlen_zero(data)) {
842  ast_log(LOG_WARNING, "%s: Channel name or unique ID required\n", function);
843  return -1;
844  }
845 
846  chan_found = ast_channel_get_by_name(data);
847  snprintf(buf, maxlen, "%d", (chan_found ? 1 : 0));
848  if (chan_found) {
849  ast_channel_unref(chan_found);
850  }
851  return 0;
852 }
853 
854 static struct ast_custom_function chan_exists_function = {
855  .name = "CHANNEL_EXISTS",
856  .read = func_chan_exists_read,
857 };
858 
859 static int func_mchan_read(struct ast_channel *chan, const char *function,
860  char *data, struct ast_str **buf, ssize_t len)
861 {
862  struct ast_channel *mchan;
863  char *template = ast_alloca(4 + strlen(data));
864 
865  if (!chan) {
866  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
867  return -1;
868  }
869 
870  mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
871  sprintf(template, "${%s}", data); /* SAFE */
872  ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
873  if (mchan) {
874  ast_channel_unref(mchan);
875  }
876  return 0;
877 }
878 
879 static int func_mchan_write(struct ast_channel *chan, const char *function,
880  char *data, const char *value)
881 {
882  struct ast_channel *mchan;
883 
884  if (!chan) {
885  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
886  return -1;
887  }
888 
889  mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
890  pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
891  if (mchan) {
892  ast_channel_unref(mchan);
893  }
894  return 0;
895 }
896 
897 static struct ast_custom_function mchan_function = {
898  .name = "MASTER_CHANNEL",
899  .read2 = func_mchan_read,
900  .write = func_mchan_write,
901 };
902 
903 static int unload_module(void)
904 {
905  int res = 0;
906 
907  res |= ast_custom_function_unregister(&channel_function);
908  res |= ast_custom_function_unregister(&channels_function);
909  res |= ast_custom_function_unregister(&chan_exists_function);
910  res |= ast_custom_function_unregister(&mchan_function);
911 
912  return res;
913 }
914 
915 static int load_module(void)
916 {
917  int res = 0;
918 
919  res |= ast_custom_function_register(&channel_function);
920  res |= ast_custom_function_register(&channels_function);
921  res |= ast_custom_function_register(&chan_exists_function);
922  res |= ast_custom_function_register(&mchan_function);
923 
924  return res;
925 }
926 
927 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");
const char * name
Definition: pbx.h:119
Tone Indication Support.
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
Main Channel structure associated with a channel.
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1422
Asterisk main include file. File version handling, generic pbx functions.
#define AST_OPTION_TXGAIN
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
Definition: indications.h:205
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
Definition: channel.c:7442
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
globally accessible channel datastores
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
int ast_bridge_features_ds_set_string(struct ast_channel *chan, const char *features)
Sets the features a channel will use upon being bridged.
Definition: bridge_basic.c:189
int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
Pop the top of the channel hangup handler stack.
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Structure for a data store object.
Definition: datastore.h:64
#define AST_OPTION_TDD
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
const char * data
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7422
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Utility functions.
char * ast_print_group(char *buf, int buflen, ast_group_t group)
Print call and pickup groups into buffer.
Definition: channel.c:8031
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4360
General Asterisk PBX channel definitions.
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition: channel.c:2499
#define AST_OPTION_RELAXDTMF
A set of tones for a given locale.
Definition: indications.h:74
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:384
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
Core PBX routines and definitions.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_bridge_features_ds_get_string(struct ast_channel *chan, char *buffer, size_t buf_size)
writes a channel's DTMF features to a buffer string
Definition: bridge_basic.c:208
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define AST_OPTION_DIGIT_DETECT
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7675
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:591
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
Support for dynamic strings.
Definition: strings.h:623
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define AST_OPTION_RXGAIN
Channel datastore data for max forwards.
Definition: max_forwards.c:29
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
Definition: indications.c:439
static struct ast_tone_zone * ast_tone_zone_ref(struct ast_tone_zone *tz)
Increase the reference count on an ast_tone_zone.
Definition: indications.h:216
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
#define AST_OPTION_CHANNEL_WRITE
Handle channel write data If a channel needs to process the data from a func_channel write operation ...
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
Structure to handle passing func_channel_write info to channels via setoption.
Definition: channel.h:589
void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
Push the given hangup handler onto the channel hangup handler stack.
Basic bridge subclass API.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:66
#define AST_OPTION_FAX_DETECT
After Bridge Execution API.
static int enabled
Whether or not we are storing history.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10564
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1360
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
Definition: channel.c:10496
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
Definition: bridge_after.c:622
void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
Read after bridge goto if it exists.
Definition: bridge_after.c:394
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
Definition: logger.c:2288
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition: channel.c:1408
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
Bridging API.
Asterisk module definitions.
char * ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *groups)
Print named call groups and named pickup groups.
Definition: channel.c:8056
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
Definition: channel.c:636
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558