40 #include "asterisk/features_config.h"
45 #include "asterisk/stasis_bridges.h"
46 #include "asterisk/stasis_channels.h"
51 #define NORMAL_FLAGS (AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY \
52 | AST_BRIDGE_FLAG_SMART)
54 #define TRANSFER_FLAGS AST_BRIDGE_FLAG_SMART
83 .
type =
"bridge-dtmf-features",
98 static int set_feature_flag_from_char(
struct ast_flags *feature_flags,
char feature)
102 ast_set_flag(feature_flags, AST_FEATURE_REDIRECT);
105 ast_set_flag(feature_flags, AST_FEATURE_PARKCALL);
108 ast_set_flag(feature_flags, AST_FEATURE_DISCONNECT);
111 ast_set_flag(feature_flags, AST_FEATURE_AUTOMON);
114 ast_set_flag(feature_flags, AST_FEATURE_AUTOMIXMON);
133 static int dtmf_features_flags_to_string(
struct ast_flags *feature_flags,
char *buffer,
size_t buffer_size)
135 size_t buffer_expended = 0;
136 unsigned int cur_feature;
137 static const struct {
141 {
'T', AST_FEATURE_REDIRECT },
142 {
'K', AST_FEATURE_PARKCALL },
143 {
'H', AST_FEATURE_DISCONNECT },
144 {
'W', AST_FEATURE_AUTOMON },
145 {
'X', AST_FEATURE_AUTOMIXMON },
148 for (cur_feature = 0; cur_feature < ARRAY_LEN(associations); cur_feature++) {
149 if (ast_test_flag(feature_flags, associations[cur_feature].flag)) {
150 if (buffer_expended == buffer_size - 1) {
151 buffer[buffer_expended] =
'\0';
154 buffer[buffer_expended++] = associations[cur_feature].letter;
158 buffer[buffer_expended] =
'\0';
162 static int build_dtmf_features(
struct ast_flags *flags,
const char *features)
166 char missing_features[strlen(features) + 1];
167 size_t number_of_missing_features = 0;
169 for (feature = features; *feature; feature++) {
170 if (!isupper(*feature)) {
171 ast_log(LOG_ERROR,
"Features string '%s' rejected because it contains non-uppercase feature.\n", features);
175 if (set_feature_flag_from_char(flags, *feature)) {
176 missing_features[number_of_missing_features++] = *feature;
180 missing_features[number_of_missing_features] =
'\0';
182 if (number_of_missing_features) {
183 ast_log(LOG_WARNING,
"Features '%s' from features string '%s' can not be applied.\n", missing_features, features);
193 if (build_dtmf_features(&flags, features)) {
197 ast_channel_lock(chan);
199 ast_channel_unlock(chan);
200 ast_log(LOG_ERROR,
"Failed to apply features datastore for '%s' to channel '%s'\n", features, ast_channel_name(chan));
203 ast_channel_unlock(chan);
213 ast_channel_lock(chan);
215 ast_channel_unlock(chan);
218 held_copy = *channel_flags;
219 ast_channel_unlock(chan);
221 return dtmf_features_flags_to_string(&held_copy, buffer, buf_size);
224 static int bridge_features_ds_set_full(
struct ast_channel *chan,
struct ast_flags *flags,
int replace)
231 ds_flags = datastore->
data;
235 flags->flags = flags->flags | ds_flags->flags;
241 datastore = ast_datastore_alloc(&dtmf_features_info, NULL);
253 datastore->
data = ds_flags;
260 return bridge_features_ds_set_full(chan, flags, 1);
265 return bridge_features_ds_set_full(chan, flags, 0);
276 return datastore->
data;
290 static int basic_hangup_hook(
struct ast_bridge_channel *bridge_channel,
void *hook_pvt)
292 int bridge_count = 0;
301 if (2 <= bridge_count) {
346 static int builtin_feature_get_exten(
struct ast_channel *chan,
const char *feature_name,
char *buf,
size_t len)
350 return ast_get_builtin_feature(chan, feature_name, buf, len);
371 char dtmf[AST_FEATURE_MAX_LEN];
375 if (ast_test_flag(flags, feature_flag)
376 && !builtin_feature_get_exten(chan, feature_name, dtmf,
sizeof(dtmf))
377 && !ast_strlen_zero(dtmf)) {
381 ast_log(LOG_ERROR,
"Channel %s: Requested DTMF feature %s not available.\n",
382 ast_channel_name(chan), feature_name);
405 ast_channel_lock(chan);
407 ast_channel_unlock(chan);
436 const void *payload,
size_t payload_size)
475 static int dynamic_dtmf_hook_trip(
struct ast_bridge_channel *bridge_channel,
void *hook_pvt)
479 const char *activated_name;
484 size_t len_activated;
488 len_name = strlen(pvt->
app_name) + 1;
492 ast_channel_lock(bridge_channel->
chan);
494 ast_channel_unlock(bridge_channel->
chan);
495 len_activated = strlen(activated_name) + 1;
496 len_data =
sizeof(*run_data) + len_name + len_args + len_moh + len_feature + len_activated;
501 run_data->
moh_offset = len_moh ? len_name + len_args : 0;
517 if (ast_test_flag(pvt, AST_FEATURE_FLAG_ONPEER)) {
520 dynamic_dtmf_hook_callback, run_data, len_data);
522 dynamic_dtmf_hook_callback(bridge_channel, run_data, len_data);
543 static int dynamic_dtmf_hook_add(
struct ast_bridge_features *features,
unsigned int flags,
const char *dtmf,
const char *feature_name,
const char *
app_name,
const char *app_args,
const char *moh_class)
546 size_t len_name = strlen(app_name) + 1;
547 size_t len_args = ast_strlen_zero(app_args) ? 0 : strlen(app_args) + 1;
548 size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
549 size_t len_feature = strlen(feature_name) + 1;
550 size_t len_data =
sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
560 hook_data->
moh_offset = len_moh ? len_name + len_args : 0;
562 strcpy(hook_data->
app_name, app_name);
580 static int setup_dynamic_feature(
void *obj,
void *arg,
void *data,
int flags)
586 *res |= dynamic_dtmf_hook_add(features,
587 item->activate_on_self ? AST_FEATURE_FLAG_ONSELF : AST_FEATURE_FLAG_ONPEER,
588 item->dtmf, item->name, item->app, item->app_data, item->moh_class);
609 ast_channel_lock(chan);
610 applicationmap = ast_get_chan_applicationmap(chan);
611 ast_channel_unlock(chan);
612 if (applicationmap) {
613 ao2_callback_data(applicationmap, 0, setup_dynamic_feature, features, &res);
634 res |= setup_bridge_features_builtin(bridge_channel->
features, bridge_channel->
chan);
635 res |= setup_bridge_features_dynamic(bridge_channel->
features, bridge_channel->
chan);
644 || bridge_basic_setup_features(bridge_channel);
663 if (add_normal_hooks(
self, bridge_channel)) {
674 ast_assert(personality != NULL);
681 ast_bridge_channel_update_linkedids(bridge_channel, swap);
682 ast_bridge_channel_update_accountcodes(bridge_channel, swap);
691 ast_assert(personality != NULL);
697 ast_bridge_channel_update_accountcodes(NULL, bridge_channel);
702 static void bridge_basic_destroy(
struct ast_bridge *
self)
706 ao2_cleanup(personality);
1352 static
void attended_transfer_properties_destructor(
void *obj)
1356 ast_debug(1,
"Destroy attended transfer properties %p\n", props);
1366 ast_cond_destroy(&props->
cond);
1379 static const char *get_transfer_context(
struct ast_channel *transferer,
const char *
context)
1381 if (!ast_strlen_zero(context)) {
1385 if (!ast_strlen_zero(context)) {
1388 context = ast_channel_context(transferer);
1389 if (!ast_strlen_zero(context)) {
1404 static const char *get_transfer_exten(
struct ast_channel *transferer,
const char *
exten)
1406 if (!ast_strlen_zero(exten)) {
1410 if (!ast_strlen_zero(exten)) {
1426 struct ast_channel *transferer,
const char *context)
1435 props = ao2_alloc(
sizeof(*props), attended_transfer_properties_destructor);
1437 ast_log(LOG_ERROR,
"Unable to create props - channel %s, context %s\n",
1438 ast_channel_name(transferer), context);
1442 ast_cond_init(&props->
cond, NULL);
1445 ast_log(LOG_ERROR,
"Unable to initialize prop fields - channel %s, context %s\n",
1446 ast_channel_name(transferer), context);
1455 xfer_cfg = ast_get_chan_features_xfer_config(props->
transferer);
1457 ast_log(LOG_ERROR,
"Unable to get transfer configuration from channel %s\n", ast_channel_name(props->
transferer));
1463 if (transferer_features) {
1483 addr = strchr(tech,
'/');
1485 ast_log(LOG_ERROR,
"Transferer channel name does not follow typical channel naming format (tech/address)\n");
1491 serial = strrchr(addr,
'-');
1500 ast_debug(1,
"Allocated attended transfer properties %p for transfer from %s\n",
1526 ast_debug(1,
"Shutting down attended transfer %p\n", props);
1555 ast_log(LOG_ERROR,
"Unable to push event to attended transfer queue. Expect transfer to fail\n");
1559 list->stimulus = stimulus;
1562 ast_cond_signal(&props->
cond);
1573 if (list->stimulus == stimulus) {
1640 ast_channel_lock(transferer);
1642 ast_channel_unlock(transferer);
1644 if (transferer_bridge == transferee_bridge) {
1646 transferer, transferee, transfer_target);
1647 }
else if (transferer_bridge == target_bridge) {
1649 transferer, transfer_target, transferee);
1655 ao2_cleanup(transferer_bridge);
1668 transferee_channel, target_channel);
1670 if (!transfer_msg) {
1671 ast_log(LOG_ERROR,
"Unable to publish successful attended transfer from %s\n",
1678 ao2_cleanup(transfer_msg);
1691 transferee_channel, target_channel);
1693 if (!transfer_msg) {
1694 ast_log(LOG_ERROR,
"Unable to publish successful three-way transfer from %s\n",
1702 ao2_cleanup(transfer_msg);
1716 if (!transfer_msg) {
1717 ast_log(LOG_ERROR,
"Unable to publish failed transfer from %s\n",
1724 ao2_cleanup(transfer_msg);
1737 ast_channel_lock(chan);
1739 ast_channel_unlock(chan);
1741 if (bridge_channel) {
1756 ast_channel_lock(chan);
1757 sound = ast_get_chan_features_xferfailsound(chan);
1758 ast_channel_unlock(chan);
1775 ast_channel_lock(chan);
1776 sound = ast_get_chan_features_xferfailsound(chan);
1777 ast_channel_unlock(chan);
1796 ast_channel_lock(chan);
1798 ast_channel_unlock(chan);
1800 if (bridge_channel) {
1817 ast_channel_lock(chan);
1819 ast_channel_unlock(chan);
1821 if (bridge_channel) {
1834 ast_channel_lock(chan);
1836 ast_channel_unlock(chan);
1838 if (bridge_channel) {
1898 ast_channel_lock(channel);
1900 ast_channel_unlock(channel);
1902 if (bridge_channel) {
1903 ao2_lock(bridge_channel);
1905 ao2_unlock(bridge_channel);
1907 bridge_do_move(dest, bridge_channel, 1, 0);
1913 ao2_cleanup(bridge_channel);
1922 ast_alloca(num_channels *
sizeof(*kick_bridge_channels)) : NULL;
1924 int num_bridge_channels = 0;
1928 for (i = 0; i < num_channels; ++i) {
1931 kick_bridge_channel = bridge_find_channel(src, kick_channels[i]);
1932 if (!kick_bridge_channel) {
1933 kick_bridge_channel = bridge_find_channel(dest, kick_channels[i]);
1940 if (!kick_bridge_channel) {
1944 kick_bridge_channels[num_bridge_channels++] = kick_bridge_channel;
1947 bridge_do_merge(dest, src, kick_bridge_channels, num_bridge_channels, 0);
2040 .enter = calling_target_enter,
2041 .exit = calling_target_exit,
2045 .state_name =
"Hesitant",
2046 .enter = hesitant_enter,
2047 .exit = hesitant_exit,
2051 .state_name =
"Rebridge",
2052 .enter = rebridge_enter,
2056 .state_name =
"Resume",
2057 .enter = resume_enter,
2061 .state_name =
"Threeway",
2062 .enter = threeway_enter,
2066 .state_name =
"Consulting",
2067 .enter = consulting_enter,
2068 .exit = consulting_exit,
2071 .state_name =
"Double Checking",
2072 .enter = double_checking_enter,
2073 .exit = double_checking_exit,
2076 .state_name =
"Complete",
2077 .enter = complete_enter,
2081 .state_name =
"Blond",
2082 .enter = blond_enter,
2086 .state_name =
"Blond Non-Final",
2087 .enter = blond_nonfinal_enter,
2088 .exit = blond_nonfinal_exit,
2092 .state_name =
"Recalling",
2093 .enter = recalling_enter,
2094 .exit = recalling_exit,
2098 .state_name =
"Wait to Retransfer",
2099 .enter = wait_to_retransfer_enter,
2100 .exit = wait_to_retransfer_exit,
2104 .state_name =
"Retransfer",
2105 .enter = retransfer_enter,
2106 .exit = retransfer_exit,
2110 .state_name =
"Wait to Recall",
2111 .enter = wait_to_recall_enter,
2112 .exit = wait_to_recall_exit,
2116 .state_name =
"Fail",
2117 .enter = fail_enter,
2156 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2158 return props->
state;
2196 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2198 return props->
state;
2220 &transferee_channel, &target_channel);
2280 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2282 return props->
state;
2322 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2324 return props->
state;
2334 &transferee_channel, &target_channel);
2350 &transferee_channel, &target_channel);
2366 res = blond_enter(props);
2397 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2399 return props->
state;
2519 common_recall_channel_setup(recall, props->
transferer);
2520 ast_channel_unlock(recall);
2583 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2585 return props->
state;
2615 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2617 return props->
state;
2633 snprintf(destination,
sizeof(destination),
"%s@%s", props->
exten, props->
context);
2640 ast_log(LOG_ERROR,
"Unable to request outbound channel for recall target\n");
2645 ast_log(LOG_ERROR,
"Unable to attach framehook to recall target\n");
2666 ast_log(LOG_ERROR,
"Unable to place outbound call to recall target\n");
2675 ast_log(LOG_ERROR,
"Unable to place recall target into bridge\n");
2709 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2711 return props->
state;
2741 ast_log(LOG_WARNING,
"Unexpected stimulus '%s' received in attended transfer state '%s'\n",
2743 return props->
state;
2765 ast_debug(1,
"Transferer on attended transfer %p pressed abort sequence\n", props);
2779 ast_debug(1,
"Transferer on attended transfer %p pressed complete sequence\n", props);
2793 ast_debug(1,
"Transferer on attended transfer %p pressed threeway sequence\n", props);
2807 ast_debug(1,
"Transferer on attended transfer %p pressed swap sequence\n", props);
2821 ast_debug(1,
"Transferer on attended transfer %p hung up\n", props);
2850 ast_debug(1,
"Detected an answer for recall attempt on attended transfer %p\n", props);
2869 static void transfer_target_framehook_destroy_cb(
void *data)
2877 const char *abort_dtmf;
2878 const char *complete_dtmf;
2879 const char *threeway_dtmf;
2880 const char *swap_dtmf;
2927 if (self->num_channels == 1) {
2935 if (!transferer_bridge_channel) {
2939 not_transferer =
AST_LIST_FIRST(&self->channels) != transferer_bridge_channel;
2940 ao2_ref(transferer_bridge_channel, -1);
2941 if (not_transferer) {
2971 if (self->num_channels == 0) {
2977 if (self->num_channels == 1) {
2991 if (target_bridge_channel) {
2995 ao2_ref(target_bridge_channel, -1);
3007 transfer_pull(
self, bridge_channel, props);
3010 recall_pull(
self, bridge_channel, props);
3025 struct timeval relative_timeout = { 0, };
3026 struct timeval absolute_timeout;
3027 struct timespec timeout_arg;
3041 timeout_arg.tv_sec = absolute_timeout.tv_sec;
3042 timeout_arg.tv_nsec = absolute_timeout.tv_usec * 1000;
3044 if (ast_cond_timedwait(&props->
cond,
lock, &timeout_arg) == ETIMEDOUT) {
3049 stimulus = list->stimulus;
3074 callid = ast_channel_callid(props->
transferer);
3083 ast_debug(1,
"About to enter state %s for attended transfer %p\n", state_properties[props->
state].
state_name, props);
3086 state_properties[props->
state].
enter(props)) {
3087 ast_log(LOG_ERROR,
"State %s enter function returned an error for attended transfer %p\n",
3093 ast_debug(1,
"State %s is a terminal state. Ending attended transfer %p\n",
3098 stimulus = wait_for_stimulus(props);
3100 ast_debug(1,
"Received stimulus %s on attended transfer %p\n", stimulus_strs[stimulus], props);
3102 ast_assert(state_properties[props->
state].
exit != NULL);
3104 props->
state = state_properties[props->
state].
exit(props, stimulus);
3106 ast_debug(1,
"Told to enter state %s exit on attended transfer %p\n", state_properties[props->
state].
state_name, props);
3121 .
version = AST_FRAMEHOOK_INTERFACE_VERSION,
3123 .destroy_cb = transfer_target_framehook_destroy_cb,
3125 .disable_inheritance = 1,
3129 target_interface.
data = props;
3131 ast_channel_lock(channel);
3133 ast_channel_unlock(channel);
3150 xfer_cfg = ast_get_chan_features_xfer_config(chan);
3154 if (attended_transfer) {
3187 char *announce_sound, *retry_sound, *invalid_sound;
3188 const char *extenoverride;
3190 ast_channel_lock(chan);
3191 extenoverride = get_transfer_exten(chan, NULL);
3193 if (!ast_strlen_zero(extenoverride)) {
3195 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str, NULL)) ? 1 : 0;
3198 ast_channel_unlock(chan);
3199 ast_verb(3,
"Transfering call to '%s@%s'", exten, context);
3202 ast_log(LOG_WARNING,
"Override extension '%s' does not exist in context '%s'\n", extenoverride, context);
3206 xfer_cfg = ast_get_chan_features_xfer_config(chan);
3208 ast_log(LOG_ERROR,
"Channel %s: Unable to get transfer configuration\n",
3209 ast_channel_name(chan));
3210 ast_channel_unlock(chan);
3219 ast_channel_unlock(chan);
3222 if (!ast_strlen_zero(announce_sound)) {
3242 ast_channel_name(chan), attempts);
3243 res =
ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
3249 ast_channel_name(chan), attempts, exten, res > 0 ?
"Success" :
"Failure");
3255 if (ast_strlen_zero(exten)) {
3256 ast_verb(3,
"Channel %s: Dialed no digits.\n", ast_channel_name(chan));
3258 ast_verb(3,
"Channel %s: Dialed '%s@%s' does not exist.\n",
3259 ast_channel_name(chan), exten, context);
3261 if (attempts < max_attempts) {
3266 memset(exten, 0, exten_len);
3272 }
while (res > 0 && attempts < max_attempts);
3277 ast_channel_name(chan), res == 0 ?
"Success" :
"Failure");
3279 return res ? -1 : 0;
3288 ast_channel_unlock(dest);
3289 ast_channel_unlock(caller);
3299 ast_channel_lock(caller);
3300 caps =
ao2_bump(ast_channel_nativeformats(caller));
3301 ast_channel_unlock(caller);
3304 chan =
ast_request(
"Local", caps, NULL, caller, destination, &cause);
3321 ast_channel_unlock(chan);
3322 ast_channel_unlock(caller);
3325 copy_caller_data(chan, caller);
3352 ast_verb(3,
"Channel %s: Started DTMF attended transfer.\n",
3353 ast_channel_name(bridge_channel->
chan));
3356 ast_log(LOG_ERROR,
"Channel %s: Attended transfer attempted on unsupported bridge type '%s'.\n",
3369 ast_verb(3,
"Channel %s: Bridge '%s' does not permit merging at this time.\n",
3370 ast_channel_name(bridge_channel->
chan), bridge->
uniqueid);
3377 attended_transfer ? attended_transfer->
context : NULL);
3379 ast_log(LOG_ERROR,
"Channel %s: Unable to allocate control structure for performing attended transfer.\n",
3380 ast_channel_name(bridge_channel->
chan));
3388 if (add_transferer_role(props->
transferer, attended_transfer)) {
3389 ast_log(LOG_ERROR,
"Channel %s: Unable to set transferrer bridge role.\n",
3390 ast_channel_name(bridge_channel->
chan));
3405 ast_verb(3,
"Channel %s: Unable to acquire target extension for attended transfer.\n",
3406 ast_channel_name(bridge_channel->
chan));
3415 snprintf(destination,
sizeof(destination),
"%s@%s", props->
exten, props->
context);
3417 ast_debug(1,
"Channel %s: Attended transfer target '%s'\n",
3418 ast_channel_name(bridge_channel->
chan), destination);
3423 ast_log(LOG_ERROR,
"Channel %s: Unable to request outbound channel for attended transfer target.\n",
3424 ast_channel_name(bridge_channel->
chan));
3435 ast_log(LOG_ERROR,
"Channel %s: Unable to create bridge for attended transfer target.\n",
3436 ast_channel_name(bridge_channel->
chan));
3447 ast_log(LOG_ERROR,
"Channel %s: Unable to attach framehook to transfer target.\n",
3448 ast_channel_name(bridge_channel->
chan));
3463 ast_log(LOG_ERROR,
"Channel %s: Unable to place outbound call to transfer target.\n",
3464 ast_channel_name(bridge_channel->
chan));
3480 ast_log(LOG_ERROR,
"Channel %s: Unable to place transfer target into bridge.\n",
3481 ast_channel_name(bridge_channel->
chan));
3491 ast_log(LOG_ERROR,
"Channel %s: Unable to create monitoring thread for attended transfer.\n",
3492 ast_channel_name(bridge_channel->
chan));
3508 struct ast_channel *transferer_channel = user_data_wrapper->data;
3511 copy_caller_data(new_channel, transferer_channel);
3520 const char *xfer_context;
3521 char *goto_on_blindxfer;
3523 ast_verb(3,
"Channel %s: Started DTMF blind transfer.\n",
3524 ast_channel_name(bridge_channel->
chan));
3528 ast_channel_lock(bridge_channel->
chan);
3530 blind_transfer ? blind_transfer->
context : NULL));
3532 "GOTO_ON_BLINDXFR"),
""));
3533 ast_channel_unlock(bridge_channel->
chan);
3536 if (
grab_transfer(bridge_channel->
chan, xfer_exten,
sizeof(xfer_exten), xfer_context)) {
3541 ast_debug(1,
"Channel %s: Blind transfer target '%s@%s'\n",
3542 ast_channel_name(bridge_channel->
chan), xfer_exten, xfer_context);
3544 if (!ast_strlen_zero(goto_on_blindxfer)) {
3545 const char *chan_context;
3546 const char *chan_exten;
3549 ast_debug(1,
"Channel %s: After transfer, transferrer goes to %s\n",
3550 ast_channel_name(bridge_channel->
chan), goto_on_blindxfer);
3552 ast_channel_lock(bridge_channel->
chan);
3553 chan_context =
ast_strdupa(ast_channel_context(bridge_channel->
chan));
3555 chan_priority = ast_channel_priority(bridge_channel->
chan);
3556 ast_channel_unlock(bridge_channel->
chan);
3558 chan_context, chan_exten, chan_priority, goto_on_blindxfer);
3563 && !ast_strlen_zero(goto_on_blindxfer)) {
3597 static void personality_destructor(
void *obj)
3607 static void on_personality_change_normal(
struct ast_bridge *bridge)
3612 if (add_normal_hooks(bridge, iter)) {
3613 ast_log(LOG_WARNING,
"Unable to set up bridge hooks for channel %s. Features may not work properly\n",
3614 ast_channel_name(iter->
chan));
3624 details->
v_table = &personality_normal_v_table;
3629 details->
v_table = &personality_atxfer_v_table;
3633 ast_log(LOG_WARNING,
"Asked to initialize unexpected basic bridge personality type.\n");
3647 personality = ao2_alloc(
sizeof(*personality), personality_destructor);
3653 init_details(&personality->
details[i], i);
3669 bridge = bridge_basic_personality_alloc(bridge);
3699 personality_normal_v_table.
name =
"normal";
3700 personality_normal_v_table.
push = bridge_personality_normal_push;
3702 personality_atxfer_v_table.
name =
"attended transfer";
3703 personality_atxfer_v_table.
push = bridge_personality_atxfer_push;
3704 personality_atxfer_v_table.
pull = bridge_personality_atxfer_pull;
enum attended_transfer_state(* exit)(struct attended_transfer_properties *props, enum attended_transfer_stimulus stimulus)
static int transfer_target_framehook_consume(void *data, enum ast_frame_type type)
Callback function which informs upstream if we are consuming a frame of a specific type...
static void clear_stimulus_queue(struct attended_transfer_properties *props)
Free backlog of stimuli in the queue.
static void attended_transfer_properties_shutdown(struct attended_transfer_properties *props)
Initiate shutdown of attended transfer properties.
Main Channel structure associated with a channel.
static void bridge_basic_change_personality(struct ast_bridge *bridge, enum bridge_basic_personality_type type, void *user_data)
Change basic bridge personality.
static void play_failsound(struct ast_channel *chan)
Helper method to play a fail sound on a channel in a bridge.
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Feature configuration relating to transfers.
struct ast_bridge * ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request)
Adjust the bridge_channel's bridge merge inhibit request count.
#define ast_bridge_lock_both(bridge1, bridge2)
Lock two bridges.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_flags feature_flags
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
int atxfercallbackretries
static void publish_transfer_success(struct attended_transfer_properties *props, struct ast_channel *transferee_channel, struct ast_channel *target_channel)
Send a stasis publication for a successful attended transfer.
const ast_string_field uniqueid
struct ast_bridge_features * features
void * ast_dial_get_user_data(struct ast_dial *dial)
Return the user data on a dial structure.
char complete[MAXIMUM_DTMF_FEATURE_STRING]
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Main dialing structure. Contains global options, channels being dialed, and more! ...
const ast_string_field xfersound
Message representing attended transfer.
unsigned int bridge_flags
void ast_party_id_reset(struct ast_party_id *id)
Destroy and initialize the given party id structure.
Structure that contains features information.
const ast_string_field atxferabort
static void publish_transfer_threeway(struct attended_transfer_properties *props, struct ast_channel *transferee_channel, struct ast_channel *target_channel)
Send a stasis publication for an attended transfer that ends in a threeway call.
#define ast_channel_unref(c)
Decrease channel reference count.
static void bridge_merge(struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel **kick_channels, unsigned int num_channels)
Wrapper for bridge_do_merge.
static void recall_callback(struct ast_dial *dial)
Dial callback when attempting to recall the original transferer channel.
const ast_string_field atxferthreeway
void ast_channel_remove_bridge_role(struct ast_channel *chan, const char *role_name)
Removes a bridge role from a channel.
attended_transfer_state_flags
Flags that indicate properties of attended transfer states.
int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Enable a built in feature on a bridge features structure.
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
Wait to Retransfer state.
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
An applicationmap configuration item.
void(* on_personality_change)(struct ast_bridge *bridge)
const ast_string_field atxfercomplete
void ast_bridge_publish_attended_transfer(struct ast_attended_transfer_message *transfer_msg)
Publish an attended transfer.
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
struct ast_bridge * transferee_bridge
int ast_bridge_channel_write_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
Write a control frame into the bridge with data.
const ast_string_field transferer_addr
void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
Run an application on the bridge channel.
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
static void get_transfer_party_non_transferer_bridge(struct ast_bridge *bridge, struct ast_channel **party)
Get a desired transfer party for a bridge the transferer is not in.
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
enum bridge_basic_personality_type current
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
unsigned int atxferdropcall
enum bridge_channel_state state
Structure for a data store type.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
static void get_transfer_parties_transferer_bridge(struct ast_bridge *transferer_bridge, struct ast_bridge *other_bridge, struct ast_channel *transferer, struct ast_channel **transferer_peer, struct ast_channel **other_party)
Get the transferee and transfer target when the transferer is in a bridge with one of the desired par...
const char * stimulus_strs[]
String representations of the various stimuli.
const ast_string_field transferannouncesound
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
bridge_basic_personality_type
unsigned int inhibit_merge
Count of the active temporary requests to inhibit bridge merges. Zero if merges are allowed...
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
int ast_bridge_channel_write_callback(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_custom_callback_option flags, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size)
Write a bridge action custom callback frame into the bridge.
Structure for a data store object.
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
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.
unsigned int transferdigittimeout
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static void stream_failsound(struct ast_channel *chan)
Helper method to stream a fail sound on a channel.
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
const ast_string_field exten
static int atxfer_complete(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses complete sequence.
const ast_string_field transferer_type
Properties of an attended transfer state.
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Queue the given frame to everyone else.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
void ast_free_ptr(void *ptr)
free() wrapper
struct ast_channel * transfer_target
int ast_attended_transfer_message_add_merge(struct ast_attended_transfer_message *transfer_msg, struct ast_bridge *final_bridge)
Add details for a bridge merge to an attended transfer message.
struct ast_channel * ast_bridge_peer(struct ast_bridge *bridge, struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
unsigned int transferdialattempts
static struct ast_channel * dial_transfer(struct ast_channel *caller, const char *destination)
Helper function that creates an outgoing channel and returns it immediately.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_frame_subclass subclass
struct ast_channel * recall_target
void ast_party_caller_copy(struct ast_party_caller *dest, const struct ast_party_caller *src)
Copy the source caller information to the destination caller.
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
static void play_sound(struct ast_channel *chan, const char *sound)
Helper method to play a sound on a channel in a bridge.
void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
Set user data on a dial structure.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value)
Set a role option on a channel.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
const ast_string_field transferretrysound
struct ast_attended_transfer_message * ast_attended_transfer_message_create(int is_external, struct ast_channel *to_transferee, struct ast_bridge *transferee_bridge, struct ast_channel *to_transfer_target, struct ast_bridge *target_bridge, struct ast_channel *transferee, struct ast_channel *transfer_target)
Create an Attended transfer message to be published.
enum ast_transfer_result result
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
enum ast_transfer_result ast_bridge_transfer_blind(int is_external, struct ast_channel *transferer, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
Blind transfer target to the extension and context provided.
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
General Asterisk PBX channel definitions.
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
int ast_bridge_features_ds_append(struct ast_channel *chan, struct ast_flags *flags)
Append basic bridge DTMF feature flags on the channel.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
enum attended_transfer_state state
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_bridging_init_basic(void)
int ast_bridge_features_ds_set(struct ast_channel *chan, struct ast_flags *flags)
Set basic bridge DTMF feature flags datastore on the channel.
unsigned int atxferloopdelay
static void ringing(struct ast_channel *chan)
Helper method to send a ringing indication to a channel in a bridge.
void ast_bridge_merge_inhibit(struct ast_bridge *bridge, int request)
Adjust the bridge merge inhibit request count.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
#define AST_STRING_FIELD(name)
Declare a string field.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
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
static void bridge_ringing(struct ast_bridge *bridge)
Helper method to send a ringing indication to all channels in a bridge.
struct ast_flags transferer_features
static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
Helper function that presents dialtone and grabs extension.
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
static void bridge_hold(struct ast_bridge *bridge)
Helper method to send a hold frame to all channels in a bridge.
#define ast_debug(level,...)
Log a DEBUG message.
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Details for specific basic bridge personalities.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
void ast_bridge_basic_set_flags(struct ast_bridge *bridge, unsigned int flags)
Set feature flags on a basic bridge.
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Core PBX routines and definitions.
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
attended_transfer_superstate
Attended transfer superstates.
struct ast_bridge * bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Initialize the base class of the bridge.
char context[AST_MAX_CONTEXT]
#define ast_test_suite_event_notify(s, f,...)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
ast_frame_type
Frame types.
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
const struct ast_bridge_methods * v_table
static int atxfer_threeway(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses threeway sequence.
int ast_channel_has_role(struct ast_channel *channel, const char *role_name)
Check if a role exists on a channel.
struct ast_bridge * target_bridge
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
char context[AST_MAX_CONTEXT]
Structure that contains information about a bridge.
static struct ast_frame * transfer_target_framehook_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
Frame hook for transfer target channel.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static int atxfer_abort(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses abort sequence.
static void * attended_transfer_monitor_thread(void *data)
The main loop for the attended transfer monitor thread.
int ast_bridge_hangup_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a hangup hook to a bridge features structure.
unsigned int atxfernoanswertimeout
static void remove_hooks_on_personality_change(struct ast_bridge *bridge)
Remove appropriate hooks when basic bridge personality changes.
int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_hook_callback callback, const char *dtmf)
Register a handler for a built in feature.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Connected Line/Party information.
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
struct ast_bridge_methods ast_bridge_basic_v_table
Bridge basic class virtual method table.
const char * app_name(struct ast_app *app)
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
static void publish_transfer_fail(struct attended_transfer_properties *props)
Send a stasis publication for a failed attended transfer.
int(* enter)(struct attended_transfer_properties *props)
const ast_string_field atxferswap
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
char threeway[MAXIMUM_DTMF_FEATURE_STRING]
structure that organizes different personalities for basic bridges.
attended_transfer_stimulus
Stimuli that can cause transfer state changes.
ast_bridge_builtin_feature
Built in DTMF features.
Bridge virtual methods table definition.
#define ast_bridge_unlock(bridge)
Unlock the bridge.
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
union ast_frame::@224 data
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
#define ast_calloc(num, len)
A wrapper for calloc()
struct ast_dial * ast_dial_create(void)
New dialing structure.
static int atxfer_transferer_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Hangup hook for transferer channel.
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
static struct attended_transfer_properties * attended_transfer_properties_alloc(struct ast_channel *transferer, const char *context)
Allocate and initialize attended transfer properties.
static int atxfer_swap(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
DTMF hook when transferer presses swap sequence.
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
static int feature_blind_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Internal built in feature for blind transfers.
void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int is_attended)
Set the relevant transfer variables for a single channel.
int ast_attended_transfer_message_add_threeway(struct ast_attended_transfer_message *transfer_msg, struct ast_channel *survivor_channel, struct ast_bridge *survivor_bridge)
Add details for an attended transfer that was resolved as a three-way call.
struct ast_channel * swap
struct ast_bridge_methods * v_table
Basic bridge subclass API.
void ast_bridge_features_remove(struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags flags)
Remove marked bridge channel feature hooks.
Structure used to handle boolean flags.
int ast_bridge_dtmf_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a DTMF hook to a bridge features structure.
int ast_bridge_features_ds_set_string(struct ast_channel *chan, const char *features)
Sets the features a channel will use upon being bridged.
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Structure that contains configuration information for the attended transfer built in feature...
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_bridge_lock(bridge)
Lock the bridge.
int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
Write a hold frame into the bridge.
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
struct ast_bridge_channels_list channels
struct ast_party_connected_line original_transferer_colp
static void get_transfer_parties(struct ast_channel *transferer, struct ast_bridge *transferee_bridge, struct ast_bridge *target_bridge, struct ast_channel **transferee, struct ast_channel **transfer_target)
determine transferee and transfer target for an attended transfer
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
After Bridge Execution API.
#define ast_channel_ref(c)
Increase channel reference count.
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
char abort[MAXIMUM_DTMF_FEATURE_STRING]
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Queue a bridge action play file frame onto the bridge channel.
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
Present a dialtone and collect a certain length extension.
static void unhold(struct ast_channel *chan)
Helper method to take a channel in a bridge off hold.
enum attended_transfer_state_flags flags
AO2 object that wraps data for transfer_channel_cb.
Data structure associated with a single frame of data.
const ast_string_field context
const char * ast_channel_get_role_option(struct ast_channel *channel, const char *role_name, const char *option)
Retrieve the value of a requested role option from a channel.
static void bridge_move(struct ast_bridge *dest, struct ast_bridge *src, struct ast_channel *channel, struct ast_channel *swap)
Wrapper for bridge_do_move.
ast_bridge_pull_channel_fn pull
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.
ast_bridge_destructor_fn destroy
ast_bridge_push_channel_fn push
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
int atxfernoanswertimeout
static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Internal built in feature for attended transfers.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
struct personality_details details[BRIDGE_BASIC_PERSONALITY_END]
Structure that contains configuration information for the blind transfer built in feature...
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
Write an unhold frame into the bridge.
const ast_string_field xfersound
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
static void bridge_unhold(struct ast_bridge *bridge)
Helper method to send an unhold frame to all channels in a bridge.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
struct ast_channel * transferer
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ast_party_id priv
Private connected party ID.
unsigned int atxfercallbackretries
unsigned int num_channels
int ast_stopstream(struct ast_channel *c)
Stops a stream.
const ast_string_field transferinvalidsound
char swap[MAXIMUM_DTMF_FEATURE_STRING]
enum attended_transfer_superstate superstate
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
Collection of data related to an attended transfer attempt.
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.