Wed Aug 18 22:33:52 2010

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: 250732 $")
00030 
00031 #include <regex.h>
00032 
00033 #include "asterisk/module.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/utils.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/indications.h"
00039 #include "asterisk/stringfields.h"
00040 
00041 #define locked_copy_string(chan, dest, source, len) \
00042    do { \
00043       ast_channel_lock(chan); \
00044       ast_copy_string(dest, source, len); \
00045       ast_channel_unlock(chan); \
00046    } while (0)
00047 #define locked_string_field_set(chan, field, source) \
00048    do { \
00049       ast_channel_lock(chan); \
00050       ast_string_field_set(chan, field, source); \
00051       ast_channel_unlock(chan); \
00052    } while (0)
00053 
00054 char *transfercapability_table[0x20] = {
00055    "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00056    "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00057    "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00058    "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
00059 
00060 static int func_channel_read(struct ast_channel *chan, const char *function,
00061               char *data, char *buf, size_t len)
00062 {
00063    int ret = 0;
00064 
00065    if (!strcasecmp(data, "audionativeformat"))
00066       /* use the _multiple version when chan->nativeformats holds multiple formats */
00067       /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */
00068       ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len);
00069    else if (!strcasecmp(data, "videonativeformat"))
00070       /* use the _multiple version when chan->nativeformats holds multiple formats */
00071       /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */
00072       ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len);
00073    else if (!strcasecmp(data, "audioreadformat"))
00074       ast_copy_string(buf, ast_getformatname(chan->readformat), len);
00075    else if (!strcasecmp(data, "audiowriteformat"))
00076       ast_copy_string(buf, ast_getformatname(chan->writeformat), len);
00077 #ifdef CHANNEL_TRACE
00078    else if (!strcasecmp(data, "trace")) {
00079       ast_channel_lock(chan);
00080       ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
00081       ast_channel_unlock(chan);
00082    }
00083 #endif
00084    else if (!strcasecmp(data, "tonezone") && chan->zone)
00085       locked_copy_string(chan, buf, chan->zone->country, len);
00086    else if (!strcasecmp(data, "language"))
00087       locked_copy_string(chan, buf, chan->language, len);
00088    else if (!strcasecmp(data, "musicclass"))
00089       locked_copy_string(chan, buf, chan->musicclass, len);
00090    else if (!strcasecmp(data, "parkinglot"))
00091       locked_copy_string(chan, buf, chan->parkinglot, len);
00092    else if (!strcasecmp(data, "state"))
00093       locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
00094    else if (!strcasecmp(data, "channeltype"))
00095       locked_copy_string(chan, buf, chan->tech->type, len);
00096    else if (!strcasecmp(data, "transfercapability"))
00097       locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
00098    else if (!strcasecmp(data, "callgroup")) {
00099       char groupbuf[256];
00100       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
00101    } else if (!chan->tech->func_channel_read
00102        || chan->tech->func_channel_read(chan, function, data, buf, len)) {
00103       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
00104       ret = -1;
00105    }
00106 
00107    return ret;
00108 }
00109 
00110 static int func_channel_write(struct ast_channel *chan, const char *function,
00111                char *data, const char *value)
00112 {
00113    int ret = 0;
00114    signed char gainset;
00115 
00116    if (!strcasecmp(data, "language"))
00117       locked_string_field_set(chan, language, value);
00118    else if (!strcasecmp(data, "parkinglot"))
00119       locked_string_field_set(chan, parkinglot, value);
00120    else if (!strcasecmp(data, "musicclass"))
00121       locked_string_field_set(chan, musicclass, value);
00122 #ifdef CHANNEL_TRACE
00123    else if (!strcasecmp(data, "trace")) {
00124       ast_channel_lock(chan);
00125       if (ast_true(value)) 
00126          ret = ast_channel_trace_enable(chan);
00127       else if (ast_false(value)) 
00128          ret = ast_channel_trace_disable(chan);
00129       else {
00130          ret = -1;
00131          ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).");
00132       }
00133       ast_channel_unlock(chan);
00134    }
00135 #endif
00136    else if (!strcasecmp(data, "tonezone")) {
00137       struct tone_zone *new_zone;
00138       if (!(new_zone = ast_get_indication_zone(value))) {
00139          ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
00140          ret = -1;   
00141       } else 
00142          chan->zone = new_zone;
00143    } else if (!strcasecmp(data, "callgroup"))
00144       chan->callgroup = ast_get_group(value);
00145    else if (!strcasecmp(data, "txgain")) {
00146       sscanf(value, "%4hhd", &gainset);
00147       ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
00148    } else if (!strcasecmp(data, "rxgain")) {
00149       sscanf(value, "%4hhd", &gainset);
00150       ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
00151    } else if (!strcasecmp(data, "transfercapability")) {
00152       unsigned short i;
00153       for (i = 0; i < 0x20; i++) {
00154          if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
00155             chan->transfercapability = i;
00156             break;
00157          }
00158       }
00159    } else if (!chan->tech->func_channel_write
00160        || chan->tech->func_channel_write(chan, function, data, value)) {
00161       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
00162             data);
00163       ret = -1;
00164    }
00165 
00166    return ret;
00167 }
00168 
00169 static struct ast_custom_function channel_function = {
00170    .name = "CHANNEL",
00171    .synopsis = "Gets/sets various pieces of information about the channel.",
00172    .syntax = "CHANNEL(item)",
00173    .desc = "Gets/set various pieces of information about the channel.\n"
00174       "Standard items (provided by all channel technologies) are:\n"
00175       "R/O  audioreadformat    format currently being read\n"
00176       "R/O  audionativeformat  format used natively for audio\n"
00177       "R/O  audiowriteformat   format currently being written\n"
00178       "R/W  callgroup          call groups for call pickup\n"
00179       "R/O  channeltype        technology used for channel\n"
00180       "R/W  language           language for sounds played\n"
00181       "R/W  musicclass         class (from musiconhold.conf) for hold music\n"
00182       "R/W  parkinglot         parkinglot for parking\n"
00183       "R/W  rxgain             set rxgain level on channel drivers that support it\n"
00184       "R/O  state              state for channel\n"
00185       "R/W  tonezone           zone for indications played\n"
00186       "R/W  transfercapability ISDN transfer capability (one of SPEECH, DIGITAL,\n"
00187       "                          RESTRICTED_DIGITAL, 3K1AUDIO, DIGITAL_W_TONES, or VIDEO).\n"
00188       "R/W  txgain             set txgain level on channel drivers that support it\n"
00189       "R/O  videonativeformat  format used natively for video\n"
00190 #ifdef CHANNEL_TRACE
00191       "R/W  trace              whether or not context tracing is enabled\n"
00192 #endif
00193       "\n"
00194       "chan_sip provides the following additional options:\n"
00195       "R/O    peerip             Get the IP address of the peer\n"
00196       "R/O    recvip             Get the source IP address of the peer\n"
00197       "R/O    from               Get the URI from the From: header\n"
00198       "R/O    uri                Get the URI from the Contact: header\n"
00199       "R/O    useragent          Get the useragent\n"
00200       "R/O    peername           Get the name of the peer\n"
00201       "R/O    t38passthrough     1 if T38 is offered or enabled in this channel, otherwise 0\n"
00202       "R/O    rtpqos             Get QOS information about the RTP stream\n"
00203       "       This option takes two additional arguments:\n"
00204       "  Argument 1:\n"
00205       "    audio                 Get data about the audio stream\n"
00206       "    video                 Get data about the video stream\n"
00207       "    text                  Get data about the text stream\n"
00208       "  Argument 2:\n"
00209       "    local_ssrc            Local SSRC (stream ID)\n"
00210       "    local_lostpackets     Local lost packets\n"
00211       "    local_jitter          Local calculated jitter\n"
00212       "    local_maxjitter       Local calculated jitter (maximum)\n"
00213       "    local_minjitter       Local calculated jitter (minimum)\n"
00214       "    local_normdevjitter   Local calculated jitter (normal deviation)\n"
00215       "    local_stdevjitter     Local calculated jitter (standard deviation)\n"
00216       "    local_count           Number of received packets\n"
00217       "    remote_ssrc           Remote SSRC (stream ID)\n"
00218       "    remote_lostpackets    Remote lost packets\n"
00219       "    remote_jitter         Remote reported jitter\n"
00220       "    remote_maxjitter      Remote calculated jitter (maximum)\n"
00221       "    remote_minjitter      Remote calculated jitter (minimum)\n"
00222       "    remote_normdevjitter  Remote calculated jitter (normal deviation)\n"
00223       "    remote_stdevjitter    Remote calculated jitter (standard deviation)\n"
00224       "    remote_count          Number of transmitted packets\n"
00225       "    rtt                   Round trip time\n"
00226       "    maxrtt                Round trip time (maximum)\n"
00227       "    minrtt                Round trip time (minimum)\n"
00228       "    normdevrtt            Round trip time (normal deviation)\n"
00229       "    stdevrtt              Round trip time (standard deviation)\n"
00230       "    all                   All statistics (in a form suited to logging, but not for parsing)\n"
00231       "R/O    rtpdest            Get remote RTP destination information\n"
00232       "       This option takes one additional argument:\n"
00233       "  Argument 1:\n"
00234       "    audio                 Get audio destination\n"
00235       "    video                 Get video destination\n"
00236       "    text                  Get text destination\n"
00237       "\n"
00238       "chan_iax2 provides the following additional options:\n"
00239       "R/O    peerip             Get the peer's ip address\n"
00240       "R/O    peername           Get the peer's username\n"
00241       "\n"
00242       "Additional items may be available from the channel driver providing\n"
00243       "the channel; see its documentation for details.\n"
00244       "\n"
00245       "Any item requested that is not available on the current channel will\n"
00246       "return an empty string.\n",
00247    .read = func_channel_read,
00248    .write = func_channel_write,
00249 };
00250 
00251 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
00252 {
00253    struct ast_channel *c = NULL;
00254    regex_t re;
00255    int res;
00256    size_t buflen = 0;
00257    
00258    buf[0] = '\0';
00259 
00260    if (!ast_strlen_zero(data)) {
00261       if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
00262          regerror(res, &re, buf, maxlen);
00263          ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
00264          return -1;
00265       }
00266    }
00267 
00268    for (c = ast_channel_walk_locked(NULL); c; ast_channel_unlock(c), c = ast_channel_walk_locked(c)) {
00269       if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
00270          size_t namelen = strlen(c->name);
00271          if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
00272             if (!ast_strlen_zero(buf)) {
00273                strcat(buf, " ");
00274                buflen++;
00275             }
00276             strcat(buf, c->name);
00277             buflen += namelen;
00278          } else {
00279             ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
00280          }
00281       }
00282    }
00283 
00284    if (!ast_strlen_zero(data)) {
00285       regfree(&re);
00286    }
00287 
00288    return 0;
00289 }
00290 
00291 static struct ast_custom_function channels_function = {
00292    .name = "CHANNELS",
00293    .synopsis = "Gets the list of channels, optionally filtering by a regular expression.",
00294    .syntax = "CHANNEL([regular expression])",
00295    .desc =
00296 "Gets the list of channels, optionally filtering by a regular expression.  If\n"
00297 "no argument is provided, all known channels are returned.  The regular\n"
00298 "expression must correspond to the POSIX.2 specification, as shown in\n"
00299 "regex(7).  The list returned will be space-delimited.\n",
00300    .read = func_channels_read,
00301 };
00302 
00303 static int unload_module(void)
00304 {
00305    int res = 0;
00306    
00307    res |= ast_custom_function_unregister(&channel_function);
00308    res |= ast_custom_function_unregister(&channels_function);
00309    
00310    return res;
00311 }
00312 
00313 static int load_module(void)
00314 {
00315    int res = 0;
00316    
00317    res |= ast_custom_function_register(&channel_function);
00318    res |= ast_custom_function_register(&channels_function);
00319    
00320    return res;
00321 }
00322 
00323 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");

Generated on Wed Aug 18 22:33:52 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7