Mon Jun 27 16:50:53 2011

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

Generated on Mon Jun 27 16:50:53 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7