Tue Aug 20 16:34:33 2013

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

Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1