Wed Jan 8 2020 09:49:47

Asterisk developer's documentation


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 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 411313 $")
34 
35 #include <regex.h>
36 #include <ctype.h>
37 
38 #include "asterisk/module.h"
39 #include "asterisk/channel.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 
47 /*** DOCUMENTATION
48  <function name="CHANNELS" language="en_US">
49  <synopsis>
50  Gets the list of channels, optionally filtering by a regular expression.
51  </synopsis>
52  <syntax>
53  <parameter name="regular_expression" />
54  </syntax>
55  <description>
56  <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
57  no argument is provided, all known channels are returned. The
58  <replaceable>regular_expression</replaceable> must correspond to
59  the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
60  will be space-delimited.</para>
61  </description>
62  </function>
63  <function name="MASTER_CHANNEL" language="en_US">
64  <synopsis>
65  Gets or sets variables on the master channel
66  </synopsis>
67  <description>
68  <para>Allows access to the channel which created the current channel, if any. If the channel is already
69  a master channel, then accesses local channel variables.</para>
70  </description>
71  </function>
72  <function name="CHANNEL" language="en_US">
73  <synopsis>
74  Gets/sets various pieces of information about the channel.
75  </synopsis>
76  <syntax>
77  <parameter name="item" required="true">
78  <para>Standard items (provided by all channel technologies) are:</para>
79  <enumlist>
80  <enum name="amaflags">
81  <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
82  When read from a channel, the integer value will always be returned.
83  When written to a channel, both the string format or integer value
84  is accepted.</para>
85  <enumlist>
86  <enum name="1"><para><literal>OMIT</literal></para></enum>
87  <enum name="2"><para><literal>BILLING</literal></para></enum>
88  <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
89  </enumlist>
90  </enum>
91  <enum name="accountcode">
92  <para>R/W the channel's account code.</para>
93  </enum>
94  <enum name="audioreadformat">
95  <para>R/O format currently being read.</para>
96  </enum>
97  <enum name="audionativeformat">
98  <para>R/O format used natively for audio.</para>
99  </enum>
100  <enum name="audiowriteformat">
101  <para>R/O format currently being written.</para>
102  </enum>
103  <enum name="callgroup">
104  <para>R/W call groups for call pickup.</para>
105  </enum>
106  <enum name="channeltype">
107  <para>R/O technology used for channel.</para>
108  </enum>
109  <enum name="checkhangup">
110  <para>R/O Whether the channel is hanging up (1/0)</para>
111  </enum>
112  <enum name="language">
113  <para>R/W language for sounds played.</para>
114  </enum>
115  <enum name="musicclass">
116  <para>R/W class (from musiconhold.conf) for hold music.</para>
117  </enum>
118  <enum name="name">
119  <para>The name of the channel</para>
120  </enum>
121  <enum name="parkinglot">
122  <para>R/W parkinglot for parking.</para>
123  </enum>
124  <enum name="rxgain">
125  <para>R/W set rxgain level on channel drivers that support it.</para>
126  </enum>
127  <enum name="secure_bridge_signaling">
128  <para>Whether or not channels bridged to this channel require secure signaling</para>
129  </enum>
130  <enum name="secure_bridge_media">
131  <para>Whether or not channels bridged to this channel require secure media</para>
132  </enum>
133  <enum name="state">
134  <para>R/O state for channel</para>
135  </enum>
136  <enum name="tonezone">
137  <para>R/W zone for indications played</para>
138  </enum>
139  <enum name="transfercapability">
140  <para>R/W ISDN Transfer Capability, one of:</para>
141  <enumlist>
142  <enum name="SPEECH" />
143  <enum name="DIGITAL" />
144  <enum name="RESTRICTED_DIGITAL" />
145  <enum name="3K1AUDIO" />
146  <enum name="DIGITAL_W_TONES" />
147  <enum name="VIDEO" />
148  </enumlist>
149  </enum>
150  <enum name="txgain">
151  <para>R/W set txgain level on channel drivers that support it.</para>
152  </enum>
153  <enum name="videonativeformat">
154  <para>R/O format used natively for video</para>
155  </enum>
156  <enum name="trace">
157  <para>R/W whether or not context tracing is enabled, only available
158  <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
159  </enum>
160  </enumlist>
161  <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
162  <enumlist>
163  <enum name="peerip">
164  <para>R/O Get the IP address of the peer.</para>
165  </enum>
166  <enum name="recvip">
167  <para>R/O Get the source IP address of the peer.</para>
168  </enum>
169  <enum name="from">
170  <para>R/O Get the URI from the From: header.</para>
171  </enum>
172  <enum name="uri">
173  <para>R/O Get the URI from the Contact: header.</para>
174  </enum>
175  <enum name="useragent">
176  <para>R/O Get the useragent.</para>
177  </enum>
178  <enum name="peername">
179  <para>R/O Get the name of the peer.</para>
180  </enum>
181  <enum name="t38passthrough">
182  <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
183  otherwise <literal>0</literal></para>
184  </enum>
185  <enum name="rtpqos">
186  <para>R/O Get QOS information about the RTP stream</para>
187  <para> This option takes two additional arguments:</para>
188  <para> Argument 1:</para>
189  <para> <literal>audio</literal> Get data about the audio stream</para>
190  <para> <literal>video</literal> Get data about the video stream</para>
191  <para> <literal>text</literal> Get data about the text stream</para>
192  <para> Argument 2:</para>
193  <para> <literal>local_ssrc</literal> Local SSRC (stream ID)</para>
194  <para> <literal>local_lostpackets</literal> Local lost packets</para>
195  <para> <literal>local_jitter</literal> Local calculated jitter</para>
196  <para> <literal>local_maxjitter</literal> Local calculated jitter (maximum)</para>
197  <para> <literal>local_minjitter</literal> Local calculated jitter (minimum)</para>
198  <para> <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
199  <para> <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
200  <para> <literal>local_count</literal> Number of received packets</para>
201  <para> <literal>remote_ssrc</literal> Remote SSRC (stream ID)</para>
202  <para> <literal>remote_lostpackets</literal>Remote lost packets</para>
203  <para> <literal>remote_jitter</literal> Remote reported jitter</para>
204  <para> <literal>remote_maxjitter</literal> Remote calculated jitter (maximum)</para>
205  <para> <literal>remote_minjitter</literal> Remote calculated jitter (minimum)</para>
206  <para> <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
207  <para> <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
208  <para> <literal>remote_count</literal> Number of transmitted packets</para>
209  <para> <literal>rtt</literal> Round trip time</para>
210  <para> <literal>maxrtt</literal> Round trip time (maximum)</para>
211  <para> <literal>minrtt</literal> Round trip time (minimum)</para>
212  <para> <literal>normdevrtt</literal> Round trip time (normal deviation)</para>
213  <para> <literal>stdevrtt</literal> Round trip time (standard deviation)</para>
214  <para> <literal>all</literal> All statistics (in a form suited to logging,
215  but not for parsing)</para>
216  </enum>
217  <enum name="rtpdest">
218  <para>R/O Get remote RTP destination information.</para>
219  <para> This option takes one additional argument:</para>
220  <para> Argument 1:</para>
221  <para> <literal>audio</literal> Get audio destination</para>
222  <para> <literal>video</literal> Get video destination</para>
223  <para> <literal>text</literal> Get text destination</para>
224  <para> Defaults to <literal>audio</literal> if unspecified.</para>
225  </enum>
226  <enum name="rtpsource">
227  <para>R/O Get source RTP destination information.</para>
228  <para> This option takes one additional argument:</para>
229  <para> Argument 1:</para>
230  <para> <literal>audio</literal> Get audio destination</para>
231  <para> <literal>video</literal> Get video destination</para>
232  <para> <literal>text</literal> Get text destination</para>
233  <para> Defaults to <literal>audio</literal> if unspecified.</para>
234  </enum>
235  </enumlist>
236  <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
237  <enumlist>
238  <enum name="osptoken">
239  <para>R/O Get the peer's osptoken.</para>
240  </enum>
241  <enum name="peerip">
242  <para>R/O Get the peer's ip address.</para>
243  </enum>
244  <enum name="peername">
245  <para>R/O Get the peer's username.</para>
246  </enum>
247  <enum name="secure_signaling">
248  <para>R/O Get the if the IAX channel is secured.</para>
249  </enum>
250  <enum name="secure_media">
251  <para>R/O Get the if the IAX channel is secured.</para>
252  </enum>
253  </enumlist>
254  <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
255  <enumlist>
256  <enum name="dahdi_channel">
257  <para>R/O DAHDI channel related to this channel.</para>
258  </enum>
259  <enum name="dahdi_span">
260  <para>R/O DAHDI span related to this channel.</para>
261  </enum>
262  <enum name="dahdi_type">
263  <para>R/O DAHDI channel type, one of:</para>
264  <enumlist>
265  <enum name="analog" />
266  <enum name="mfc/r2" />
267  <enum name="pri" />
268  <enum name="pseudo" />
269  <enum name="ss7" />
270  </enumlist>
271  </enum>
272  <enum name="keypad_digits">
273  <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
274  </enum>
275  <enum name="reversecharge">
276  <para>R/O PRI Reverse Charging Indication, one of:</para>
277  <enumlist>
278  <enum name="-1"> <para>None</para></enum>
279  <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
280  </enumlist>
281  </enum>
282  <enum name="no_media_path">
283  <para>R/O PRI Nonzero if the channel has no B channel.
284  The channel is either on hold or a call waiting call.</para>
285  </enum>
286  <enum name="buffers">
287  <para>W/O Change the channel's buffer policy (for the current call only)</para>
288  <para>This option takes two arguments:</para>
289  <para> Number of buffers,</para>
290  <para> Buffer policy being one of:</para>
291  <para> <literal>full</literal></para>
292  <para> <literal>immediate</literal></para>
293  <para> <literal>half</literal></para>
294  </enum>
295  <enum name="echocan_mode">
296  <para>W/O Change the configuration of the active echo
297  canceller on the channel (if any), for the current call
298  only.</para>
299  <para>Possible values are:</para>
300  <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitalized)</para>
301  <para> <literal>off</literal> Disabled</para>
302  <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
303  completely disabled)</para>
304  <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
305  </enum>
306  </enumlist>
307  </parameter>
308  </syntax>
309  <description>
310  <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
311  be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
312  requested that is not available on the current channel will return an empty string.</para>
313  </description>
314  </function>
315  ***/
316 
317 #define locked_copy_string(chan, dest, source, len) \
318  do { \
319  ast_channel_lock(chan); \
320  ast_copy_string(dest, source, len); \
321  ast_channel_unlock(chan); \
322  } while (0)
323 #define locked_string_field_set(chan, field, source) \
324  do { \
325  ast_channel_lock(chan); \
326  ast_string_field_set(chan, field, source); \
327  ast_channel_unlock(chan); \
328  } while (0)
329 
330 static const char * const transfercapability_table[0x20] = {
331  "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
332  "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
333  "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
334  "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
335 
336 static int func_channel_read(struct ast_channel *chan, const char *function,
337  char *data, char *buf, size_t len)
338 {
339  int ret = 0;
340 
341  if (!chan) {
342  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
343  return -1;
344  }
345 
346  if (!strcasecmp(data, "audionativeformat"))
347  /* use the _multiple version when chan->nativeformats holds multiple formats */
348  /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */
350  else if (!strcasecmp(data, "videonativeformat"))
351  /* use the _multiple version when chan->nativeformats holds multiple formats */
352  /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */
354  else if (!strcasecmp(data, "audioreadformat"))
355  ast_copy_string(buf, ast_getformatname(chan->readformat), len);
356  else if (!strcasecmp(data, "audiowriteformat"))
358 #ifdef CHANNEL_TRACE
359  else if (!strcasecmp(data, "trace")) {
360  ast_channel_lock(chan);
361  ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
362  ast_channel_unlock(chan);
363  }
364 #endif
365  else if (!strcasecmp(data, "tonezone") && chan->zone)
366  locked_copy_string(chan, buf, chan->zone->country, len);
367  else if (!strcasecmp(data, "language"))
368  locked_copy_string(chan, buf, chan->language, len);
369  else if (!strcasecmp(data, "musicclass"))
370  locked_copy_string(chan, buf, chan->musicclass, len);
371  else if (!strcasecmp(data, "name")) {
372  locked_copy_string(chan, buf, chan->name, len);
373  } else if (!strcasecmp(data, "parkinglot"))
374  locked_copy_string(chan, buf, chan->parkinglot, len);
375  else if (!strcasecmp(data, "state"))
376  locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
377  else if (!strcasecmp(data, "channeltype"))
378  locked_copy_string(chan, buf, chan->tech->type, len);
379  else if (!strcasecmp(data, "accountcode"))
380  locked_copy_string(chan, buf, chan->accountcode, len);
381  else if (!strcasecmp(data, "checkhangup")) {
382  ast_channel_lock(chan);
383  ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
384  ast_channel_unlock(chan);
385  } else if (!strcasecmp(data, "peeraccount"))
386  locked_copy_string(chan, buf, chan->peeraccount, len);
387  else if (!strcasecmp(data, "hangupsource"))
388  locked_copy_string(chan, buf, chan->hangupsource, len);
389  else if (!strcasecmp(data, "appname") && chan->appl)
390  locked_copy_string(chan, buf, chan->appl, len);
391  else if (!strcasecmp(data, "appdata") && chan->data)
392  locked_copy_string(chan, buf, chan->data, len);
393  else if (!strcasecmp(data, "exten") && chan->data)
394  locked_copy_string(chan, buf, chan->exten, len);
395  else if (!strcasecmp(data, "context") && chan->data)
396  locked_copy_string(chan, buf, chan->context, len);
397  else if (!strcasecmp(data, "userfield") && chan->data)
398  locked_copy_string(chan, buf, chan->userfield, len);
399  else if (!strcasecmp(data, "channame") && chan->data)
400  locked_copy_string(chan, buf, chan->name, len);
401  else if (!strcasecmp(data, "linkedid")) {
402  ast_channel_lock(chan);
403  if (ast_strlen_zero(chan->linkedid)) {
404  /* fall back on the channel's uniqueid if linkedid is unset */
405  ast_copy_string(buf, chan->uniqueid, len);
406  }
407  else {
408  ast_copy_string(buf, chan->linkedid, len);
409  }
410  ast_channel_unlock(chan);
411  } else if (!strcasecmp(data, "peer")) {
412  struct ast_channel *p;
413  ast_channel_lock(chan);
414  p = ast_bridged_channel(chan);
415  if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */
416  ast_copy_string(buf, (p ? p->name : ""), len);
417  else {
418  /* a dummy channel can still pass along bridged peer info via
419  the BRIDGEPEER variable */
420  const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
421  if (!ast_strlen_zero(pname))
422  ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
423  else
424  buf[0] = 0;
425  }
426  ast_channel_unlock(chan);
427  } else if (!strcasecmp(data, "uniqueid")) {
428  locked_copy_string(chan, buf, chan->uniqueid, len);
429  } else if (!strcasecmp(data, "transfercapability"))
430  locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
431  else if (!strcasecmp(data, "callgroup")) {
432  char groupbuf[256];
433  locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
434  } else if (!strcasecmp(data, "amaflags")) {
435  char amabuf[256];
436  snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags);
437  locked_copy_string(chan, buf, amabuf, len);
438  } else if (!strncasecmp(data, "secure_bridge_", 14)) {
439  struct ast_datastore *ds;
440  ast_channel_lock(chan);
441  if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
442  struct ast_secure_call_store *encrypt = ds->data;
443  if (!strcasecmp(data, "secure_bridge_signaling")) {
444  snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
445  } else if (!strcasecmp(data, "secure_bridge_media")) {
446  snprintf(buf, len, "%s", encrypt->media ? "1" : "");
447  }
448  }
449  ast_channel_unlock(chan);
450  } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) {
451  ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
452  ret = -1;
453  }
454 
455  return ret;
456 }
457 
458 static int func_channel_write_real(struct ast_channel *chan, const char *function,
459  char *data, const char *value)
460 {
461  int ret = 0;
462  signed char gainset;
463 
464  if (!strcasecmp(data, "language"))
465  locked_string_field_set(chan, language, value);
466  else if (!strcasecmp(data, "parkinglot"))
467  locked_string_field_set(chan, parkinglot, value);
468  else if (!strcasecmp(data, "musicclass"))
469  locked_string_field_set(chan, musicclass, value);
470  else if (!strcasecmp(data, "accountcode"))
471  locked_string_field_set(chan, accountcode, value);
472  else if (!strcasecmp(data, "userfield"))
473  locked_string_field_set(chan, userfield, value);
474  else if (!strcasecmp(data, "amaflags")) {
475  ast_channel_lock(chan);
476  if(isdigit(*value)) {
477  sscanf(value, "%30d", &chan->amaflags);
478  } else if (!strcasecmp(value,"OMIT")){
479  chan->amaflags = 1;
480  } else if (!strcasecmp(value,"BILLING")){
481  chan->amaflags = 2;
482  } else if (!strcasecmp(value,"DOCUMENTATION")){
483  chan->amaflags = 3;
484  }
485  ast_channel_unlock(chan);
486  } else if (!strcasecmp(data, "peeraccount"))
487  locked_string_field_set(chan, peeraccount, value);
488  else if (!strcasecmp(data, "hangupsource"))
489  /* XXX - should we be forcing this here? */
490  ast_set_hangupsource(chan, value, 0);
491 #ifdef CHANNEL_TRACE
492  else if (!strcasecmp(data, "trace")) {
493  ast_channel_lock(chan);
494  if (ast_true(value))
495  ret = ast_channel_trace_enable(chan);
496  else if (ast_false(value))
497  ret = ast_channel_trace_disable(chan);
498  else {
499  ret = -1;
500  ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
501  }
502  ast_channel_unlock(chan);
503  }
504 #endif
505  else if (!strcasecmp(data, "tonezone")) {
506  struct ast_tone_zone *new_zone;
507  if (!(new_zone = ast_get_indication_zone(value))) {
508  ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
509  ret = -1;
510  } else {
511  ast_channel_lock(chan);
512  if (chan->zone) {
513  chan->zone = ast_tone_zone_unref(chan->zone);
514  }
515  chan->zone = ast_tone_zone_ref(new_zone);
516  ast_channel_unlock(chan);
517  new_zone = ast_tone_zone_unref(new_zone);
518  }
519  } else if (!strcasecmp(data, "callgroup"))
520  chan->callgroup = ast_get_group(value);
521  else if (!strcasecmp(data, "txgain")) {
522  sscanf(value, "%4hhd", &gainset);
523  ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
524  } else if (!strcasecmp(data, "rxgain")) {
525  sscanf(value, "%4hhd", &gainset);
526  ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
527  } else if (!strcasecmp(data, "transfercapability")) {
528  unsigned short i;
529  for (i = 0; i < 0x20; i++) {
530  if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
531  chan->transfercapability = i;
532  break;
533  }
534  }
535  } else if (!strncasecmp(data, "secure_bridge_", 14)) {
536  struct ast_datastore *ds;
537  struct ast_secure_call_store *store;
538 
539  if (!chan || !value) {
540  return -1;
541  }
542 
543  ast_channel_lock(chan);
544  if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
545  if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
546  ast_channel_unlock(chan);
547  return -1;
548  }
549  if (!(store = ast_calloc(1, sizeof(*store)))) {
550  ast_channel_unlock(chan);
551  ast_free(ds);
552  return -1;
553  }
554  ds->data = store;
555  ast_channel_datastore_add(chan, ds);
556  } else {
557  store = ds->data;
558  }
559  ast_channel_unlock(chan);
560 
561  if (!strcasecmp(data, "secure_bridge_signaling")) {
562  store->signaling = ast_true(value) ? 1 : 0;
563  } else if (!strcasecmp(data, "secure_bridge_media")) {
564  store->media = ast_true(value) ? 1 : 0;
565  }
566  } else if (!chan->tech->func_channel_write
567  || chan->tech->func_channel_write(chan, function, data, value)) {
568  ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
569  data);
570  ret = -1;
571  }
572 
573  return ret;
574 }
575 
576 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
577 {
578  int res;
579  ast_chan_write_info_t write_info = {
581  .write_fn = func_channel_write_real,
582  .chan = chan,
583  .function = function,
584  .data = data,
585  .value = value,
586  };
587 
588  if (!chan) {
589  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
590  return -1;
591  }
592 
593  res = func_channel_write_real(chan, function, data, value);
594  ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
595 
596  return res;
597 }
598 
600  .name = "CHANNEL",
601  .read = func_channel_read,
602  .write = func_channel_write,
603 };
604 
605 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
606 {
607  struct ast_channel *c = NULL;
608  regex_t re;
609  int res;
610  size_t buflen = 0;
611  struct ast_channel_iterator *iter;
612 
613  buf[0] = '\0';
614 
615  if (!ast_strlen_zero(data)) {
616  if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
617  regerror(res, &re, buf, maxlen);
618  ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
619  return -1;
620  }
621  }
622 
623  if (!(iter = ast_channel_iterator_all_new())) {
624  if (!ast_strlen_zero(data)) {
625  regfree(&re);
626  }
627  return -1;
628  }
629 
630  while ((c = ast_channel_iterator_next(iter))) {
631  ast_channel_lock(c);
632  if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
633  size_t namelen = strlen(c->name);
634  if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
635  if (!ast_strlen_zero(buf)) {
636  strcat(buf, " ");
637  buflen++;
638  }
639  strcat(buf, c->name);
640  buflen += namelen;
641  } else {
642  ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
643  }
644  }
646  c = ast_channel_unref(c);
647  }
648 
650 
651  if (!ast_strlen_zero(data)) {
652  regfree(&re);
653  }
654 
655  return 0;
656 }
657 
659  .name = "CHANNELS",
660  .read = func_channels_read,
661 };
662 
663 static int func_mchan_read(struct ast_channel *chan, const char *function,
664  char *data, struct ast_str **buf, ssize_t len)
665 {
666  struct ast_channel *mchan;
667  char *template = ast_alloca(4 + strlen(data));
668 
669  if (!chan) {
670  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
671  return -1;
672  }
673 
674  mchan = ast_channel_get_by_name(chan->linkedid);
675  sprintf(template, "${%s}", data); /* SAFE */
676  ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
677  if (mchan) {
678  ast_channel_unref(mchan);
679  }
680  return 0;
681 }
682 
683 static int func_mchan_write(struct ast_channel *chan, const char *function,
684  char *data, const char *value)
685 {
686  struct ast_channel *mchan;
687 
688  if (!chan) {
689  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
690  return -1;
691  }
692 
693  mchan = ast_channel_get_by_name(chan->linkedid);
694  pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
695  if (mchan) {
696  ast_channel_unref(mchan);
697  }
698  return 0;
699 }
700 
702  .name = "MASTER_CHANNEL",
703  .read2 = func_mchan_read,
704  .write = func_mchan_write,
705 };
706 
707 static int unload_module(void)
708 {
709  int res = 0;
710 
711  res |= ast_custom_function_unregister(&channel_function);
712  res |= ast_custom_function_unregister(&channels_function);
713  res |= ast_custom_function_unregister(&mchan_function);
714 
715  return res;
716 }
717 
718 static int load_module(void)
719 {
720  int res = 0;
721 
722  res |= ast_custom_function_register(&channel_function);
723  res |= ast_custom_function_register(&channels_function);
724  res |= ast_custom_function_register(&mchan_function);
725 
726  return res;
727 }
728 
729 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");
int(* func_channel_read)(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Provide additional read items for CHANNEL() dialplan function.
Definition: channel.h:600
const ast_string_field peeraccount
Definition: channel.h:787
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:155
Tone Indication Support.
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
const char *const type
Definition: channel.h:508
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1715
Asterisk main include file. File version handling, generic pbx functions.
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
struct ast_tone_zone * zone
Definition: channel.h:767
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:204
const ast_string_field uniqueid
Definition: channel.h:787
format_t writeformat
Definition: channel.h:854
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
Definition: func_channel.c:605
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
globally accessible channel datastores
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
static struct ast_custom_function channel_function
Definition: func_channel.c:599
struct ast_cdr * cdr
Definition: channel.h:766
unsigned short transfercapability
Definition: channel.h:863
format_t nativeformats
Definition: channel.h:852
Structure for a data store object.
Definition: datastore.h:54
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:2604
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:1007
const char * data
Definition: channel.h:755
int value
Definition: syslog.c:39
const ast_string_field linkedid
Definition: channel.h:787
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:7795
static int func_mchan_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: func_channel.c:683
const char * appl
Definition: channel.h:754
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
ast_group_t callgroup
Definition: channel.h:818
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
String fields in structures.
Utility functions.
char * ast_print_group(char *buf, int buflen, ast_group_t group)
print call- and pickup groups into buffer
Definition: channel.c:8236
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&#39;s bridge.
Definition: channel.c:2769
#define AST_OPTION_CHANNEL_WRITE
Handle channel write data If a channel needs to process the data from a func_channel write operation ...
Definition: frame.h:484
A set of tones for a given locale.
Definition: indications.h:73
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Data structure associated with a custom dialplan function.
Definition: pbx.h:95
#define locked_copy_string(chan, dest, source, len)
Definition: func_channel.c:317
const ast_string_field parkinglot
Definition: channel.h:787
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7987
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:806
struct ast_datastore_info secure_call_info
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define LOG_ERROR
Definition: logger.h:155
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:484
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static struct ast_custom_function channels_function
Definition: func_channel.c:658
static int load_module(void)
Definition: func_channel.c:718
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
Definition: indications.c:451
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
Definition: channel.h:839
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
const ast_string_field name
Definition: channel.h:787
const ast_string_field hangupsource
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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:215
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define locked_string_field_set(chan, field, source)
Definition: func_channel.c:323
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:663
#define AST_FORMAT_VIDEO_MASK
Definition: frame.h:290
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
Structure to handle passing func_channel_write info to channels via setoption.
Definition: channel.h:482
#define AST_FORMAT_AUDIO_MASK
Definition: frame.h:274
const ast_string_field userfield
Definition: channel.h:787
static const char *const transfercapability_table[0x20]
Definition: func_channel.c:330
char country[16]
Country code that this set of tones is for.
Definition: indications.h:75
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...
Definition: pbx.c:10546
void * data
Definition: datastore.h:56
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
static int func_channel_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Definition: func_channel.c:336
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
#define AST_OPTION_RXGAIN
Definition: frame.h:463
static int func_channel_write_real(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: func_channel.c:458
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1649
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
const ast_string_field musicclass
Definition: channel.h:787
const ast_string_field accountcode
Definition: channel.h:787
static int unload_module(void)
Definition: func_channel.c:707
static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: func_channel.c:576
const char * name
Definition: pbx.h:96
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition: channel.c:1701
int(* func_channel_write)(struct ast_channel *chan, const char *function, char *data, const char *value)
Provide additional write items for CHANNEL() dialplan function.
Definition: channel.h:603
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
Asterisk module definitions.
int amaflags
Definition: channel.h:843
struct ast_channel_tech * tech
Definition: channel.h:743
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
const ast_string_field language
Definition: channel.h:787
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define AST_OPTION_TXGAIN
Definition: frame.h:458
static struct ast_custom_function mchan_function
Definition: func_channel.c:701