Fri Aug 17 00:17:16 2018

Asterisk developer's documentation


func_channel.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2006, Digium, Inc.
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*! \file
00018  *
00019  * \brief Channel info dialplan functions
00020  *
00021  * \author Kevin P. Fleming <kpfleming@digium.com>
00022  * \author Ben Winslow
00023  *
00024  * \ingroup functions
00025  */
00026 
00027 /*** MODULEINFO
00028    <support_level>core</support_level>
00029  ***/
00030 
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 411313 $")
00034 
00035 #include <regex.h>
00036 #include <ctype.h>
00037 
00038 #include "asterisk/module.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/utils.h"
00042 #include "asterisk/app.h"
00043 #include "asterisk/indications.h"
00044 #include "asterisk/stringfields.h"
00045 #include "asterisk/global_datastores.h"
00046 
00047 /*** DOCUMENTATION
00048    <function name="CHANNELS" language="en_US">
00049       <synopsis>
00050          Gets the list of channels, optionally filtering by a regular expression.
00051       </synopsis>
00052       <syntax>
00053          <parameter name="regular_expression" />
00054       </syntax>
00055       <description>
00056          <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
00057          no argument is provided, all known channels are returned. The
00058          <replaceable>regular_expression</replaceable> must correspond to
00059          the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
00060          will be space-delimited.</para>
00061       </description>
00062    </function>
00063    <function name="MASTER_CHANNEL" language="en_US">
00064       <synopsis>
00065          Gets or sets variables on the master channel
00066       </synopsis>
00067       <description>
00068          <para>Allows access to the channel which created the current channel, if any.  If the channel is already
00069          a master channel, then accesses local channel variables.</para>
00070       </description>
00071    </function>
00072    <function name="CHANNEL" language="en_US">
00073       <synopsis>
00074          Gets/sets various pieces of information about the channel.
00075       </synopsis>
00076       <syntax>
00077          <parameter name="item" required="true">
00078             <para>Standard items (provided by all channel technologies) are:</para>
00079             <enumlist>
00080                <enum name="amaflags">
00081                   <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
00082                   When read from a channel, the integer value will always be returned.
00083                   When written to a channel, both the string format or integer value
00084                   is accepted.</para>
00085                   <enumlist>
00086                      <enum name="1"><para><literal>OMIT</literal></para></enum>
00087                      <enum name="2"><para><literal>BILLING</literal></para></enum>
00088                      <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
00089                   </enumlist>
00090                </enum>
00091                <enum name="accountcode">
00092                   <para>R/W the channel's account code.</para>
00093                </enum>
00094                <enum name="audioreadformat">
00095                   <para>R/O format currently being read.</para>
00096                </enum>
00097                <enum name="audionativeformat">
00098                   <para>R/O format used natively for audio.</para>
00099                </enum>
00100                <enum name="audiowriteformat">
00101                   <para>R/O format currently being written.</para>
00102                </enum>
00103                <enum name="callgroup">
00104                   <para>R/W call groups for call pickup.</para>
00105                </enum>
00106                <enum name="channeltype">
00107                   <para>R/O technology used for channel.</para>
00108                </enum>
00109                <enum name="checkhangup">
00110                   <para>R/O Whether the channel is hanging up (1/0)</para>
00111                </enum>
00112                <enum name="language">
00113                   <para>R/W language for sounds played.</para>
00114                </enum>
00115                <enum name="musicclass">
00116                   <para>R/W class (from musiconhold.conf) for hold music.</para>
00117                </enum>
00118                <enum name="name">
00119                   <para>The name of the channel</para>
00120                </enum>
00121                <enum name="parkinglot">
00122                   <para>R/W parkinglot for parking.</para>
00123                </enum>
00124                <enum name="rxgain">
00125                   <para>R/W set rxgain level on channel drivers that support it.</para>
00126                </enum>
00127                <enum name="secure_bridge_signaling">
00128                   <para>Whether or not channels bridged to this channel require secure signaling</para>
00129                </enum>
00130                <enum name="secure_bridge_media">
00131                   <para>Whether or not channels bridged to this channel require secure media</para>
00132                </enum>
00133                <enum name="state">
00134                   <para>R/O state for channel</para>
00135                </enum>
00136                <enum name="tonezone">
00137                   <para>R/W zone for indications played</para>
00138                </enum>
00139                <enum name="transfercapability">
00140                   <para>R/W ISDN Transfer Capability, one of:</para>
00141                   <enumlist>
00142                      <enum name="SPEECH" />
00143                      <enum name="DIGITAL" />
00144                      <enum name="RESTRICTED_DIGITAL" />
00145                      <enum name="3K1AUDIO" />
00146                      <enum name="DIGITAL_W_TONES" />
00147                      <enum name="VIDEO" />
00148                   </enumlist>
00149                </enum>
00150                <enum name="txgain">
00151                   <para>R/W set txgain level on channel drivers that support it.</para>
00152                </enum>
00153                <enum name="videonativeformat">
00154                   <para>R/O format used natively for video</para>
00155                </enum>
00156                <enum name="trace">
00157                   <para>R/W whether or not context tracing is enabled, only available
00158                   <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
00159                </enum>
00160             </enumlist>
00161             <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
00162             <enumlist>
00163                <enum name="peerip">
00164                   <para>R/O Get the IP address of the peer.</para>
00165                </enum>
00166                <enum name="recvip">
00167                   <para>R/O Get the source IP address of the peer.</para>
00168                </enum>
00169                <enum name="from">
00170                   <para>R/O Get the URI from the From: header.</para>
00171                </enum>
00172                <enum name="uri">
00173                   <para>R/O Get the URI from the Contact: header.</para>
00174                </enum>
00175                <enum name="useragent">
00176                   <para>R/O Get the useragent.</para>
00177                </enum>
00178                <enum name="peername">
00179                   <para>R/O Get the name of the peer.</para>
00180                </enum>
00181                <enum name="t38passthrough">
00182                   <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
00183                   otherwise <literal>0</literal></para>
00184                </enum>
00185                <enum name="rtpqos">
00186                   <para>R/O Get QOS information about the RTP stream</para>
00187                   <para>    This option takes two additional arguments:</para>
00188                   <para>    Argument 1:</para>
00189                   <para>     <literal>audio</literal>             Get data about the audio stream</para>
00190                   <para>     <literal>video</literal>             Get data about the video stream</para>
00191                   <para>     <literal>text</literal>              Get data about the text stream</para>
00192                   <para>    Argument 2:</para>
00193                   <para>     <literal>local_ssrc</literal>        Local SSRC (stream ID)</para>
00194                   <para>     <literal>local_lostpackets</literal> Local lost packets</para>
00195                   <para>     <literal>local_jitter</literal>      Local calculated jitter</para>
00196                   <para>     <literal>local_maxjitter</literal>   Local calculated jitter (maximum)</para>
00197                   <para>     <literal>local_minjitter</literal>   Local calculated jitter (minimum)</para>
00198                   <para>     <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
00199                   <para>     <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
00200                   <para>     <literal>local_count</literal>       Number of received packets</para>
00201                   <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
00202                   <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
00203                   <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
00204                   <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
00205                   <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
00206                   <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
00207                   <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
00208                   <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
00209                   <para>     <literal>rtt</literal>               Round trip time</para>
00210                   <para>     <literal>maxrtt</literal>            Round trip time (maximum)</para>
00211                   <para>     <literal>minrtt</literal>            Round trip time (minimum)</para>
00212                   <para>     <literal>normdevrtt</literal>        Round trip time (normal deviation)</para>
00213                   <para>     <literal>stdevrtt</literal>          Round trip time (standard deviation)</para>
00214                   <para>     <literal>all</literal>               All statistics (in a form suited to logging,
00215                   but not for parsing)</para>
00216                </enum>
00217                <enum name="rtpdest">
00218                   <para>R/O Get remote RTP destination information.</para>
00219                   <para>   This option takes one additional argument:</para>
00220                   <para>    Argument 1:</para>
00221                   <para>     <literal>audio</literal>             Get audio destination</para>
00222                   <para>     <literal>video</literal>             Get video destination</para>
00223                   <para>     <literal>text</literal>              Get text destination</para>
00224                   <para>   Defaults to <literal>audio</literal> if unspecified.</para>
00225                </enum>
00226                <enum name="rtpsource">
00227                   <para>R/O Get source RTP destination information.</para>
00228                   <para>   This option takes one additional argument:</para>
00229                   <para>    Argument 1:</para>
00230                   <para>     <literal>audio</literal>             Get audio destination</para>
00231                   <para>     <literal>video</literal>             Get video destination</para>
00232                   <para>     <literal>text</literal>              Get text destination</para>
00233                   <para>   Defaults to <literal>audio</literal> if unspecified.</para>
00234                </enum>
00235             </enumlist>
00236             <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
00237             <enumlist>
00238                <enum name="osptoken">
00239                   <para>R/O Get the peer's osptoken.</para>
00240                </enum>
00241                <enum name="peerip">
00242                   <para>R/O Get the peer's ip address.</para>
00243                </enum>
00244                <enum name="peername">
00245                   <para>R/O Get the peer's username.</para>
00246                </enum>
00247                <enum name="secure_signaling">
00248                   <para>R/O Get the if the IAX channel is secured.</para>
00249                </enum>
00250                <enum name="secure_media">
00251                   <para>R/O Get the if the IAX channel is secured.</para>
00252                </enum>
00253             </enumlist>
00254             <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
00255             <enumlist>
00256                <enum name="dahdi_channel">
00257                   <para>R/O DAHDI channel related to this channel.</para>
00258                </enum>
00259                <enum name="dahdi_span">
00260                   <para>R/O DAHDI span related to this channel.</para>
00261                </enum>
00262                <enum name="dahdi_type">
00263                   <para>R/O DAHDI channel type, one of:</para>
00264                   <enumlist>
00265                      <enum name="analog" />
00266                      <enum name="mfc/r2" />
00267                      <enum name="pri" />
00268                      <enum name="pseudo" />
00269                      <enum name="ss7" />
00270                   </enumlist>
00271                </enum>
00272                <enum name="keypad_digits">
00273                   <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
00274                </enum>
00275                <enum name="reversecharge">
00276                   <para>R/O PRI Reverse Charging Indication, one of:</para>
00277                   <enumlist>
00278                      <enum name="-1"> <para>None</para></enum>
00279                      <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
00280                   </enumlist>
00281                </enum>
00282                <enum name="no_media_path">
00283                   <para>R/O PRI Nonzero if the channel has no B channel.
00284                   The channel is either on hold or a call waiting call.</para>
00285                </enum>
00286                <enum name="buffers">
00287                   <para>W/O Change the channel's buffer policy (for the current call only)</para>
00288                   <para>This option takes two arguments:</para>
00289                   <para>   Number of buffers,</para>
00290                   <para>   Buffer policy being one of:</para>
00291                   <para>       <literal>full</literal></para>
00292                   <para>       <literal>immediate</literal></para>
00293                   <para>       <literal>half</literal></para>
00294                </enum>
00295                <enum name="echocan_mode">
00296                   <para>W/O Change the configuration of the active echo
00297                   canceller on the channel (if any), for the current call
00298                   only.</para>
00299                   <para>Possible values are:</para>
00300                   <para>   <literal>on</literal>   Normal mode (the echo canceller is actually reinitalized)</para>
00301                   <para>   <literal>off</literal>  Disabled</para>
00302                   <para>   <literal>fax</literal>  FAX/data mode (NLP disabled if possible, otherwise
00303                      completely disabled)</para>
00304                   <para>   <literal>voice</literal>   Voice mode (returns from FAX mode, reverting the changes that were made)</para>
00305                </enum>
00306             </enumlist>
00307          </parameter>
00308       </syntax>
00309       <description>
00310          <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
00311          be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
00312          requested that is not available on the current channel will return an empty string.</para>
00313       </description>
00314    </function>
00315  ***/
00316 
00317 #define locked_copy_string(chan, dest, source, len) \
00318    do { \
00319       ast_channel_lock(chan); \
00320       ast_copy_string(dest, source, len); \
00321       ast_channel_unlock(chan); \
00322    } while (0)
00323 #define locked_string_field_set(chan, field, source) \
00324    do { \
00325       ast_channel_lock(chan); \
00326       ast_string_field_set(chan, field, source); \
00327       ast_channel_unlock(chan); \
00328    } while (0)
00329 
00330 static const char * const transfercapability_table[0x20] = {
00331    "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00332    "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00333    "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00334    "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
00335 
00336 static int func_channel_read(struct ast_channel *chan, const char *function,
00337               char *data, char *buf, size_t len)
00338 {
00339    int ret = 0;
00340 
00341    if (!chan) {
00342       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00343       return -1;
00344    }
00345 
00346    if (!strcasecmp(data, "audionativeformat"))
00347       /* use the _multiple version when chan->nativeformats holds multiple formats */
00348       /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */
00349       ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len);
00350    else if (!strcasecmp(data, "videonativeformat"))
00351       /* use the _multiple version when chan->nativeformats holds multiple formats */
00352       /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */
00353       ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len);
00354    else if (!strcasecmp(data, "audioreadformat"))
00355       ast_copy_string(buf, ast_getformatname(chan->readformat), len);
00356    else if (!strcasecmp(data, "audiowriteformat"))
00357       ast_copy_string(buf, ast_getformatname(chan->writeformat), len);
00358 #ifdef CHANNEL_TRACE
00359    else if (!strcasecmp(data, "trace")) {
00360       ast_channel_lock(chan);
00361       ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
00362       ast_channel_unlock(chan);
00363    }
00364 #endif
00365    else if (!strcasecmp(data, "tonezone") && chan->zone)
00366       locked_copy_string(chan, buf, chan->zone->country, len);
00367    else if (!strcasecmp(data, "language"))
00368       locked_copy_string(chan, buf, chan->language, len);
00369    else if (!strcasecmp(data, "musicclass"))
00370       locked_copy_string(chan, buf, chan->musicclass, len);
00371    else if (!strcasecmp(data, "name")) {
00372       locked_copy_string(chan, buf, chan->name, len);
00373    } else if (!strcasecmp(data, "parkinglot"))
00374       locked_copy_string(chan, buf, chan->parkinglot, len);
00375    else if (!strcasecmp(data, "state"))
00376       locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
00377    else if (!strcasecmp(data, "channeltype"))
00378       locked_copy_string(chan, buf, chan->tech->type, len);
00379    else if (!strcasecmp(data, "accountcode"))
00380       locked_copy_string(chan, buf, chan->accountcode, len);
00381    else if (!strcasecmp(data, "checkhangup")) {
00382       ast_channel_lock(chan);
00383       ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
00384       ast_channel_unlock(chan);
00385    } else if (!strcasecmp(data, "peeraccount"))
00386       locked_copy_string(chan, buf, chan->peeraccount, len);
00387    else if (!strcasecmp(data, "hangupsource"))
00388       locked_copy_string(chan, buf, chan->hangupsource, len);
00389    else if (!strcasecmp(data, "appname") && chan->appl)
00390       locked_copy_string(chan, buf, chan->appl, len);
00391    else if (!strcasecmp(data, "appdata") && chan->data)
00392       locked_copy_string(chan, buf, chan->data, len);
00393    else if (!strcasecmp(data, "exten") && chan->data)
00394       locked_copy_string(chan, buf, chan->exten, len);
00395    else if (!strcasecmp(data, "context") && chan->data)
00396       locked_copy_string(chan, buf, chan->context, len);
00397    else if (!strcasecmp(data, "userfield") && chan->data)
00398       locked_copy_string(chan, buf, chan->userfield, len);
00399    else if (!strcasecmp(data, "channame") && chan->data)
00400       locked_copy_string(chan, buf, chan->name, len);
00401    else if (!strcasecmp(data, "linkedid")) {
00402       ast_channel_lock(chan);
00403       if (ast_strlen_zero(chan->linkedid)) {
00404          /* fall back on the channel's uniqueid if linkedid is unset */
00405          ast_copy_string(buf, chan->uniqueid, len);
00406       }
00407       else {
00408          ast_copy_string(buf, chan->linkedid, len);
00409       }
00410       ast_channel_unlock(chan);
00411    } else if (!strcasecmp(data, "peer")) {
00412       struct ast_channel *p;
00413       ast_channel_lock(chan);
00414       p = ast_bridged_channel(chan);
00415       if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */
00416          ast_copy_string(buf, (p ? p->name : ""), len);
00417       else {
00418          /* a dummy channel can still pass along bridged peer info via
00419                            the BRIDGEPEER variable */
00420          const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
00421          if (!ast_strlen_zero(pname))
00422             ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
00423          else
00424             buf[0] = 0;
00425       }
00426       ast_channel_unlock(chan);
00427    } else if (!strcasecmp(data, "uniqueid")) {
00428       locked_copy_string(chan, buf, chan->uniqueid, len);
00429    } else if (!strcasecmp(data, "transfercapability"))
00430       locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
00431    else if (!strcasecmp(data, "callgroup")) {
00432       char groupbuf[256];
00433       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
00434    } else if (!strcasecmp(data, "amaflags")) {
00435       char amabuf[256];
00436       snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags);
00437       locked_copy_string(chan, buf, amabuf, len);
00438    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00439       struct ast_datastore *ds;
00440       ast_channel_lock(chan);
00441       if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00442          struct ast_secure_call_store *encrypt = ds->data;
00443          if (!strcasecmp(data, "secure_bridge_signaling")) {
00444             snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
00445          } else if (!strcasecmp(data, "secure_bridge_media")) {
00446             snprintf(buf, len, "%s", encrypt->media ? "1" : "");
00447          }
00448       }
00449       ast_channel_unlock(chan);
00450    } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) {
00451       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
00452       ret = -1;
00453    }
00454 
00455    return ret;
00456 }
00457 
00458 static int func_channel_write_real(struct ast_channel *chan, const char *function,
00459                char *data, const char *value)
00460 {
00461    int ret = 0;
00462    signed char gainset;
00463 
00464    if (!strcasecmp(data, "language"))
00465       locked_string_field_set(chan, language, value);
00466    else if (!strcasecmp(data, "parkinglot"))
00467       locked_string_field_set(chan, parkinglot, value);
00468    else if (!strcasecmp(data, "musicclass"))
00469       locked_string_field_set(chan, musicclass, value);
00470    else if (!strcasecmp(data, "accountcode"))
00471       locked_string_field_set(chan, accountcode, value);
00472    else if (!strcasecmp(data, "userfield"))
00473       locked_string_field_set(chan, userfield, value);
00474    else if (!strcasecmp(data, "amaflags")) {
00475       ast_channel_lock(chan);
00476       if(isdigit(*value)) {
00477          sscanf(value, "%30d", &chan->amaflags);
00478       } else if (!strcasecmp(value,"OMIT")){
00479          chan->amaflags = 1;
00480       } else if (!strcasecmp(value,"BILLING")){
00481          chan->amaflags = 2;
00482       } else if (!strcasecmp(value,"DOCUMENTATION")){
00483          chan->amaflags = 3;
00484       }
00485       ast_channel_unlock(chan);
00486    } else if (!strcasecmp(data, "peeraccount"))
00487       locked_string_field_set(chan, peeraccount, value);
00488    else if (!strcasecmp(data, "hangupsource"))
00489       /* XXX - should we be forcing this here? */
00490       ast_set_hangupsource(chan, value, 0);
00491 #ifdef CHANNEL_TRACE
00492    else if (!strcasecmp(data, "trace")) {
00493       ast_channel_lock(chan);
00494       if (ast_true(value))
00495          ret = ast_channel_trace_enable(chan);
00496       else if (ast_false(value))
00497          ret = ast_channel_trace_disable(chan);
00498       else {
00499          ret = -1;
00500          ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
00501       }
00502       ast_channel_unlock(chan);
00503    }
00504 #endif
00505    else if (!strcasecmp(data, "tonezone")) {
00506       struct ast_tone_zone *new_zone;
00507       if (!(new_zone = ast_get_indication_zone(value))) {
00508          ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
00509          ret = -1;
00510       } else {
00511          ast_channel_lock(chan);
00512          if (chan->zone) {
00513             chan->zone = ast_tone_zone_unref(chan->zone);
00514          }
00515          chan->zone = ast_tone_zone_ref(new_zone);
00516          ast_channel_unlock(chan);
00517          new_zone = ast_tone_zone_unref(new_zone);
00518       }
00519    } else if (!strcasecmp(data, "callgroup"))
00520       chan->callgroup = ast_get_group(value);
00521    else if (!strcasecmp(data, "txgain")) {
00522       sscanf(value, "%4hhd", &gainset);
00523       ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
00524    } else if (!strcasecmp(data, "rxgain")) {
00525       sscanf(value, "%4hhd", &gainset);
00526       ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
00527    } else if (!strcasecmp(data, "transfercapability")) {
00528       unsigned short i;
00529       for (i = 0; i < 0x20; i++) {
00530          if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
00531             chan->transfercapability = i;
00532             break;
00533          }
00534       }
00535    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00536       struct ast_datastore *ds;
00537       struct ast_secure_call_store *store;
00538 
00539       if (!chan || !value) {
00540          return -1;
00541       }
00542 
00543       ast_channel_lock(chan);
00544       if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00545          if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
00546             ast_channel_unlock(chan);
00547             return -1;
00548          }
00549          if (!(store = ast_calloc(1, sizeof(*store)))) {
00550             ast_channel_unlock(chan);
00551             ast_free(ds);
00552             return -1;
00553          }
00554          ds->data = store;
00555          ast_channel_datastore_add(chan, ds);
00556       } else {
00557          store = ds->data;
00558       }
00559       ast_channel_unlock(chan);
00560 
00561       if (!strcasecmp(data, "secure_bridge_signaling")) {
00562          store->signaling = ast_true(value) ? 1 : 0;
00563       } else if (!strcasecmp(data, "secure_bridge_media")) {
00564          store->media = ast_true(value) ? 1 : 0;
00565       }
00566    } else if (!chan->tech->func_channel_write
00567        || chan->tech->func_channel_write(chan, function, data, value)) {
00568       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
00569             data);
00570       ret = -1;
00571    }
00572 
00573    return ret;
00574 }
00575 
00576 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
00577 {
00578    int res;
00579    ast_chan_write_info_t write_info = {
00580       .version = AST_CHAN_WRITE_INFO_T_VERSION,
00581       .write_fn = func_channel_write_real,
00582       .chan = chan,
00583       .function = function,
00584       .data = data,
00585       .value = value,
00586    };
00587 
00588    if (!chan) {
00589       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00590       return -1;
00591    }
00592 
00593    res = func_channel_write_real(chan, function, data, value);
00594    ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
00595 
00596    return res;
00597 }
00598 
00599 static struct ast_custom_function channel_function = {
00600    .name = "CHANNEL",
00601    .read = func_channel_read,
00602    .write = func_channel_write,
00603 };
00604 
00605 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
00606 {
00607    struct ast_channel *c = NULL;
00608    regex_t re;
00609    int res;
00610    size_t buflen = 0;
00611    struct ast_channel_iterator *iter;
00612 
00613    buf[0] = '\0';
00614 
00615    if (!ast_strlen_zero(data)) {
00616       if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
00617          regerror(res, &re, buf, maxlen);
00618          ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
00619          return -1;
00620       }
00621    }
00622 
00623    if (!(iter = ast_channel_iterator_all_new())) {
00624       if (!ast_strlen_zero(data)) {
00625          regfree(&re);
00626       }
00627       return -1;
00628    }
00629 
00630    while ((c = ast_channel_iterator_next(iter))) {
00631       ast_channel_lock(c);
00632       if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
00633          size_t namelen = strlen(c->name);
00634          if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
00635             if (!ast_strlen_zero(buf)) {
00636                strcat(buf, " ");
00637                buflen++;
00638             }
00639             strcat(buf, c->name);
00640             buflen += namelen;
00641          } else {
00642             ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
00643          }
00644       }
00645       ast_channel_unlock(c);
00646       c = ast_channel_unref(c);
00647    }
00648 
00649    ast_channel_iterator_destroy(iter);
00650 
00651    if (!ast_strlen_zero(data)) {
00652       regfree(&re);
00653    }
00654 
00655    return 0;
00656 }
00657 
00658 static struct ast_custom_function channels_function = {
00659    .name = "CHANNELS",
00660    .read = func_channels_read,
00661 };
00662 
00663 static int func_mchan_read(struct ast_channel *chan, const char *function,
00664               char *data, struct ast_str **buf, ssize_t len)
00665 {
00666    struct ast_channel *mchan;
00667    char *template = ast_alloca(4 + strlen(data));
00668 
00669    if (!chan) {
00670       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00671       return -1;
00672    }
00673 
00674    mchan = ast_channel_get_by_name(chan->linkedid);
00675    sprintf(template, "${%s}", data); /* SAFE */
00676    ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
00677    if (mchan) {
00678       ast_channel_unref(mchan);
00679    }
00680    return 0;
00681 }
00682 
00683 static int func_mchan_write(struct ast_channel *chan, const char *function,
00684                char *data, const char *value)
00685 {
00686    struct ast_channel *mchan;
00687 
00688    if (!chan) {
00689       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00690       return -1;
00691    }
00692 
00693    mchan = ast_channel_get_by_name(chan->linkedid);
00694    pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
00695    if (mchan) {
00696       ast_channel_unref(mchan);
00697    }
00698    return 0;
00699 }
00700 
00701 static struct ast_custom_function mchan_function = {
00702    .name = "MASTER_CHANNEL",
00703    .read2 = func_mchan_read,
00704    .write = func_mchan_write,
00705 };
00706 
00707 static int unload_module(void)
00708 {
00709    int res = 0;
00710 
00711    res |= ast_custom_function_unregister(&channel_function);
00712    res |= ast_custom_function_unregister(&channels_function);
00713    res |= ast_custom_function_unregister(&mchan_function);
00714 
00715    return res;
00716 }
00717 
00718 static int load_module(void)
00719 {
00720    int res = 0;
00721 
00722    res |= ast_custom_function_register(&channel_function);
00723    res |= ast_custom_function_register(&channels_function);
00724    res |= ast_custom_function_register(&mchan_function);
00725 
00726    return res;
00727 }
00728 
00729 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");

Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1