Sat Apr 26 2014 22:01:36

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: 411314 $")
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 numeric call pickup groups that this channel is a member.</para>
00105                </enum>
00106                <enum name="pickupgroup">
00107                   <para>R/W numeric call pickup groups this channel can pickup.</para>
00108                </enum>
00109                <enum name="namedcallgroup">
00110                   <para>R/W named call pickup groups that this channel is a member.</para>
00111                </enum>
00112                <enum name="namedpickupgroup">
00113                   <para>R/W named call pickup groups this channel can pickup.</para>
00114                </enum>
00115                <enum name="channeltype">
00116                   <para>R/O technology used for channel.</para>
00117                </enum>
00118                <enum name="checkhangup">
00119                   <para>R/O Whether the channel is hanging up (1/0)</para>
00120                </enum>
00121                <enum name="hangup_handler_pop">
00122                   <para>W/O Replace the most recently added hangup handler
00123                   with a new hangup handler on the channel if supplied.  The
00124                   assigned string is passed to the Gosub application when
00125                   the channel is hung up.  Any optionally omitted context
00126                   and exten are supplied by the channel pushing the handler
00127                   before it is pushed.</para>
00128                </enum>
00129                <enum name="hangup_handler_push">
00130                   <para>W/O Push a hangup handler onto the channel hangup
00131                   handler stack.  The assigned string is passed to the
00132                   Gosub application when the channel is hung up.  Any
00133                   optionally omitted context and exten are supplied by the
00134                   channel pushing the handler before it is pushed.</para>
00135                </enum>
00136                <enum name="hangup_handler_wipe">
00137                   <para>W/O Wipe the entire hangup handler stack and replace
00138                   with a new hangup handler on the channel if supplied.  The
00139                   assigned string is passed to the Gosub application when
00140                   the channel is hung up.  Any optionally omitted context
00141                   and exten are supplied by the channel pushing the handler
00142                   before it is pushed.</para>
00143                </enum>
00144                <enum name="language">
00145                   <para>R/W language for sounds played.</para>
00146                </enum>
00147                <enum name="musicclass">
00148                   <para>R/W class (from musiconhold.conf) for hold music.</para>
00149                </enum>
00150                <enum name="name">
00151                   <para>The name of the channel</para>
00152                </enum>
00153                <enum name="parkinglot">
00154                   <para>R/W parkinglot for parking.</para>
00155                </enum>
00156                <enum name="rxgain">
00157                   <para>R/W set rxgain level on channel drivers that support it.</para>
00158                </enum>
00159                <enum name="secure_bridge_signaling">
00160                   <para>Whether or not channels bridged to this channel require secure signaling</para>
00161                </enum>
00162                <enum name="secure_bridge_media">
00163                   <para>Whether or not channels bridged to this channel require secure media</para>
00164                </enum>
00165                <enum name="state">
00166                   <para>R/O state for channel</para>
00167                </enum>
00168                <enum name="tonezone">
00169                   <para>R/W zone for indications played</para>
00170                </enum>
00171                <enum name="transfercapability">
00172                   <para>R/W ISDN Transfer Capability, one of:</para>
00173                   <enumlist>
00174                      <enum name="SPEECH" />
00175                      <enum name="DIGITAL" />
00176                      <enum name="RESTRICTED_DIGITAL" />
00177                      <enum name="3K1AUDIO" />
00178                      <enum name="DIGITAL_W_TONES" />
00179                      <enum name="VIDEO" />
00180                   </enumlist>
00181                </enum>
00182                <enum name="txgain">
00183                   <para>R/W set txgain level on channel drivers that support it.</para>
00184                </enum>
00185                <enum name="videonativeformat">
00186                   <para>R/O format used natively for video</para>
00187                </enum>
00188                <enum name="trace">
00189                   <para>R/W whether or not context tracing is enabled, only available
00190                   <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
00191                </enum>
00192             </enumlist>
00193             <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
00194             <enumlist>
00195                <enum name="peerip">
00196                   <para>R/O Get the IP address of the peer.</para>
00197                </enum>
00198                <enum name="recvip">
00199                   <para>R/O Get the source IP address of the peer.</para>
00200                </enum>
00201                <enum name="from">
00202                   <para>R/O Get the URI from the From: header.</para>
00203                </enum>
00204                <enum name="uri">
00205                   <para>R/O Get the URI from the Contact: header.</para>
00206                </enum>
00207                <enum name="useragent">
00208                   <para>R/O Get the useragent.</para>
00209                </enum>
00210                <enum name="peername">
00211                   <para>R/O Get the name of the peer.</para>
00212                </enum>
00213                <enum name="t38passthrough">
00214                   <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
00215                   otherwise <literal>0</literal></para>
00216                </enum>
00217                <enum name="rtpqos">
00218                   <para>R/O Get QOS information about the RTP stream</para>
00219                   <para>    This option takes two additional arguments:</para>
00220                   <para>    Argument 1:</para>
00221                   <para>     <literal>audio</literal>             Get data about the audio stream</para>
00222                   <para>     <literal>video</literal>             Get data about the video stream</para>
00223                   <para>     <literal>text</literal>              Get data about the text stream</para>
00224                   <para>    Argument 2:</para>
00225                   <para>     <literal>local_ssrc</literal>        Local SSRC (stream ID)</para>
00226                   <para>     <literal>local_lostpackets</literal> Local lost packets</para>
00227                   <para>     <literal>local_jitter</literal>      Local calculated jitter</para>
00228                   <para>     <literal>local_maxjitter</literal>   Local calculated jitter (maximum)</para>
00229                   <para>     <literal>local_minjitter</literal>   Local calculated jitter (minimum)</para>
00230                   <para>     <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
00231                   <para>     <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
00232                   <para>     <literal>local_count</literal>       Number of received packets</para>
00233                   <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
00234                   <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
00235                   <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
00236                   <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
00237                   <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
00238                   <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
00239                   <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
00240                   <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
00241                   <para>     <literal>rtt</literal>               Round trip time</para>
00242                   <para>     <literal>maxrtt</literal>            Round trip time (maximum)</para>
00243                   <para>     <literal>minrtt</literal>            Round trip time (minimum)</para>
00244                   <para>     <literal>normdevrtt</literal>        Round trip time (normal deviation)</para>
00245                   <para>     <literal>stdevrtt</literal>          Round trip time (standard deviation)</para>
00246                   <para>     <literal>all</literal>               All statistics (in a form suited to logging,
00247                   but not for parsing)</para>
00248                </enum>
00249                <enum name="rtpdest">
00250                   <para>R/O Get remote RTP destination information.</para>
00251                   <para>   This option takes one additional argument:</para>
00252                   <para>    Argument 1:</para>
00253                   <para>     <literal>audio</literal>             Get audio destination</para>
00254                   <para>     <literal>video</literal>             Get video destination</para>
00255                   <para>     <literal>text</literal>              Get text destination</para>
00256                   <para>   Defaults to <literal>audio</literal> if unspecified.</para>
00257                </enum>
00258                <enum name="rtpsource">
00259                   <para>R/O Get source RTP destination information.</para>
00260                   <para>   This option takes one additional argument:</para>
00261                   <para>    Argument 1:</para>
00262                   <para>     <literal>audio</literal>             Get audio destination</para>
00263                   <para>     <literal>video</literal>             Get video destination</para>
00264                   <para>     <literal>text</literal>              Get text destination</para>
00265                   <para>   Defaults to <literal>audio</literal> if unspecified.</para>
00266                </enum>
00267             </enumlist>
00268             <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
00269             <enumlist>
00270                <enum name="osptoken">
00271                   <para>R/O Get the peer's osptoken.</para>
00272                </enum>
00273                <enum name="peerip">
00274                   <para>R/O Get the peer's ip address.</para>
00275                </enum>
00276                <enum name="peername">
00277                   <para>R/O Get the peer's username.</para>
00278                </enum>
00279                <enum name="secure_signaling">
00280                   <para>R/O Get the if the IAX channel is secured.</para>
00281                </enum>
00282                <enum name="secure_media">
00283                   <para>R/O Get the if the IAX channel is secured.</para>
00284                </enum>
00285             </enumlist>
00286             <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
00287             <enumlist>
00288                <enum name="dahdi_channel">
00289                   <para>R/O DAHDI channel related to this channel.</para>
00290                </enum>
00291                <enum name="dahdi_span">
00292                   <para>R/O DAHDI span related to this channel.</para>
00293                </enum>
00294                <enum name="dahdi_type">
00295                   <para>R/O DAHDI channel type, one of:</para>
00296                   <enumlist>
00297                      <enum name="analog" />
00298                      <enum name="mfc/r2" />
00299                      <enum name="pri" />
00300                      <enum name="pseudo" />
00301                      <enum name="ss7" />
00302                   </enumlist>
00303                </enum>
00304                <enum name="keypad_digits">
00305                   <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
00306                </enum>
00307                <enum name="reversecharge">
00308                   <para>R/O PRI Reverse Charging Indication, one of:</para>
00309                   <enumlist>
00310                      <enum name="-1"> <para>None</para></enum>
00311                      <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
00312                   </enumlist>
00313                </enum>
00314                <enum name="no_media_path">
00315                   <para>R/O PRI Nonzero if the channel has no B channel.
00316                   The channel is either on hold or a call waiting call.</para>
00317                </enum>
00318                <enum name="buffers">
00319                   <para>W/O Change the channel's buffer policy (for the current call only)</para>
00320                   <para>This option takes two arguments:</para>
00321                   <para>   Number of buffers,</para>
00322                   <para>   Buffer policy being one of:</para>
00323                   <para>       <literal>full</literal></para>
00324                   <para>       <literal>immediate</literal></para>
00325                   <para>       <literal>half</literal></para>
00326                </enum>
00327                <enum name="echocan_mode">
00328                   <para>W/O Change the configuration of the active echo
00329                   canceller on the channel (if any), for the current call
00330                   only.</para>
00331                   <para>Possible values are:</para>
00332                   <para>   <literal>on</literal>   Normal mode (the echo canceller is actually reinitalized)</para>
00333                   <para>   <literal>off</literal>  Disabled</para>
00334                   <para>   <literal>fax</literal>  FAX/data mode (NLP disabled if possible, otherwise
00335                      completely disabled)</para>
00336                   <para>   <literal>voice</literal>   Voice mode (returns from FAX mode, reverting the changes that were made)</para>
00337                </enum>
00338             </enumlist>
00339             <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
00340             <enumlist>
00341                <enum name="faxdetect">
00342                   <para>R/W Fax Detect</para>
00343                   <para>Returns 0 or 1</para>
00344                   <para>Write yes or no</para>
00345                </enum>
00346                <enum name="t38support">
00347                   <para>R/W t38support</para>
00348                   <para>Returns 0 or 1</para>
00349                   <para>Write yes or no</para>
00350                </enum>
00351                <enum name="h323id_url">
00352                   <para>R/0 Returns caller URL</para>
00353                </enum>
00354                <enum name="caller_h323id">
00355                   <para>R/0 Returns caller h323id</para>
00356                </enum>
00357                <enum name="caller_dialeddigits">
00358                   <para>R/0 Returns caller dialed digits</para>
00359                </enum>
00360                <enum name="caller_email">
00361                   <para>R/0 Returns caller email</para>
00362                </enum>
00363                <enum name="callee_email">
00364                   <para>R/0 Returns callee email</para>
00365                </enum>
00366                <enum name="callee_dialeddigits">
00367                   <para>R/0 Returns callee dialed digits</para>
00368                </enum>
00369                <enum name="caller_url">
00370                   <para>R/0 Returns caller URL</para>
00371                </enum>
00372             </enumlist>
00373          </parameter>
00374       </syntax>
00375       <description>
00376          <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
00377          be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
00378          requested that is not available on the current channel will return an empty string.</para>
00379       </description>
00380    </function>
00381  ***/
00382 
00383 #define locked_copy_string(chan, dest, source, len) \
00384    do { \
00385       ast_channel_lock(chan); \
00386       ast_copy_string(dest, source, len); \
00387       ast_channel_unlock(chan); \
00388    } while (0)
00389 #define locked_string_field_set(chan, field, source) \
00390    do { \
00391       ast_channel_lock(chan); \
00392       ast_channel_##field##_set(chan, source); \
00393       ast_channel_unlock(chan); \
00394    } while (0)
00395 
00396 static const char * const transfercapability_table[0x20] = {
00397    "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00398    "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00399    "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00400    "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
00401 
00402 static int func_channel_read(struct ast_channel *chan, const char *function,
00403               char *data, char *buf, size_t len)
00404 {
00405    int ret = 0;
00406    struct ast_format_cap *tmpcap;
00407 
00408    if (!chan) {
00409       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00410       return -1;
00411    }
00412 
00413    if (!strcasecmp(data, "audionativeformat")) {
00414       char tmp[512];
00415 
00416       if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
00417          ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
00418          tmpcap = ast_format_cap_destroy(tmpcap);
00419       }
00420    } else if (!strcasecmp(data, "videonativeformat")) {
00421       char tmp[512];
00422 
00423       if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
00424          ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
00425          tmpcap = ast_format_cap_destroy(tmpcap);
00426       }
00427    } else if (!strcasecmp(data, "audioreadformat")) {
00428       ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
00429    } else if (!strcasecmp(data, "audiowriteformat")) {
00430       ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
00431 #ifdef CHANNEL_TRACE
00432    } else if (!strcasecmp(data, "trace")) {
00433       ast_channel_lock(chan);
00434       ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
00435       ast_channel_unlock(chan);
00436 #endif
00437    } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan))
00438       locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
00439    else if (!strcasecmp(data, "language"))
00440       locked_copy_string(chan, buf, ast_channel_language(chan), len);
00441    else if (!strcasecmp(data, "musicclass"))
00442       locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
00443    else if (!strcasecmp(data, "name")) {
00444       locked_copy_string(chan, buf, ast_channel_name(chan), len);
00445    } else if (!strcasecmp(data, "parkinglot"))
00446       locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
00447    else if (!strcasecmp(data, "state"))
00448       locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
00449    else if (!strcasecmp(data, "channeltype"))
00450       locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
00451    else if (!strcasecmp(data, "accountcode"))
00452       locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
00453    else if (!strcasecmp(data, "checkhangup")) {
00454       ast_channel_lock(chan);
00455       ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
00456       ast_channel_unlock(chan);
00457    } else if (!strcasecmp(data, "peeraccount"))
00458       locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
00459    else if (!strcasecmp(data, "hangupsource"))
00460       locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
00461    else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
00462       locked_copy_string(chan, buf, ast_channel_appl(chan), len);
00463    else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
00464       locked_copy_string(chan, buf, ast_channel_data(chan), len);
00465    else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
00466       locked_copy_string(chan, buf, ast_channel_exten(chan), len);
00467    else if (!strcasecmp(data, "context") && ast_channel_data(chan))
00468       locked_copy_string(chan, buf, ast_channel_context(chan), len);
00469    else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
00470       locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
00471    else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
00472       locked_copy_string(chan, buf, ast_channel_name(chan), len);
00473    else if (!strcasecmp(data, "linkedid")) {
00474       ast_channel_lock(chan);
00475       if (ast_strlen_zero(ast_channel_linkedid(chan))) {
00476          /* fall back on the channel's uniqueid if linkedid is unset */
00477          ast_copy_string(buf, ast_channel_uniqueid(chan), len);
00478       }
00479       else {
00480          ast_copy_string(buf, ast_channel_linkedid(chan), len);
00481       }
00482       ast_channel_unlock(chan);
00483    } else if (!strcasecmp(data, "peer")) {
00484       struct ast_channel *p;
00485 
00486       ast_channel_lock(chan);
00487       p = ast_bridged_channel(chan);
00488       if (p || ast_channel_tech(chan) || ast_channel_cdr(chan)) /* dummy channel? if so, we hid the peer name in the language */
00489          ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
00490       else {
00491          /* a dummy channel can still pass along bridged peer info via
00492                            the BRIDGEPEER variable */
00493          const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
00494          if (!ast_strlen_zero(pname))
00495             ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
00496          else
00497             buf[0] = 0;
00498       }
00499       ast_channel_unlock(chan);
00500    } else if (!strcasecmp(data, "uniqueid")) {
00501       locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
00502    } else if (!strcasecmp(data, "transfercapability")) {
00503       locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
00504    } else if (!strcasecmp(data, "callgroup")) {
00505       char groupbuf[256];
00506 
00507       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
00508    } else if (!strcasecmp(data, "pickupgroup")) {
00509       char groupbuf[256];
00510 
00511       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
00512    } else if (!strcasecmp(data, "namedcallgroup")) {
00513       struct ast_str *tmp_str = ast_str_alloca(1024);
00514 
00515       locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
00516    } else if (!strcasecmp(data, "namedpickupgroup")) {
00517       struct ast_str *tmp_str = ast_str_alloca(1024);
00518 
00519       locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
00520    } else if (!strcasecmp(data, "amaflags")) {
00521       ast_channel_lock(chan);
00522       snprintf(buf, len, "%d", ast_channel_amaflags(chan));
00523       ast_channel_unlock(chan);
00524    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00525       struct ast_datastore *ds;
00526 
00527       ast_channel_lock(chan);
00528       if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00529          struct ast_secure_call_store *encrypt = ds->data;
00530          if (!strcasecmp(data, "secure_bridge_signaling")) {
00531             snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
00532          } else if (!strcasecmp(data, "secure_bridge_media")) {
00533             snprintf(buf, len, "%s", encrypt->media ? "1" : "");
00534          }
00535       }
00536       ast_channel_unlock(chan);
00537    } 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)) {
00538       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
00539       ret = -1;
00540    }
00541 
00542    return ret;
00543 }
00544 
00545 static int func_channel_write_real(struct ast_channel *chan, const char *function,
00546                char *data, const char *value)
00547 {
00548    int ret = 0;
00549    signed char gainset;
00550 
00551    if (!strcasecmp(data, "language"))
00552       locked_string_field_set(chan, language, value);
00553    else if (!strcasecmp(data, "parkinglot"))
00554       locked_string_field_set(chan, parkinglot, value);
00555    else if (!strcasecmp(data, "musicclass"))
00556       locked_string_field_set(chan, musicclass, value);
00557    else if (!strcasecmp(data, "accountcode"))
00558       locked_string_field_set(chan, accountcode, value);
00559    else if (!strcasecmp(data, "userfield"))
00560       locked_string_field_set(chan, userfield, value);
00561    else if (!strcasecmp(data, "amaflags")) {
00562       ast_channel_lock(chan);
00563       if(isdigit(*value)) {
00564          int amaflags;
00565          sscanf(value, "%30d", &amaflags);
00566          ast_channel_amaflags_set(chan, amaflags);
00567       } else if (!strcasecmp(value,"OMIT")){
00568          ast_channel_amaflags_set(chan, 1);
00569       } else if (!strcasecmp(value,"BILLING")){
00570          ast_channel_amaflags_set(chan, 2);
00571       } else if (!strcasecmp(value,"DOCUMENTATION")){
00572          ast_channel_amaflags_set(chan, 3);
00573       }
00574       ast_channel_unlock(chan);
00575    } else if (!strcasecmp(data, "peeraccount"))
00576       locked_string_field_set(chan, peeraccount, value);
00577    else if (!strcasecmp(data, "hangupsource"))
00578       /* XXX - should we be forcing this here? */
00579       ast_set_hangupsource(chan, value, 0);
00580 #ifdef CHANNEL_TRACE
00581    else if (!strcasecmp(data, "trace")) {
00582       ast_channel_lock(chan);
00583       if (ast_true(value))
00584          ret = ast_channel_trace_enable(chan);
00585       else if (ast_false(value))
00586          ret = ast_channel_trace_disable(chan);
00587       else {
00588          ret = -1;
00589          ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
00590       }
00591       ast_channel_unlock(chan);
00592    }
00593 #endif
00594    else if (!strcasecmp(data, "tonezone")) {
00595       struct ast_tone_zone *new_zone;
00596       if (!(new_zone = ast_get_indication_zone(value))) {
00597          ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
00598          ret = -1;
00599       } else {
00600          ast_channel_lock(chan);
00601          if (ast_channel_zone(chan)) {
00602             ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
00603          }
00604          ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
00605          ast_channel_unlock(chan);
00606          new_zone = ast_tone_zone_unref(new_zone);
00607       }
00608    } else if (!strcasecmp(data, "callgroup")) {
00609       ast_channel_lock(chan);
00610       ast_channel_callgroup_set(chan, ast_get_group(value));
00611       ast_channel_unlock(chan);
00612    } else if (!strcasecmp(data, "pickupgroup")) {
00613       ast_channel_lock(chan);
00614       ast_channel_pickupgroup_set(chan, ast_get_group(value));
00615       ast_channel_unlock(chan);
00616    } else if (!strcasecmp(data, "namedcallgroup")) {
00617       struct ast_namedgroups *groups = ast_get_namedgroups(value);
00618 
00619       ast_channel_lock(chan);
00620       ast_channel_named_callgroups_set(chan, groups);
00621       ast_channel_unlock(chan);
00622       ast_unref_namedgroups(groups);
00623    } else if (!strcasecmp(data, "namedpickupgroup")) {
00624       struct ast_namedgroups *groups = ast_get_namedgroups(value);
00625 
00626       ast_channel_lock(chan);
00627       ast_channel_named_pickupgroups_set(chan, groups);
00628       ast_channel_unlock(chan);
00629       ast_unref_namedgroups(groups);
00630    } else if (!strcasecmp(data, "txgain")) {
00631       sscanf(value, "%4hhd", &gainset);
00632       ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
00633    } else if (!strcasecmp(data, "rxgain")) {
00634       sscanf(value, "%4hhd", &gainset);
00635       ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
00636    } else if (!strcasecmp(data, "transfercapability")) {
00637       unsigned short i;
00638 
00639       ast_channel_lock(chan);
00640       for (i = 0; i < 0x20; i++) {
00641          if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
00642             ast_channel_transfercapability_set(chan, i);
00643             break;
00644          }
00645       }
00646       ast_channel_unlock(chan);
00647    } else if (!strcasecmp(data, "hangup_handler_pop")) {
00648       /* Pop one hangup handler before pushing the new handler. */
00649       ast_pbx_hangup_handler_pop(chan);
00650       ast_pbx_hangup_handler_push(chan, value);
00651    } else if (!strcasecmp(data, "hangup_handler_push")) {
00652       ast_pbx_hangup_handler_push(chan, value);
00653    } else if (!strcasecmp(data, "hangup_handler_wipe")) {
00654       /* Pop all hangup handlers before pushing the new handler. */
00655       while (ast_pbx_hangup_handler_pop(chan)) {
00656       }
00657       ast_pbx_hangup_handler_push(chan, value);
00658    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00659       struct ast_datastore *ds;
00660       struct ast_secure_call_store *store;
00661 
00662       if (!chan || !value) {
00663          return -1;
00664       }
00665 
00666       ast_channel_lock(chan);
00667       if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00668          if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
00669             ast_channel_unlock(chan);
00670             return -1;
00671          }
00672          if (!(store = ast_calloc(1, sizeof(*store)))) {
00673             ast_channel_unlock(chan);
00674             ast_free(ds);
00675             return -1;
00676          }
00677          ds->data = store;
00678          ast_channel_datastore_add(chan, ds);
00679       } else {
00680          store = ds->data;
00681       }
00682 
00683       if (!strcasecmp(data, "secure_bridge_signaling")) {
00684          store->signaling = ast_true(value) ? 1 : 0;
00685       } else if (!strcasecmp(data, "secure_bridge_media")) {
00686          store->media = ast_true(value) ? 1 : 0;
00687       }
00688       ast_channel_unlock(chan);
00689    } else if (!ast_channel_tech(chan)->func_channel_write
00690        || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
00691       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
00692             data);
00693       ret = -1;
00694    }
00695 
00696    return ret;
00697 }
00698 
00699 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
00700 {
00701    int res;
00702    ast_chan_write_info_t write_info = {
00703       .version = AST_CHAN_WRITE_INFO_T_VERSION,
00704       .write_fn = func_channel_write_real,
00705       .chan = chan,
00706       .function = function,
00707       .data = data,
00708       .value = value,
00709    };
00710 
00711    if (!chan) {
00712       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00713       return -1;
00714    }
00715 
00716    res = func_channel_write_real(chan, function, data, value);
00717    ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
00718 
00719    return res;
00720 }
00721 
00722 static struct ast_custom_function channel_function = {
00723    .name = "CHANNEL",
00724    .read = func_channel_read,
00725    .write = func_channel_write,
00726 };
00727 
00728 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
00729 {
00730    struct ast_channel *c = NULL;
00731    regex_t re;
00732    int res;
00733    size_t buflen = 0;
00734    struct ast_channel_iterator *iter;
00735 
00736    buf[0] = '\0';
00737 
00738    if (!ast_strlen_zero(data)) {
00739       if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
00740          regerror(res, &re, buf, maxlen);
00741          ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
00742          return -1;
00743       }
00744    }
00745 
00746    if (!(iter = ast_channel_iterator_all_new())) {
00747       if (!ast_strlen_zero(data)) {
00748          regfree(&re);
00749       }
00750       return -1;
00751    }
00752 
00753    while ((c = ast_channel_iterator_next(iter))) {
00754       ast_channel_lock(c);
00755       if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
00756          size_t namelen = strlen(ast_channel_name(c));
00757          if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
00758             if (!ast_strlen_zero(buf)) {
00759                strcat(buf, " ");
00760                buflen++;
00761             }
00762             strcat(buf, ast_channel_name(c));
00763             buflen += namelen;
00764          } else {
00765             ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
00766          }
00767       }
00768       ast_channel_unlock(c);
00769       c = ast_channel_unref(c);
00770    }
00771 
00772    ast_channel_iterator_destroy(iter);
00773 
00774    if (!ast_strlen_zero(data)) {
00775       regfree(&re);
00776    }
00777 
00778    return 0;
00779 }
00780 
00781 static struct ast_custom_function channels_function = {
00782    .name = "CHANNELS",
00783    .read = func_channels_read,
00784 };
00785 
00786 static int func_mchan_read(struct ast_channel *chan, const char *function,
00787               char *data, struct ast_str **buf, ssize_t len)
00788 {
00789    struct ast_channel *mchan;
00790    char *template = ast_alloca(4 + strlen(data));
00791 
00792    if (!chan) {
00793       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00794       return -1;
00795    }
00796 
00797    mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
00798    sprintf(template, "${%s}", data); /* SAFE */
00799    ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
00800    if (mchan) {
00801       ast_channel_unref(mchan);
00802    }
00803    return 0;
00804 }
00805 
00806 static int func_mchan_write(struct ast_channel *chan, const char *function,
00807                char *data, const char *value)
00808 {
00809    struct ast_channel *mchan;
00810 
00811    if (!chan) {
00812       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
00813       return -1;
00814    }
00815 
00816    mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
00817    pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
00818    if (mchan) {
00819       ast_channel_unref(mchan);
00820    }
00821    return 0;
00822 }
00823 
00824 static struct ast_custom_function mchan_function = {
00825    .name = "MASTER_CHANNEL",
00826    .read2 = func_mchan_read,
00827    .write = func_mchan_write,
00828 };
00829 
00830 static int unload_module(void)
00831 {
00832    int res = 0;
00833 
00834    res |= ast_custom_function_unregister(&channel_function);
00835    res |= ast_custom_function_unregister(&channels_function);
00836    res |= ast_custom_function_unregister(&mchan_function);
00837 
00838    return res;
00839 }
00840 
00841 static int load_module(void)
00842 {
00843    int res = 0;
00844 
00845    res |= ast_custom_function_register(&channel_function);
00846    res |= ast_custom_function_register(&channels_function);
00847    res |= ast_custom_function_register(&mchan_function);
00848 
00849    return res;
00850 }
00851 
00852 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");