48 #include "asterisk/max_forwards.h"
350 #define locked_copy_string(chan, dest, source, len) \
352 ast_channel_lock(chan); \
353 ast_copy_string(dest, source, len); \
354 ast_channel_unlock(chan); \
356 #define locked_string_field_set(chan, field, source) \
358 ast_channel_lock(chan); \
359 ast_channel_##field##_set(chan, source); \
360 ast_channel_unlock(chan); \
363 static const char *
const transfercapability_table[0x20] = {
364 "SPEECH",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
365 "DIGITAL",
"RESTRICTED_DIGITAL",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
366 "3K1AUDIO",
"DIGITAL_W_TONES",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
367 "VIDEO",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK", };
369 static int func_channel_read(
struct ast_channel *chan,
const char *
function,
370 char *data,
char *buf,
size_t len)
376 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n",
function);
380 if (!strcasecmp(data,
"audionativeformat")) {
385 ast_channel_lock(chan);
387 ast_channel_unlock(chan);
391 }
else if (!strcasecmp(data,
"videonativeformat")) {
396 ast_channel_lock(chan);
398 ast_channel_unlock(chan);
402 }
else if (!strcasecmp(data,
"audioreadformat")) {
404 }
else if (!strcasecmp(data,
"audiowriteformat")) {
406 }
else if (!strcasecmp(data,
"tonezone") && ast_channel_zone(chan)) {
407 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
408 }
else if (!strcasecmp(data,
"dtmf_features")) {
412 }
else if (!strcasecmp(data,
"language"))
413 locked_copy_string(chan, buf, ast_channel_language(chan), len);
414 else if (!strcasecmp(data,
"musicclass"))
415 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
416 else if (!strcasecmp(data,
"name")) {
417 locked_copy_string(chan, buf, ast_channel_name(chan), len);
418 }
else if (!strcasecmp(data,
"parkinglot"))
419 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
420 else if (!strcasecmp(data,
"state"))
422 else if (!strcasecmp(data,
"onhold")) {
423 locked_copy_string(chan, buf,
425 }
else if (!strcasecmp(data,
"channeltype"))
427 else if (!strcasecmp(data,
"accountcode"))
428 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
429 else if (!strcasecmp(data,
"checkhangup")) {
431 }
else if (!strcasecmp(data,
"peeraccount"))
432 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
433 else if (!strcasecmp(data,
"hangupsource"))
434 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
435 else if (!strcasecmp(data,
"appname") && ast_channel_appl(chan))
436 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
437 else if (!strcasecmp(data,
"appdata") && ast_channel_data(chan))
438 locked_copy_string(chan, buf, ast_channel_data(chan), len);
439 else if (!strcasecmp(data,
"exten"))
440 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
441 else if (!strcasecmp(data,
"context"))
442 locked_copy_string(chan, buf, ast_channel_context(chan), len);
443 else if (!strcasecmp(data,
"lastexten"))
444 locked_copy_string(chan, buf, ast_channel_lastexten(chan), len);
445 else if (!strcasecmp(data,
"lastcontext"))
446 locked_copy_string(chan, buf, ast_channel_lastcontext(chan), len);
447 else if (!strcasecmp(data,
"userfield"))
448 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
449 else if (!strcasecmp(data,
"channame"))
450 locked_copy_string(chan, buf, ast_channel_name(chan), len);
451 else if (!strcasecmp(data,
"linkedid")) {
452 ast_channel_lock(chan);
453 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
460 ast_channel_unlock(chan);
461 }
else if (!strcasecmp(data,
"peer")) {
467 ast_channel_lock(peer);
469 ast_channel_unlock(peer);
473 ast_channel_lock(chan);
484 if (!ast_strlen_zero(pname)) {
488 ast_channel_unlock(chan);
490 }
else if (!strcasecmp(data,
"uniqueid")) {
491 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
492 }
else if (!strcasecmp(data,
"transfercapability")) {
493 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
494 }
else if (!strcasecmp(data,
"callgroup")) {
497 locked_copy_string(chan, buf,
ast_print_group(groupbuf,
sizeof(groupbuf), ast_channel_callgroup(chan)), len);
498 }
else if (!strcasecmp(data,
"pickupgroup")) {
501 locked_copy_string(chan, buf,
ast_print_group(groupbuf,
sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
502 }
else if (!strcasecmp(data,
"namedcallgroup")) {
503 struct ast_str *tmp_str = ast_str_alloca(1024);
505 locked_copy_string(chan, buf,
ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
506 }
else if (!strcasecmp(data,
"namedpickupgroup")) {
507 struct ast_str *tmp_str = ast_str_alloca(1024);
509 locked_copy_string(chan, buf,
ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
510 }
else if (!strcasecmp(data,
"after_bridge_goto")) {
512 }
else if (!strcasecmp(data,
"amaflags")) {
513 ast_channel_lock(chan);
514 snprintf(buf, len,
"%u", ast_channel_amaflags(chan));
515 ast_channel_unlock(chan);
516 }
else if (!strncasecmp(data,
"secure_bridge_", 14)) {
520 ast_channel_lock(chan);
524 if (!strcasecmp(data,
"secure_bridge_signaling")) {
525 snprintf(buf, len,
"%s", encrypt->signaling ?
"1" :
"");
526 }
else if (!strcasecmp(data,
"secure_bridge_media")) {
527 snprintf(buf, len,
"%s", encrypt->media ?
"1" :
"");
530 ast_channel_unlock(chan);
531 }
else if (!strcasecmp(data,
"max_forwards")) {
532 ast_channel_lock(chan);
533 snprintf(buf, len,
"%d", ast_max_forwards_get(chan));
534 ast_channel_unlock(chan);
535 }
else if (!strcasecmp(data,
"callid")) {
539 ast_channel_lock(chan);
540 callid = ast_channel_callid(chan);
544 ast_channel_unlock(chan);
545 }
else if (!strcasecmp(data,
"tdd")) {
547 int status_size = (int)
sizeof(status);
552 }
else if (!strcasecmp(data,
"digitdetect")) {
554 int status_size = (int)
sizeof(status);
559 }
else if (!strcasecmp(data,
"faxdetect")) {
561 int status_size = (int)
sizeof(status);
566 }
else if (!strcasecmp(data,
"device_name")) {
569 ast_log(LOG_WARNING,
"Unknown or unavailable item requested: '%s'\n", data);
576 static int func_channel_write_real(
struct ast_channel *chan,
const char *
function,
577 char *data,
const char *value)
582 if (!strcasecmp(data,
"language"))
583 locked_string_field_set(chan, language, value);
584 else if (!strcasecmp(data,
"parkinglot"))
585 locked_string_field_set(chan, parkinglot, value);
586 else if (!strcasecmp(data,
"musicclass"))
587 locked_string_field_set(chan, musicclass, value);
588 else if (!strcasecmp(data,
"accountcode"))
589 locked_string_field_set(chan, accountcode, value);
590 else if (!strcasecmp(data,
"userfield"))
591 locked_string_field_set(chan, userfield, value);
592 else if (!strcasecmp(data,
"after_bridge_goto")) {
593 if (ast_strlen_zero(value)) {
598 }
else if (!strcasecmp(data,
"amaflags")) {
601 if (isdigit(*value)) {
602 if (sscanf(value,
"%30d", &amaflags) != 1) {
603 amaflags = AST_AMA_NONE;
608 ast_channel_lock(chan);
610 ast_channel_unlock(chan);
611 }
else if (!strcasecmp(data,
"peeraccount"))
612 locked_string_field_set(chan, peeraccount, value);
613 else if (!strcasecmp(data,
"hangupsource"))
616 else if (!strcasecmp(data,
"tonezone")) {
619 ast_log(LOG_ERROR,
"Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
622 ast_channel_lock(chan);
623 if (ast_channel_zone(chan)) {
627 ast_channel_unlock(chan);
630 }
else if (!strcasecmp(data,
"dtmf_features")) {
632 }
else if (!strcasecmp(data,
"callgroup")) {
633 ast_channel_lock(chan);
635 ast_channel_unlock(chan);
636 }
else if (!strcasecmp(data,
"pickupgroup")) {
637 ast_channel_lock(chan);
639 ast_channel_unlock(chan);
640 }
else if (!strcasecmp(data,
"namedcallgroup")) {
643 ast_channel_lock(chan);
644 ast_channel_named_callgroups_set(chan, groups);
645 ast_channel_unlock(chan);
646 ast_unref_namedgroups(groups);
647 }
else if (!strcasecmp(data,
"namedpickupgroup")) {
650 ast_channel_lock(chan);
651 ast_channel_named_pickupgroups_set(chan, groups);
652 ast_channel_unlock(chan);
653 ast_unref_namedgroups(groups);
654 }
else if (!strcasecmp(data,
"tdd")) {
656 if (!strcasecmp(value,
"mate")) {
662 }
else if (!strcasecmp(data,
"relaxdtmf")) {
663 char enabled =
ast_true(value) ? 1 : 0;
665 }
else if (!strcasecmp(data,
"txgain")) {
666 sscanf(value,
"%4hhd", &gainset);
668 }
else if (!strcasecmp(data,
"rxgain")) {
669 sscanf(value,
"%4hhd", &gainset);
671 }
else if (!strcasecmp(data,
"digitdetect")) {
672 char enabled =
ast_true(value) ? 1 : 0;
674 }
else if (!strcasecmp(data,
"faxdetect")) {
675 char enabled =
ast_true(value) ? 1 : 0;
677 }
else if (!strcasecmp(data,
"transfercapability")) {
680 ast_channel_lock(chan);
681 for (i = 0; i < 0x20; i++) {
682 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value,
"UNK")) {
683 ast_channel_transfercapability_set(chan, i);
687 ast_channel_unlock(chan);
688 }
else if (!strcasecmp(data,
"hangup_handler_pop")) {
692 }
else if (!strcasecmp(data,
"hangup_handler_push")) {
694 }
else if (!strcasecmp(data,
"hangup_handler_wipe")) {
699 }
else if (!strncasecmp(data,
"secure_bridge_", 14)) {
703 if (!chan || !value) {
707 ast_channel_lock(chan);
709 if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
710 ast_channel_unlock(chan);
713 if (!(store =
ast_calloc(1,
sizeof(*store)))) {
714 ast_channel_unlock(chan);
724 if (!strcasecmp(data,
"secure_bridge_signaling")) {
725 store->signaling =
ast_true(value) ? 1 : 0;
726 }
else if (!strcasecmp(data,
"secure_bridge_media")) {
727 store->media =
ast_true(value) ? 1 : 0;
729 ast_channel_unlock(chan);
730 }
else if (!strcasecmp(data,
"max_forwards")) {
732 if (sscanf(value,
"%d", &max_forwards) != 1) {
733 ast_log(LOG_WARNING,
"Unable to set max forwards to '%s'\n", value);
736 ast_channel_lock(chan);
737 ret = ast_max_forwards_set(chan, max_forwards);
738 ast_channel_unlock(chan);
741 ||
ast_channel_tech(chan)->func_channel_write(chan,
function, data, value)) {
742 ast_log(LOG_WARNING,
"Unknown or unavailable item requested: '%s'\n",
750 static int func_channel_write(
struct ast_channel *chan,
const char *
function,
char *data,
const char *value)
755 .write_fn = func_channel_write_real,
757 .function =
function,
763 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n",
function);
767 res = func_channel_write_real(chan,
function, data, value);
775 .read = func_channel_read,
776 .write = func_channel_write,
779 static int func_channels_read(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t maxlen)
789 if (!ast_strlen_zero(data)) {
790 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
791 regerror(res, &re, buf, maxlen);
792 ast_log(LOG_WARNING,
"Error compiling regular expression for %s(%s): %s\n",
function, data, buf);
798 if (!ast_strlen_zero(data)) {
806 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
807 size_t namelen = strlen(ast_channel_name(c));
808 if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
809 if (!ast_strlen_zero(buf)) {
813 strcat(buf, ast_channel_name(c));
816 ast_log(LOG_WARNING,
"Number of channels exceeds the available buffer space. Output will be truncated!\n");
819 ast_channel_unlock(c);
825 if (!ast_strlen_zero(data)) {
834 .read = func_channels_read,
837 static int func_chan_exists_read(
struct ast_channel *chan,
const char *
function,
char *data,
char *buf,
size_t maxlen)
841 if (ast_strlen_zero(data)) {
842 ast_log(LOG_WARNING,
"%s: Channel name or unique ID required\n",
function);
847 snprintf(buf, maxlen,
"%d", (chan_found ? 1 : 0));
855 .
name =
"CHANNEL_EXISTS",
856 .read = func_chan_exists_read,
859 static int func_mchan_read(
struct ast_channel *chan,
const char *
function,
860 char *data,
struct ast_str **buf, ssize_t len)
863 char *
template =
ast_alloca(4 + strlen(data));
866 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n",
function);
871 sprintf(
template,
"${%s}", data);
879 static int func_mchan_write(
struct ast_channel *chan,
const char *
function,
880 char *data,
const char *value)
885 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n",
function);
898 .
name =
"MASTER_CHANNEL",
899 .read2 = func_mchan_read,
900 .write = func_mchan_write,
903 static int unload_module(
void)
915 static int load_module(
void)
927 AST_MODULE_INFO_STANDARD(
ASTERISK_GPL_KEY,
"Channel information dialplan functions");
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
Main Channel structure associated with a channel.
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_OPTION_TXGAIN
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
globally accessible channel datastores
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
ast_channel_state
ast_channel states
int ast_bridge_features_ds_set_string(struct ast_channel *chan, const char *features)
Sets the features a channel will use upon being bridged.
int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
Pop the top of the channel hangup handler stack.
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
char * ast_print_group(char *buf, int buflen, ast_group_t group)
Print call and pickup groups into buffer.
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
General Asterisk PBX channel definitions.
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
#define AST_OPTION_RELAXDTMF
A set of tones for a given locale.
Data structure associated with a custom dialplan function.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
int ast_bridge_features_ds_get_string(struct ast_channel *chan, char *buffer, size_t buf_size)
writes a channel's DTMF features to a buffer string
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define AST_OPTION_DIGIT_DETECT
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Support for dynamic strings.
#define AST_OPTION_RXGAIN
Channel datastore data for max forwards.
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
static struct ast_tone_zone * ast_tone_zone_ref(struct ast_tone_zone *tz)
Increase the reference count on an ast_tone_zone.
#define AST_OPTION_CHANNEL_WRITE
Handle channel write data If a channel needs to process the data from a func_channel write operation ...
#define ast_calloc(num, len)
A wrapper for calloc()
Structure to handle passing func_channel_write info to channels via setoption.
void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
Push the given hangup handler onto the channel hangup handler stack.
Basic bridge subclass API.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define AST_OPTION_FAX_DETECT
After Bridge Execution API.
static int enabled
Whether or not we are storing history.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
Read after bridge goto if it exists.
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Asterisk module definitions.
char * ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *groups)
Print named call groups and named pickup groups.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.