Tue Aug 20 16:35:04 2013

Asterisk developer's documentation


func_channel.c File Reference

Channel info dialplan functions. More...

#include "asterisk.h"
#include <regex.h>
#include <ctype.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/indications.h"
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"

Go to the source code of this file.

Defines

#define locked_copy_string(chan, dest, source, len)
#define locked_string_field_set(chan, field, source)

Functions

 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Channel information dialplan functions")
static int func_channel_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
static int func_channel_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int func_channel_write_real (struct ast_channel *chan, const char *function, char *data, const char *value)
static int func_channels_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
static int func_mchan_read (struct ast_channel *chan, const char *function, char *data, struct ast_str **buf, ssize_t len)
static int func_mchan_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int load_module (void)
static int unload_module (void)

Variables

static struct ast_custom_function channel_function
static struct ast_custom_function channels_function
static struct ast_custom_function mchan_function
static const char *const transfercapability_table [0x20]

Detailed Description

Channel info dialplan functions.

Author:
Kevin P. Fleming <kpfleming@digium.com>
Ben Winslow

Definition in file func_channel.c.


Define Documentation

#define locked_copy_string ( chan,
dest,
source,
len   ) 
Value:
do { \
      ast_channel_lock(chan); \
      ast_copy_string(dest, source, len); \
      ast_channel_unlock(chan); \
   } while (0)

Definition at line 284 of file func_channel.c.

Referenced by func_channel_read().

#define locked_string_field_set ( chan,
field,
source   ) 
Value:
do { \
      ast_channel_lock(chan); \
      ast_string_field_set(chan, field, source); \
      ast_channel_unlock(chan); \
   } while (0)

Definition at line 290 of file func_channel.c.

Referenced by func_channel_write_real().


Function Documentation

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Channel information dialplan functions"   
)
static int func_channel_read ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 303 of file func_channel.c.

References ast_channel::_state, ast_channel::amaflags, ast_channel::appl, ast_bridged_channel(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname(), ast_log(), ast_print_group(), ast_state2str(), ast_strlen_zero(), ast_channel::callgroup, ast_channel::cdr, ast_channel::context, ast_tone_zone::country, ast_datastore::data, ast_channel::data, ast_channel::exten, ast_channel_tech::func_channel_read, locked_copy_string, LOG_WARNING, ast_secure_call_store::media, ast_channel::nativeformats, pbx_builtin_getvar_helper(), ast_channel::readformat, secure_call_info, ast_secure_call_store::signaling, ast_channel::tech, ast_channel::transfercapability, ast_channel_tech::type, ast_channel::writeformat, and ast_channel::zone.

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 }

static int func_channel_write ( struct ast_channel chan,
const char *  function,
char *  data,
const char *  value 
) [static]

Definition at line 538 of file func_channel.c.

References AST_CHAN_WRITE_INFO_T_VERSION, ast_channel_setoption(), AST_OPTION_CHANNEL_WRITE, ast_channel::data, and func_channel_write_real().

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 }

static int func_channel_write_real ( struct ast_channel chan,
const char *  function,
char *  data,
const char *  value 
) [static]

Definition at line 420 of file func_channel.c.

References accountcode, ast_channel::amaflags, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_datastore_alloc, ast_false(), ast_free, ast_get_group(), ast_get_indication_zone(), ast_log(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, ast_set_hangupsource(), ast_tone_zone_ref(), ast_tone_zone_unref(), ast_true(), ast_channel::callgroup, ast_datastore::data, ast_channel_tech::func_channel_write, language, locked_string_field_set, LOG_ERROR, LOG_WARNING, ast_secure_call_store::media, musicclass, parkinglot, secure_call_info, ast_secure_call_store::signaling, ast_channel::tech, ast_channel::transfercapability, and ast_channel::zone.

Referenced by func_channel_write().

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 }

static int func_channels_read ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  maxlen 
) [static]

Definition at line 562 of file func_channel.c.

References ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_log(), ast_strlen_zero(), and LOG_WARNING.

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 }

static int func_mchan_read ( struct ast_channel chan,
const char *  function,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 620 of file func_channel.c.

References ast_alloca, ast_channel_get_by_name(), ast_channel_unref, and ast_str_substitute_variables().

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 }

static int func_mchan_write ( struct ast_channel chan,
const char *  function,
char *  data,
const char *  value 
) [static]

Definition at line 633 of file func_channel.c.

References ast_channel_get_by_name(), ast_channel_unref, and pbx_builtin_setvar_helper().

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 }

static int load_module ( void   )  [static]

Definition at line 661 of file func_channel.c.

References ast_custom_function_register.

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 }

static int unload_module ( void   )  [static]

Definition at line 650 of file func_channel.c.

References ast_custom_function_unregister().

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 }


Variable Documentation

Initial value:
 {
   .name = "CHANNEL",
   .read = func_channel_read,
   .write = func_channel_write,
}

Definition at line 556 of file func_channel.c.

Initial value:
 {
   .name = "CHANNELS",
   .read = func_channels_read,
}

Definition at line 615 of file func_channel.c.

Initial value:
 {
   .name = "MASTER_CHANNEL",
   .read2 = func_mchan_read,
   .write = func_mchan_write,
}

Definition at line 644 of file func_channel.c.

const char* const transfercapability_table[0x20] [static]
Initial value:
 {
   "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
   "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
   "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
   "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", }

Definition at line 297 of file func_channel.c.


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