Wed May 16 06:33:33 2012

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: 361476 $")
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="audioreadformat">
00081                   <para>R/O format currently being read.</para>
00082                </enum>
00083                <enum name="audionativeformat">
00084                   <para>R/O format used natively for audio.</para>
00085                </enum>
00086                <enum name="audiowriteformat">
00087                   <para>R/O format currently being written.</para>
00088                </enum>
00089                <enum name="callgroup">
00090                   <para>R/W call groups for call pickup.</para>
00091                </enum>
00092                <enum name="pickupgroup">
00093                   <para>R/W call groups for call pickup.</para>
00094                </enum>
00095                <enum name="channeltype">
00096                   <para>R/O technology used for channel.</para>
00097                </enum>
00098                <enum name="checkhangup">
00099                   <para>R/O Whether the channel is hanging up (1/0)</para>
00100                </enum>
00101                <enum name="language">
00102                   <para>R/W language for sounds played.</para>
00103                </enum>
00104                <enum name="musicclass">
00105                   <para>R/W class (from musiconhold.conf) for hold music.</para>
00106                </enum>
00107                <enum name="name">
00108                   <para>The name of the channel</para>
00109                </enum>
00110                <enum name="parkinglot">
00111                   <para>R/W parkinglot for parking.</para>
00112                </enum>
00113                <enum name="rxgain">
00114                   <para>R/W set rxgain level on channel drivers that support it.</para>
00115                </enum>
00116                <enum name="secure_bridge_signaling">
00117                   <para>Whether or not channels bridged to this channel require secure signaling</para>
00118                </enum>
00119                <enum name="secure_bridge_media">
00120                   <para>Whether or not channels bridged to this channel require secure media</para>
00121                </enum>
00122                <enum name="state">
00123                   <para>R/O state for channel</para>
00124                </enum>
00125                <enum name="tonezone">
00126                   <para>R/W zone for indications played</para>
00127                </enum>
00128                <enum name="transfercapability">
00129                   <para>R/W ISDN Transfer Capability, one of:</para>
00130                   <enumlist>
00131                      <enum name="SPEECH" />
00132                      <enum name="DIGITAL" />
00133                      <enum name="RESTRICTED_DIGITAL" />
00134                      <enum name="3K1AUDIO" />
00135                      <enum name="DIGITAL_W_TONES" />
00136                      <enum name="VIDEO" />
00137                   </enumlist>
00138                </enum>
00139                <enum name="txgain">
00140                   <para>R/W set txgain level on channel drivers that support it.</para>
00141                </enum>
00142                <enum name="videonativeformat">
00143                   <para>R/O format used natively for video</para>
00144                </enum>
00145                <enum name="trace">
00146                   <para>R/W whether or not context tracing is enabled, only available
00147                   <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
00148                </enum>
00149             </enumlist>
00150             <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
00151             <enumlist>
00152                <enum name="peerip">
00153                   <para>R/O Get the IP address of the peer.</para>
00154                </enum>
00155                <enum name="recvip">
00156                   <para>R/O Get the source IP address of the peer.</para>
00157                </enum>
00158                <enum name="from">
00159                   <para>R/O Get the URI from the From: header.</para>
00160                </enum>
00161                <enum name="uri">
00162                   <para>R/O Get the URI from the Contact: header.</para>
00163                </enum>
00164                <enum name="useragent">
00165                   <para>R/O Get the useragent.</para>
00166                </enum>
00167                <enum name="peername">
00168                   <para>R/O Get the name of the peer.</para>
00169                </enum>
00170                <enum name="t38passthrough">
00171                   <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
00172                   otherwise <literal>0</literal></para>
00173                </enum>
00174                <enum name="rtpqos">
00175                   <para>R/O Get QOS information about the RTP stream</para>
00176                   <para>    This option takes two additional arguments:</para>
00177                   <para>    Argument 1:</para>
00178                   <para>     <literal>audio</literal>             Get data about the audio stream</para>
00179                   <para>     <literal>video</literal>             Get data about the video stream</para>
00180                   <para>     <literal>text</literal>              Get data about the text stream</para>
00181                   <para>    Argument 2:</para>
00182                   <para>     <literal>local_ssrc</literal>        Local SSRC (stream ID)</para>
00183                   <para>     <literal>local_lostpackets</literal> Local lost packets</para>
00184                   <para>     <literal>local_jitter</literal>      Local calculated jitter</para>
00185                   <para>     <literal>local_maxjitter</literal>   Local calculated jitter (maximum)</para>
00186                   <para>     <literal>local_minjitter</literal>   Local calculated jitter (minimum)</para>
00187                   <para>     <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
00188                   <para>     <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
00189                   <para>     <literal>local_count</literal>       Number of received packets</para>
00190                   <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
00191                   <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
00192                   <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
00193                   <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
00194                   <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
00195                   <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
00196                   <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
00197                   <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
00198                   <para>     <literal>rtt</literal>               Round trip time</para>
00199                   <para>     <literal>maxrtt</literal>            Round trip time (maximum)</para>
00200                   <para>     <literal>minrtt</literal>            Round trip time (minimum)</para>
00201                   <para>     <literal>normdevrtt</literal>        Round trip time (normal deviation)</para>
00202                   <para>     <literal>stdevrtt</literal>          Round trip time (standard deviation)</para>
00203                   <para>     <literal>all</literal>               All statistics (in a form suited to logging,
00204                   but not for parsing)</para>
00205                </enum>
00206                <enum name="rtpdest">
00207                   <para>R/O Get remote RTP destination information.</para>
00208                   <para>   This option takes one additional argument:</para>
00209                   <para>    Argument 1:</para>
00210                   <para>     <literal>audio</literal>             Get audio destination</para>
00211                   <para>     <literal>video</literal>             Get video destination</para>
00212                   <para>     <literal>text</literal>              Get text destination</para>
00213                </enum>
00214             </enumlist>
00215             <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
00216             <enumlist>
00217                <enum name="peerip">
00218                   <para>R/O Get the peer's ip address.</para>
00219                </enum>
00220                <enum name="peername">
00221                   <para>R/O Get the peer's username.</para>
00222                </enum>
00223             </enumlist>
00224             <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
00225             <enumlist>
00226                <enum name="dahdi_channel">
00227                   <para>R/O DAHDI channel related to this channel.</para>
00228                </enum>
00229                <enum name="dahdi_span">
00230                   <para>R/O DAHDI span related to this channel.</para>
00231                </enum>
00232                <enum name="dahdi_type">
00233                   <para>R/O DAHDI channel type, one of:</para>
00234                   <enumlist>
00235                      <enum name="analog" />
00236                      <enum name="mfc/r2" />
00237                      <enum name="pri" />
00238                      <enum name="pseudo" />
00239                      <enum name="ss7" />
00240                   </enumlist>
00241                </enum>
00242                <enum name="keypad_digits">
00243                   <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
00244                </enum>
00245                <enum name="reversecharge">
00246                   <para>R/O PRI Reverse Charging Indication, one of:</para>
00247                   <enumlist>
00248                      <enum name="-1"> <para>None</para></enum>
00249                      <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
00250                   </enumlist>
00251                </enum>
00252                <enum name="no_media_path">
00253                   <para>R/O PRI Nonzero if the channel has no B channel.
00254                   The channel is either on hold or a call waiting call.</para>
00255                </enum>
00256             </enumlist>
00257             <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
00258             <enumlist>
00259                <enum name="faxdetect">
00260                   <para>Fax Detect [R/W]</para>
00261                   <para>Returns 0 or 1</para>
00262                   <para>Write yes or no</para>
00263                </enum>
00264                <enum name="t38support">
00265                   <para>t38support [R/W]</para>
00266                   <para>Returns 0 or 1</para>
00267                   <para>Write yes or no</para>
00268                </enum>
00269                <enum name="h323id">
00270                   <para>Returns h323id [R]</para>
00271                </enum>
00272             </enumlist>
00273          </parameter>
00274       </syntax>
00275       <description>
00276          <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
00277          be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
00278          requested that is not available on the current channel will return an empty string.</para>
00279       </description>
00280    </function>
00281  ***/
00282 
00283 #define locked_copy_string(chan, dest, source, len) \
00284    do { \
00285       ast_channel_lock(chan); \
00286       ast_copy_string(dest, source, len); \
00287       ast_channel_unlock(chan); \
00288    } while (0)
00289 #define locked_string_field_set(chan, field, source) \
00290    do { \
00291       ast_channel_lock(chan); \
00292       ast_channel_##field##_set(chan, source); \
00293       ast_channel_unlock(chan); \
00294    } while (0)
00295 
00296 static const char * const transfercapability_table[0x20] = {
00297    "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00298    "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00299    "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00300    "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
00301 
00302 static int func_channel_read(struct ast_channel *chan, const char *function,
00303               char *data, char *buf, size_t len)
00304 {
00305    int ret = 0;
00306    char tmp[512];
00307    struct ast_format_cap *tmpcap;
00308 
00309    if (!strcasecmp(data, "audionativeformat")) {
00310       if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
00311          ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
00312          tmpcap = ast_format_cap_destroy(tmpcap);
00313       }
00314    } else if (!strcasecmp(data, "videonativeformat")) {
00315       if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
00316          ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
00317          tmpcap = ast_format_cap_destroy(tmpcap);
00318       }
00319    } else if (!strcasecmp(data, "audioreadformat")) {
00320       ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
00321    } else if (!strcasecmp(data, "audiowriteformat")) {
00322       ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
00323 #ifdef CHANNEL_TRACE
00324    } else if (!strcasecmp(data, "trace")) {
00325       ast_channel_lock(chan);
00326       ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
00327       ast_channel_unlock(chan);
00328 #endif
00329    } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan))
00330       locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
00331    else if (!strcasecmp(data, "language"))
00332       locked_copy_string(chan, buf, ast_channel_language(chan), len);
00333    else if (!strcasecmp(data, "musicclass"))
00334       locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
00335    else if (!strcasecmp(data, "name")) {
00336       locked_copy_string(chan, buf, ast_channel_name(chan), len);
00337    } else if (!strcasecmp(data, "parkinglot"))
00338       locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
00339    else if (!strcasecmp(data, "state"))
00340       locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
00341    else if (!strcasecmp(data, "channeltype"))
00342       locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
00343    else if (!strcasecmp(data, "accountcode"))
00344       locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
00345    else if (!strcasecmp(data, "checkhangup")) {
00346       ast_channel_lock(chan);
00347       ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
00348       ast_channel_unlock(chan);
00349    } else if (!strcasecmp(data, "peeraccount"))
00350       locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
00351    else if (!strcasecmp(data, "hangupsource"))
00352       locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
00353    else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
00354       locked_copy_string(chan, buf, ast_channel_appl(chan), len);
00355    else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
00356       locked_copy_string(chan, buf, ast_channel_data(chan), len);
00357    else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
00358       locked_copy_string(chan, buf, ast_channel_exten(chan), len);
00359    else if (!strcasecmp(data, "context") && ast_channel_data(chan))
00360       locked_copy_string(chan, buf, ast_channel_context(chan), len);
00361    else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
00362       locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
00363    else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
00364       locked_copy_string(chan, buf, ast_channel_name(chan), len);
00365    else if (!strcasecmp(data, "linkedid")) {
00366       ast_channel_lock(chan);
00367       if (ast_strlen_zero(ast_channel_linkedid(chan))) {
00368          /* fall back on the channel's uniqueid if linkedid is unset */
00369          ast_copy_string(buf, ast_channel_uniqueid(chan), len);
00370       }
00371       else {
00372          ast_copy_string(buf, ast_channel_linkedid(chan), len);
00373       }
00374       ast_channel_unlock(chan);
00375    } else if (!strcasecmp(data, "peer")) {
00376       struct ast_channel *p;
00377       ast_channel_lock(chan);
00378       p = ast_bridged_channel(chan);
00379       if (p || ast_channel_tech(chan) || ast_channel_cdr(chan)) /* dummy channel? if so, we hid the peer name in the language */
00380          ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
00381       else {
00382          /* a dummy channel can still pass along bridged peer info via
00383                            the BRIDGEPEER variable */
00384          const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
00385          if (!ast_strlen_zero(pname))
00386             ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
00387          else
00388             buf[0] = 0;
00389       }
00390       ast_channel_unlock(chan);
00391    } else if (!strcasecmp(data, "uniqueid")) {
00392       locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
00393    } else if (!strcasecmp(data, "transfercapability")) {
00394       locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
00395    } else if (!strcasecmp(data, "callgroup")) {
00396       char groupbuf[256];
00397       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
00398    } else if (!strcasecmp(data, "pickupgroup")) {
00399       char groupbuf[256];
00400       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
00401    } else if (!strcasecmp(data, "amaflags")) {
00402       char amabuf[256];
00403       snprintf(amabuf,sizeof(amabuf), "%d", ast_channel_amaflags(chan));
00404       locked_copy_string(chan, buf, amabuf, len);
00405    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00406       struct ast_datastore *ds;
00407       ast_channel_lock(chan);
00408       if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00409          struct ast_secure_call_store *encrypt = ds->data;
00410          if (!strcasecmp(data, "secure_bridge_signaling")) {
00411             snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
00412          } else if (!strcasecmp(data, "secure_bridge_media")) {
00413             snprintf(buf, len, "%s", encrypt->media ? "1" : "");
00414          }
00415       }
00416       ast_channel_unlock(chan);
00417    } 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)) {
00418       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
00419       ret = -1;
00420    }
00421 
00422    return ret;
00423 }
00424 
00425 static int func_channel_write_real(struct ast_channel *chan, const char *function,
00426                char *data, const char *value)
00427 {
00428    int ret = 0;
00429    signed char gainset;
00430 
00431    if (!strcasecmp(data, "language"))
00432       locked_string_field_set(chan, language, value);
00433    else if (!strcasecmp(data, "parkinglot"))
00434       locked_string_field_set(chan, parkinglot, value);
00435    else if (!strcasecmp(data, "musicclass"))
00436       locked_string_field_set(chan, musicclass, value);
00437    else if (!strcasecmp(data, "accountcode"))
00438       locked_string_field_set(chan, accountcode, value);
00439    else if (!strcasecmp(data, "userfield"))
00440       locked_string_field_set(chan, userfield, value);
00441    else if (!strcasecmp(data, "amaflags")) {
00442       ast_channel_lock(chan);
00443       if(isdigit(*value)) {
00444          int amaflags;
00445          sscanf(value, "%30d", &amaflags);
00446          ast_channel_amaflags_set(chan, amaflags);
00447       } else if (!strcasecmp(value,"OMIT")){
00448          ast_channel_amaflags_set(chan, 1);
00449       } else if (!strcasecmp(value,"BILLING")){
00450          ast_channel_amaflags_set(chan, 2);
00451       } else if (!strcasecmp(value,"DOCUMENTATION")){
00452          ast_channel_amaflags_set(chan, 3);
00453       }
00454       ast_channel_unlock(chan);
00455    } else if (!strcasecmp(data, "peeraccount"))
00456       locked_string_field_set(chan, peeraccount, value);
00457    else if (!strcasecmp(data, "hangupsource"))
00458       /* XXX - should we be forcing this here? */
00459       ast_set_hangupsource(chan, value, 0);
00460 #ifdef CHANNEL_TRACE
00461    else if (!strcasecmp(data, "trace")) {
00462       ast_channel_lock(chan);
00463       if (ast_true(value)) 
00464          ret = ast_channel_trace_enable(chan);
00465       else if (ast_false(value))
00466          ret = ast_channel_trace_disable(chan);
00467       else {
00468          ret = -1;
00469          ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
00470       }
00471       ast_channel_unlock(chan);
00472    }
00473 #endif
00474    else if (!strcasecmp(data, "tonezone")) {
00475       struct ast_tone_zone *new_zone;
00476       if (!(new_zone = ast_get_indication_zone(value))) {
00477          ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
00478          ret = -1;   
00479       } else {
00480          ast_channel_lock(chan);
00481          if (ast_channel_zone(chan)) {
00482             ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
00483          }
00484          ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
00485          ast_channel_unlock(chan);
00486          new_zone = ast_tone_zone_unref(new_zone);
00487       }
00488    } else if (!strcasecmp(data, "callgroup")) {
00489       ast_channel_callgroup_set(chan, ast_get_group(value));
00490    } else if (!strcasecmp(data, "pickupgroup")) {
00491       ast_channel_pickupgroup_set(chan, ast_get_group(value));
00492    } else if (!strcasecmp(data, "txgain")) {
00493       sscanf(value, "%4hhd", &gainset);
00494       ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
00495    } else if (!strcasecmp(data, "rxgain")) {
00496       sscanf(value, "%4hhd", &gainset);
00497       ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
00498    } else if (!strcasecmp(data, "transfercapability")) {
00499       unsigned short i;
00500       for (i = 0; i < 0x20; i++) {
00501          if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
00502             ast_channel_transfercapability_set(chan, i);
00503             break;
00504          }
00505       }
00506    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00507       struct ast_datastore *ds;
00508       struct ast_secure_call_store *store;
00509 
00510       if (!chan || !value) {
00511          return -1;
00512       }
00513 
00514       ast_channel_lock(chan);
00515       if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00516          if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
00517             ast_channel_unlock(chan);
00518             return -1;
00519          }
00520          if (!(store = ast_calloc(1, sizeof(*store)))) {
00521             ast_channel_unlock(chan);
00522             ast_free(ds);
00523             return -1;
00524          }
00525          ds->data = store;
00526          ast_channel_datastore_add(chan, ds);
00527       } else {
00528          store = ds->data;
00529       }
00530       ast_channel_unlock(chan);
00531 
00532       if (!strcasecmp(data, "secure_bridge_signaling")) {
00533          store->signaling = ast_true(value) ? 1 : 0;
00534       } else if (!strcasecmp(data, "secure_bridge_media")) {
00535          store->media = ast_true(value) ? 1 : 0;
00536       }
00537    } else if (!ast_channel_tech(chan)->func_channel_write
00538        || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
00539       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
00540             data);
00541       ret = -1;
00542    }
00543 
00544    return ret;
00545 }
00546 
00547 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
00548 {
00549    int res;
00550    ast_chan_write_info_t write_info = {
00551       .version = AST_CHAN_WRITE_INFO_T_VERSION,
00552       .write_fn = func_channel_write_real,
00553       .chan = chan,
00554       .function = function,
00555       .data = data,
00556       .value = value,
00557    };
00558 
00559    res = func_channel_write_real(chan, function, data, value);
00560    ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
00561 
00562    return res;
00563 }
00564 
00565 static struct ast_custom_function channel_function = {
00566    .name = "CHANNEL",
00567    .read = func_channel_read,
00568    .write = func_channel_write,
00569 };
00570 
00571 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
00572 {
00573    struct ast_channel *c = NULL;
00574    regex_t re;
00575    int res;
00576    size_t buflen = 0;
00577    struct ast_channel_iterator *iter;
00578 
00579    buf[0] = '\0';
00580 
00581    if (!ast_strlen_zero(data)) {
00582       if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
00583          regerror(res, &re, buf, maxlen);
00584          ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
00585          return -1;
00586       }
00587    }
00588 
00589    if (!(iter = ast_channel_iterator_all_new())) {
00590       if (!ast_strlen_zero(data)) {
00591          regfree(&re);
00592       }
00593       return -1;
00594    }
00595 
00596    while ((c = ast_channel_iterator_next(iter))) {
00597       ast_channel_lock(c);
00598       if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
00599          size_t namelen = strlen(ast_channel_name(c));
00600          if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
00601             if (!ast_strlen_zero(buf)) {
00602                strcat(buf, " ");
00603                buflen++;
00604             }
00605             strcat(buf, ast_channel_name(c));
00606             buflen += namelen;
00607          } else {
00608             ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
00609          }
00610       }
00611       ast_channel_unlock(c);
00612       c = ast_channel_unref(c);
00613    }
00614 
00615    ast_channel_iterator_destroy(iter);
00616 
00617    if (!ast_strlen_zero(data)) {
00618       regfree(&re);
00619    }
00620 
00621    return 0;
00622 }
00623 
00624 static struct ast_custom_function channels_function = {
00625    .name = "CHANNELS",
00626    .read = func_channels_read,
00627 };
00628 
00629 static int func_mchan_read(struct ast_channel *chan, const char *function,
00630               char *data, struct ast_str **buf, ssize_t len)
00631 {
00632    struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
00633    char *template = alloca(4 + strlen(data));
00634    sprintf(template, "${%s}", data); /* SAFE */
00635    ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
00636    if (mchan) {
00637       ast_channel_unref(mchan);
00638    }
00639    return 0;
00640 }
00641 
00642 static int func_mchan_write(struct ast_channel *chan, const char *function,
00643                char *data, const char *value)
00644 {
00645    struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
00646    pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
00647    if (mchan) {
00648       ast_channel_unref(mchan);
00649    }
00650    return 0;
00651 }
00652 
00653 static struct ast_custom_function mchan_function = {
00654    .name = "MASTER_CHANNEL",
00655    .read2 = func_mchan_read,
00656    .write = func_mchan_write,
00657 };
00658 
00659 static int unload_module(void)
00660 {
00661    int res = 0;
00662 
00663    res |= ast_custom_function_unregister(&channel_function);
00664    res |= ast_custom_function_unregister(&channels_function);
00665    res |= ast_custom_function_unregister(&mchan_function);
00666 
00667    return res;
00668 }
00669 
00670 static int load_module(void)
00671 {
00672    int res = 0;
00673 
00674    res |= ast_custom_function_register(&channel_function);
00675    res |= ast_custom_function_register(&channels_function);
00676    res |= ast_custom_function_register(&mchan_function);
00677 
00678    return res;
00679 }
00680 
00681 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");

Generated on Wed May 16 06:33:33 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6