Thu Apr 3 08:21:49 2014

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"
Include dependency graph for func_channel.c:

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 317 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 323 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 336 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.

00338 {
00339    int ret = 0;
00340 
00341    if (!strcasecmp(data, "audionativeformat"))
00342       /* use the _multiple version when chan->nativeformats holds multiple formats */
00343       /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */
00344       ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len);
00345    else if (!strcasecmp(data, "videonativeformat"))
00346       /* use the _multiple version when chan->nativeformats holds multiple formats */
00347       /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */
00348       ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len);
00349    else if (!strcasecmp(data, "audioreadformat"))
00350       ast_copy_string(buf, ast_getformatname(chan->readformat), len);
00351    else if (!strcasecmp(data, "audiowriteformat"))
00352       ast_copy_string(buf, ast_getformatname(chan->writeformat), len);
00353 #ifdef CHANNEL_TRACE
00354    else if (!strcasecmp(data, "trace")) {
00355       ast_channel_lock(chan);
00356       ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
00357       ast_channel_unlock(chan);
00358    }
00359 #endif
00360    else if (!strcasecmp(data, "tonezone") && chan->zone)
00361       locked_copy_string(chan, buf, chan->zone->country, len);
00362    else if (!strcasecmp(data, "language"))
00363       locked_copy_string(chan, buf, chan->language, len);
00364    else if (!strcasecmp(data, "musicclass"))
00365       locked_copy_string(chan, buf, chan->musicclass, len);
00366    else if (!strcasecmp(data, "name")) {
00367       locked_copy_string(chan, buf, chan->name, len);
00368    } else if (!strcasecmp(data, "parkinglot"))
00369       locked_copy_string(chan, buf, chan->parkinglot, len);
00370    else if (!strcasecmp(data, "state"))
00371       locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
00372    else if (!strcasecmp(data, "channeltype"))
00373       locked_copy_string(chan, buf, chan->tech->type, len);
00374    else if (!strcasecmp(data, "accountcode"))
00375       locked_copy_string(chan, buf, chan->accountcode, len);
00376    else if (!strcasecmp(data, "checkhangup")) {
00377       ast_channel_lock(chan);
00378       ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
00379       ast_channel_unlock(chan);
00380    } else if (!strcasecmp(data, "peeraccount"))
00381       locked_copy_string(chan, buf, chan->peeraccount, len);
00382    else if (!strcasecmp(data, "hangupsource"))
00383       locked_copy_string(chan, buf, chan->hangupsource, len);
00384    else if (!strcasecmp(data, "appname") && chan->appl)
00385       locked_copy_string(chan, buf, chan->appl, len);
00386    else if (!strcasecmp(data, "appdata") && chan->data)
00387       locked_copy_string(chan, buf, chan->data, len);
00388    else if (!strcasecmp(data, "exten") && chan->data)
00389       locked_copy_string(chan, buf, chan->exten, len);
00390    else if (!strcasecmp(data, "context") && chan->data)
00391       locked_copy_string(chan, buf, chan->context, len);
00392    else if (!strcasecmp(data, "userfield") && chan->data)
00393       locked_copy_string(chan, buf, chan->userfield, len);
00394    else if (!strcasecmp(data, "channame") && chan->data)
00395       locked_copy_string(chan, buf, chan->name, len);
00396    else if (!strcasecmp(data, "linkedid")) {
00397       ast_channel_lock(chan);
00398       if (ast_strlen_zero(chan->linkedid)) {
00399          /* fall back on the channel's uniqueid if linkedid is unset */
00400          ast_copy_string(buf, chan->uniqueid, len);
00401       }
00402       else {
00403          ast_copy_string(buf, chan->linkedid, len);
00404       }
00405       ast_channel_unlock(chan);
00406    } else if (!strcasecmp(data, "peer")) {
00407       struct ast_channel *p;
00408       ast_channel_lock(chan);
00409       p = ast_bridged_channel(chan);
00410       if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */
00411          ast_copy_string(buf, (p ? p->name : ""), len);
00412       else {
00413          /* a dummy channel can still pass along bridged peer info via
00414                            the BRIDGEPEER variable */
00415          const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
00416          if (!ast_strlen_zero(pname))
00417             ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
00418          else
00419             buf[0] = 0;
00420       }
00421       ast_channel_unlock(chan);
00422    } else if (!strcasecmp(data, "uniqueid")) {
00423       locked_copy_string(chan, buf, chan->uniqueid, len);
00424    } else if (!strcasecmp(data, "transfercapability"))
00425       locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
00426    else if (!strcasecmp(data, "callgroup")) {
00427       char groupbuf[256];
00428       locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
00429    } else if (!strcasecmp(data, "amaflags")) {
00430       char amabuf[256];
00431       snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags);
00432       locked_copy_string(chan, buf, amabuf, len);
00433    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00434       struct ast_datastore *ds;
00435       ast_channel_lock(chan);
00436       if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00437          struct ast_secure_call_store *encrypt = ds->data;
00438          if (!strcasecmp(data, "secure_bridge_signaling")) {
00439             snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
00440          } else if (!strcasecmp(data, "secure_bridge_media")) {
00441             snprintf(buf, len, "%s", encrypt->media ? "1" : "");
00442          }
00443       }
00444       ast_channel_unlock(chan);
00445    } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) {
00446       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
00447       ret = -1;
00448    }
00449 
00450    return ret;
00451 }

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

Definition at line 571 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().

00572 {
00573    int res;
00574    ast_chan_write_info_t write_info = {
00575       .version = AST_CHAN_WRITE_INFO_T_VERSION,
00576       .write_fn = func_channel_write_real,
00577       .chan = chan,
00578       .function = function,
00579       .data = data,
00580       .value = value,
00581    };
00582 
00583    res = func_channel_write_real(chan, function, data, value);
00584    ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
00585 
00586    return res;
00587 }

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

Definition at line 453 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().

00455 {
00456    int ret = 0;
00457    signed char gainset;
00458 
00459    if (!strcasecmp(data, "language"))
00460       locked_string_field_set(chan, language, value);
00461    else if (!strcasecmp(data, "parkinglot"))
00462       locked_string_field_set(chan, parkinglot, value);
00463    else if (!strcasecmp(data, "musicclass"))
00464       locked_string_field_set(chan, musicclass, value);
00465    else if (!strcasecmp(data, "accountcode"))
00466       locked_string_field_set(chan, accountcode, value);
00467    else if (!strcasecmp(data, "userfield"))
00468       locked_string_field_set(chan, userfield, value);
00469    else if (!strcasecmp(data, "amaflags")) {
00470       ast_channel_lock(chan);
00471       if(isdigit(*value)) {
00472          sscanf(value, "%30d", &chan->amaflags);
00473       } else if (!strcasecmp(value,"OMIT")){
00474          chan->amaflags = 1;
00475       } else if (!strcasecmp(value,"BILLING")){
00476          chan->amaflags = 2;
00477       } else if (!strcasecmp(value,"DOCUMENTATION")){
00478          chan->amaflags = 3;
00479       }
00480       ast_channel_unlock(chan);
00481    } else if (!strcasecmp(data, "peeraccount"))
00482       locked_string_field_set(chan, peeraccount, value);
00483    else if (!strcasecmp(data, "hangupsource"))
00484       /* XXX - should we be forcing this here? */
00485       ast_set_hangupsource(chan, value, 0);
00486 #ifdef CHANNEL_TRACE
00487    else if (!strcasecmp(data, "trace")) {
00488       ast_channel_lock(chan);
00489       if (ast_true(value))
00490          ret = ast_channel_trace_enable(chan);
00491       else if (ast_false(value))
00492          ret = ast_channel_trace_disable(chan);
00493       else {
00494          ret = -1;
00495          ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
00496       }
00497       ast_channel_unlock(chan);
00498    }
00499 #endif
00500    else if (!strcasecmp(data, "tonezone")) {
00501       struct ast_tone_zone *new_zone;
00502       if (!(new_zone = ast_get_indication_zone(value))) {
00503          ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
00504          ret = -1;
00505       } else {
00506          ast_channel_lock(chan);
00507          if (chan->zone) {
00508             chan->zone = ast_tone_zone_unref(chan->zone);
00509          }
00510          chan->zone = ast_tone_zone_ref(new_zone);
00511          ast_channel_unlock(chan);
00512          new_zone = ast_tone_zone_unref(new_zone);
00513       }
00514    } else if (!strcasecmp(data, "callgroup"))
00515       chan->callgroup = ast_get_group(value);
00516    else if (!strcasecmp(data, "txgain")) {
00517       sscanf(value, "%4hhd", &gainset);
00518       ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
00519    } else if (!strcasecmp(data, "rxgain")) {
00520       sscanf(value, "%4hhd", &gainset);
00521       ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
00522    } else if (!strcasecmp(data, "transfercapability")) {
00523       unsigned short i;
00524       for (i = 0; i < 0x20; i++) {
00525          if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
00526             chan->transfercapability = i;
00527             break;
00528          }
00529       }
00530    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
00531       struct ast_datastore *ds;
00532       struct ast_secure_call_store *store;
00533 
00534       if (!chan || !value) {
00535          return -1;
00536       }
00537 
00538       ast_channel_lock(chan);
00539       if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
00540          if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
00541             ast_channel_unlock(chan);
00542             return -1;
00543          }
00544          if (!(store = ast_calloc(1, sizeof(*store)))) {
00545             ast_channel_unlock(chan);
00546             ast_free(ds);
00547             return -1;
00548          }
00549          ds->data = store;
00550          ast_channel_datastore_add(chan, ds);
00551       } else {
00552          store = ds->data;
00553       }
00554       ast_channel_unlock(chan);
00555 
00556       if (!strcasecmp(data, "secure_bridge_signaling")) {
00557          store->signaling = ast_true(value) ? 1 : 0;
00558       } else if (!strcasecmp(data, "secure_bridge_media")) {
00559          store->media = ast_true(value) ? 1 : 0;
00560       }
00561    } else if (!chan->tech->func_channel_write
00562        || chan->tech->func_channel_write(chan, function, data, value)) {
00563       ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
00564             data);
00565       ret = -1;
00566    }
00567 
00568    return ret;
00569 }

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

Definition at line 595 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.

00596 {
00597    struct ast_channel *c = NULL;
00598    regex_t re;
00599    int res;
00600    size_t buflen = 0;
00601    struct ast_channel_iterator *iter;
00602 
00603    buf[0] = '\0';
00604 
00605    if (!ast_strlen_zero(data)) {
00606       if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
00607          regerror(res, &re, buf, maxlen);
00608          ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
00609          return -1;
00610       }
00611    }
00612 
00613    if (!(iter = ast_channel_iterator_all_new())) {
00614       if (!ast_strlen_zero(data)) {
00615          regfree(&re);
00616       }
00617       return -1;
00618    }
00619 
00620    while ((c = ast_channel_iterator_next(iter))) {
00621       ast_channel_lock(c);
00622       if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
00623          size_t namelen = strlen(c->name);
00624          if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
00625             if (!ast_strlen_zero(buf)) {
00626                strcat(buf, " ");
00627                buflen++;
00628             }
00629             strcat(buf, c->name);
00630             buflen += namelen;
00631          } else {
00632             ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
00633          }
00634       }
00635       ast_channel_unlock(c);
00636       c = ast_channel_unref(c);
00637    }
00638 
00639    ast_channel_iterator_destroy(iter);
00640 
00641    if (!ast_strlen_zero(data)) {
00642       regfree(&re);
00643    }
00644 
00645    return 0;
00646 }

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 653 of file func_channel.c.

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

00655 {
00656    struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid);
00657    char *template = ast_alloca(4 + strlen(data));
00658    sprintf(template, "${%s}", data); /* SAFE */
00659    ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
00660    if (mchan) {
00661       ast_channel_unref(mchan);
00662    }
00663    return 0;
00664 }

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

Definition at line 666 of file func_channel.c.

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

00668 {
00669    struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid);
00670    pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
00671    if (mchan) {
00672       ast_channel_unref(mchan);
00673    }
00674    return 0;
00675 }

static int load_module ( void   )  [static]

Definition at line 694 of file func_channel.c.

References ast_custom_function_register.

00695 {
00696    int res = 0;
00697 
00698    res |= ast_custom_function_register(&channel_function);
00699    res |= ast_custom_function_register(&channels_function);
00700    res |= ast_custom_function_register(&mchan_function);
00701 
00702    return res;
00703 }

static int unload_module ( void   )  [static]

Definition at line 683 of file func_channel.c.

References ast_custom_function_unregister().

00684 {
00685    int res = 0;
00686 
00687    res |= ast_custom_function_unregister(&channel_function);
00688    res |= ast_custom_function_unregister(&channels_function);
00689    res |= ast_custom_function_unregister(&mchan_function);
00690 
00691    return res;
00692 }


Variable Documentation

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

Definition at line 589 of file func_channel.c.

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

Definition at line 648 of file func_channel.c.

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

Definition at line 677 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 330 of file func_channel.c.


Generated on 3 Apr 2014 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1