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] |
Channel info dialplan functions.
Definition in file func_channel.c.
| #define locked_copy_string | ( | chan, | |||
| dest, | |||||
| source, | |||||
| len | ) |
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 | ) |
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().
| 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 }
struct ast_custom_function channel_function [static] |
{
.name = "CHANNEL",
.read = func_channel_read,
.write = func_channel_write,
}
Definition at line 589 of file func_channel.c.
struct ast_custom_function channels_function [static] |
{
.name = "CHANNELS",
.read = func_channels_read,
}
Definition at line 648 of file func_channel.c.
struct ast_custom_function mchan_function [static] |
{
.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] |
{
"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.
1.6.1