Asterisk - The Open Source Telephony Project  GIT-master-44aef04
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  *
24  * \ingroup functions
25  */
26 
27 /*** MODULEINFO
28  <support_level>core</support_level>
29  ***/
30 
31 #include "asterisk.h"
32 
33 #include <regex.h>
34 #include <ctype.h>
35 
36 #include "asterisk/module.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/bridge.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/utils.h"
41 #include "asterisk/app.h"
42 #include "asterisk/indications.h"
43 #include "asterisk/stringfields.h"
45 #include "asterisk/bridge_basic.h"
46 #include "asterisk/bridge_after.h"
47 #include "asterisk/max_forwards.h"
48 
49 /*** DOCUMENTATION
50  <function name="CHANNELS" language="en_US">
51  <synopsis>
52  Gets the list of channels, optionally filtering by a regular expression.
53  </synopsis>
54  <syntax>
55  <parameter name="regular_expression" />
56  </syntax>
57  <description>
58  <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
59  no argument is provided, all known channels are returned. The
60  <replaceable>regular_expression</replaceable> must correspond to
61  the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
62  will be space-delimited.</para>
63  </description>
64  </function>
65  <function name="MASTER_CHANNEL" language="en_US">
66  <synopsis>
67  Gets or sets variables on the master channel
68  </synopsis>
69  <description>
70  <para>Allows access to the oldest channel associated with the current
71  channel if it still exists. If the channel is the master channel or
72  the master channel no longer exists then access local channel variables
73  instead. In other words, the master channel is the channel identified by
74  the channel's linkedid.</para>
75  </description>
76  </function>
77  <function name="CHANNEL" language="en_US">
78  <synopsis>
79  Gets/sets various pieces of information about the channel.
80  </synopsis>
81  <syntax>
82  <parameter name="item" required="true">
83  <para>Standard items (provided by all channel technologies) are:</para>
84  <enumlist>
85  <enum name="amaflags">
86  <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
87  When read from a channel, the integer value will always be returned.
88  When written to a channel, both the string format or integer value
89  is accepted.</para>
90  <enumlist>
91  <enum name="1"><para><literal>OMIT</literal></para></enum>
92  <enum name="2"><para><literal>BILLING</literal></para></enum>
93  <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
94  </enumlist>
95  </enum>
96  <enum name="accountcode">
97  <para>R/W the channel's account code.</para>
98  </enum>
99  <enum name="audioreadformat">
100  <para>R/O format currently being read.</para>
101  </enum>
102  <enum name="audionativeformat">
103  <para>R/O format used natively for audio.</para>
104  </enum>
105  <enum name="audiowriteformat">
106  <para>R/O format currently being written.</para>
107  </enum>
108  <enum name="dtmf_features">
109  <para>R/W The channel's DTMF bridge features.
110  May include one or more of 'T' 'K' 'H' 'W' and 'X' in a similar manner to options
111  in the <literal>Dial</literal> application. When setting it, the features string
112  must be all upper case.</para>
113  </enum>
114  <enum name="callgroup">
115  <para>R/W numeric call pickup groups that this channel is a member.</para>
116  </enum>
117  <enum name="pickupgroup">
118  <para>R/W numeric call pickup groups this channel can pickup.</para>
119  </enum>
120  <enum name="namedcallgroup">
121  <para>R/W named call pickup groups that this channel is a member.</para>
122  </enum>
123  <enum name="namedpickupgroup">
124  <para>R/W named call pickup groups this channel can pickup.</para>
125  </enum>
126  <enum name="channeltype">
127  <para>R/O technology used for channel.</para>
128  </enum>
129  <enum name="checkhangup">
130  <para>R/O Whether the channel is hanging up (1/0)</para>
131  </enum>
132  <enum name="after_bridge_goto">
133  <para>R/W the parseable goto string indicating where the channel is
134  expected to return to in the PBX after exiting the next bridge it joins
135  on the condition that it doesn't hang up. The parseable goto string uses
136  the same syntax as the <literal>Goto</literal> application.</para>
137  </enum>
138  <enum name="hangup_handler_pop">
139  <para>W/O Replace the most recently added hangup handler
140  with a new hangup handler on the channel if supplied. The
141  assigned string is passed to the Gosub application when
142  the channel is hung up. Any optionally omitted context
143  and exten are supplied by the channel pushing the handler
144  before it is pushed.</para>
145  </enum>
146  <enum name="hangup_handler_push">
147  <para>W/O Push a hangup handler onto the channel hangup
148  handler stack. The assigned string is passed to the
149  Gosub application when the channel is hung up. Any
150  optionally omitted context and exten are supplied by the
151  channel pushing the handler before it is pushed.</para>
152  </enum>
153  <enum name="hangup_handler_wipe">
154  <para>W/O Wipe the entire hangup handler stack and replace
155  with a new hangup handler on the channel if supplied. The
156  assigned string is passed to the Gosub application when
157  the channel is hung up. Any optionally omitted context
158  and exten are supplied by the channel pushing the handler
159  before it is pushed.</para>
160  </enum>
161  <enum name="onhold">
162  <para>R/O Whether or not the channel is onhold. (1/0)</para>
163  </enum>
164  <enum name="language">
165  <para>R/W language for sounds played.</para>
166  </enum>
167  <enum name="musicclass">
168  <para>R/W class (from musiconhold.conf) for hold music.</para>
169  </enum>
170  <enum name="name">
171  <para>The name of the channel</para>
172  </enum>
173  <enum name="parkinglot">
174  <para>R/W parkinglot for parking.</para>
175  </enum>
176  <enum name="rxgain">
177  <para>R/W set rxgain level on channel drivers that support it.</para>
178  </enum>
179  <enum name="secure_bridge_signaling">
180  <para>Whether or not channels bridged to this channel require secure signaling (1/0)</para>
181  </enum>
182  <enum name="secure_bridge_media">
183  <para>Whether or not channels bridged to this channel require secure media (1/0)</para>
184  </enum>
185  <enum name="state">
186  <para>R/O state of the channel</para>
187  </enum>
188  <enum name="tonezone">
189  <para>R/W zone for indications played</para>
190  </enum>
191  <enum name="transfercapability">
192  <para>R/W ISDN Transfer Capability, one of:</para>
193  <enumlist>
194  <enum name="SPEECH" />
195  <enum name="DIGITAL" />
196  <enum name="RESTRICTED_DIGITAL" />
197  <enum name="3K1AUDIO" />
198  <enum name="DIGITAL_W_TONES" />
199  <enum name="VIDEO" />
200  </enumlist>
201  </enum>
202  <enum name="txgain">
203  <para>R/W set txgain level on channel drivers that support it.</para>
204  </enum>
205  <enum name="videonativeformat">
206  <para>R/O format used natively for video</para>
207  </enum>
208  <enum name="hangupsource">
209  <para>R/W returns the channel responsible for hangup.</para>
210  </enum>
211  <enum name="appname">
212  <para>R/O returns the internal application name.</para>
213  </enum>
214  <enum name="appdata">
215  <para>R/O returns the application data if available.</para>
216  </enum>
217  <enum name="exten">
218  <para>R/O returns the extension for an outbound channel.</para>
219  </enum>
220  <enum name="context">
221  <para>R/O returns the context for an outbound channel.</para>
222  </enum>
223  <enum name="channame">
224  <para>R/O returns the channel name for an outbound channel.</para>
225  </enum>
226  <enum name="uniqueid">
227  <para>R/O returns the channel uniqueid.</para>
228  </enum>
229  <enum name="linkedid">
230  <para>R/O returns the linkedid if available, otherwise returns the uniqueid.</para>
231  </enum>
232  <enum name="max_forwards">
233  <para>R/W The maximum number of forwards allowed.</para>
234  </enum>
235  <enum name="callid">
236  <para>R/O Call identifier log tag associated with the channel
237  e.g., <literal>[C-00000000]</literal>.</para>
238  </enum>
239  </enumlist>
240  <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL'])" />
241  </parameter>
242  </syntax>
243  <description>
244  <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
245  be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
246  requested that is not available on the current channel will return an empty string.</para>
247  <example title="Standard CHANNEL item examples">
248  ; Push a hangup handler subroutine existing at dialplan
249  ; location default,s,1 onto the current channel
250  same => n,Set(CHANNEL(hangup_handler_push)=default,s,1)
251 
252  ; Set the current tonezone to Germany (de)
253  same => n,Set(CHANNEL(tonezone)=de)
254 
255  ; Set the allowed maximum number of forwarding attempts
256  same => n,Set(CHANNEL(max_forwards)=10)
257 
258  ; If this channel is ejected from its next bridge, and if
259  ; the channel is not hung up, begin executing dialplan at
260  ; location default,after-bridge,1
261  same => n,Set(CHANNEL(after_bridge_goto)=default,after-bridge,1)
262 
263  ; Log the current state of the channel
264  same => n,Log(NOTICE, This channel is: ${CHANNEL(state)})
265  </example>
266  <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL_EXAMPLES'])" />
267  </description>
268  </function>
269  ***/
270 
271 #define locked_copy_string(chan, dest, source, len) \
272  do { \
273  ast_channel_lock(chan); \
274  ast_copy_string(dest, source, len); \
275  ast_channel_unlock(chan); \
276  } while (0)
277 #define locked_string_field_set(chan, field, source) \
278  do { \
279  ast_channel_lock(chan); \
280  ast_channel_##field##_set(chan, source); \
281  ast_channel_unlock(chan); \
282  } while (0)
283 
284 static const char * const transfercapability_table[0x20] = {
285  "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
286  "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
287  "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
288  "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
289 
290 static int func_channel_read(struct ast_channel *chan, const char *function,
291  char *data, char *buf, size_t len)
292 {
293  int ret = 0;
294  struct ast_format_cap *tmpcap;
295 
296  if (!chan) {
297  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
298  return -1;
299  }
300 
301  if (!strcasecmp(data, "audionativeformat")) {
303  if (tmpcap) {
304  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
305 
306  ast_channel_lock(chan);
308  ast_channel_unlock(chan);
309  ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
310  ao2_ref(tmpcap, -1);
311  }
312  } else if (!strcasecmp(data, "videonativeformat")) {
314  if (tmpcap) {
315  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
316 
317  ast_channel_lock(chan);
319  ast_channel_unlock(chan);
320  ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
321  ao2_ref(tmpcap, -1);
322  }
323  } else if (!strcasecmp(data, "audioreadformat")) {
325  } else if (!strcasecmp(data, "audiowriteformat")) {
327  } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
328  locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
329  } else if (!strcasecmp(data, "dtmf_features")) {
330  if (ast_bridge_features_ds_get_string(chan, buf, len)) {
331  buf[0] = '\0';
332  }
333  } else if (!strcasecmp(data, "language"))
334  locked_copy_string(chan, buf, ast_channel_language(chan), len);
335  else if (!strcasecmp(data, "musicclass"))
336  locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
337  else if (!strcasecmp(data, "name")) {
338  locked_copy_string(chan, buf, ast_channel_name(chan), len);
339  } else if (!strcasecmp(data, "parkinglot"))
340  locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
341  else if (!strcasecmp(data, "state"))
342  locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
343  else if (!strcasecmp(data, "onhold")) {
344  locked_copy_string(chan, buf,
345  ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len);
346  } else if (!strcasecmp(data, "channeltype"))
347  locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
348  else if (!strcasecmp(data, "accountcode"))
349  locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
350  else if (!strcasecmp(data, "checkhangup")) {
351  locked_copy_string(chan, buf, ast_check_hangup(chan) ? "1" : "0", len);
352  } else if (!strcasecmp(data, "peeraccount"))
353  locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
354  else if (!strcasecmp(data, "hangupsource"))
355  locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
356  else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
357  locked_copy_string(chan, buf, ast_channel_appl(chan), len);
358  else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
359  locked_copy_string(chan, buf, ast_channel_data(chan), len);
360  else if (!strcasecmp(data, "exten"))
361  locked_copy_string(chan, buf, ast_channel_exten(chan), len);
362  else if (!strcasecmp(data, "context"))
363  locked_copy_string(chan, buf, ast_channel_context(chan), len);
364  else if (!strcasecmp(data, "userfield"))
365  locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
366  else if (!strcasecmp(data, "channame"))
367  locked_copy_string(chan, buf, ast_channel_name(chan), len);
368  else if (!strcasecmp(data, "linkedid")) {
369  ast_channel_lock(chan);
371  /* fall back on the channel's uniqueid if linkedid is unset */
372  ast_copy_string(buf, ast_channel_uniqueid(chan), len);
373  }
374  else {
375  ast_copy_string(buf, ast_channel_linkedid(chan), len);
376  }
377  ast_channel_unlock(chan);
378  } else if (!strcasecmp(data, "peer")) {
379  struct ast_channel *peer;
380 
381  peer = ast_channel_bridge_peer(chan);
382  if (peer) {
383  /* Only real channels could have a bridge peer this way. */
384  ast_channel_lock(peer);
385  ast_copy_string(buf, ast_channel_name(peer), len);
386  ast_channel_unlock(peer);
387  ast_channel_unref(peer);
388  } else {
389  buf[0] = '\0';
390  ast_channel_lock(chan);
391  if (!ast_channel_tech(chan)) {
392  const char *pname;
393 
394  /*
395  * A dummy channel can still pass along bridged peer info
396  * via the BRIDGEPEER variable.
397  *
398  * A horrible kludge, but... how else?
399  */
400  pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
401  if (!ast_strlen_zero(pname)) {
402  ast_copy_string(buf, pname, len);
403  }
404  }
405  ast_channel_unlock(chan);
406  }
407  } else if (!strcasecmp(data, "uniqueid")) {
408  locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
409  } else if (!strcasecmp(data, "transfercapability")) {
411  } else if (!strcasecmp(data, "callgroup")) {
412  char groupbuf[256];
413 
414  locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
415  } else if (!strcasecmp(data, "pickupgroup")) {
416  char groupbuf[256];
417 
418  locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
419  } else if (!strcasecmp(data, "namedcallgroup")) {
420  struct ast_str *tmp_str = ast_str_alloca(1024);
421 
423  } else if (!strcasecmp(data, "namedpickupgroup")) {
424  struct ast_str *tmp_str = ast_str_alloca(1024);
425 
427  } else if (!strcasecmp(data, "after_bridge_goto")) {
428  ast_bridge_read_after_goto(chan, buf, len);
429  } else if (!strcasecmp(data, "amaflags")) {
430  ast_channel_lock(chan);
431  snprintf(buf, len, "%u", ast_channel_amaflags(chan));
432  ast_channel_unlock(chan);
433  } else if (!strncasecmp(data, "secure_bridge_", 14)) {
434  struct ast_datastore *ds;
435 
436  buf[0] = '\0';
437  ast_channel_lock(chan);
438  if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
439  struct ast_secure_call_store *encrypt = ds->data;
440 
441  if (!strcasecmp(data, "secure_bridge_signaling")) {
442  snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
443  } else if (!strcasecmp(data, "secure_bridge_media")) {
444  snprintf(buf, len, "%s", encrypt->media ? "1" : "");
445  }
446  }
447  ast_channel_unlock(chan);
448  } else if (!strcasecmp(data, "max_forwards")) {
449  ast_channel_lock(chan);
450  snprintf(buf, len, "%d", ast_max_forwards_get(chan));
451  ast_channel_unlock(chan);
452  } else if (!strcasecmp(data, "callid")) {
453  ast_callid callid;
454 
455  buf[0] = '\0';
456  ast_channel_lock(chan);
457  callid = ast_channel_callid(chan);
458  if (callid) {
459  ast_callid_strnprint(buf, len, callid);
460  }
461  ast_channel_unlock(chan);
462  } 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)) {
463  ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
464  ret = -1;
465  }
466 
467  return ret;
468 }
469 
470 static int func_channel_write_real(struct ast_channel *chan, const char *function,
471  char *data, const char *value)
472 {
473  int ret = 0;
474  signed char gainset;
475 
476  if (!strcasecmp(data, "language"))
477  locked_string_field_set(chan, language, value);
478  else if (!strcasecmp(data, "parkinglot"))
479  locked_string_field_set(chan, parkinglot, value);
480  else if (!strcasecmp(data, "musicclass"))
481  locked_string_field_set(chan, musicclass, value);
482  else if (!strcasecmp(data, "accountcode"))
483  locked_string_field_set(chan, accountcode, value);
484  else if (!strcasecmp(data, "userfield"))
485  locked_string_field_set(chan, userfield, value);
486  else if (!strcasecmp(data, "after_bridge_goto")) {
487  if (ast_strlen_zero(value)) {
489  } else {
491  }
492  } else if (!strcasecmp(data, "amaflags")) {
493  int amaflags;
494 
495  if (isdigit(*value)) {
496  if (sscanf(value, "%30d", &amaflags) != 1) {
497  amaflags = AST_AMA_NONE;
498  }
499  } else {
500  amaflags = ast_channel_string2amaflag(value);
501  }
502  ast_channel_lock(chan);
503  ast_channel_amaflags_set(chan, amaflags);
504  ast_channel_unlock(chan);
505  } else if (!strcasecmp(data, "peeraccount"))
506  locked_string_field_set(chan, peeraccount, value);
507  else if (!strcasecmp(data, "hangupsource"))
508  /* XXX - should we be forcing this here? */
509  ast_set_hangupsource(chan, value, 0);
510  else if (!strcasecmp(data, "tonezone")) {
511  struct ast_tone_zone *new_zone;
512  if (!(new_zone = ast_get_indication_zone(value))) {
513  ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
514  ret = -1;
515  } else {
516  ast_channel_lock(chan);
517  if (ast_channel_zone(chan)) {
519  }
520  ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
521  ast_channel_unlock(chan);
522  new_zone = ast_tone_zone_unref(new_zone);
523  }
524  } else if (!strcasecmp(data, "dtmf_features")) {
525  ret = ast_bridge_features_ds_set_string(chan, value);
526  } else if (!strcasecmp(data, "callgroup")) {
527  ast_channel_lock(chan);
529  ast_channel_unlock(chan);
530  } else if (!strcasecmp(data, "pickupgroup")) {
531  ast_channel_lock(chan);
533  ast_channel_unlock(chan);
534  } else if (!strcasecmp(data, "namedcallgroup")) {
535  struct ast_namedgroups *groups = ast_get_namedgroups(value);
536 
537  ast_channel_lock(chan);
538  ast_channel_named_callgroups_set(chan, groups);
539  ast_channel_unlock(chan);
540  ast_unref_namedgroups(groups);
541  } else if (!strcasecmp(data, "namedpickupgroup")) {
542  struct ast_namedgroups *groups = ast_get_namedgroups(value);
543 
544  ast_channel_lock(chan);
546  ast_channel_unlock(chan);
547  ast_unref_namedgroups(groups);
548  } else if (!strcasecmp(data, "txgain")) {
549  sscanf(value, "%4hhd", &gainset);
550  ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
551  } else if (!strcasecmp(data, "rxgain")) {
552  sscanf(value, "%4hhd", &gainset);
553  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
554  } else if (!strcasecmp(data, "transfercapability")) {
555  unsigned short i;
556 
557  ast_channel_lock(chan);
558  for (i = 0; i < 0x20; i++) {
559  if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
561  break;
562  }
563  }
564  ast_channel_unlock(chan);
565  } else if (!strcasecmp(data, "hangup_handler_pop")) {
566  /* Pop one hangup handler before pushing the new handler. */
568  ast_pbx_hangup_handler_push(chan, value);
569  } else if (!strcasecmp(data, "hangup_handler_push")) {
570  ast_pbx_hangup_handler_push(chan, value);
571  } else if (!strcasecmp(data, "hangup_handler_wipe")) {
572  /* Pop all hangup handlers before pushing the new handler. */
573  while (ast_pbx_hangup_handler_pop(chan)) {
574  }
575  ast_pbx_hangup_handler_push(chan, value);
576  } else if (!strncasecmp(data, "secure_bridge_", 14)) {
577  struct ast_datastore *ds;
578  struct ast_secure_call_store *store;
579 
580  if (!chan || !value) {
581  return -1;
582  }
583 
584  ast_channel_lock(chan);
585  if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
586  if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
587  ast_channel_unlock(chan);
588  return -1;
589  }
590  if (!(store = ast_calloc(1, sizeof(*store)))) {
591  ast_channel_unlock(chan);
592  ast_free(ds);
593  return -1;
594  }
595  ds->data = store;
596  ast_channel_datastore_add(chan, ds);
597  } else {
598  store = ds->data;
599  }
600 
601  if (!strcasecmp(data, "secure_bridge_signaling")) {
602  store->signaling = ast_true(value) ? 1 : 0;
603  } else if (!strcasecmp(data, "secure_bridge_media")) {
604  store->media = ast_true(value) ? 1 : 0;
605  }
606  ast_channel_unlock(chan);
607  } else if (!strcasecmp(data, "max_forwards")) {
608  int max_forwards;
609  if (sscanf(value, "%d", &max_forwards) != 1) {
610  ast_log(LOG_WARNING, "Unable to set max forwards to '%s'\n", value);
611  ret = -1;
612  } else {
613  ast_channel_lock(chan);
614  ret = ast_max_forwards_set(chan, max_forwards);
615  ast_channel_unlock(chan);
616  }
617  } else if (!ast_channel_tech(chan)->func_channel_write
618  || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
619  ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
620  data);
621  ret = -1;
622  }
623 
624  return ret;
625 }
626 
627 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
628 {
629  int res;
630  ast_chan_write_info_t write_info = {
632  .write_fn = func_channel_write_real,
633  .chan = chan,
634  .function = function,
635  .data = data,
636  .value = value,
637  };
638 
639  if (!chan) {
640  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
641  return -1;
642  }
643 
644  res = func_channel_write_real(chan, function, data, value);
645  ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
646 
647  return res;
648 }
649 
651  .name = "CHANNEL",
652  .read = func_channel_read,
653  .write = func_channel_write,
654 };
655 
656 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
657 {
658  struct ast_channel *c = NULL;
659  regex_t re;
660  int res;
661  size_t buflen = 0;
662  struct ast_channel_iterator *iter;
663 
664  buf[0] = '\0';
665 
666  if (!ast_strlen_zero(data)) {
667  if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
668  regerror(res, &re, buf, maxlen);
669  ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
670  return -1;
671  }
672  }
673 
674  if (!(iter = ast_channel_iterator_all_new())) {
675  if (!ast_strlen_zero(data)) {
676  regfree(&re);
677  }
678  return -1;
679  }
680 
681  while ((c = ast_channel_iterator_next(iter))) {
682  ast_channel_lock(c);
683  if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
684  size_t namelen = strlen(ast_channel_name(c));
685  if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
686  if (!ast_strlen_zero(buf)) {
687  strcat(buf, " ");
688  buflen++;
689  }
690  strcat(buf, ast_channel_name(c));
691  buflen += namelen;
692  } else {
693  ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
694  }
695  }
697  c = ast_channel_unref(c);
698  }
699 
701 
702  if (!ast_strlen_zero(data)) {
703  regfree(&re);
704  }
705 
706  return 0;
707 }
708 
710  .name = "CHANNELS",
711  .read = func_channels_read,
712 };
713 
714 static int func_mchan_read(struct ast_channel *chan, const char *function,
715  char *data, struct ast_str **buf, ssize_t len)
716 {
717  struct ast_channel *mchan;
718  char *template = ast_alloca(4 + strlen(data));
719 
720  if (!chan) {
721  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
722  return -1;
723  }
724 
726  sprintf(template, "${%s}", data); /* SAFE */
727  ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
728  if (mchan) {
729  ast_channel_unref(mchan);
730  }
731  return 0;
732 }
733 
734 static int func_mchan_write(struct ast_channel *chan, const char *function,
735  char *data, const char *value)
736 {
737  struct ast_channel *mchan;
738 
739  if (!chan) {
740  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
741  return -1;
742  }
743 
745  pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
746  if (mchan) {
747  ast_channel_unref(mchan);
748  }
749  return 0;
750 }
751 
753  .name = "MASTER_CHANNEL",
754  .read2 = func_mchan_read,
755  .write = func_mchan_write,
756 };
757 
758 static int unload_module(void)
759 {
760  int res = 0;
761 
762  res |= ast_custom_function_unregister(&channel_function);
763  res |= ast_custom_function_unregister(&channels_function);
764  res |= ast_custom_function_unregister(&mchan_function);
765 
766  return res;
767 }
768 
769 static int load_module(void)
770 {
771  int res = 0;
772 
773  res |= ast_custom_function_register(&channel_function);
774  res |= ast_custom_function_register(&channels_function);
775  res |= ast_custom_function_register(&mchan_function);
776 
777  return res;
778 }
779 
780 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");
const char * name
Definition: pbx.h:119
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:162
static const char type[]
Definition: chan_ooh323.c:109
Tone Indication Support.
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:428
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
#define ast_channel_lock(chan)
Definition: channel.h:2902
Main Channel structure associated with a channel.
int ast_max_forwards_set(struct ast_channel *chan, int starting_count)
Set the starting max forwards for a particular channel.
Definition: max_forwards.c:105
int ast_max_forwards_get(struct ast_channel *chan)
Get the current max forwards for a particular channel.
Definition: max_forwards.c:121
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
int ast_channel_hold_state(const struct ast_channel *chan)
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1418
Asterisk main include file. File version handling, generic pbx functions.
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:163
static int amaflags
Definition: chan_iax2.c:431
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
#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:2938
static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
Definition: func_channel.c:656
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
struct ast_tone_zone * ast_channel_zone(const struct ast_channel *chan)
globally accessible channel datastores
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
static struct ast_custom_function channel_function
Definition: func_channel.c:650
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
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.
unsigned int ast_callid
Definition: logger.h:87
static struct test_val c
#define ast_str_alloca(init_len)
Definition: strings.h:800
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:68
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:2390
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:638
#define NULL
Definition: resample.c:96
const char * data
const struct ast_datastore_info secure_call_info
int value
Definition: syslog.c:37
void ast_channel_zone_set(struct ast_channel *chan, struct ast_tone_zone *value)
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:7421
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_linkedid(const struct ast_channel *chan)
static int func_mchan_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: func_channel.c:734
struct ast_namedgroups * ast_channel_named_callgroups(const struct ast_channel *chan)
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:8032
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4374
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
const char * ast_channel_accountcode(const struct ast_channel *chan)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it&#39;s bridge.
Definition: channel.c:2490
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 locked_copy_string(chan, dest, source, len)
Definition: func_channel.c:271
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:117
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:396
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7617
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
const char * ast_channel_exten(const struct ast_channel *chan)
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:441
int ast_bridge_features_ds_get_string(struct ast_channel *chan, char *buffer, size_t buf_size)
writes a channel&#39;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:290
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_userfield(const struct ast_channel *chan)
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7674
#define LOG_ERROR
Definition: logger.h:285
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:592
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: main/utils.c:1822
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define AST_OPTION_RXGAIN
static char country[80]
Definition: pbx_dundi.c:205
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
static struct ast_custom_function channels_function
Definition: func_channel.c:709
static int load_module(void)
Definition: func_channel.c:769
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:433
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:1939
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:736
const char * ast_channel_appl(const struct ast_channel *chan)
#define locked_string_field_set(chan, field, source)
Definition: func_channel.c:277
const char * ast_channel_peeraccount(const struct ast_channel *chan)
#define ast_strlen_zero(a)
Definition: muted.c:73
static int func_mchan_read(struct ast_channel *chan, const char *function, char *data, struct ast_str **buf, ssize_t len)
Definition: func_channel.c:714
#define ast_channel_unlock(chan)
Definition: channel.h:2903
#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_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Structure to handle passing func_channel_write info to channels via setoption.
Definition: channel.h:590
void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
Push the given hangup handler onto the channel hangup handler stack.
const char * ast_channel_hangupsource(const struct ast_channel *chan)
static const char *const transfercapability_table[0x20]
Definition: func_channel.c:284
Basic bridge subclass API.
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
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...
const char * ast_channel_data(const struct ast_channel *chan)
void * data
Definition: datastore.h:70
After Bridge Execution API.
static int func_channel_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Definition: func_channel.c:290
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct ast_namedgroups * ast_channel_named_pickupgroups(const struct ast_channel *chan)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10658
const char * ast_channel_name(const struct ast_channel *chan)
static int func_channel_write_real(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: func_channel.c:470
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1356
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
static int unload_module(void)
Definition: func_channel.c:758
const char * ast_channel_language(const struct ast_channel *chan)
static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: func_channel.c:627
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
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:636
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
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:406
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
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7731
ast_group_t ast_channel_callgroup(const struct ast_channel *chan)
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition: channel.c:1404
#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:1450
Bridging API.
Asterisk module definitions.
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
char * ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *groups)
Print named call groups and named pickup groups.
Definition: channel.c:8057
enum ama_flags ast_channel_amaflags(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2376
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
const char * ast_channel_parkinglot(const struct ast_channel *chan)
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
const char * ast_channel_musicclass(const struct ast_channel *chan)
static struct ast_custom_function mchan_function
Definition: func_channel.c:752