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

Generated on Thu Apr 16 06:27:35 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6